All Choir static resource configuration lives in ~/.choir.d/config.json. Secret values live in ~/.choir.d/secrets.json. Runtime state (sessions, events, memory) lives in Postgres.

Secret Management Pattern

Secret values are never stored in config.json. Every resource that needs a secret contains a "secret" field referencing a named secret in ~/.choir.d/secrets.json (authoritative source for v1). choirctl secret set|delete updates that file.

# Set a secret
echo 'sk-...' | choirctl secret set openrouter-key

# List secret names (never values)
choirctl secret list

# Push the current secrets.json snapshot to choird + running agents
choirctl secret apply

choirctl config apply does not reload secret values; secrets are refreshed only via choirctl secret apply.

Two-Phase Load/Apply

Configuration changes follow a two-phase workflow:

  1. Edit config.json on disk.
  2. choirctl config load – read and validate the file, stage in choird.
  3. choirctl config diff – review staged vs running changes (categorized as hot-reloadable or restart-required).
  4. choirctl config apply – push hot-reloadable changes to running agents.
  5. For restart-required changes, use choirctl agent update <agent-id> or choirctl agent update-all.

Full config.json Reference

global_repo

URL and ref for the shared tools/skills/identity git repository.

"global_repo": {
  "url": "git@github.com:org/choir-global.git",
  "ref": "main"
}
Field Type Description
url string Git clone URL (SSH or HTTPS)
ref string Branch or tag to track

Host-side choird git operations for global_repo and agent image builds inherit the host’s normal git behavior directly (~/.gitconfig, credential helpers, ssh-agent, ~/.ssh/config).

workspaces

Named workspace definitions with explicit host paths. Workspaces are exclusive resources – only one agent may lease a workspace at a time.

"workspaces": {
  "main-ws": { "path": "/var/lib/choir/workspaces/main" },
  "scratch": { "path": "/var/lib/choir/workspaces/scratch" }
}
Field Type Description
path string Absolute host filesystem path

models

Named LLM model/provider pairs. Models are shared resources. Must support OpenAI-compatible tool calling.

"models": {
  "sonnet": {
    "provider": "openrouter",
    "model": "anthropic/claude-sonnet-4-20250514",
    "endpoint": "https://openrouter.ai/api/v1",
    "temperature": 0.7,
    "reasoning_effort": null,
    "secret": "openrouter-key"
  }
}
Field Type Description
provider string Provider identifier (e.g. "openrouter")
model string Model identifier for the provider
endpoint string API base URL
temperature number or null Sampling temperature. null for reasoning models (o1, o3)
reasoning_effort string or null "low", "medium", "high" for o-series models. null otherwise
secret string Named secret reference for the API key

tts

Named text-to-speech provider configurations. Shared resources. v1 supports ElevenLabs only.

"tts": {
  "eleven": {
    "provider": "elevenlabs",
    "model_id": "eleven_multilingual_v2",
    "endpoint": "https://api.elevenlabs.io/v1",
    "secret": "elevenlabs-key"
  }
}
Field Type Description
provider string TTS provider ("elevenlabs")
model_id string TTS model identifier
endpoint string API base URL
secret string Named secret reference

voice_profiles

Named voice configurations referencing a TTS provider. Shared resources.

"voice_profiles": {
  "default-en": {
    "tts": "eleven",
    "voice_id": "...",
    "output_format": "opus_48000_128",
    "voice_settings": {
      "stability": 0.5,
      "similarity_boost": 0.75,
      "style": 0.0,
      "use_speaker_boost": true,
      "speed": 1.0
    }
  }
}
Field Type Description
tts string Reference to a named TTS provider
voice_id string Provider-specific voice identifier
output_format string Audio format (opus_48000_128, mp3_44100_128, pcm_16000, etc.)
voice_settings.stability number 0.0-1.0. Lower = more expressive
voice_settings.similarity_boost number 0.0-1.0. Higher = closer to original voice
voice_settings.style number 0.0-1.0. 0 = minimal latency
voice_settings.use_speaker_boost boolean Boost speaker similarity (increases latency)
voice_settings.speed number 0.5-2.0. 1.0 = normal speed

git_identities

Named git identities with name, email, and auth credentials for agents. Exclusive resources – at most one agent may lease a given identity at a time.

"git_identities": {
  "dev-identity": {
    "name": "Dev Agent",
    "email": "dev@choir.local",
    "secret": "git-dev-token",
    "ssh_key": "git-dev-ssh-key",
    "ssh_secret": "git-dev-ssh-secret"
  }
}
Field Type Description
name string Git user.name
email string Git user.email
secret string Named secret reference for HTTPS auth credentials. Supports either username:password or token-only values.
ssh_key string Named secret reference for the SSH private key
ssh_secret string Named secret reference for the SSH shared secret / key passphrase

