agentbreeder

Tools — Lifecycle & Registry

Define, register, sandbox-test, and wire custom tools into agents. Includes inline and registry-based tool definitions.

Tools are functions agents can call during a conversation. AgentBreeder supports two kinds:

KindWhen to use
Custom function toolA Python function you write — registered with a JSON Schema
MCP server toolAn MCP server exposing tools over stdio or HTTP — see MCP Servers →

Both kinds are stored in the shared org tool registry and referenced the same way in agent.yaml.

Standard library (shipped)

AgentBreeder ships a small first-party stdlib at engine.tools.standard.*. Two tools are available out of the box:

ToolModulePurpose
web-searchengine.tools.standard.web_searchTavily-backed web search
markdown-writerengine.tools.standard.markdown_writerWrite a Markdown file to disk

Reference these from agent.yaml exactly like any other registered tool: tools: [{ref: tools/web-search}, {ref: tools/markdown-writer}].


Concepts

ConceptMeaning
Registry toolTool stored by name — retrieved by ref at deploy time
Inline toolTool defined directly in agent.yaml — no registry entry needed
JSON SchemaDefines the input (and optionally output) shape of the tool
SandboxIsolated Docker container for testing tool code before wiring to an agent
Usage graphWhich agents in the org reference this tool — visible in Studio and API

Step 1 — Define

Write a Python function. The function signature becomes the tool's input schema.

# tools/order_lookup.py

def order_lookup(order_id: str, include_tracking: bool = False) -> dict:
    """
    Look up an order by ID.

    Args:
        order_id: The order ID (format: ORD-XXXXXX)
        include_tracking: Whether to include shipping tracking info

    Returns:
        dict with order status, items, and optionally tracking
    """
    # Your implementation here
    return {
        "order_id": order_id,
        "status": "shipped",
        "items": ["Widget A", "Widget B"],
        "tracking": "1Z999AA10123456784" if include_tracking else None,
    }

Define the JSON Schema for the tool's inputs:

{
  "type": "object",
  "properties": {
    "order_id": {
      "type": "string",
      "description": "The order ID in format ORD-XXXXXX"
    },
    "include_tracking": {
      "type": "boolean",
      "description": "Whether to include shipping tracking info",
      "default": false
    }
  },
  "required": ["order_id"]
}

Step 2 — Register

Go to Registry → Tools → New Tool. Fill in:

  • Name — slug-friendly (e.g., order-lookup)
  • Typefunction, mcp, or api
  • Description — shown in the registry and to agents
  • Schema — paste your JSON Schema
  • Endpoint — URL if the tool is hosted (optional for function tools)

Click Register. The tool is now available as tools/order-lookup.

# Push a tool — auto-detects language from the input:
#   .py file       → endpoint = python:<abs_path>
#   .ts/.js/.mjs   → endpoint = node:<abs_path>
#   module path    → kept as-is for in-process import (e.g., engine.tools.standard.web_search)
agentbreeder registry tool push tools/order_lookup.py \
  --description "Look up an order by ID, with optional tracking info"

agentbreeder registry tool push engine.tools.standard.web_search \
  --description "Tavily web search"

# List tools
agentbreeder registry tool list

# Run a tool with structured args
agentbreeder registry tool run order-lookup \
  --args '{"order_id": "ORD-123456", "include_tracking": true}'

All registry tool commands require AGENTBREEDER_API_TOKEN (a JWT from POST /api/v1/auth/login). tool run requires the deployer role.

curl -X POST http://localhost:8000/api/v1/registry/tools \
  -H "Content-Type: application/json" \
  -d '{
    "name": "order-lookup",
    "description": "Look up an order by ID, with optional tracking info",
    "tool_type": "function",
    "schema_definition": {
      "type": "object",
      "properties": {
        "order_id": { "type": "string", "description": "Order ID (ORD-XXXXXX)" },
        "include_tracking": { "type": "boolean", "default": false }
      },
      "required": ["order_id"]
    },
    "source": "manual"
  }'

