# Shannon - Production-Oriented Multi-Agent Orchestration Framework # https://github.com/Kocoro-lab/Shannon # # NOTE: Run `make setup` before first launch to download required config files # and create your .env file, then add at least one LLM API key. x-defaults: &defaults restart: unless-stopped logging: driver: json-file options: max-size: 100m max-file: '3' x-shannon-config: &shannon-config volumes: - ./config:/app/config:ro services: postgres: <<: *defaults image: ${GLOBAL_REGISTRY:-}pgvector/pgvector:${POSTGRES_VERSION:-pg16} environment: TZ: ${TZ:-UTC} POSTGRES_USER: ${POSTGRES_USER:-shannon} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-shannon} POSTGRES_DB: ${POSTGRES_DB:-shannon} volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: [CMD-SHELL, 'pg_isready -U ${POSTGRES_USER:-shannon} -d ${POSTGRES_DB:-shannon}'] interval: 5s timeout: 5s retries: 20 start_period: 15s deploy: resources: limits: cpus: ${POSTGRES_CPU_LIMIT:-1.0} memory: ${POSTGRES_MEMORY_LIMIT:-1G} reservations: cpus: ${POSTGRES_CPU_RESERVATION:-0.25} memory: ${POSTGRES_MEMORY_RESERVATION:-256M} redis: <<: *defaults image: ${GLOBAL_REGISTRY:-}redis:${REDIS_VERSION:-7.2-alpine} volumes: - redis_data:/data healthcheck: test: [CMD, redis-cli, ping] interval: 5s timeout: 5s retries: 10 start_period: 5s deploy: resources: limits: cpus: ${REDIS_CPU_LIMIT:-0.5} memory: ${REDIS_MEMORY_LIMIT:-512M} reservations: cpus: ${REDIS_CPU_RESERVATION:-0.1} memory: ${REDIS_MEMORY_RESERVATION:-128M} qdrant: <<: *defaults image: ${GLOBAL_REGISTRY:-}qdrant/qdrant:${QDRANT_VERSION:-v1.17} environment: TZ: ${TZ:-UTC} volumes: - qdrant_data:/qdrant/storage healthcheck: test: [CMD-SHELL, 'wget -qO- http://localhost:6333/health | grep -q ok || exit 1'] interval: 10s timeout: 5s retries: 10 start_period: 15s deploy: resources: limits: cpus: ${QDRANT_CPU_LIMIT:-1.0} memory: ${QDRANT_MEMORY_LIMIT:-1G} reservations: cpus: ${QDRANT_CPU_RESERVATION:-0.25} memory: ${QDRANT_MEMORY_RESERVATION:-256M} temporal: <<: *defaults image: ${GLOBAL_REGISTRY:-}temporalio/auto-setup:${TEMPORAL_VERSION:-1.28.3} environment: TZ: ${TZ:-UTC} DB: postgres12 DB_PORT: ${POSTGRES_PORT:-5432} POSTGRES_USER: ${POSTGRES_USER:-shannon} POSTGRES_PWD: ${POSTGRES_PASSWORD:-shannon} POSTGRES_SEEDS: postgres depends_on: postgres: condition: service_healthy healthcheck: test: [CMD-SHELL, 'temporal operator cluster health --address localhost:7233 | grep -q SERVING || exit 1'] interval: 15s timeout: 10s retries: 10 start_period: 60s deploy: resources: limits: cpus: ${TEMPORAL_CPU_LIMIT:-1.0} memory: ${TEMPORAL_MEMORY_LIMIT:-1G} reservations: cpus: ${TEMPORAL_CPU_RESERVATION:-0.25} memory: ${TEMPORAL_MEMORY_RESERVATION:-256M} temporal-ui: <<: *defaults image: ${GLOBAL_REGISTRY:-}temporalio/ui:${TEMPORAL_UI_VERSION:-2.40.1} environment: TZ: ${TZ:-UTC} TEMPORAL_ADDRESS: temporal:7233 ports: - '${TEMPORAL_UI_PORT_OVERRIDE:-8088}:8080' depends_on: temporal: condition: service_healthy healthcheck: test: [CMD-SHELL, 'wget -qO- http://localhost:8080 > /dev/null || exit 1'] interval: 15s timeout: 5s retries: 5 start_period: 20s profiles: - metrics deploy: resources: limits: cpus: ${TEMPORAL_UI_CPU_LIMIT:-0.5} memory: ${TEMPORAL_UI_MEMORY_LIMIT:-256M} reservations: cpus: ${TEMPORAL_UI_CPU_RESERVATION:-0.1} memory: ${TEMPORAL_UI_MEMORY_RESERVATION:-128M} llm-service: <<: [*defaults, *shannon-config] image: ${GLOBAL_REGISTRY:-}waylandzhang/llm-service:${SHANNON_VERSION:-v0.3.1} environment: TZ: ${TZ:-UTC} # LLM API Keys (at least one is required) OPENAI_API_KEY: ${OPENAI_API_KEY:-} ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-} GOOGLE_API_KEY: ${GOOGLE_API_KEY:-} XAI_API_KEY: ${XAI_API_KEY:-} DEEPSEEK_API_KEY: ${DEEPSEEK_API_KEY:-} # Optional search/tool API keys SERPAPI_API_KEY: ${SERPAPI_API_KEY:-} FIRECRAWL_API_KEY: ${FIRECRAWL_API_KEY:-} # Internal service configuration POSTGRES_HOST: postgres POSTGRES_PORT: ${POSTGRES_PORT:-5432} POSTGRES_USER: ${POSTGRES_USER:-shannon} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-shannon} POSTGRES_DB: ${POSTGRES_DB:-shannon} POSTGRES_SSLMODE: ${POSTGRES_SSLMODE:-disable} REDIS_URL: ${REDIS_URL:-redis://redis:6379} REDIS_ADDR: ${REDIS_ADDR:-redis:6379} QDRANT_HOST: ${QDRANT_HOST:-qdrant} QDRANT_PORT: ${QDRANT_PORT:-6333} AGENT_CORE_ADDR: agent-core:50051 # Config paths LLM_CONFIG_PATH: /app/config MODELS_CONFIG_PATH: ${MODELS_CONFIG_PATH:-/app/config/models.yaml} # Model selection DEFAULT_MODEL_TIER: ${DEFAULT_MODEL_TIER:-small} MAX_TOKENS: ${MAX_TOKENS:-2000} TEMPERATURE: ${TEMPERATURE:-0.7} MAX_TOKENS_PER_REQUEST: ${MAX_TOKENS_PER_REQUEST:-10000} # Telemetry OTEL_ENABLED: ${OTEL_ENABLED:-false} DEBUG: ${DEBUG:-false} ENVIRONMENT: ${ENVIRONMENT:-production} depends_on: postgres: condition: service_healthy redis: condition: service_healthy qdrant: condition: service_healthy agent-core: condition: service_started healthcheck: test: [CMD-SHELL, 'wget -qO- http://localhost:8001/health > /dev/null || exit 1'] interval: 15s timeout: 5s retries: 10 start_period: 30s deploy: resources: limits: cpus: ${LLM_SERVICE_CPU_LIMIT:-2.0} memory: ${LLM_SERVICE_MEMORY_LIMIT:-2G} reservations: cpus: ${LLM_SERVICE_CPU_RESERVATION:-0.5} memory: ${LLM_SERVICE_MEMORY_RESERVATION:-512M} agent-core: <<: [*defaults, *shannon-config] # Note: agent-core is only built for linux/amd64. # On Apple Silicon (ARM64), Docker Desktop uses Rosetta emulation automatically. image: ${GLOBAL_REGISTRY:-}waylandzhang/agent-core:${SHANNON_VERSION:-v0.3.1} platform: linux/amd64 environment: TZ: ${TZ:-UTC} RUST_LOG: ${RUST_LOG:-info} CONFIG_PATH: /app/config/features.yaml WASI_MEMORY_LIMIT_MB: ${WASI_MEMORY_LIMIT_MB:-512} WASI_TIMEOUT_SECONDS: ${WASI_TIMEOUT_SECONDS:-60} SHANNON_USE_WASI_SANDBOX: ${SHANNON_USE_WASI_SANDBOX:-1} ENFORCE_TIMEOUT_SECONDS: ${ENFORCE_TIMEOUT_SECONDS:-300} ENFORCE_MAX_TOKENS: ${ENFORCE_MAX_TOKENS:-32768} OTEL_ENABLED: ${OTEL_ENABLED:-false} volumes: - ./config:/app/config:ro - shannon_sessions:/app/sessions healthcheck: test: [CMD-SHELL, 'pgrep -x shannon-agent-core > /dev/null || exit 1'] interval: 15s timeout: 5s retries: 5 start_period: 20s deploy: resources: limits: cpus: ${AGENT_CORE_CPU_LIMIT:-2.0} memory: ${AGENT_CORE_MEMORY_LIMIT:-2G} reservations: cpus: ${AGENT_CORE_CPU_RESERVATION:-0.5} memory: ${AGENT_CORE_MEMORY_RESERVATION:-512M} orchestrator: <<: [*defaults, *shannon-config] image: ${GLOBAL_REGISTRY:-}waylandzhang/orchestrator:${SHANNON_VERSION:-v0.3.1} environment: TZ: ${TZ:-UTC} # Temporal workflow engine TEMPORAL_HOST_PORT: temporal:7233 TEMPORAL_NAMESPACE: ${TEMPORAL_NAMESPACE:-default} # Internal service URLs LLM_SERVICE_URL: ${LLM_SERVICE_URL:-http://llm-service:8001} QDRANT_HOST: ${QDRANT_HOST:-qdrant} QDRANT_PORT: ${QDRANT_PORT:-6333} # Database and cache POSTGRES_HOST: postgres POSTGRES_PORT: ${POSTGRES_PORT:-5432} POSTGRES_USER: ${POSTGRES_USER:-shannon} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-shannon} POSTGRES_DB: ${POSTGRES_DB:-shannon} POSTGRES_SSLMODE: ${POSTGRES_SSLMODE:-disable} REDIS_ADDR: ${REDIS_ADDR:-redis:6379} REDIS_URL: ${REDIS_URL:-redis://redis:6379} REDIS_TTL_SECONDS: ${REDIS_TTL_SECONDS:-3600} # Worker pool sizing WORKER_ACT_CRITICAL: ${WORKER_ACT_CRITICAL:-12} WORKER_WF_CRITICAL: ${WORKER_WF_CRITICAL:-12} WORKER_ACT_HIGH: ${WORKER_ACT_HIGH:-10} WORKER_WF_HIGH: ${WORKER_WF_HIGH:-10} WORKER_ACT_NORMAL: ${WORKER_ACT_NORMAL:-8} WORKER_WF_NORMAL: ${WORKER_WF_NORMAL:-8} WORKER_ACT_LOW: ${WORKER_ACT_LOW:-4} WORKER_WF_LOW: ${WORKER_WF_LOW:-4} # Workflow settings WORKFLOW_SYNTH_BYPASS_SINGLE: ${WORKFLOW_SYNTH_BYPASS_SINGLE:-true} PROVIDER_RATE_CONTROL_ENABLED: ${PROVIDER_RATE_CONTROL_ENABLED:-false} # Security JWT_SECRET: ${JWT_SECRET:-development-only-secret-change-in-production} # Telemetry OTEL_ENABLED: ${OTEL_ENABLED:-false} DEBUG: ${DEBUG:-false} ENVIRONMENT: ${ENVIRONMENT:-production} depends_on: temporal: condition: service_healthy redis: condition: service_healthy postgres: condition: service_healthy llm-service: condition: service_healthy agent-core: condition: service_started healthcheck: test: [CMD-SHELL, 'wget -qO- http://localhost:8081/health > /dev/null || exit 1'] interval: 15s timeout: 5s retries: 10 start_period: 60s deploy: resources: limits: cpus: ${ORCHESTRATOR_CPU_LIMIT:-2.0} memory: ${ORCHESTRATOR_MEMORY_LIMIT:-2G} reservations: cpus: ${ORCHESTRATOR_CPU_RESERVATION:-0.5} memory: ${ORCHESTRATOR_MEMORY_RESERVATION:-512M} gateway: <<: [*defaults, *shannon-config] image: ${GLOBAL_REGISTRY:-}waylandzhang/gateway:${SHANNON_VERSION:-v0.3.1} environment: TZ: ${TZ:-UTC} PORT: ${GATEWAY_PORT:-8080} ORCHESTRATOR_GRPC: ${ORCHESTRATOR_GRPC:-orchestrator:50052} ADMIN_SERVER: ${ADMIN_SERVER:-http://orchestrator:8081} # Database and cache POSTGRES_HOST: postgres POSTGRES_PORT: ${POSTGRES_PORT:-5432} POSTGRES_USER: ${POSTGRES_USER:-shannon} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-shannon} POSTGRES_DB: ${POSTGRES_DB:-shannon} POSTGRES_SSLMODE: ${POSTGRES_SSLMODE:-disable} REDIS_URL: ${REDIS_URL:-redis://redis:6379} # Security JWT_SECRET: ${JWT_SECRET:-development-only-secret-change-in-production} # Set GATEWAY_SKIP_AUTH=0 to enable authentication in production GATEWAY_SKIP_AUTH: ${GATEWAY_SKIP_AUTH:-1} ports: - '${GATEWAY_PORT_OVERRIDE:-8080}:8080' depends_on: orchestrator: condition: service_healthy redis: condition: service_healthy postgres: condition: service_healthy healthcheck: test: [CMD-SHELL, 'wget -qO- http://localhost:8080/health > /dev/null || exit 1'] interval: 15s timeout: 5s retries: 10 start_period: 30s deploy: resources: limits: cpus: ${GATEWAY_CPU_LIMIT:-1.0} memory: ${GATEWAY_MEMORY_LIMIT:-512M} reservations: cpus: ${GATEWAY_CPU_RESERVATION:-0.25} memory: ${GATEWAY_MEMORY_RESERVATION:-256M} volumes: postgres_data: redis_data: qdrant_data: shannon_sessions: