Tools
agent_toolset_20260401 is the hosted toolset. An agent that carries it gets a persistent bash shell and a filesystem, inside its session's own container, and can search and fetch the web. An agent without it can only write messages. A tool set to enabled: false is never offered to the model.
| Tool | What it does |
|---|---|
| bash | Runs a shell command in the sandbox. |
| read | Reads a file. |
| write | Writes a file, creating the parent directories. |
| edit | Replaces a string in a file. |
| glob | Finds files by pattern. |
| grep | Searches file contents. |
| web_search | Searches the web and returns results with excerpts. |
| web_fetch | Fetches a URL and returns its text, or the PDF it serves. |
The shell
The bash session persists across calls and across turns. The working directory, the exported variables and the background processes survive to the next command. A command times out after five minutes. Run long work in the background and poll it.
The tool writes output over 100,000 characters to a file in the sandbox and gives the model a preview naming it. Reading the rest is another tool call, not a download.
The shell is lost when the container stops after a quiet session. The filesystem is not.
The web
Each web tool takes its own config beside its name. A page comes back as a document block and a search as search_result blocks, as the Managed Agents API returns them.
| Field | What it does |
|---|---|
| allowed_domains | Both tools. Only these domains and their subdomains; web_search also takes a path, as example.com/docs. Up to 64. |
| blocked_domains | Both tools. Never these. One of the two lists, not both. |
| max_content_tokens | web_fetch. Cuts the page's text to about this many tokens. |
| user_location | web_search. Its country biases the results. |
web_fetch honours robots.txt, never dials a private address, and checks every redirect hop against the same rules. A refusal is a tool result the model reads, not a failed turn.
Permission policies
The toolset entry carries a default in default_config and an entry per tool in configs, each with enabled and a policy. A tool under always_ask does not run until you answer.
{
"type": "agent_toolset_20260401",
"default_config": { "permission_policy": { "type": "always_allow" } },
"configs": [
{
"name": "bash",
"permission_policy": { "type": "always_ask" }
}
]
}| Policy | Effect |
|---|---|
| always_allow | The tool runs. This is the default. |
| always_ask | The turn stops and waits for your answer before the call runs. |
Answering a tool
When a tool asks, the turn ends with session.status_idle and a stop reason of requires_action, which names the agent.tool_use event ids that are waiting. Answer each one with a user.tool_confirmation.
await client.beta.sessions.events.send(session.id, {
events: [
{
type: "user.tool_confirmation",
tool_use_id: "sevt_...",
result: "deny",
deny_message: "Do not touch the release branch.",
},
],
});A denial carries an optional message, which the agent reads as the tool's result. Every agent.tool_use event also carries evaluated_permission, what the policy decided, and evaluation, the policy that decided it. A call under auto runs: coreloop makes no call of its own on it.
MCP servers
An agent's mcp_servers are connected the first time a turn needs its tools, and their tools are offered beside the sandbox's. An mcp_toolset defaults to always_ask, so a call waits for a user.tool_confirmation unless the toolset or the tool allows it. A call is an agent.mcp_tool_use, named by the server's own tool name and mcp_server_name; its result is an agent.mcp_tool_result that names it by mcp_tool_use_id. In mcp_server_name, every character but letters, digits, _ and - reads as _: mcp.deepwiki.com is mcp_deepwiki_com.
A server that cannot be reached is reported as a session.error of type mcp_connection_failed_error or mcp_authentication_failed_error, and the turn runs without its tools. It is tried again on the next turn.
A server that needs a token finds it in a vault the session names in vault_ids: the credential whose mcp_server_url is the server's URL, sent as a bearer. The first vault in vault_ids that holds the URL wins. A refused mcp_oauth token is refreshed once and the connect tried again.
Custom tools
A tools entry of type custom is a tool your client runs. It carries a name, a description and an input_schema. A call is an agent.custom_tool_use with the name and the input, and the turn ends with session.status_idle and a stop reason of requires_action that names it. The session waits until you send the result as a user.custom_tool_result.
await client.beta.sessions.events.send(session.id, {
events: [
{
type: "user.custom_tool_result",
custom_tool_use_id: "sevt_...",
content: [{ type: "text", text: "status: shipped" }],
},
],
});The result takes text, image, document and search_result blocks, read as a message's images and documents are. A custom tool cannot share a name with another tool of the agent.
A model message can call a custom tool and a sandbox tool together. The sandbox tool runs once every custom call of the message has its result.
Not yet
The Managed Agents API also takes web_fetch's url_sources. coreloop refuses a url_sources value.
Soon: url_sources.