Response:

{
  "data": {
    "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "name": "order-lookup",
    "description": "Look up an order by ID...",
    "tool_type": "function",
    "status": "active",
    "source": "manual",
    "created_at": "2026-04-14T00:00:00Z"
  }
}
from agenthub import Agent

agent = (
    Agent("support-agent")
        .with_framework("langgraph")
        .with_tools([
            "tools/order-lookup",       # registry reference
            "tools/zendesk-mcp",
        ])
        .with_deploy(cloud="aws", runtime="app-runner")
)
import { Agent } from "@agentbreeder/sdk";

const agent = new Agent("support-agent")
  .withFramework("langgraph")
  .withTools(["tools/order-lookup", "tools/zendesk-mcp"])
  .withDeploy({ cloud: "aws", runtime: "app-runner" });

Auto-Discover Tools with Scan

Run agentbreeder scan to discover tools from MCP servers and model gateways on your machine. Discovered tools are auto-registered in the registry and immediately usable as tools/ refs:

agentbreeder scan
# Found MCP servers:
#   zendesk    stdio  ./.mcp.json  (3 tools)
#   slack      stdio  ./.mcp.json  (5 tools)

Step 3 — Sandbox Test

Before wiring a tool into a live agent, test it in an isolated Docker sandbox. The sandbox runs your Python code with 256MB memory, no network access by default, and a 30-second timeout.

curl -X POST http://localhost:8000/api/v1/tools/sandbox/execute \
  -H "Content-Type: application/json" \
  -d '{
    "code": "def run(input):\n    return {\"order_id\": input[\"order_id\"], \"status\": \"shipped\"}",
    "input_json": { "order_id": "ORD-123456" },
    "timeout_seconds": 15,
    "network_enabled": false,
    "tool_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  }'

Response:

{
  "data": {
    "execution_id": "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy",
    "output": "{\"order_id\": \"ORD-123456\", \"status\": \"shipped\"}",
    "stdout": "{\"order_id\": \"ORD-123456\", \"status\": \"shipped\"}\n",
    "stderr": "",
    "exit_code": 0,
    "duration_ms": 142,
    "timed_out": false,
    "error": null
  }
}

Sandbox in Studio

Open any tool in the registry, click Test in Sandbox, paste your input JSON, and click Run. Output, stdout, stderr, and duration are shown inline.

Network access

Set network_enabled: true only if your tool code calls external services. Keep it false during unit testing to avoid flaky results and accidental side effects.


Step 3b — Execute / Try it (registered tools)

Once a tool is registered, run it directly without the sandbox. The execute endpoint dispatches based on the endpoint field stored on the tool record:

curl -X POST http://localhost:8000/api/v1/registry/tools/{tool_id}/execute \
  -H "Authorization: Bearer $AGENTBREEDER_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "args": { "query": "transformer attention", "max_results": 3 }
  }'

Response:

{
  "data": {
    "output": { "results": [ /* ... */ ] },
    "stdout": "",
    "stderr": "",
    "exit_code": 0,
    "duration_ms": 412,
    "error": null
  }
}

Endpoint dispatch

engine/tool_runner.py picks a dispatcher from the endpoint prefix:

PrefixDispatcherExample
engine.tools.standard.<name>In-process Python importmarkdown-writer, ~25 ms
python:<abs_path>Python subprocessget-current-time, ~50 ms
node:<abs_path>Node subprocess via npx tsxget-utc-time, ~1.5 s cold
http(s)://...HTTP POST with JSON body(configurable)

Auth: requires the deployer role.

Try it tab in Studio

Open any tool at /tools/:id and switch to the Try it tab. Studio auto-generates a form from the tool's SCHEMA, you fill in the inputs, hit Run, and the result panel shows output, stdout/stderr, exit code, and duration inline.


Step 4 — Use in agent.yaml

name: microlearning-ebook-agent
framework: google_adk