notion_integrations

Named Notion integrations. Exclusive resources.

"notion_integrations": {
  "personal-wiki": {
    "secret": "notion-personal-key"
  }
}
Field Type Description
secret string Named secret reference for the integration token

email_accounts

Named email accounts with SMTP/IMAP configuration. Exclusive when sharing is "exclusive", shared when "shared".

"email_accounts": {
  "primary-email": {
    "smtp_host": "smtp.example.com",
    "smtp_port": 587,
    "imap_host": "imap.example.com",
    "imap_port": 993,
    "sharing": "exclusive",
    "secret": "email-primary-creds"
  }
}
Field Type Description
smtp_host string SMTP server hostname
smtp_port integer SMTP server port
imap_host string IMAP server hostname
imap_port integer IMAP server port
sharing string "exclusive" or "shared"
secret string Named secret reference

Named search provider configurations. Shared resources.

"search": {
  "brave": {
    "secret": "brave-api-key"
  }
}
Field Type Description
secret string Named secret reference

embedding

Embedding model configuration. Singleton (one per installation). Used by choird for memory vectorization.

"embedding": {
  "provider": "openrouter",
  "model": "text-embedding-3-small",
  "dimensions": 1536,
  "endpoint": "https://openrouter.ai/api/v1",
  "secret": "openrouter-key"
}
Field Type Description
provider string Embedding provider
model string Model identifier
dimensions integer Output vector dimensions (must match model)
endpoint string API base URL
secret string Named secret reference

gateways

Named Telegram bot instances. Each gateway is a bot with its own token.

"gateways": {
  "bot-main": {
    "type": "telegram",
    "secret": "tg-bot-main-token"
  }
}
Field Type Description
type string Gateway type ("telegram")
secret string Named secret reference for the bot token

dms

Named DM bindings. Each DM references a gateway and a Telegram user ID. The set of DMs for a bot implicitly forms that bot’s allowlist – messages from unconfigured user IDs are silently ignored.

"dms": {
  "admin-dm": { "gateway": "bot-main", "user_id": "123456789", "admin": true },
  "user-dm":  { "gateway": "bot-main", "user_id": "987654321", "admin": false }
}
Field Type Description
gateway string Reference to a named gateway
user_id string Telegram user ID
admin boolean true for full choirctl-equivalent access; false for bound-agent-only

postgres

PostgreSQL connection configuration. choird manages per-agent schemas automatically.

"postgres": {
  "host": "localhost",
  "port": 5432,
  "database": "choir",
  "secret": "postgres-admin-creds"
}
Field Type Description
host string Database hostname
port integer Database port
database string Database name
secret string Named secret reference for admin credentials

agents

Named agent definitions. Each agent references a per-agent git repo and a set of default resource bindings.

"agents": {
  "agent-1": {
    "repo": {
      "url": "git@github.com:org/choir-agent-1.git",
      "ref": "main"
    },
    "defaults": {
      "workspace": "main-ws",
      "llm": "sonnet",
      "voice_profile": "default-en",
      "git_identity": "dev-identity",
      "notion": "personal-wiki",
      "email": "primary-email",
      "dm": "admin-dm"
    }
  }
}
Field Type Description
repo.url string Per-agent git repo URL
repo.ref string Branch or tag to track
defaults.workspace string Default workspace name
defaults.llm string Default LLM model name
defaults.voice_profile string Default voice profile name (optional)
defaults.git_identity string Default git identity name
defaults.notion string Default Notion integration name (optional)
defaults.email string Default email account name (optional)
defaults.dm string Default DM binding name

All defaults are overridable at agent start time via flags.

Tunable Defaults

Top-level numeric fields for runtime behavior:

"heartbeat_interval_ms": 5000,
"crash_detection_threshold_ms": 10000,
"rate_limit_retry_ms": 1000,
"log_archive_threshold_lines": 100000
Field Type Default Description
heartbeat_interval_ms integer 5000 Agent heartbeat interval in milliseconds
crash_detection_threshold_ms integer 10000 Time without heartbeat before crash detection. Should be >= 2x heartbeat interval
rate_limit_retry_ms integer 1000 Default retry delay for LLM rate limits when no Retry-After header
log_archive_threshold_lines integer 100000 Line count threshold for choird log archival

Resource Classification

Type Resources Access Mode
Shared Models, TTS, voice profiles, search, email (shared mode) Any number of agents concurrently
Exclusive Workspaces, git identities, Notion, email (exclusive mode), DMs, browser contexts Leased to one agent at a time

Exclusive resources are leased at agent start and released at session end (stop, crash, terminate). If an exclusive resource is already leased, the start is rejected.

For the full design specification, see DESIGN.md.