Documentation Index
Fetch the complete documentation index at: https://autonomy.computer/docs/llms.txt
Use this file to discover all available pages before exploring further.
Tools are functions that agents invoke to take actions and gather information.
In each iteration of an agent’s loop, the model returns the next steps as tool calls.
The agent invokes these tools, gathers their responses, and continues its loop.
Wrap Python functions to create tools. Any function becomes a tool that your agent invokes.
from autonomy import Agent, Model, Node, Tool
from datetime import datetime, UTC
def get_weather(city: str) -> str:
"""
Get the current weather for a city.
Args:
city: The name of the city
"""
# In a real app, this would call a weather API
return f"The weather in {city} is sunny and 72°F"
def current_iso8601_utc_time():
"""
Returns the current UTC time in ISO 8601 format.
"""
return datetime.now(UTC).isoformat() + "Z"
async def main(node):
await Agent.start(
node=node,
name="henry",
instructions="You are Henry, a helpful assistant",
model=Model("claude-sonnet-4-v1"),
tools=[
Tool(get_weather),
Tool(current_iso8601_utc_time)
]
)
Node.start(main)
FROM ghcr.io/build-trust/autonomy-python
COPY . .
ENTRYPOINT ["python", "main.py"]
name: tools-example
pods:
- name: main-pod
public: true
containers:
- name: main
image: main
http POST \
"https://CLUSTER-ZONE.cluster.autonomy.computer/agents/henry" \
message="What's the weather in San Francisco and what time is it?"
The Tool() wrapper converts your function into a tool specification. Docstrings become tool descriptions that help the model understand when to use the tool. Type hints define parameter types (converted to JSON schema). Both sync and async functions are supported.
Model Context Protocol (MCP) provides agents with tools from external servers. MCP servers expose standardized interfaces to services like web search, databases, and APIs.
Define MCP servers in your autonomy.yaml:
name: mcp-example
pods:
- name: main-pod
public: true
containers:
- name: main
image: main
- name: mcp
image: ghcr.io/build-trust/mcp-proxy
env:
- BRAVE_API_KEY: secrets.BRAVE_API_KEY
args:
["--sse-port", "8001", "--pass-environment", "--",
"npx", "-y", "@modelcontextprotocol/server-brave-search"]
Store your API key in secrets.yaml:
BRAVE_API_KEY: "YOUR_BRAVE_API_KEY_HERE"
Reference MCP server tools using McpTool():
from autonomy import Agent, Model, Node, McpTool, McpClient, Tool
from datetime import datetime, UTC
def current_iso8601_utc_time():
"""
Returns the current UTC time in ISO 8601 format.
"""
return datetime.now(UTC).isoformat() + "Z"
async def main(node):
await Agent.start(
node=node,
name="henry",
instructions="""
You are Henry, an expert legal assistant.
When answering questions, decide if a web search would improve your response.
If so, use the brave_web_search tool to find current information.
""",
model=Model("claude-sonnet-4-v1"),
tools=[
McpTool("brave_search", "brave_web_search"),
Tool(current_iso8601_utc_time)
]
)
Node.start(
main,
mcp_clients=[
McpClient(name="brave_search", address="http://localhost:8001/sse")
]
)
FROM ghcr.io/build-trust/autonomy-python
COPY . .
ENTRYPOINT ["python", "main.py"]
http POST \
"https://CLUSTER-ZONE.cluster.autonomy.computer/agents/henry" \
message="Find recent Supreme Court decisions on contract law"
The agent will use the brave_web_search tool to find current information and incorporate it into its response.
Agents have access to several built-in tools:
Always available without configuration:
get_current_time_utc - Get current time in UTC timezone
get_current_time - Get current time in a specific timezone (e.g., “America/New_York”)
await Agent.start(
node=node,
name="assistant",
instructions="You are a helpful assistant",
model=Model("claude-sonnet-4-v1")
)
# Agent can automatically use get_current_time_utc and get_current_time
Human-in-the-Loop
Agents pause and request user input during interactive conversations. See Human-in-the-loop for complete documentation on the ask_user_for_input tool.
- Filesystem tools - Read, write, and search files. See Filesystem Tools.
- Subagent tools - Delegate work to specialized sub-agents. See Subagents.
Tool Factories create scope-aware tools that are instantiated per-user, per-conversation, or per-agent. This is essential for multi-tenant applications where tools need isolated resources.
Use tool factories when:
- Tools need per-user or per-conversation state
- Tools access user-specific resources (databases, files, APIs)
- Tools require tenant isolation for security
- Static tool instances can’t be shared safely
Create a class that implements the create_tools() method:
from autonomy import Agent, Model, Node, Tool, ToolFactory
from typing import Optional, List
class DatabaseToolFactory(ToolFactory):
"""
Creates tenant-isolated database tools.
Each tenant gets their own database connection with isolated data access.
"""
def __init__(self, connection_string: str):
self.connection_string = connection_string
def create_tools(
self,
scope: Optional[str],
conversation: Optional[str],
agent_name: Optional[str] = None
) -> List:
"""
Create database tools for a specific tenant.
Args:
scope: Tenant/user identifier (e.g., "tenant-123", "user-alice")
conversation: Conversation identifier
agent_name: Agent name
Returns:
List of Tool instances with tenant-specific database connections
"""
# Create tenant-specific database connection
tenant_id = scope or "default"
db = Database(self.connection_string, tenant=tenant_id)
def query_records(table: str, filter: str = ""):
"""
Query records from a database table.
Args:
table: Table name to query
filter: Optional SQL WHERE clause filter
"""
return db.query(f"SELECT * FROM {table} WHERE {filter}" if filter else f"SELECT * FROM {table}")
def insert_record(table: str, data: dict):
"""
Insert a record into a database table.
Args:
table: Table name
data: Record data as key-value pairs
"""
return db.insert(table, data)
return [
Tool(query_records),
Tool(insert_record)
]
async def main(node):
# Create factory instance
db_factory = DatabaseToolFactory("postgresql://localhost/mydb")
await Agent.start(
node=node,
name="assistant",
instructions="You are a helpful assistant with database access",
model=Model("claude-sonnet-4-v1"),
tools=[db_factory] # Pass factory, not individual tools
)
Node.start(main)
The agent framework detects the factory implements ToolFactory. For each conversation, the framework calls create_tools(scope, conversation, agent_name). You create tools with proper isolation based on the provided context. Each user/conversation gets their own tool instances with isolated resources.
Static tools (using Tool(func)):
- Same instance shared across all users and conversations
- Suitable for stateless operations (time, calculations, read-only APIs)
- Simple and efficient
Factory tools (using ToolFactory):
- New instances created per-user/per-conversation
- Suitable for stateful operations (databases, filesystems, user-specific APIs)
- Provides tenant isolation and security
Tools are described to models using JSON schema format:
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a city",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "The name of the city"
}
},
"required": ["city"]
}
}
}
The Tool() wrapper automatically generates this specification from:
- Function name → tool name
- Docstring → description
- Type hints → parameter types
- Required vs optional parameters
Type Coercion
The framework coerces JSON values to match Python type hints:
def calculate(amount: int, rate: float, active: bool):
"""Calculate something with typed parameters"""
return amount * rate if active else 0
# JSON: {"amount": "100", "rate": "1.5", "active": "true"}
# Coerced to: {"amount": 100, "rate": 1.5, "active": True}
Supported coercions:
str → int, float, bool
- String booleans: “true”/“false”, “yes”/“no”, “1”/“0”
- Numbers to strings
- Empty/null handling
Error Handling
Tool errors are captured and returned as strings to the model:
def divide(a: int, b: int) -> float:
"""Divide two numbers"""
return a / b
# If b=0: "Tool execution failed: ZeroDivisionError: division by zero"
The agent sees the error and decides how to respond—retry with different parameters, ask for clarification, or explain the problem to the user.
Size Limits
- JSON arguments: 1MB maximum
- Tool responses: No hard limit, but keep responses concise for model context efficiency