Core Concepts
February 17, 2026 · View on GitHub
This guide explains the fundamental building blocks of CHUK Tool Processor.
What CHUK Tool Processor Is (and Isn't)
CHUK Tool Processor is a tool execution runtime for AI systems. It deliberately does not:
- Plan workflows or decide which tools to call
- Manage conversation history or memory
- Implement agent loops or reasoning chains
It does:
- Execute tool calls reliably, with timeouts, retries, caching, and rate limits
- Parse tool calls from any LLM format (Anthropic XML, OpenAI tool_calls, JSON)
- Run tools locally, in isolated subprocesses, or remotely via MCP
- Provide observability (tracing, metrics) for tool execution
This separation is intentional. Higher-level planners (your agent, LangChain, LlamaIndex) decide which tools to call. CHUK Tool Processor makes sure those calls actually succeed.
Table of Contents
- Tool Registry
- Execution Strategies
- Execution Wrappers (Middleware)
- Input Parsers (Plugins)
- MCP Integration
1. Tool Registry
The registry is where you register tools for execution. Tools can be:
- Simple classes with an
async execute()method - ValidatedTool subclasses with Pydantic validation
- StreamingTool for real-time incremental results
- Functions registered via
register_fn_tool()
Note: The registry is global by default, but you can create isolated registries with
create_registry()for multi-tenant apps. See PRODUCTION_PATTERNS.md.
Basic Tool Registration
from chuk_tool_processor import register_tool
@register_tool(name="calculator")
class Calculator:
async def execute(self, a: float, b: float, operation: str) -> dict:
ops = {"add": a + b, "multiply": a * b, "subtract": a - b}
return {"result": ops.get(operation, 0)}
Validated Tool with Pydantic
from chuk_tool_processor import register_tool
from chuk_tool_processor.models.validated_tool import ValidatedTool
from pydantic import BaseModel, Field
@register_tool(name="weather")
class WeatherTool(ValidatedTool):
class Arguments(BaseModel):
location: str = Field(..., description="City name")
units: str = Field("celsius", description="Temperature units")
class Result(BaseModel):
temperature: float
conditions: str
async def _execute(self, location: str, units: str) -> Result:
# Your weather API logic here
return self.Result(temperature=22.5, conditions="Sunny")
Short Decorator Syntax
from chuk_tool_processor import tool
@tool(name="search") # Shorter alternative to @register_tool
class SearchTool:
async def execute(self, query: str) -> dict:
return {"results": [f"Found: {query}"]}
2. Execution Strategies
Strategies determine how tools run:
| Strategy | Use Case | Trade-offs |
|---|---|---|
| InProcessStrategy | Fast, trusted tools | Speed ✅, Isolation ❌ |
| IsolatedStrategy | Untrusted or risky code | Isolation ✅, Speed ❌ |
Parallel Execution
Both strategies execute tools concurrently by default. Results return in completion order (faster tools return first), not submission order. Use ToolResult.tool to match results to original calls.
Using InProcessStrategy (Default)
from chuk_tool_processor import ToolProcessor
async with ToolProcessor() as processor:
# Tools run in the same process (fast)
results = await processor.process(tool_calls)
Using IsolatedStrategy
from chuk_tool_processor import ToolProcessor, IsolatedStrategy, get_default_registry
async def main():
registry = await get_default_registry()
processor = ToolProcessor(
strategy=IsolatedStrategy(
registry=registry,
max_workers=4,
default_timeout=30.0
)
)
async with processor:
# Tools run in separate subprocesses (safe)
results = await processor.process(tool_calls)
Note:
IsolatedStrategyis an alias ofSubprocessStrategyfor backwards compatibility. UseIsolatedStrategyfor clarity—it better communicates the security boundary intent.
When to Use Each Strategy
| Scenario | Recommended Strategy |
|---|---|
| Trusted internal tools | InProcessStrategy |
| External/user-provided code | IsolatedStrategy |
| LLM-generated code execution | IsolatedStrategy |
| Performance-critical path | InProcessStrategy |
| Tools that might crash | IsolatedStrategy |
3. Execution Wrappers (Middleware)
Wrappers add production features as composable layers:
processor = ToolProcessor(
enable_caching=True, # Cache expensive calls
cache_ttl=600, # 10 minutes
enable_rate_limiting=True, # Prevent abuse
global_rate_limit=100, # 100 req/min globally
enable_retries=True, # Auto-retry failures
max_retries=3 # Up to 3 attempts
)
Execution Order
The processor stacks wrappers automatically:
Request → Cache → Rate Limit → Retry → Strategy → Tool
↓
Response ← Cache ← Rate Limit ← Retry ← Strategy ← Tool
Available Wrappers
| Wrapper | Purpose | Key Options |
|---|---|---|
| Cache | Avoid redundant calls | cache_ttl, enable_caching |
| Rate Limit | Prevent abuse | global_rate_limit, tool_rate_limits |
| Retry | Handle transient failures | max_retries, retry_delay |
| Circuit Breaker | Prevent cascading failures | enable_circuit_breaker |
See CONFIGURATION.md for all options.
4. Input Parsers (Plugins)
Parsers extract tool calls from various LLM output formats. All formats work automatically—no configuration needed.
XML Tags (Anthropic-style)
<tool name="search" args='{"query": "Python"}'/>
OpenAI tool_calls (JSON)
{
"tool_calls": [
{
"type": "function",
"function": {
"name": "search",
"arguments": "{\"query\": \"Python\"}"
}
}
]
}
Direct JSON (array of calls)
[
{ "tool": "search", "arguments": { "query": "Python" } }
]
Input Format Compatibility
| Format | Example | Use Case |
|---|---|---|
| XML Tool Tag | <tool name="search" args='{"q":"Python"}'/> | Anthropic Claude, XML-based LLMs |
| OpenAI tool_calls | JSON object (above) | OpenAI GPT-4 function calling |
| Direct JSON | [{"tool": "search", "arguments": {"q": "Python"}}] | Generic API integrations |
| Single dict | {"tool": "search", "arguments": {"q": "Python"}} | Programmatic calls |
5. MCP Integration (External Tools)
Connect to remote tool servers using the Model Context Protocol. CHUK Tool Processor supports three transport mechanisms for different use cases.
Transport Comparison
| Transport | Use Case | Real Examples |
|---|---|---|
| HTTP Streamable | Cloud APIs, SaaS services | Notion (mcp.notion.com) |
| STDIO | Local tools, databases | SQLite (mcp-server-sqlite), Echo (chuk-mcp-echo) |
| SSE | Legacy cloud services | Atlassian (mcp.atlassian.com) |
HTTP Streamable (Recommended for Cloud)
Modern HTTP streaming transport for cloud-based MCP servers:
from chuk_tool_processor.mcp import setup_mcp_http_streamable
servers = [
{
"name": "notion",
"url": "https://mcp.notion.com/mcp",
"headers": {"Authorization": f"Bearer {access_token}"}
}
]
processor, manager = await setup_mcp_http_streamable(
servers=servers,
namespace="notion",
initialization_timeout=120.0,
enable_caching=True,
enable_retries=True
)
# Use Notion tools through MCP
results = await processor.process(
'<tool name="notion.search_pages" args=\'{"query": "meeting notes"}\'/>'
)
STDIO (Best for Local Tools)
For running local MCP servers as subprocesses:
from chuk_tool_processor.mcp import setup_mcp_stdio
processor, manager = await setup_mcp_stdio(
config_file="mcp_config.json",
servers=["sqlite"],
namespace="db",
initialization_timeout=120.0
)
results = await processor.process(
'<tool name="db.query" args=\'{"sql": "SELECT * FROM users LIMIT 10"}\'/>'
)
SSE (Legacy Support)
For backward compatibility with older MCP servers:
from chuk_tool_processor.mcp import setup_mcp_sse
servers = [
{
"name": "atlassian",
"url": "https://mcp.atlassian.com/v1/sse",
"headers": {"Authorization": f"Bearer {access_token}"}
}
]
processor, manager = await setup_mcp_sse(
servers=servers,
namespace="atlassian",
initialization_timeout=120.0
)
Architecture with MCP
LLM Output
↓
Tool Processor
↓
┌──────────────┬────────────────────┐
│ Local Tools │ Remote Tools (MCP) │
└──────────────┴────────────────────┘
Relationship with chuk-mcp:
chuk-mcpis a low-level MCP protocol client (handles transports, protocol negotiation)chuk-tool-processorwrapschuk-mcpto integrate external tools into your execution pipeline- You can use local tools, remote MCP tools, or both in the same processor
For detailed MCP examples, see MCP_INTEGRATION.md.
Related Documentation
- GETTING_STARTED.md - Step-by-step tutorials
- PRODUCTION_PATTERNS.md - Production-grade patterns
- CONFIGURATION.md - All configuration options
- MCP_INTEGRATION.md - Detailed MCP guide