Configuration
Talon uses a single YAML file (talond.yaml by default). All fields are optional — sensible defaults apply when omitted. Credentials use ${ENV_VAR} substitution.
Pass a custom config path with --config:
node dist/index.js --config /etc/talon/talond.yamlEnvironment variable substitution
Section titled “Environment variable substitution”Any config value can reference an environment variable:
channels: - name: my-telegram type: telegram config: botToken: ${TELEGRAM_BOT_TOKEN}Variables are loaded from .env at startup. Use talonctl env-check to audit for missing variables.
storage
Section titled “storage”SQLite database location.
storage: type: sqlite path: data/talond.sqlite| Field | Default | Description |
|---|---|---|
type | sqlite | Database backend. Only sqlite is supported. |
path | data/talond.sqlite | Path to the SQLite file. Created on first run. |
personas
Section titled “personas”An array of agent personas. Each persona has its own system prompt, model, skills, and capability policy.
personas: - name: assistant model: claude-sonnet-4-6 systemPromptFile: personas/assistant/system.md skills: - web-search subagents: - session-summarizer - memory-groomer - memory-retriever capabilities: allow: - channel.send:my-telegram - memory.access:* - net.http - schedule.manage:own - subagent.invoke:* requireApproval: - db.query maxConcurrent: 2| Field | Default | Description |
|---|---|---|
name | required | Unique identifier for this persona |
model | claude-sonnet-4-6 | Model ID passed to the provider |
provider | (default provider) | Override the agent runner provider for this persona |
systemPromptFile | — | Path to the system prompt Markdown file |
skills | [] | List of skill names to attach |
subagents | [] | List of sub-agent names the persona can invoke |
capabilities.allow | [] | Capability labels the persona can use freely |
capabilities.requireApproval | [] | Capability labels that require user confirmation |
maxConcurrent | — | Max parallel agent runs for this persona |
See Personas guide and capability labels for the full list.
Tool instruction files
Section titled “Tool instruction files”Each capability can have a companion Markdown file in templates/tool-instructions/ that provides behavioral guidance to the agent. Files are named after the capability prefix — for example templates/tool-instructions/net.http.md. Only instruction files for capabilities the persona is allowed to use are included in the prompt.
Edit or add files in this directory to customise how the agent behaves when using a specific tool. See Tool instructions for the full details.
channels
Section titled “channels”Channel connectors. Each entry has a type, a name, and a connector-specific config block.
channels: - name: my-telegram type: telegram enabled: true showToolCalls: true config: botToken: ${TELEGRAM_BOT_TOKEN} allowedChatIds: - 123456789| Field | Default | Description |
|---|---|---|
name | required | Unique identifier for this channel |
type | required | telegram, slack, discord, whatsappBaileys, email, terminal |
enabled | true | Enable or disable this channel at startup |
showToolCalls | false | Send a status message to the channel on each tool call |
config | {} | Connector-specific configuration (varies by type) |
See the Channels guide for per-connector config fields.
bindings
Section titled “bindings”Route channels to personas.
bindings: - persona: assistant channel: my-telegram isDefault: true - persona: researcher channel: my-slack isDefault: true| Field | Default | Description |
|---|---|---|
persona | required | Persona name |
channel | required | Channel name |
isDefault | false | Mark as the default binding for this channel |
Controls the durable message queue.
queue: maxAttempts: 3 backoffBaseMs: 1000 backoffMaxMs: 60000 concurrencyLimit: 5| Field | Default | Description |
|---|---|---|
maxAttempts | 3 | Max delivery attempts before dead-lettering |
backoffBaseMs | 1000 | Initial retry delay in ms |
backoffMaxMs | 60000 | Max retry delay in ms (exponential backoff cap) |
concurrencyLimit | 5 | Max messages processed simultaneously |
agentRunner
Section titled “agentRunner”Foreground agent execution. Configures which provider runs the main conversation agent and how context rotation works.
agentRunner: defaultProvider: claude-code providers: claude-code: enabled: true command: claude contextWindowTokens: 200000 contextManagement: enabled: true triggerMetric: cache_read_input_tokens thresholdRatio: 0.5 recentMessageCount: 10 summarizer: session-summarizer codex-cli: enabled: false command: codex contextWindowTokens: 400000 contextManagement: enabled: true triggerMetric: cache_read_input_tokens thresholdRatio: 0.8 recentMessageCount: 10 summarizer: session-summarizer options: defaultModel: gpt-5.4 openai-compatible: enabled: false command: node contextWindowTokens: 256000 contextManagement: enabled: true triggerMetric: input_tokens thresholdRatio: 0.75 recentMessageCount: 10 summarizer: session-summarizer options: baseUrl: ${OLLAMA_BASE_URL} defaultModel: glm-5.1 providerId: ollama gemini-cli: enabled: false command: gemini contextWindowTokens: 1000000| Field | Default | Description |
|---|---|---|
defaultProvider | claude-code | Provider to use when none is specified per-persona |
providers.<name>.enabled | true | Enable this provider |
providers.<name>.command | claude | CLI command to invoke |
providers.<name>.contextWindowTokens | 200000 | Context window size for rotation calculations |
providers.<name>.options | {} | Provider-specific options (e.g. defaultModel: gpt-5.4 for codex-cli) |
contextManagement.enabled | true | Enable automatic session rotation |
contextManagement.triggerMetric | cache_read_input_tokens | Token metric to monitor |
contextManagement.thresholdRatio | 0.5 | Fraction of contextWindowTokens that triggers rotation |
contextManagement.recentMessageCount | 10 | Verbatim messages to include after rotation |
contextManagement.summarizer | session-summarizer | Sub-agent used to compress history |
Multiple providers
Section titled “Multiple providers”Talon supports multiple agent providers. Configure them under agentRunner.providers:
agentRunner: defaultProvider: claude-code providers: claude-code: enabled: true command: claude contextWindowTokens: 200000 contextManagement: enabled: true triggerMetric: cache_read_input_tokens thresholdRatio: 0.5 recentMessageCount: 10 summarizer: session-summarizer codex-cli: enabled: false command: codex contextWindowTokens: 400000 contextManagement: enabled: true triggerMetric: cache_read_input_tokens thresholdRatio: 0.8 recentMessageCount: 10 summarizer: session-summarizer options: defaultModel: gpt-5.4 gemini-cli: enabled: false command: gemini contextWindowTokens: 1000000Available providers:
- claude-code — Claude Code CLI (default). SDK strategy, resumable sessions, context management.
- gemini-cli — Google Gemini CLI. CLI strategy, 1M token context. No session resumption.
- codex-cli — OpenAI Codex CLI. SDK-style foreground streaming, 400k context, resumable sessions. Set model via
options.defaultModel. - openai-compatible — Experimental wrapper-backed provider for Ollama and other OpenAI-compatible endpoints. Set endpoint and auth mapping via
options.baseUrl,options.defaultModel, andoptions.providerId.
Set a per-persona provider override with the provider field:
personas: - name: researcher model: gemini-2.0-flash provider: gemini-cliSee the Providers guide for full configuration details and per-persona provider routing.
backgroundAgent
Section titled “backgroundAgent”Long-running Claude Code workers for deep tasks.
backgroundAgent: enabled: true maxConcurrent: 3 defaultTimeoutMinutes: 30 defaultProvider: claude-code providers: claude-code: enabled: true command: claude contextWindowTokens: 200000 codex-cli: enabled: false command: codex contextWindowTokens: 400000 options: defaultModel: gpt-5.4 openai-compatible: enabled: false command: node contextWindowTokens: 256000 options: baseUrl: ${OLLAMA_BASE_URL} defaultModel: glm-5.1 providerId: ollama| Field | Default | Description |
|---|---|---|
enabled | true | Globally enable background workers |
maxConcurrent | 3 | Max simultaneous background workers |
defaultTimeoutMinutes | 30 | Wall-clock timeout per worker (15–480 min) |
defaultProvider | claude-code | Provider for background workers |
claudePath | — | Explicit path to the Claude Code binary |
providers.<name>.options | {} | Provider-specific options (for example defaultModel: gpt-5.4 for codex-cli, or baseUrl / providerId for openai-compatible) |
AI provider credentials.
auth: mode: subscription providers: anthropic: apiKey: ${SUBAGENT_ANTHROPIC_API_KEY} openai: apiKey: ${OPENAI_API_KEY} ollama: apiKey: ${OLLAMA_API_KEY} baseURL: http://localhost:11434/v1 openai-compatible: apiKey: ${OPENAI_COMPATIBLE_API_KEY} baseURL: https://example.com/v1| Field | Default | Description |
|---|---|---|
mode | subscription | subscription (Claude Code login) or api_key |
apiKey | — | API key for api_key mode |
providers.<name>.apiKey | — | API key for a specific provider |
providers.<name>.baseURL | — | Custom base URL (for Ollama or proxies) |
For openai-compatible, Talon looks up credentials under auth.providers.<options.providerId> first. If that slot does not exist, it falls back to auth.providers.openai-compatible.
scheduler
Section titled “scheduler”Controls how often the scheduler checks for due tasks.
scheduler: tickIntervalMs: 5000| Field | Default | Description |
|---|---|---|
tickIntervalMs | 5000 | Scheduler tick interval in ms (minimum 1000) |
langfuse
Section titled “langfuse”Observability tracing. Disabled by default.
langfuse: enabled: true publicKey: ${LANGFUSE_PUBLIC_KEY} secretKey: ${LANGFUSE_SECRET_KEY} baseUrl: https://cloud.langfuse.com environment: production exportMode: batched flushAt: 20 flushIntervalSeconds: 5| Field | Default | Description |
|---|---|---|
enabled | false | Enable Langfuse tracing |
publicKey | — | Required when enabled |
secretKey | — | Required when enabled |
baseUrl | https://cloud.langfuse.com | Langfuse instance URL |
environment | production | Environment tag on traces |
exportMode | batched | batched or immediate |
flushAt | 20 | Batch size before flush |
flushIntervalSeconds | 5 | Max seconds between flushes |
governance
Section titled “governance”Runtime guardrails for autonomous agents — spending caps, rate limiting, and loop detection. All sub-sections are optional. Omit the entire block to disable governance.
governance: spending: daily_token_cap: 5000000 hourly_token_cap: 1000000 warn_at_percent: 80 per_persona: researcher: daily_token_cap: 2000000 rate_limits: inbound_per_minute: 30 inbound_per_user_per_minute: 10 api_calls_per_minute: 60 loop_detection: max_turns_per_run: 50 duplicate_call_threshold: 5 max_queue_depth_per_thread: 100| Field | Default | Description |
|---|---|---|
spending.daily_token_cap | — | Max tokens per persona per 24h rolling window |
spending.hourly_token_cap | — | Max tokens per persona per 1h rolling window |
spending.warn_at_percent | 80 | Log a warning when usage exceeds this percentage |
spending.per_persona.<name> | — | Per-persona cap overrides (daily and/or hourly) |
rate_limits.inbound_per_minute | 30 | Max inbound messages per channel per minute |
rate_limits.inbound_per_user_per_minute | 10 | Max inbound messages per sender per minute |
rate_limits.api_calls_per_minute | 60 | Reserved for future API rate limiting |
loop_detection.max_turns_per_run | 50 | Hard turn limit per agent run |
loop_detection.duplicate_call_threshold | 5 | Consecutive identical tool calls before blocking |
loop_detection.max_queue_depth_per_thread | 100 | Max queued messages per thread before rejecting |
See the Config schema reference for the current field reference.
Internal daemon-to-CLI communication. Rarely needs changing.
ipc: pollIntervalMs: 500 daemonSocketDir: data/ipc/daemonlogLevel and dataDir
Section titled “logLevel and dataDir”logLevel: info # trace | debug | info | warn | error | fataldataDir: data # root directory for all runtime data