Skip to main content

Overview

Shannon supports three ways to add custom tools:
No Proto/Rust/Go changes required - all tools use generic containers for maximum flexibility.
Key Features:
  • ✅ 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 config/shannon.yaml under the mcp_tools section:
Required Fields:
  • enabled: Set to true to activate
  • url: HTTP endpoint (must be POST, accepts JSON)
  • func_name: Internal function name
  • description: Clear description shown to LLM
  • category: Tool category (e.g., search, data, analytics, code)
  • cost_per_use: Estimated cost in USD
  • parameters: Array of parameter definitions
2

Configure Domain Access

For Development (permissive):Add to .env:
For Production (recommended):
3

Add API Keys

Add your API key to .env:
4

Restart Service

You must recreate the service (not just restart):
Wait for health check:
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:
Your endpoint should return JSON:

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.
For domain-specific APIs requiring custom transformations, see the Vendor Adapter Pattern section below or the comprehensive Vendor Adapters Guide.

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 (2 retries, configurable via OPENAPI_RETRIES)
  • ✅ Configurable rate limits and timeouts
  • ✅ Relative server URLs (resolved against spec URL)
  • ✅ Basic $ref resolution (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:
  • Cannot upload files or binary data
  • Workaround: Use base64-encoded files in JSON body
  • Affected: Image generation, file processing, document upload 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 bearer auth_type
  • No style, explode, or deepObject serialization
  • Only basic path/query parameter substitution
  • Affected: APIs with complex array/object query parameters
  • No remote $ref resolution (e.g., https://example.com/schemas/Pet.json)
  • Only local refs (#/components/...) supported
  • Workaround: Merge external schemas into single spec file
  • No allOf, oneOf, anyOf support
  • Only basic type mapping
  • Affected: APIs with polymorphic types or complex validation
  • No application/x-www-form-urlencoded content type
  • Only JSON request bodies supported
What Works Well:
  • ✅ Simple REST APIs with JSON request/response
  • ✅ APIs with Bearer/API Key/Basic authentication
  • ✅ Read-heavy operations (GET requests)
  • ✅ Well-structured specs with local $ref references
  • ✅ Path and query parameters (primitives)
For specs with relative server URLs (e.g., /api/v3), you must provide the spec via spec_url (not spec_inline) so Shannon can resolve the full base URL.

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

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
Use MCP/OpenAPI instead when:
  • 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:
OpenAPI Configuration:

Testing & Verification

Health Checks

List Tools

Execute Tools

Direct execution:
Batch execution:
Via workflow:

Troubleshooting

Symptom: Tool doesn’t appear in /tools/listDebug steps:
Symptom: URL host 'example.com' not in allowed domainsSolutions:
  1. Development: Use wildcard
  2. Production: Add specific domain
Symptom: ToolResult { success: false, error: "..." }Debug:
Symptom: Circuit breaker open for <url> (too many failures)Debug:
Prevent:
  • Increase failure threshold: MCP_CB_FAILURES=10
  • Increase recovery time: MCP_CB_RECOVERY_SECONDS=120
  • Fix underlying API issues

Security Best Practices

Domain Allowlisting

API Key Management

Never hardcode API keys in configuration files!
❌ Bad:
✅ Good:
Store in .env (not tracked by git):
For production: Use secrets management
  • 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., usersmy: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: Key takeaways:
  • ✅ Zero proto/Rust/Go changes (generic google.protobuf.Struct containers)
  • ✅ Security built-in (domain allowlisting, rate limiting, circuit breakers)
  • ✅ Cost tracking automatic (set cost_per_use in metadata)
  • ✅ Schema-driven (OpenAI-compatible JSON schemas)

Next Steps

Vendor Adapters

Build vendor-specific integrations

Extending Shannon

Explore all extension methods

Configuration

Complete configuration reference

API Reference

Explore the REST API