> ## 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.

# Coding Agents: How to create agents that can invoke tools

> Give Autonomy Agents access to tools written in Python tools or provided by MCP (Model Context Protocol). The enables agents that can perform actions, access external data, and integrate with services like web search.

# A guide for coding agents to create agents that can invoke tools

Enhance **Autonomy** agents with tools that perform specific actions, access external data, and integrate with external services using Python functions or MCP servers.

> **Key Terms**: See the [definitions section of the main guide](https://autonomy.computer/docs/_for-coding-agents.md#definitions).

*Keywords: tools, python tools, mcp tools, web search*

This guide shows how to create agents with both Python tools and MCP tools for external service integration.

## Built-in Tools

Autonomy automatically provides built-in tools to agents:

### Always Available

These tools are automatically available to all agents without any configuration:

* **`get_current_time_utc`** - Get the current time in UTC timezone
* **`get_current_time`** - Get the current time in a specific timezone (e.g., "America/New\_York", "Europe/London", "Asia/Tokyo")

### Available When Enabled

* **`ask_user_for_input`** - Request input from the user (human-in-the-loop)
  * **Requires:** `enable_ask_for_user_input=True` when calling `Agent.start()`
  * **Default:** Not enabled (defaults to `False`)

### Subagent Tools

When an agent has `subagents` configured, these tools are automatically added:

* **`start_subagent`** - Start a configured subagent on-demand
* **`delegate_to_subagent`** - Delegate a task to a specific subagent and wait for response
* **`delegate_to_subagents_parallel`** - Delegate multiple tasks to parallel subagent instances
* **`list_subagents`** - List all configured and running subagents with their status
* **`stop_subagent`** - Stop a running subagent

## Creating Agents with Tools

Autonomy agents can use two types of custom tools:

1. **Python Tools** - Functions defined directly in your code
2. **MCP Tools** - Tools from Model Context Protocol servers

### Complete Example: Agent with Both Tool Types

This example shows an agent with a Python tool (time) and MCP tool (web search):

#### Project Structure

```
your-app/
├── autonomy.yaml
├── secrets.yaml
└── images/main/
    ├── Dockerfile
    └── main.py
```

#### main.py

```python theme={null}
from datetime import datetime, UTC
from autonomy import Agent, Model, Node, McpTool, McpClient, Tool


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, use web search if it improves your response.
        """,
        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"),
    ],
)
```

#### autonomy.yaml

```yaml theme={null}
name: example006
pods:
  - name: main-pod
    public: true
    containers:
      - name: main
        image: main

      - name: brave
        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"]
```

#### secrets.yaml

```yaml theme={null}
BRAVE_API_KEY: "YOUR_BRAVE_API_KEY_HERE"
```

Get a Brave API key by signing up at [https://brave.com/search/api/](https://brave.com/search/api/)

#### Dockerfile

```dockerfile theme={null}
FROM ghcr.io/build-trust/autonomy-python:latest
COPY . .
ENTRYPOINT ["python", "main.py"]
```

### Deploy and Test

Deploy your zone:

```bash theme={null}
autonomy zone deploy
```

Test the agent:

```bash theme={null}
timeout 15s curl --silent --request POST \
--header "Content-Type: application/json" \
--data '{ "message": "Which companies were acquired today?" }' \
"https://${CLUSTER}-${ZONE}.cluster.autonomy.computer/agents/henry"
```

## How It Works

**Python Tools**: Define functions and wrap them with `Tool()`. The agent calls these functions directly in your code.

**MCP Tools**: Configure MCP servers in `autonomy.yaml` as containers using `ghcr.io/build-trust/mcp-proxy`. Register them with `McpClient()` and reference with `McpTool()`. The MCP proxy runs alongside your agent in the same pod.

**Tool Selection**: The agent analyzes the user's message and your instructions to decide which tools to use and when.

## MCP Servers in Multi-Pod Deployments

> **IMPORTANT**: MCP servers are accessed over `localhost`. When your zone has nodes distributed across multiple pods, each pod that needs MCP tools must have its own MCP server container.

### Why This Matters

Containers within the same pod share a network namespace and communicate via `localhost`. When you distribute nodes across multiple pods (using `clones` or separate pod definitions), each pod runs on a different machine. An agent running in one pod cannot access MCP servers in another pod over `localhost`.

### Example: Distributed Workers with MCP Tools

If you have workers across multiple pods that need MCP tools, configure the MCP server in each pod:

#### autonomy.yaml

```yaml theme={null}
name: distributed
pods:
  - name: main-pod
    public: true
    containers:
      - name: main
        image: main
      - name: brave
        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"]

  - name: runner-pod
    clones: 3
    containers:
      - name: runner
        image: runner
      - name: brave
        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"]
```

#### images/runner/main.py

```python theme={null}
from autonomy import Agent, Model, Node, McpTool, McpClient


async def main(node):
    await Agent.start(
        node=node,
        name="searcher",
        instructions="You search the web for information.",
        model=Model("nova-micro-v1"),
        tools=[
            McpTool("brave_search", "brave_web_search"),
        ],
    )


Node.start(
    main,
    mcp_clients=[
        McpClient(name="brave_search", address="http://localhost:8001/sse"),
    ],
)
```

**Key Points:**

* **Both `main-pod` and `runner-pod` have their own `brave` container** - Each pod needs its own MCP server
* **Each clone of `runner-pod` gets its own MCP server** - The 3 clones each run independently with their own brave container
* **All MCP clients use `localhost`** - Each node connects to the MCP server in its own pod
* **Environment variables are duplicated** - Each pod needs the same secrets configuration

### Decision Guide

| Scenario | MCP Server Configuration |
| - | - |
| Single pod with one node | One MCP server container in that pod |
| Single pod with multiple agents | One MCP server container shared by all agents |
| Multiple pods with clones | MCP server container in each pod definition |
| Only main-pod needs MCP tools | MCP server only in main-pod |
| All pods need MCP tools | MCP server in every pod definition |

## Using Built-in Time Tools

Agents can check the current time without any configuration. The built-in time tools are automatically available:

### Example: Agent with Time Awareness

```python theme={null}
from autonomy import Agent, Model, Node


async def main(node):
    await Agent.start(
        node=node,
        name="henry",
        instructions="""
            You are Henry, a helpful assistant.
            
            When users ask about time, use the built-in time tools:
            - Use get_current_time_utc() for UTC time
            - Use get_current_time(timezone="...") for specific timezones
        """,
        model=Model("claude-sonnet-4-v1"),
    )


Node.start(main)
```

### Test Time Tools

```bash theme={null}
# Test UTC time
timeout 15s curl --silent --request POST \
--header "Content-Type: application/json" \
--data '{ "message": "What is the current UTC time?" }' \
"https://${CLUSTER}-${ZONE}.cluster.autonomy.computer/agents/henry"

# Test timezone-specific time
timeout 15s curl --silent --request POST \
--header "Content-Type: application/json" \
--data '{ "message": "What time is it in Tokyo?" }' \
"https://${CLUSTER}-${ZONE}.cluster.autonomy.computer/agents/henry"
```

The agent will automatically use:

* `get_current_time_utc()` to get UTC time
* `get_current_time(timezone="Asia/Tokyo")` to get Tokyo time

## Using the Ask User for Input Tool

The `ask_user_for_input` tool enables human-in-the-loop interactions where the agent can pause and request input from the user.

### Example: Agent with User Input Capability

```python theme={null}
from autonomy import Agent, Model, Node


async def main(node):
    await Agent.start(
        node=node,
        name="henry",
        instructions="""
            You are Henry, an expert legal assistant.
            
            When you need information from the user, use ask_user_for_input.
        """,
        model=Model("claude-sonnet-4-v1"),
        enable_ask_for_user_input=True,  # Enable the tool
    )


Node.start(main)
```

**Key Points:**

* Set `enable_ask_for_user_input=True` when calling `Agent.start()`
* The agent can call this tool to pause and wait for user response
* The conversation resumes after the user provides input
* Useful for gathering missing information, confirmations, or clarifications

## Related Guides

* [How to create and deploy a new Autonomy app](https://autonomy.computer/docs/_for-coding-agents/create-a-new-autonomy-app.md)
* [How to configure apps with environment variables and secrets](https://autonomy.computer/docs/_for-coding-agents/configure-apps.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.