Overview
Shannon supports three ways to add custom tools:| Method | Best For | Code Changes | Restart Required |
|---|---|---|---|
| MCP Tools | External HTTP APIs, rapid prototyping | None | ✅ Service only |
| OpenAPI Tools | REST APIs with OpenAPI specs | None | ✅ Service only |
| Built-in Tools | Complex logic, database access, performance | Python code | ✅ Service only |
No Proto/Rust/Go changes required - all tools use generic containers for maximum flexibility.
- ✅ Dynamic registration via API or YAML config
- ✅ Built-in rate limiting and circuit breakers
- ✅ Domain allowlisting for security
- ✅ Cost tracking and budget enforcement
Quick Start: Adding MCP Tools
MCP (Model Context Protocol) tools let you integrate any HTTP endpoint as a Shannon tool with zero code changes.1
Add Tool Definition
Edit Required Fields:
config/shannon.yaml under the mcp_tools section:enabled: Set totrueto activateurl: HTTP endpoint (must be POST, accepts JSON)func_name: Internal function namedescription: Clear description shown to LLMcategory: Tool category (e.g.,search,data,analytics,code)cost_per_use: Estimated cost in USDparameters: Array of parameter definitions
2
Configure Domain Access
For Development (permissive):Add to For Production (recommended):
.env:3
Add API Keys
Add your API key to
.env:4
Restart Service
5
Verify Registration
Check logs:List tools via API:Get tool schema:
6
Test Your Tool
Direct execution:Via workflow:
MCP Request Convention
Shannon sends POST requests in this format:Alternative: Runtime API Registration
For development/testing only (tools lost on restart):
Adding OpenAPI Tools
For REST APIs with OpenAPI 3.x specifications, Shannon can automatically generate tools.Features
Supported:- ✅ OpenAPI 3.0 and 3.1 specs
- ✅ URL-based or inline spec loading
- ✅ JSON request/response bodies
- ✅ Path and query parameters
- ✅ Bearer, API Key (header/query), Basic auth
- ✅ Operation filtering by operationId or tags
- ✅ Circuit breaker (5 failures → 60s cooldown)
- ✅ Retry logic with exponential backoff (3 retries, configurable via
OPENAPI_RETRIES) - ✅ Configurable rate limits and timeouts
- ✅ Relative server URLs (resolved against spec URL)
- ✅ Basic
$refresolution (local references to#/components/schemas/*)
Limitations
Shannon OpenAPI integration is production-ready for ~70% of REST APIs (JSON-based with simple auth). The following features are not yet supported:File Upload APIs (multipart/form-data)
File Upload APIs (multipart/form-data)
- Cannot upload files or binary data
- Workaround: Use base64-encoded files in JSON body
- Affected: Image generation, file processing, document upload APIs
OAuth-Protected APIs
OAuth-Protected APIs
- No OAuth 2.0 flows (Authorization Code, Client Credentials)
- Can only use Bearer tokens (manually obtained)
- Affected: Google APIs, GitHub, Slack, Twitter, etc.
- Workaround: Manually obtain OAuth token and use
bearerauth_type
Complex Parameter Encoding
Complex Parameter Encoding
- No
style,explode, ordeepObjectserialization - Only basic path/query parameter substitution
- Affected: APIs with complex array/object query parameters
Multi-File OpenAPI Specs
Multi-File OpenAPI Specs
- No remote
$refresolution (e.g.,https://example.com/schemas/Pet.json) - Only local refs (
#/components/...) supported - Workaround: Merge external schemas into single spec file
Advanced Schema Combinators
Advanced Schema Combinators
- No
allOf,oneOf,anyOfsupport - Only basic type mapping
- Affected: APIs with polymorphic types or complex validation
Form-Encoded Requests
Form-Encoded Requests
- No
application/x-www-form-urlencodedcontent type - Only JSON request bodies supported
- ✅ Simple REST APIs with JSON request/response
- ✅ APIs with Bearer/API Key/Basic authentication
- ✅ Read-heavy operations (GET requests)
- ✅ Well-structured specs with local
$refreferences - ✅ Path and query parameters (primitives)
Quick Start
1
Add Tool Definition
Edit
config/shannon.yaml under openapi_tools:2
Configure Environment
Add to
.env:3
Restart Service
4
Verify & Test
Validate spec first:Response:Execute tool:
Authentication Examples
- Bearer Token
- API Key in Query
- Basic Auth
- API Key in Header
Adding Built-in Python Tools
For complex logic, database access, or performance-critical operations.When to Use Built-in Tools
Use built-in tools when:- Need direct database/Redis access
- Require complex Python libraries (pandas, numpy)
- Performance-critical (avoid HTTP roundtrip)
- Need session state management
- Implement security-sensitive operations
- Integrating external APIs
- Want no-code deployment
- Prototyping quickly
- Third-party service integration
1
Create Tool Class
Create file in
python/llm-service/llm_service/tools/builtin/my_custom_tool.py:2
Runtime Registration (Optional)
Register OpenAPI tools dynamically via API (uses the same admin token as MCP):Response includes registered operations and effective limits.
3
Register Tool
Edit
python/llm-service/llm_service/api/tools.py around line 228:4
Restart Service
5
Test Tool
Advanced: Session-Aware Tools
For tools that maintain state across executions:Configuration Reference
MCP Tool Configuration
OpenAPI Tool Configuration
Environment Variables
MCP Configuration:Testing & Verification
Health Checks
List Tools
Execute Tools
Direct execution:Troubleshooting
Tool Not Registered
Tool Not Registered
Symptom: Tool doesn’t appear in
/tools/listDebug steps:Domain Validation Error
Domain Validation Error
Symptom:
URL host 'example.com' not in allowed domainsSolutions:-
Development: Use wildcard
-
Production: Add specific domain
Tool Execution Fails
Tool Execution Fails
Symptom:
ToolResult { success: false, error: "..." }Debug:Circuit Breaker Triggered
Circuit Breaker Triggered
Symptom: Prevent:
Circuit breaker open for <url> (too many failures)Debug:- Increase failure threshold:
MCP_CB_FAILURES=10 - Increase recovery time:
MCP_CB_RECOVERY_SECONDS=120 - Fix underlying API issues
Security Best Practices
Domain Allowlisting
- Development
- Staging
- Production
API Key Management
❌ Bad:.env (not tracked by git):
- Docker secrets
- Kubernetes secrets
- HashiCorp Vault
- AWS Secrets Manager
Dangerous Tools
Mark tools that modify state or access sensitive resources:Vendor Adapter Pattern
For domain-specific APIs and custom agents When integrating proprietary or internal APIs that require domain-specific transformations, use the vendor adapter pattern to keep vendor logic separate from Shannon’s core infrastructure.When to Use
Use vendor adapters when your API integration requires:- Custom field name aliasing (e.g.,
users→my:unique_users) - Request/response transformations
- Dynamic parameter injection from session context
- Domain-specific validation or normalization
- Specialized agent roles with custom system prompts
Quick Example
1
Create Vendor Adapter
python/llm-service/llm_service/tools/vendor_adapters/myvendor.py:2
Register Adapter
python/llm-service/llm_service/tools/vendor_adapters/__init__.py:3
Configure with Vendor Flag
config/overlays/shannon.myvendor.yaml:4
Use Environment
Benefits
- ✅ Clean separation: Vendor code isolated from Shannon core
- ✅ No core changes: Shannon infrastructure remains generic
- ✅ Conditional loading: Graceful fallback if vendor module unavailable
- ✅ Easy testing: Unit test adapters in isolation
- ✅ Secrets management: All tokens via environment variables
Complete Guide
For a comprehensive guide including:- Custom agent roles for specialized domains
- Session context injection patterns
- Testing strategies
- Best practices and troubleshooting
Vendor Adapters Guide
Learn how to build vendor-specific integrations with the adapter pattern
Summary
Three ways to add tools:| Method | Command | Config File | Code Changes |
|---|---|---|---|
| MCP | docker compose up -d --force-recreate llm-service | config/shannon.yaml | None |
| OpenAPI | docker compose up -d --force-recreate llm-service | config/shannon.yaml | None |
| Built-in | docker compose up -d --force-recreate llm-service | api/tools.py + new file | Python only |
- ✅ Zero proto/Rust/Go changes (generic
google.protobuf.Structcontainers) - ✅ Security built-in (domain allowlisting, rate limiting, circuit breakers)
- ✅ Cost tracking automatic (set
cost_per_usein metadata) - ✅ Schema-driven (OpenAI-compatible JSON schemas)