Skip to main content
MeepaGateway uses a YAML config file. The default location is ~/.meepagateway/config.yaml. Specify a custom path with --config:
meepagateway --config /path/to/config.yaml start
If no config file exists on first run, the gateway enters setup mode.

File format

The config is YAML. Top-level sections:
providers:        # LLM providers and routing
cron:             # Cron scheduler settings
captain:          # Captain Dashboard settings
hooks:            # Inbound webhook configuration
agents:           # List of agent definitions

providers

providers:
  primary: anthropic
  fallback:
    - openai
  health_check_interval: 30s
  providers:
    anthropic:
      api_key_env: ANTHROPIC_API_KEY
      model: claude-opus-4-6
    openai:
      api_key_env: OPENAI_API_KEY
      model: gpt-4o
      base_url: https://api.openai.com/v1  # optional
      max_tokens: 8192                     # optional
FieldTypeRequiredDescription
primarystringyesName of the primary provider. Must match a key under providers.providers.
fallbacklistnoOrdered list of fallback provider names tried when primary is unhealthy.
health_check_intervaldurationyesHow often to poll provider health (e.g. 30s, 5m).
Per-provider fields (under providers.providers.<name>):
FieldTypeRequiredDescription
api_key_envstringyesEnvironment variable holding the API key.
modelstringyesDefault model for this provider.
base_urlstringnoOverride the provider’s API base URL. Useful for proxies or OpenAI-compatible endpoints.
max_tokensintegernoMaximum tokens per response.

captain

captain:
  enabled: true
  bind: 127.0.0.1
  port: 63372
  exposure: local
  password_hash: "$argon2..."      # set via setup wizard
  api_keys: []                     # managed by the gateway, not hand-edited
  webauthn_credentials: []         # managed by the gateway
  public_url: ""                   # for cloudflare_tunnel / reverse_proxy modes
  cloudflare_token: ""             # for cloudflare_tunnel mode
FieldTypeDefaultDescription
enabledbooltrueEnable the Captain Dashboard.
bindstring127.0.0.1IP address to bind the dashboard listener.
portinteger63372Port for the dashboard.
exposurestringlocalHow the dashboard is exposed. See below.
password_hashstringArgon2-hashed password. Set via setup wizard, not by hand.
public_urlstringPublic URL (for cloudflare_tunnel or reverse_proxy exposure).
cloudflare_tokenstringCloudflare tunnel token (for cloudflare_tunnel exposure).
Exposure modes:
ValueBehavior
localBind 127.0.0.1 — localhost only (default)
lanBind 0.0.0.0 — local network
tailscale_privateBind 127.0.0.1, tailscale serve proxies
cloudflare_tunnelBind 127.0.0.1, Cloudflare tunnel routes to captain port
tailscale_funnelBind 0.0.0.0, Tailscale Funnel
reverse_proxyBind 0.0.0.0, user-managed reverse proxy

cron

cron:
  enabled: true
  max_concurrent_runs: 3
FieldTypeDefaultDescription
enabledbooltrueEnable the cron subsystem.
max_concurrent_runsinteger3Maximum concurrent cron jobs across all agents.
Cron jobs are defined per-agent under agents[].cron_jobs. See Cron.

agents

Each item in the agents list defines one agent. All configuration fields are set directly on the agent.
agents:
  - id: meepa
    name: Meepa
    default: true
    provider: null
    model: null
    max_iterations: 10
    max_tool_failures: 3
    image_config:
      enabled: false
      base_image: ghcr.io/bogpad/meepagateway-sandbox:latest
      packages: []
      env_vars: {}
      inject_credentials_env: true
      inject_secrets_env: true
      redact_secrets: true
    tools: null
    file_access:
      unrestricted: true
      allow_read: []
      allow_read_write: []
      deny: []
      allow_home_dotfiles: false
      allow_network: true
    container_mode:
      enabled: true
      image: ''
      memory_limit: 512m
      timeout_seconds: 300
      network: bridge
    connectors:
      - name: meepachat
        type: meepachat
        webhook: false
        bot_token: ${sops:meepachat.bot_token}
        url: https://chat.meepachat.ai
    cron_jobs: []
FieldTypeRequiredDescription
idstringyesUnique identifier. Used in API paths and logs.
namestringyesDisplay name.
defaultboolnoMark as the default agent. Exactly one agent must be default.
providerstringnoLLM provider to use. Defaults to providers.primary.
modelstringnoModel override for this agent.
max_iterationsintegernoMaximum agent loop iterations per message. Default: 10.
max_tool_failuresintegernoMaximum consecutive failures before the agent is nudged. Default: 3.
Agent workspace is auto-derived from the ID: ~/.meepagateway/agents/{id}/. Files in the workspace (SOUL.md, MEMORY.md, USER.md, memory.db, skills/, .mcp.json) are not configured here.

file_access

Controls which paths the file tools can read or write.
file_access:
  unrestricted: true        # if true, all other fields are ignored
  allow_read: []            # paths allowed for read-only access
  allow_read_write: []      # paths allowed for read+write access
  deny: []                  # paths explicitly denied
  allow_home_dotfiles: false
  allow_network: true
FieldTypeDefaultDescription
unrestrictedbooltrueAllow access to all paths. When true, other fields are ignored.
allow_readlist[]Paths the agent may read.
allow_read_writelist[]Paths the agent may read and write.
denylist[]Paths explicitly blocked. Takes precedence over allow lists.
allow_home_dotfilesboolfalseAllow reading dotfiles in the home directory.
allow_networkbooltrueAllow network access from tools.

