Skip to content

Tool System

The tool system provides a type-safe, permission-aware, token-efficient framework for agent capabilities. It supports 4 tool types with lazy loading that saves 60--90% of context tokens.

Architecture Overview

Lazy Loading Strategy

The key insight: at session start, the agent only needs tool names and descriptions to decide which tools to use. Full JSON Schema definitions are loaded on demand.

Token Savings

ApproachTokens at Session StartTokens per Tool
Traditional (all definitions)~5,000--15,000~200--500 each
Lazy loading (index only)~50 (ToolSearch meta-tool)~5 each (name + 1-line desc)
Savings60--90%

The ToolActivationSet uses LRU eviction with a ceiling of 20 active tools. When a new tool is activated and the set is full, the least recently used tool's full definition is evicted (but it remains in the index for re-activation).

Tool Definition

Every tool declares its interface via ToolDefinition:

rust
ToolDefinition {
    name: ToolName,                    // unique identifier
    description: String,               // human-readable purpose
    help: Option<String>,              // extended usage info
    parameters: serde_json::Value,     // JSON Schema Draft 7
    result_schema: Option<Value>,      // expected output schema
    category: ToolCategory,            // FileSystem, Network, Shell, ...
    tool_type: ToolType,               // BuiltIn, Mcp, Custom, Dynamic
    capabilities: Vec<Capability>,     // required runtime capabilities
    is_dangerous: bool,                // triggers permission check
}

Tool Categories

CategoryExamples
FileSystemFileRead, FileWrite, FileDelete, FileMove
NetworkWebSearch, WebFetch
ShellShellExec
SearchToolSearch, CodeSearch
MemoryMemoryStore, MemoryRecall
KnowledgeKnowledgeSearch, KnowledgeIngest
AgentTask, AskUser
WorkflowWorkflowCreate, WorkflowRun
ScheduleScheduleCreate, ScheduleList
InteractionAskUser
CustomUser-defined categories

Execution Pipeline

Execution Steps (detailed)

  1. Meta-tool interception: ToolSearch, Task, Plan, Workflow*, Schedule* are intercepted before the registry
  2. Registry lookup: registry.get_tool(name) -- returns the Tool trait object
  3. Schema validation: JsonSchemaValidator::validate() checks input arguments against the tool's JSON Schema
  4. Pre-execution middleware: The Tool middleware chain runs with phase: "pre". If any middleware sets ctx.aborted = true, execution is blocked
  5. Tool execution: tool.execute(ToolInput) runs the actual tool logic
  6. Post-execution middleware: Runs with phase: "post" -- failures are logged but never propagated
  7. Result truncation: truncate_tool_result() enforces a hard 10K character cap
  8. Special handling: Browser/WebFetch results are stripped of URL metadata; AskUser results block on user input

Multi-Format Tool Call Parsing

y-agent supports multiple tool call formats for compatibility with different LLM providers:

ProviderFormatParser
OpenAI/AnthropicNative tool_calls fieldDirect deserialization
OpenAI (fallback)XML-tagged in contentparse_tool_calls()
DeepSeekDSML formatparse_tool_calls()
MiniMaxCustom formatparse_tool_calls()
GLM4Custom formatparse_tool_calls()
Qwen3CoderCustom formatparse_tool_calls()
OllamaPrompt-based (XML in response)parse_tool_calls()

The agent execution loop first checks for native tool_calls in the response. If none are found, it falls back to parse_tool_calls() which attempts to extract tool calls from the text content.

Tool Calling Modes

ModeHow Tools Are DeclaredWhen Used
NativeSent via API tools parameterOpenAI, Anthropic, Gemini (API-level support)
PromptBasedInjected as XML tags in system promptOllama, compatible providers (no native API support)

The mode is determined per-provider and stored in ToolCallingMode. The context pipeline adjusts tool injection accordingly.

Permission Model

Tools interact with the permission system at two levels:

Definition-Level

rust
ToolDefinition {
    is_dangerous: bool,  // declared by the tool author
    // ...
}

Runtime Evaluation

Dynamic Tools

Agents can create and manage tools at runtime:

Meta-ToolPurpose
tool_createDefine a new tool with name, description, schema
tool_updateModify an existing dynamic tool

Dynamic tools receive ToolType::Dynamic and are subject to the same validation and permission checks as built-in tools.

Rate Limiting

The RateLimiter enforces per-tool rate limits:

  • Configurable max calls per time window
  • Prevents runaway tool loops before the LoopGuard triggers
  • Rate limit violations return an error message to the LLM (not a hard failure)

Built-In Tools

ToolCategoryDangerousDescription
FileReadFileSystemNoRead file contents
FileWriteFileSystemNoWrite/create files
FileDeleteFileSystemYesDelete files
FileMoveFileSystemNoMove/rename files
ShellExecShellYesExecute shell commands
WebSearchNetworkNoWeb search queries
MemoryStoreMemoryNoStore long-term memory
MemoryRecallMemoryNoRecall from memory
ToolSearchSearchNoSearch and activate tools
TaskAgentNoDelegate to sub-agent
PlanAgentNoStructured planning
AskUserInteractionNoRequest user input
BrowserToolNetworkNoCDP browser automation

Released under the MIT License.