Documentation Index Fetch the complete documentation index at: https://docs.shannon.run/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Shannon can automatically generate tools from OpenAPI 3.x specifications, allowing you to integrate any REST API without writing code. The OpenAPI loader:
✅ Parses OpenAPI 3.0/3.1 specs
✅ Generates one tool per operation
✅ Handles authentication (Bearer, API Key, Basic)
✅ Supports path/query/header parameters
✅ Includes circuit breaker and rate limiting
✅ Validates requests against schema
✅ Resolves $ref references locally
Configuration Reference
Basic Configuration
# config/shannon.yaml or config/overlays/shannon.myvendor.yaml
openapi_tools :
tool_collection_name :
enabled : true | false # Enable/disable this tool collection
spec_path : string # Path to OpenAPI spec file
spec_url : string # OR: URL to fetch spec from
spec_inline : string # OR: Inline YAML/JSON spec
auth_type : none | api_key | bearer | basic
auth_config : object # Auth configuration (see below)
category : string # Tool category (e.g., "analytics", "data")
base_cost_per_use : float # Estimated cost per operation (USD)
rate_limit : integer # Requests per minute (default: 30)
timeout_seconds : float # Request timeout (default: 30)
max_response_bytes : integer # Max response size (default: 10MB)
operations : [ string ] # Optional: Filter by operationId
tags : [ string ] # Optional: Filter by tags
base_url : string # Optional: Override spec's base URL
Field Descriptions
Field Type Required Default Description enabledboolean Yes - Enable this tool collection spec_pathstring One of spec_* - Local file path to OpenAPI spec spec_urlstring One of spec_* - URL to fetch spec from (supports relative server URLs) spec_inlinestring One of spec_* - Inline YAML/JSON spec content auth_typeenum Yes noneAuthentication method auth_configobject If auth ≠ none {}Auth configuration (varies by type) categorystring No "api"Tool category for organization base_cost_per_usefloat No 0.001Estimated cost per invocation (USD) rate_limitinteger No 30Max requests per minute per tool timeout_secondsfloat No 30.0HTTP request timeout max_response_bytesinteger No 10485760Max response size (10MB) operationsarray[string] No All Filter to specific operationIds tagsarray[string] No All Filter operations by tags base_urlstring No From spec Override API base URL
Authentication Types
No Authentication
openapi_tools :
public_api :
enabled : true
spec_url : https://api.example.com/openapi.json
auth_type : none
Bearer Token
Used by: GitHub, GitLab, most modern APIs
openapi_tools :
github_api :
enabled : true
spec_url : https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.json
auth_type : bearer
auth_config :
token : "${GITHUB_TOKEN}" # From environment variable
# OR:
# token: "ghp_xxxxxxxxxxxxx" # Hardcoded (not recommended)
Environment Variable :
GITHUB_TOKEN = ghp_your_token_here
Headers sent :
Authorization: Bearer ghp_your_token_here
Used by: OpenAI, Anthropic, many SaaS APIs
openapi_tools :
openai_api :
enabled : true
spec_url : https://raw.githubusercontent.com/openai/openai-openapi/master/openapi.yaml
auth_type : api_key
auth_config :
api_key_name : Authorization # Header name
api_key_location : header # "header" or "query"
api_key_value : "Bearer ${OPENAI_API_KEY}" # Value with prefix
Environment Variable :
OPENAI_API_KEY = sk-your-key-here
Headers sent :
Authorization: Bearer sk-your-key-here
API Key in Query Parameter
Used by: OpenWeather, some legacy APIs
openapi_tools :
weather_api :
enabled : true
spec_url : https://api.openweathermap.org/data/3.0/openapi.json
auth_type : api_key
auth_config :
api_key_name : appid # Query param name
api_key_location : query # "query" not "header"
api_key_value : "${OPENWEATHER_KEY}"
Request URL :
GET https://api.openweathermap.org/data/3.0/weather?appid=your_key_here&q=London
Basic Authentication
Used by: Legacy APIs, internal services
openapi_tools :
legacy_api :
enabled : true
spec_path : config/openapi_specs/legacy_api.yaml
auth_type : basic
auth_config :
username : "${API_USERNAME}"
password : "${API_PASSWORD}"
Environment Variables :
API_USERNAME = admin
API_PASSWORD = secret123
Headers sent :
Authorization: Basic YWRtaW46c2VjcmV0MTIz
For vendor-specific authentication:
openapi_tools :
custom_api :
enabled : true
spec_url : https://api.custom.com/v1/openapi.json
auth_type : api_key
auth_config :
vendor : myvendor # Triggers vendor adapter
api_key_name : X-API-Key
api_key_location : header
api_key_value : "${CUSTOM_API_KEY}"
extra_headers :
X-Account-ID : "{{body.account_id}}" # Dynamic from request body
X-User-ID : "${CUSTOM_USER_ID}" # Static from environment
X-Timestamp : "{{timestamp}}" # Dynamic template
Dynamic Header Templates :
"${ENV_VAR}" - Resolved from environment
"{{body.field}}" - Resolved from request body at runtime
Static strings - Used as-is
Advanced Features
Operation Filtering
By operationId (recommended):
openapi_tools :
petstore :
spec_url : https://petstore3.swagger.io/api/v3/openapi.json
operations :
- getPetById # Only generate tool for this operation
- findPetsByStatus
- addPet
By tags :
openapi_tools :
petstore :
spec_url : https://petstore3.swagger.io/api/v3/openapi.json
tags :
- pet # Only operations tagged "pet"
- user
Base URL Override
Override the base URL from the spec:
openapi_tools :
api_staging :
spec_url : https://api.example.com/openapi.json
base_url : https://staging-api.example.com # Use staging instead
Use cases :
Testing against staging/dev environments
Internal proxies or gateways
Local development
Rate Limiting
Protect external APIs from overload:
openapi_tools :
expensive_api :
spec_url : https://expensive.api.com/openapi.json
rate_limit : 10 # Only 10 requests per minute
timeout_seconds : 60 # 60 second timeout for slow operations
Per-tool limits : Each operation generated from the spec inherits this limit.
Behavior :
Enforced via token bucket algorithm
Shared across all tool instances (single Shannon instance)
Returns error if limit exceeded
Circuit Breaker
Automatic failure protection:
Configuration (via environment):
# Circuit breaker opens after 5 failures
# Stays open for 60 seconds before allowing retry
# (These are defaults, not directly configurable per tool yet)
States :
Closed (normal): All requests pass through
Open (failing): All requests immediately rejected
Half-open (testing): One trial request allowed
Behavior :
After 5 consecutive failures → opens circuit
Circuit stays open for 60 seconds
Then allows one trial request (half-open)
Success → closes circuit
Failure → reopens for another 60 seconds
Response Size Limits
Prevent memory exhaustion:
openapi_tools :
api_with_large_responses :
spec_url : https://api.example.com/openapi.json
max_response_bytes : 52428800 # 50MB limit
Behavior :
Responses larger than limit are truncated
Error returned with truncated marker
Troubleshooting
Symptom : Tool doesn’t appear in /tools/list
Debug :
# 1. Check if spec is valid
curl -X POST http://localhost:8000/tools/openapi/validate \
-H "Content-Type: application/json" \
-d '{"spec_url": "https://api.example.com/openapi.json"}'
# 2. Check logs
docker logs shannon-llm-service-1 | grep -i "openapi"
# 3. Verify enabled flag
grep -A 5 "my_tool" config/shannon.yaml | grep enabled
Common causes :
enabled: false in config
Invalid OpenAPI spec
Domain not in OPENAPI_ALLOWED_DOMAINS
Spec fetch timeout
Circular $ref references
Domain Validation Error
Symptom : URL host 'example.com' not in allowed domains
Fix :
# Development: Allow all
OPENAPI_ALLOWED_DOMAINS = *
# Production: Specific domains
OPENAPI_ALLOWED_DOMAINS = api.github.com,api.example.com,api.partner.com
In docker-compose.yml :
services :
llm-service :
environment :
- OPENAPI_ALLOWED_DOMAINS=api.example.com
Spec Fetch Timeout
Symptom : Failed to fetch OpenAPI spec: timeout
Fix :
# Increase timeout (default: 30s)
OPENAPI_FETCH_TIMEOUT = 60
# Or use local spec file instead
openapi_tools:
my_api:
spec_path: config/openapi_specs/my_api.yaml # Local file
Circuit Breaker Triggered
Symptom : Circuit breaker open for https://api.example.com
Debug :
# Check recent errors
docker logs shannon-llm-service-1 --tail 100 | grep -i "circuit\|failure"
Fix :
Wait 60 seconds for automatic recovery
Fix underlying API issues
Increase timeout if API is slow:
Rate Limit Exceeded
Symptom : Rate limit exceeded for tool my_tool
Fix :
# Increase limit
openapi_tools :
my_api :
rate_limit : 120 # 120 requests per minute
Authentication Failures
Symptom : 401 Unauthorized or 403 Forbidden
Debug :
# Check environment variables
env | grep API_KEY
# Test token manually
curl -H "Authorization: Bearer $YOUR_TOKEN " https://api.example.com/endpoint
Common causes :
Environment variable not set
Token expired
Wrong auth type (should be bearer not api_key)
Missing Bearer prefix for API key auth
Examples
Example 1: GitHub API
openapi_tools :
github :
enabled : true
spec_url : https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.json
auth_type : bearer
auth_config :
token : "${GITHUB_TOKEN}"
category : development
rate_limit : 60
operations :
- repos/get
- repos/list-for-user
- issues/list-for-repo
Usage :
./scripts/submit_task.sh "List all repositories for user octocat"
Example 2: OpenWeather API
openapi_tools :
openweather :
enabled : true
spec_url : https://api.openweathermap.org/data/3.0/openapi.json
auth_type : api_key
auth_config :
api_key_name : appid
api_key_location : query
api_key_value : "${OPENWEATHER_API_KEY}"
category : data
rate_limit : 60
Usage :
./scripts/submit_task.sh "What's the weather forecast for Tokyo?"
Example 3: Internal API with Vendor Adapter
openapi_tools :
internal_analytics :
enabled : true
spec_path : config/openapi_specs/internal_analytics.yaml
auth_type : bearer
auth_config :
vendor : mycompany # Triggers vendor adapter
token : "${ANALYTICS_API_TOKEN}"
extra_headers :
X-Tenant-ID : "{{body.tenant_id}}"
category : analytics
base_cost_per_use : 0.005
Vendor Adapter (python/llm-service/llm_service/tools/vendor_adapters/mycompany.py):
class MyCompanyAdapter :
def transform_body ( self , body , operation_id , prompt_params ):
# Add tenant context
if prompt_params and "tenant_id" in prompt_params:
body[ "tenant_id" ] = prompt_params[ "tenant_id" ]
# Transform metric names
if "metrics" in body:
body[ "metrics" ] = [ f "myco: { m } " for m in body[ "metrics" ]]
return body
Security Best Practices
# ❌ Bad
auth_config :
token : "sk-1234567890"
# ✅ Good
auth_config :
token : "${API_TOKEN}"
# Production
OPENAPI_ALLOWED_DOMAINS = api.trusted.com,api.partner.com
# Not: OPENAPI_ALLOWED_DOMAINS=*
Set appropriate rate limits
rate_limit : 60 # Match your API provider's limits
Shannon automatically upgrades HTTP to HTTPS for external APIs
localhost/127.0.0.1 allowed on HTTP for development
max_response_bytes : 10485760 # 10MB default
See Also
Adding Custom Tools Complete tool integration guide
Vendor Adapters Domain-specific integrations
Extending Shannon Other extension methods
OpenAPI Tests Test examples and validation
Quick Reference
# Validate spec
curl -X POST http://localhost:8000/tools/openapi/validate \
-d '{"spec_url": "https://api.example.com/openapi.json"}' | jq .
# List registered tools
curl http://localhost:8000/tools/list | jq .
# Get tool schema
curl http://localhost:8000/tools/myTool/schema | jq .
# Execute tool
curl -X POST http://localhost:8000/tools/execute \
-d '{"tool_name":"myTool","parameters":{...}}' | jq .
# Test via workflow
./scripts/submit_task.sh "Your query using the tool"
Need Help?
Report issues: GitHub Issues
Examples: tests/e2e/06_openapi_petstore_test.sh