image_config

Configuration for the sandbox image used in container mode.
image_config:
  enabled: false
  base_image: ghcr.io/bogpad/meepagateway-sandbox:latest
  packages: []
  env_vars: {}
  inject_credentials_env: true
  inject_secrets_env: true
  redact_secrets: true
FieldTypeDefaultDescription
enabledboolfalseEnable image-based sandboxing.
base_imagestringOCI image to use as the sandbox base.
packageslist[]Extra packages to install in the image.
env_varsmap{}Environment variables to inject into the container.
inject_credentials_envbooltrueInject provider credential env vars.
inject_secrets_envbooltrueInject SOPS-managed secrets as env vars.
redact_secretsbooltrueRedact secret values from logs.

container_mode

Runtime settings for the container execution environment.
container_mode:
  enabled: true
  image: ''
  memory_limit: 512m
  timeout_seconds: 300
  network: bridge
FieldTypeDefaultDescription
enabledboolfalseRun agent tools inside a container.
imagestring''Override the container image (empty uses image_config.base_image).
memory_limitstring512mMemory limit for the container.
timeout_secondsinteger300Maximum seconds a container run may take.
networkstringbridgeDocker network mode.
See Isolation for full details.

Connectors

Connectors are flat objects — all fields are directly on the connector, not nested under a type key.
connectors:
  - name: meepachat
    type: meepachat
    webhook: false
    bot_token: BOT_ID.SECRET
    url: https://chat.example.com

  - name: discord-bot
    type: discord
    webhook: false
    bot_token: "Bot.Token..."
    guild_ids: []               # optional: restrict to specific guilds

  - name: telegram-bot
    type: telegram
    webhook: false
    bot_token: "1234567890:AAF..."
    poll_interval: 1s           # polling interval (or use webhook_url)
    webhook_url: ""             # optional: use webhook instead of polling
    webhook_port: null          # local port for webhook listener

  - name: slack-bot
    type: slack
    webhook: false
    bot_token: "xoxb-..."       # bot OAuth token
    app_token: "xapp-..."       # app-level token for Socket Mode

  - name: whatsapp-bot
    type: whatsapp
    webhook: false
    access_token: "..."         # WhatsApp Cloud API access token
    phone_number_id: "..."      # phone number ID from Meta dashboard
    verify_token: "..."         # webhook verification token
    webhook_port: 8444          # local port for webhook listener
Set webhook: true on any connector to use the centralized webhook system instead of per-connector polling or WebSocket.

Cron jobs

cron_jobs:
  - name: daily-digest
    enabled: true
    message: "Post the daily digest to the team channel"
    schedule:
      every: 24h          # interval schedule

  - name: weekday-standup
    enabled: true
    message: "Run the standup summary"
    schedule:
      cron: "0 0 9 * * 1-5 *"  # 7-field cron expression

  - name: one-time-reminder
    enabled: true
    message: "Send the project deadline reminder"
    schedule:
      at: "2026-12-31T09:00:00Z"  # one-shot

Tool filtering

tools:
  allow:
    - shell
    - read_file
    - write_file
  # deny:
  #   - shell
allow is an allowlist — only listed tools are available. deny removes specific tools. The two are mutually exclusive.

MCP servers

MCP servers are not configured in the main config file. Each agent has a .mcp.json file at ~/.meepagateway/agents/{id}/.mcp.json:
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
    },
    "remote-server": {
      "url": "http://localhost:9000/mcp"
    }
  }
}
Edit with: meepagateway agent mcp <id>

Environment variables

VariableDescription
ANTHROPIC_API_KEYAPI key for the Anthropic provider
OPENAI_API_KEYAPI key for the OpenAI provider
MEEPA_URLDefault gateway URL for CLI management commands
MEEPA_API_KEYAPI key for CLI authentication
RUST_LOGLog level (e.g. info, debug, meepa_gateway=debug)
Never put secrets directly in the config file. Reference them via api_key_env pointing to an environment variable.

Complete example

providers:
  primary: anthropic
  fallback:
    - openai
  health_check_interval: 30s
  providers:
    anthropic:
      api_key_env: ANTHROPIC_API_KEY
      model: claude-opus-4-6
    openai:
      api_key_env: OPENAI_API_KEY
      model: gpt-4o

cron:
  enabled: true
  max_concurrent_runs: 3

captain:
  enabled: true
  bind: 127.0.0.1
  port: 63372

agents:
  - id: meepa
    name: Meepa
    default: true
    max_iterations: 10
    max_tool_failures: 3
    file_access:
      unrestricted: true
      allow_network: true
    container_mode:
      enabled: false
    connectors:
      - name: meepachat
        type: meepachat
        webhook: false
        bot_token: ${sops:meepachat.bot_token}
        url: https://chat.example.com

  - id: coder
    name: Code Helper
    model: claude-opus-4-6
    max_iterations: 20
    file_access:
      unrestricted: false
      allow_read_write:
        - /home/user/projects
    tools:
      allow:
        - shell
        - read_file
        - write_file
    connectors:
      - name: discord-bot
        type: discord
        webhook: false
        bot_token: "Bot.Token..."
    cron_jobs:
      - name: daily-summary
        enabled: true
        message: "Summarize today's code changes"
        schedule:
          every: 24h