ToolsRepository is the registry that holds every skill an agent can call. In the SDK a skill is a Tool; agent.tools lists them. There are two kinds:
- Backend skills: catalog skills and OpenAPI imports configured in Xpander Chat. Loaded automatically when you
agents.aget(...)an agent. - Local skills: Python functions you decorate with
@register_tool. Registered in-process and merged into the agent’s skill list.
ToolsRepository yourself. agent.tools returns the configured instance for that agent.
Class layout
Constructor
In practice,
agents.aget(...) constructs a ToolsRepository for you with all four arguments populated.
Properties
list
id). Each Tool has its Configuration set and any agent-graph schema overrides applied.
functions
.list. Each callable accepts a single payload argument validated against the skill’s auto-generated Pydantic schema. The callable’s __name__ is the skill id and its __doc__ includes a usage example.
This is what Backend.aget_args injects into your agent loop’s tools=... parameter: you rarely need it directly. Useful when binding skills to an agent loop the SDK has no integration for.
Methods
get_tool_by_id
Tool with the matching id, or None.
get_tool_by_name
Tool with the matching name (display name), or None.
register_tool (classmethod)
Tool to the global local registry. Used by the @register_tool decorator: you don’t usually call this directly.
should_sync_local_tools
True when at least one local skill is marked should_add_to_graph=True and hasn’t been synced yet.
get_local_tools_for_sync
agent.aload).
aload_tool_by_id
<connection_id>_<operation_id> form and seeds it into the repository. Useful when you want to invoke a single skill without loading an agent.
The id is the connection’s id and the operation’s id joined by a single underscore, for example "23cbd764-d463-44bd-9a7b-90a6d20dac52_6a5ad4e42dab47000a601911". The connection id is in connections[].id of the skills list. The operation id is the id field of the operations list for that connection. The skill’s own id in the first half does not load.
The sync sibling is load_tool_by_id.
Patterns
Iterate every skill
Bind skills to an agent loop by hand
Standalone invocation (no agent context)
@register_tool
@register_tool turns a Python function into a skill the agent can invoke. The SDK extracts type hints and the docstring to build a schema and description automatically: there’s no manual schema writing.
calculate_sum is available to every Agents().aget(...) call as a local skill with id "calculate_sum".
Decorator forms
What it does
- Inspects the function’s parameters and type hints.
- Builds a Pydantic model (
<FunctionName>Args) from the parameters: required if no default, optional otherwise. - Constructs a
Toolwith:id= function namename= function namedescription= function docstringparameters= generated JSON schemafn= the functionis_local = Trueshould_add_to_graph = add_to_graph
- Registers the
ToolinToolsRepository’s class-level_local_toolslist (process-wide singleton). - Returns the original function unchanged:
calculate_sum(2, 3)still works as plain Python.
Examples
Async functions are supported
Optional parameters
Push to the agent graph
add_to_graph=True registers the skill on the agent in Xpander Chat for the next agents.aget(...): the SDK sync runs in the background after aget returns.
Use the function directly
Visibility rules
The decorator registers skills at module-import time on a process-wide registry. That means:- Every agent loaded by
Agents().aget(...)in this process inherits the local skills. - Skills defined inside a function body register the first time the function runs, but stay registered for the rest of the process’s lifetime.
- If you
delor rename a function after decoration, the registeredToolkeeps its captured reference (thefnattribute): it doesn’t unregister itself.
Backend.aget_args(tools=[fn]) instead: that adds callables to one specific aget_args call without polluting the global registry.
Schema details
The generated schema uses Pydantic’smodel_json_schema(mode="serialization"). Parameter names, types, and defaults map directly:
Related
Toolclass: what the decorator creates.@on_tool_before/@on_tool_after/@on_tool_error: lifecycle hooks around any skill invocation.
Tool class
Tool represents a single skill an agent can invoke: a catalog skill operation, an OpenAPI endpoint, a skill served over MCP, or a local Python function registered with @register_tool. You normally get one from agent.tools.list or agent.tools.get_tool_by_id(...).
Attributes
Computed properties
schema
tool.parameters. The model’s name is {ToolIdPascalCase}PayloadSchema. If the agent has schema overrides for this skill, they’re applied here.
payload_schema
payload field whose type is tool.schema. Useful when an agent loop expects every skill call to be wrapped in {"payload": {...}}.
Methods
ainvoke / invoke
Invoke the skill. Validates the payload against tool.schema, executes locally (is_local=True) or remotely, and returns a ToolInvocationResult.
@register_tool skill. A remote skill (catalog skill, custom function or MCP) takes its input inside body_params, query_params and path_params, as tool.parameters shows, and needs a task_id. Without one, the call comes back with is_success=False.
Returns a
ToolInvocationResult (see below). Sync sibling: tool.invoke(...).
ainvoke runs the configured skill call lifecycle hooks (@on_tool_before / @on_tool_after / @on_tool_error) around the call.
acall_remote_tool / call_remote_tool
Lower-level: makes the API call without local-skill fallback or hook execution. Used internally by ainvoke when is_local=False. Use directly only for advanced cases (preflight checks, custom invocation pipelines).
agraph_preflight_check / graph_preflight_check
Asks the runtime to validate a hypothetical skill invocation without executing it. Used internally for graph routing.
get_invocation_function
connector_id + configuration. Use for standalone invocation (no agent context):
<connection_id>_<operation_id> and returns the raw response wrapped in ToolInvocationResult. Use it after ToolsRepository.aload_tool_by_id(...) to call a single skill without an agent.
ToolInvocationResult
The shape returned by ainvoke and the standalone invocation function.
is_success and is_error are mutually exclusive in normal operation: check is_error first to branch on failure cases.
Examples
Inspect a skill’s schema
Per-call configuration override
Reporting activity for non-Agno callers
When invoking a skill outside an Agno-driven flow (e.g. from your own agent loop), setreport_activity=True so the call shows up in the task’s activity log:
False: the Agno hook reports the call automatically and you’d otherwise double-emit events.
MCP types
The Model Context Protocol (MCP) lets agents connect to skills served over MCP. The SDK exposesMCPServerDetails for declaring MCP endpoints per task, and a few enums for the supported transports and auth types.
Agent.acreate_task(mcp_servers=[...]) to attach MCP endpoints for a single run without registering them in Xpander Chat; endpoints already registered there are added automatically.
MCPServerDetails
Enums
MCPServerType
MCPServerTransport
MCPServerAuthType
Examples
Local server (stdio)
Remote with API key
Remote with OAuth2
auth_events during a run when end-user authorization is required. Register an @on_auth_event handler to route the OAuth URL to your UI.
Per-task server attachment
Limit which skills are exposed
search_repositories and get_issue will be exposed to the agent: every other skill the MCP endpoint offers is hidden.
OAuth response types (for @on_auth_event payloads)
When OAuth flows fire, event.data is shaped like one of these:
MCPOAuthResponseType values: not_supported, login_required, token_issue, token_ready.
Use these in your auth handler to display the right state to the end user (login URL vs. “we’re working on it” vs. success).
