Agent Runtime Tools
A complete guide to the tools that Crawbl agents can call. Covers every implemented tool, how tools are executed, which agents have access to which tools, and how tool usage connects to billing. Written for engineers who have not worked with the agent runtime before.
Chapter 1: What Are Tools?
Tools give agents the ability to act
An AI agent without tools can only generate text. Tools let agents do things — search the web, read files, save memories, send notifications, and more.
When a user sends a message, the agent's LLM decides which tools to call based on the conversation. The agent runtime executes the tool, returns the result to the LLM, and the LLM uses that result to compose its response.
Think of tools like apps on a phone. The phone (LLM) is capable on its own, but apps (tools) let it interact with the outside world — look things up, store data, send messages.
The tool catalog
Crawbl maintains a seed catalog of all tools at migrations/orchestrator/seed/tools.json. This single file is the source of truth for:
- The mobile app's integrations screen
- The
/v1/integrationsAPI response - The LLM's tool schema (descriptions the model sees)
Each tool has a name, display name, description, category, icon, and an implemented flag. Tools with implemented: false exist in the catalog for future phases but return a "not implemented" error if called.
Chapter 2: Two Types of Tool Execution
Tools execute in one of two ways depending on where their logic lives.
Local tools — executed in the runtime process
These tools run directly inside the agent runtime pod. They make HTTP calls or access cloud storage without going through the orchestrator.
Agent LLM → tool call → Agent Runtime (Go process) → external service
↓
result back to LLM
Current local tools:
| Tool | What it does | External service |
|---|---|---|
web_fetch | Fetches and extracts article text from a URL | Target website |
web_search_tool | Searches the internet via meta-search | SearXNG (in-cluster) |
file_read | Reads a file from workspace storage | DigitalOcean Spaces |
file_write | Writes a file to workspace storage | DigitalOcean Spaces |
MCP tools — forwarded to the orchestrator
These tools are forwarded to the orchestrator's MCP (Model Context Protocol) server over HTTP. The runtime discovers them dynamically — no tool names are hardcoded in the runtime.
Agent LLM → tool call → Agent Runtime → HMAC-signed HTTP → Orchestrator MCP Server
↓
execute + return
MCP tools include:
| Prefix | Category | Examples |
|---|---|---|
memory_* | Memory Palace | memory_search, memory_add_drawer, memory_kg_query |
orchestrator__* | Platform services | send_push_notification, get_user_profile, create_artifact |
Memory Palace tools are documented in detail in the Memory Palace Guide. This page focuses on the tool system itself, not individual memory tool semantics.
How MCP tools are secured
Every MCP request from the runtime to the orchestrator is signed with an HMAC bearer token. The token is generated per-request from:
- A shared signing key (
CRAWBL_MCP_SIGNING_KEY) - The user ID
- The workspace ID
The orchestrator verifies the signature before executing any tool. This prevents one runtime pod from calling tools on behalf of another workspace.
Chapter 3: The Tool Builder System
How tools are constructed
Tools are built once when the agent runtime pod starts, then shared across all agents in the pod. The construction happens in internal/agentruntime/tools/builders.go.
// main.go builds this once per pod
deps := tools.CommonToolDeps{
WorkspaceID: cfg.WorkspaceID,
SearXNGEndpoint: cfg.SearXNGEndpoint,
Spaces: spacesClient, // may be nil
}
localTools, err := tools.BuildCommonTools(deps)
Key design rules:
- Tool names come from constants in
catalog.go— no string literals in builders - Descriptions come from
tools.json— one source of truth for mobile, API, and LLM - Workspace scoping is closure-captured — agents cannot target other workspaces through tool arguments
- Optional tools degrade gracefully — if DigitalOcean Spaces is not configured, file tools are silently skipped; the rest of the tool set still works
Adding a new tool
To add a new local tool:
- Add the tool entry to
migrations/orchestrator/seed/tools.jsonwithimplemented: true - Add a
Tool*constant incatalog.go - Add argument and result structs in
builders.go - Write the handler in
tools/local/ - Register it in
BuildCommonTools()
The buildFunctionTool() helper handles description lookup, error wrapping, and ADK registration in one call.
Chapter 4: Implemented Tools in Detail
web_fetch — Read a webpage
Fetches a URL via HTTP GET and extracts the article text using the Mozilla Readability algorithm. Navigation, ads, scripts, and styles are stripped — only the main content is returned.
| Parameter | Default | Max | Description |
|---|---|---|---|
url | (required) | — | HTTP(S) URL to fetch |
max_bytes | 200 KB | — | Cap on response body size |
timeout_seconds | 10 | 60 | Request timeout |
Output cap: 30,000 characters (~7,500 tokens). Longer content is truncated with a marker.
Non-HTML content (JSON, plain text) is returned as-is without Readability processing.
web_search_tool — Search the internet
Queries the in-cluster SearXNG meta-search instance. SearXNG aggregates results from Google, Bing, DuckDuckGo, Brave, Qwant, Wikipedia, and Wikidata into a single deduplicated result set.
| Parameter | Default | Max | Description |
|---|---|---|---|
query | (required) | — | Free-text search query |
max_results | 5 | 15 | Number of results to return |
Each result contains:
{
"title": "Example Page Title",
"url": "https://example.com/page",
"snippet": "A brief excerpt from the page content...",
"engine": "google"
}
Timeout: 10 seconds. Response limit: 4 MiB.
See the SearXNG infrastructure page for connection details, deployment info, and debugging instructions.
file_read — Read from workspace storage
Reads a file from the workspace's DigitalOcean Spaces bucket. Files are scoped by workspace — agents cannot read files from other workspaces.
| Parameter | Description |
|---|---|
key | Object key under the workspace, e.g. uploads/trip.md |
Returns:
| Field | Description |
|---|---|
key | The requested key |
content | File body — UTF-8 text or base64-encoded binary |
content_type | MIME type (e.g., text/plain, image/png) |
encoding | "text" or "base64" |
size_bytes | File size |
Text types (text/*, application/json, application/xml, application/yaml, application/javascript) are returned as UTF-8 strings. Everything else is base64-encoded to prevent LLM corruption.
file_write — Write to workspace storage
Writes a file to the workspace's DigitalOcean Spaces bucket.
| Parameter | Default | Description |
|---|---|---|
key | (required) | Object key, e.g. drafts/email.md |
content | (required) | File body |
content_type | text/plain; charset=utf-8 | MIME type |
Workspace scoping: The workspace prefix is prepended internally. Slashes in keys create a nested directory structure.
Chapter 5: Orchestrator MCP Tools
These tools are forwarded to the orchestrator and executed server-side. The agent runtime discovers them dynamically via the MCP ListTools endpoint.
Notification tools
| Tool | Description |
|---|---|
orchestrator__send_push_notification | Send a push notification to the user's mobile device |
Context tools
| Tool | Description |
|---|---|
orchestrator__get_user_profile | Access the user's profile information and preferences |
orchestrator__get_workspace_info | Get workspace details and agent list |
orchestrator__list_conversations | List all conversations in the workspace |
orchestrator__search_past_messages | Search through past conversation messages |
Collaboration tools
| Tool | Description |
|---|---|
orchestrator__create_agent_history | Record a notable event in an agent's history log |
orchestrator__send_message_to_agent | Send a message between agents for collaboration |
Artifact tools
| Tool | Description |
|---|---|
orchestrator__create_artifact | Create a shared document or code artifact |
orchestrator__read_artifact | Read a shared artifact created by any agent |
orchestrator__update_artifact | Update a shared artifact with a new version |
orchestrator__review_artifact | Review and approve or request changes on an artifact |
Workflow tools
| Tool | Description |
|---|---|
orchestrator__create_workflow | Define a multi-step agent workflow |
orchestrator__trigger_workflow | Trigger a defined workflow |
orchestrator__check_workflow_status | Check the status of a running workflow |
orchestrator__list_workflows | List all available workflows |
Chapter 6: Agent Permissions
The three-agent architecture
The agent runtime runs three agents in a coordinator pattern:
| Agent | Role | Tool access |
|---|---|---|
| Manager | Root coordinator — routes user messages via LLM-driven delegation | Full access: 20 tools including all memory, all orchestrator tools |
| Wally | Research specialist — handles web research, URL fetching, live queries | 15 tools: web, files, memory (read-mostly), notifications, profiles |
| Eve | Scheduling specialist — handles time zones, date math, scheduling concepts | 15 tools: same as Wally (cron tools not yet implemented) |
How permissions work
Each agent has an allowed_tools list defined in migrations/orchestrator/seed/agents.json. When the agent runtime constructs an agent, only tools in this list are made available to the LLM.
An empty allowed_tools array means all tools are available. A non-empty array restricts the agent to exactly those tools. This is intentional — Manager needs broad access, while sub-agents are scoped.
Workspace scoping
Every tool operation is scoped to the workspace that owns the agent runtime pod. This is enforced at two levels:
- Local tools — the workspace ID is captured in a closure at construction time. Tool arguments never include a workspace ID field.
- MCP tools — the HMAC token embeds the workspace ID. The orchestrator extracts it from the token, not from the request body.
Cross-workspace access is impossible by design.
Chapter 7: Tools and Billing
Every tool call that involves an LLM interaction consumes tokens. The billing system tracks this automatically.
What costs money
| Action | Cost driver | Tracked by |
|---|---|---|
Agent calls web_search_tool | LLM prompt + completion tokens (the search itself is free) | Usage pipeline |
Agent calls web_fetch | LLM tokens to process the fetched content | Usage pipeline |
Agent calls file_read / file_write | Storage I/O (no LLM cost) | Not metered currently |
Agent calls memory_search | Embedding generation + LLM tokens | Usage pipeline |
| Agent calls any MCP tool | LLM tokens for the tool call + result processing | Usage pipeline |
How usage flows to billing
For the full billing pipeline walkthrough — including quota enforcement, monthly limits, cost calculation, and ClickHouse analytics — see the Billing, Usage & Cost Tracking guide.
Chapter 8: Real-World Examples
Example 1: Agent searches the web
A user asks "What's the latest news about Kubernetes 1.31?"
The Manager agent decides to use web_search_tool:
{
"tool": "web_search_tool",
"arguments": {
"query": "Kubernetes 1.31 release news",
"max_results": 5
}
}
The runtime calls SearXNG internally:
GET http://searxng.backend.svc.cluster.local:8080/search?q=Kubernetes+1.31+release+news&format=json&safesearch=0&language=en
SearXNG aggregates results from Google, Bing, DuckDuckGo, and others, returning:
{
"query": "Kubernetes 1.31 release news",
"results": [
{
"title": "Kubernetes v1.31: Elli",
"url": "https://kubernetes.io/blog/2024/08/13/kubernetes-v1-31-release/",
"snippet": "Kubernetes v1.31 introduces several new features and improvements...",
"engine": "google"
},
{
"title": "What's new in Kubernetes 1.31",
"url": "https://www.cncf.io/blog/...",
"snippet": "The latest release brings 45 enhancements...",
"engine": "bing"
}
]
}
The LLM then uses these results to compose an informed response to the user.
Example 2: Agent reads a file and sends a notification
A user asks "Summarize my trip notes and notify me when done."
The Manager delegates to Wally, who calls two tools:
Step 1 — Read the file:
{
"tool": "file_read",
"arguments": {
"key": "uploads/trip-notes.md"
}
}
Returns:
{
"key": "uploads/trip-notes.md",
"content": "# Trip to Tokyo\n\nDay 1: Arrived at Narita...",
"content_type": "text/markdown",
"encoding": "text",
"size_bytes": 4521
}
Step 2 — Send notification:
{
"tool": "orchestrator__send_push_notification",
"arguments": {
"title": "Trip Summary Ready",
"body": "Your Tokyo trip notes have been summarized. Check the conversation for details."
}
}
This is forwarded to the orchestrator via HMAC-signed MCP, which delivers the push notification through Firebase Cloud Messaging.
Chapter 9: Quick Reference
Implemented tools summary
| # | Tool | Category | Type | Status |
|---|---|---|---|---|
| 1 | web_fetch | search | local | Implemented |
| 2 | web_search_tool | search | local | Implemented |
| 3 | file_read | files | local | Implemented |
| 4 | file_write | files | local | Implemented |
| 5–23 | memory_* (19 tools) | memory | MCP | Implemented |
| 24 | orchestrator__send_push_notification | notification | MCP | Implemented |
| 25–28 | orchestrator__get_*, list_*, search_* | context | MCP | Implemented |
| 29–30 | orchestrator__create_agent_history, send_message_to_agent | integration | MCP | Implemented |
| 31–34 | orchestrator__*_artifact | integration | MCP | Implemented |
| 35–38 | orchestrator__*_workflow | integration | MCP | Implemented |
Tool defaults and limits
| Setting | Value |
|---|---|
| Web fetch default timeout | 10 seconds |
| Web fetch max timeout | 60 seconds |
| Web fetch default body limit | 200 KB |
| Web fetch output cap | 30,000 characters |
| Web search default results | 5 |
| Web search max results | 15 |
| Web search timeout | 10 seconds |
| Web search response limit | 4 MiB |
| SearXNG default endpoint | http://searxng.backend.svc.cluster.local:8080 |
Not yet implemented
These tools exist in the catalog but return "not implemented" errors:
| Tool | Category | Future purpose |
|---|---|---|
http_request | search | Make HTTP API calls to external services |
file_edit | files | Edit existing files in-place |
glob_search | files | Search files by name pattern |
content_search | files | Search inside files for text |
cron_* (6 tools) | scheduling | Create, manage, and run scheduled tasks |
calculator | utility | Mathematical calculations |
weather | utility | Weather information |
image_info | utility | Image analysis |
shell | shell | Shell command execution |
Key source files
| File | Purpose |
|---|---|
migrations/orchestrator/seed/tools.json | Master tool catalog (59 tools) |
migrations/orchestrator/seed/tool_categories.json | 9 category definitions |
migrations/orchestrator/seed/agents.json | Agent definitions with allowed_tools |
internal/agentruntime/tools/builders.go | Tool construction and CommonToolDeps |
internal/agentruntime/tools/catalog.go | Tool name constants |
internal/agentruntime/tools/local/ | Local tool implementations |
internal/agentruntime/tools/mcp/ | MCP bridge (client + HMAC transport) |
internal/agentruntime/config/defaults.go | Default endpoints and env vars |
Environment variables
| Variable | Purpose | Required |
|---|---|---|
CRAWBL_WORKSPACE_ID | Workspace this runtime serves | Yes |
CRAWBL_SEARXNG_ENDPOINT | SearXNG meta-search URL | Yes |
CRAWBL_MCP_ENDPOINT | Orchestrator MCP server URL | Yes |
CRAWBL_MCP_SIGNING_KEY | HMAC signing secret for MCP | Yes |
CRAWBL_SPACES_ENDPOINT | DigitalOcean Spaces endpoint | Optional |
CRAWBL_SPACES_REGION | Spaces region (e.g., fra1) | Optional* |
CRAWBL_SPACES_BUCKET | Spaces bucket name | Optional* |
CRAWBL_SPACES_ACCESS_KEY | Spaces access key | Optional* |
CRAWBL_SPACES_SECRET_KEY | Spaces secret key | Optional* |
*If any Spaces variable is set, all five are required.
What's next: See the Memory Palace Guide for details on the 19 memory tools, the SearXNG infrastructure page for deployment details, or the Billing & Usage guide for the full cost tracking pipeline.