Register provider-hosted tools#
A server tool runs inside a model provider, unlike an ordinary AgentTool
executed by the Agent loop. Install one provider-specific extension for each
hosted capability you want to expose:
from zett_agent.extensions.server_tools.google import GoogleServerToolExtension
from zett_agent.client import create_agent
from zett_agent.model import ServerToolDefinition
client = await create_agent(
model,
extensions=[
GoogleServerToolExtension([
"google_search",
"url_context",
]),
],
)
Every extension calls register_server_tool()
during on_tool. The resulting definitions are request-scoped and reach
every subsequent before-model hook and the final ModelRequest. They never
enter the Agent’s local tool executor.
Choose the extension that matches the endpoint#
Extension |
Default type |
Transport requirement |
|---|---|---|
|
Gemini GenerateContent; supported by GoogleProvider. |
|
|
Anthropic Messages; supported by AnthropicProvider. |
|
|
OpenRouter-compatible Chat Completions endpoint. |
|
|
OpenAI Responses API; not OpenAI Chat Completions. |
|
|
DeepSeek Responses API; not legacy Chat Completions. |
OpenAIProvider and DeepSeekProvider use Chat Completions by default. Construct
either adapter with response=True to use its Responses endpoint and enable
its hosted tools explicitly:
model = OpenAIProvider(
model="gpt-5",
api_key=os.environ["OPENAI_API_KEY"],
response=True,
)
The Responses adapter sends complete history on every request. It preserves provider output items for later function-result turns and maps hosted-tool start/completion records into the common server-tool event lifecycle. Available tool types still depend on the selected provider endpoint and model.
OpenAI and DeepSeek publish no separate web_fetch type. Their hosted
web-search workflow retrieves relevant pages itself. The defaults intentionally
use documented types instead of sending an invented fetch discriminator.
Allow protocol evolution#
Tool types are open strings and configurations are opaque mappings. New provider versions therefore do not require a zett-agent enum update:
extension = AnthropicServerToolExtension(
[
ServerToolDefinition(
"web_fetch_20260318",
{
"name": "web_fetch",
"max_uses": 3,
"allowed_domains": ["docs.python.org"],
},
),
ServerToolDefinition("code_execution_20260521"),
],
)
The provider remains responsible for model compatibility and field validation. Duplicate types in one request are rejected before network I/O because their ordering would otherwise make the active configuration ambiguous.
When none of the tools needs configuration, pass their type strings directly:
extension = GoogleServerToolExtension([
"google_search",
"url_context",
"code_execution",
])