Skip to main content
A tool is something an agent can call. You declare it once; Swarm validates every call against its schema and routes it to whatever runs it. Every tool belongs to one of three implementation classes:

The three tool classes

tools.yaml
The fields of a custom tool:
  • Required: description.
  • Optional: handler_type (defaults to http), input_schema, output_schema (aliases parameters/returns); HTTP tools add http, response_mapping, credentials.
  • Not accepted: endpoint (use http.url), type (use handler_type).
Older bundles may use workflow_registered or api_call; new tools should use handler_type: http or an MCP server.

MCP tools

Swarm acts as an MCP client. Register servers in policy.yaml:
policy.yaml
Tools are namespaced by the server’s prefix (pg.list_tables), and an agent references the prefixed name in its tools list. If a server is unreachable, Swarm logs a warning and starts anyway. See the MCP gateway reference.

Permissions

tools and native_tools cover what an agent may call. A separate list, permissions, covers what it may do to shared platform state: change routing, write to the mailbox, request a human decision, schedule a timer. These are verbs such as configure_routing, message_flow, mailbox_send, human_task_request, human_task_decide, and schedule. Rather than repeat the same list on every agent, name a permission bundle defined once in policy.yaml:
policy.yaml
An agent references the bundle by name, and may add agent-specific grants inline:
agents.yaml
The effective permission set is the bundle plus the inline list, deduplicated. Naming a bundle that policy.yaml does not define is a boot error.

The tools a permission unlocks

Most of these permissions gate a platform-builtin tool of the same name: hold the permission and the tool is offered to the agent, lack it and the tool is not. A few permissions gate other platform surfaces rather than a callable tool, such as configure_routing (adjust routing at runtime) and approve_spend (clear a budget hold). And two messaging tools need no permission at all: agent_message and mailbox_send are universal, granted to every agent.

Native capabilities

bash, web_search, and file_io are not declared in tools.yaml; they are host capabilities gated by an agent’s native_tools field (default all off):
native_tools is its own switch, separate from both tools and permissions. They cover different things: permissions are about what an agent may do to shared platform state (routing, the mailbox, entity writes), while native_tools are about what it may do on the host machine (run a shell command, search the web, read or write files). So you do not also add a permission for bash anywhere; turning on native_tools.bash is the whole grant. One thing to know on the Claude CLI runtime: there, bash, web_search, and file_io come from the CLI itself, and the platform will not stand in a substitute. If you turn one on and the runtime cannot provide it, you get a clear error at startup rather than an agent that quietly runs without it. (Setting policy.web_search_provider does not count as providing web_search here; it has to come from the CLI.)

Flow reference data

Sometimes an agent needs to read a fixed file you ship with the flow: a prompt template, a lookup table, a list of things to skip. Put the file under the flow package’s data/ directory and list it in the agent’s flow_data_access:
The agent then gets a read_flow_data tool that can open exactly those files and nothing else. These files are read-only and travel with your contracts, so they change when you redeploy, not while the flow is running. That makes them right for reference data, not for entity state or scratch files the agent writes. As with native_tools, listing the file is the whole grant: no permissions entry, and it is not part of tools. Only flow-scoped agents can use it.

Default-deny

An agent can only call a tool that is in its tools list, a universal tool, an emit tool, a generated entity tool, a read_flow_data tool (if it declares flow_data_access), or an enabled native capability. Anything else is rejected.