tools:
  - ref: tools/web-search         # engine.tools.standard.web_search
  - ref: tools/markdown-writer    # engine.tools.standard.markdown_writer
  - ref: tools/order-lookup       # your own registered tool
  - ref: mcp-servers/slack        # MCP server also referenced as a tool
name: support-agent
framework: langgraph

tools:
  - name: get_current_time
    type: function
    description: "Return the current UTC time as ISO 8601"
    schema:
      type: object
      properties: {}
      required: []
name: support-agent
framework: langgraph

tools:
  - ref: tools/order-lookup       # from registry
  - name: get_current_time        # inline, no registry entry needed
    type: function
    description: "Return the current UTC time"
    schema:
      type: object
      properties: {}

Resolver chain (local → stdlib → registry)

tools[].ref is resolved by engine.tool_resolver.resolve_tool() in this order:

  1. Local override<project>/tools/<snake_name>.py (a file in your project always wins)
  2. Standard libraryengine.tools.standard.<snake_name> (first-party, e.g., web_search, markdown_writer)
  3. Registry API — metadata fetched from /api/v1/registry/tools (the caller wraps the returned dict into a callable)

The TypeScript counterpart is resolveTool() in engine/runtimes/templates/node/_shared_loader.ts — same precedence, with local .ts / .js / .mjs files first, then registry metadata.

Wiring agent.py

# agent.py
from pathlib import Path
from engine.tool_resolver import resolve_tool

web_search = resolve_tool("tools/web-search", project_root=Path(__file__).parent)
markdown_writer = resolve_tool("tools/markdown-writer", project_root=Path(__file__).parent)

# Use them with whatever framework you're on:
TOOLS = [web_search, markdown_writer]

Import-shadow gotcha (stdlib tools)

engine/tools/standard/__init__.py must not re-export tool functions. If it does, import engine.tools.standard.web_search as ws_mod returns the function, not the module — and any registry-seed script that reads ws_mod.SCHEMA breaks at startup. Keep __init__.py empty (or limit it to package metadata).


Step 5 — Discover Tool Usage

Find every agent in your org that uses a specific tool — useful before removing or updating a tool.

GET /api/v1/registry/tools/{tool_id}/usage

Response:

{
  "data": [
    { "agent_id": "abc...", "agent_name": "support-agent", "agent_status": "deployed" },
    { "agent_id": "def...", "agent_name": "triage-agent",  "agent_status": "deployed" }
  ]
}

Tool YAML Schema

Tools can also be defined in a standalone tool.yaml file and registered via CLI:

spec_version: v1
name: order-lookup
version: 1.0.0
description: Look up an order by ID with optional tracking
team: customer-success
owner: alice@company.com
tags: [orders, ecommerce]

type: function   # function | mcp | api

input_schema:
  type: object
  properties:
    order_id:
      type: string
      description: Order ID in format ORD-XXXXXX
    include_tracking:
      type: boolean
      default: false
  required: [order_id]

output_schema:
  type: object
  properties:
    order_id: { type: string }
    status:   { type: string }
    tracking: { type: string, nullable: true }

implementation:
  language: python
  entrypoint: tools/order_lookup.py:order_lookup
  dependencies:
    - requests==2.31.0

timeout_seconds: 30
network_access: false

API Reference

MethodPathDescription
POST/api/v1/registry/toolsRegister a tool
GET/api/v1/registry/toolsList tools (filter by tool_type, source)
GET/api/v1/registry/tools/{id}Get tool with full schema
GET/api/v1/registry/tools/{id}/usageList agents using this tool
POST/api/v1/registry/tools/{id}/executeRun a registered tool (dispatches by endpoint prefix; requires deployer role)
POST/api/v1/tools/sandbox/executeExecute tool code in isolated sandbox

Next Steps

WhatWhere
Add MCP servers as toolsMCP Servers →
Build a knowledge baseKnowledge Bases →
Register system promptsPrompts →
Full agent.yaml fieldsagent.yaml Reference →

On this page