Skip to content

Configuration

Every knob Chorus reads from the environment, enumerated from process.env in the source — not from .env.example (which is partial and omits ~30 of these; lens-config-ops Finding 11). Where a “nice” default contradicts the code, this page follows the code.

Var Default Purpose
SURREAL_ENDPOINT ws://localhost:8000 SurrealDB WebSocket URL; interactive transactions require ws/wss (index.ts:36)
SURREAL_NS chorus namespace (index.ts:37)
SURREAL_DB protocol database (index.ts:38)
SURREAL_USER root DB root username (index.ts:39)
SURREAL_PASS required explicit 16–1024 byte DB password; known placeholder values are rejected before connection
CHORUS_MIGRATION_069_QUIESCENCE_ACK — one-start, non-secret exact acknowledgement for an existing schema below 069; set only after every old DB writer is stopped, then remove after 069 commits
CHORUS_MIGRATION_075_QUIESCENCE_ACK — one-start exact acknowledgement for migration 075; set only after every old DB writer is stopped, then remove and restart after 075 commits
PORT 3000 HTTP listen port (index.ts:42)
CHORUS_SHUTDOWN_TIMEOUT_MS 30000 one total first-signal drain/close deadline in milliseconds (50–300,000); expiry forces bounded abort, terminal diagnostics, and a nonzero hard exit
CHORUS_FORCE_ABORT_TIMEOUT_MS 1000 bounded best-effort abort window after a deadline or second signal (10–10,000 ms)
CHORUS_MAX_CONCURRENT_REQUESTS 16 process-wide accepted-request cap (1–1,000); excess non-liveness work fails before application or database dispatch
CHORUS_REQUEST_TIMEOUT_MS 120000 request execution deadline in milliseconds (10–600,000); timed-out work keeps its capacity slot until settlement
CHORUS_REQUEST_CIRCUIT_FAILURE_THRESHOLD 3 consecutive request timeouts (1–100) before the request circuit opens; completed application 5xx responses reset this counter
CHORUS_REQUEST_CIRCUIT_OPEN_MS 10000 open-circuit cooldown in milliseconds (10–300,000) before one half-open recovery probe
CHORUS_STOP_GRACE_PERIOD 45s Compose-only whole-second container grace; deployment preflight requires it to be strictly greater than the graceful plus force-abort budgets
CHORUS_BOOTSTRAP — required bootstrap YAML when set; zero-config is skipped and any load or execution failure aborts startup
CHORUS_URL — self URL used by the zero-config banner
SIWE_PUBLIC_URL required trusted origin used to build EIP-4361 domain, URI, and scheme; HTTPS is required except loopback HTTP
SIWE_ALLOWED_CHAIN_IDS required comma-separated unique positive EIP-155 chain IDs; empty or duplicate entries abort startup
SIWE_RPC_URL_<chainId> required per allowed chain explicit HTTPS verification transport; loopback HTTP is accepted for development only when its exact origin/CIDR is also in CHORUS_OUTBOUND_PRIVATE_ALLOWLIST; credentials, query, fragment, controls, backslashes, and surrounding whitespace are rejected
CHORUS_OUTBOUND_MAX_URL_BYTES 2048 maximum UTF-8 URL length (256–16,384)
CHORUS_OUTBOUND_MAX_REQUEST_BYTES 1048576 process-wide outbound request-body cap (1 KiB–16 MiB)
CHORUS_OUTBOUND_MAX_RESPONSE_BYTES 1048576 process-wide buffered response cap (1 KiB–16 MiB); callers may only tighten it
CHORUS_OUTBOUND_TIMEOUT_MS 10000 one deadline covering DNS, connection, TLS, headers, and body (100–60,000 ms)
CHORUS_OUTBOUND_MAX_CONCURRENCY 32 shared in-flight budget across safe outbound consumers (1–256)
CHORUS_OUTBOUND_MAX_DNS_ADDRESSES 32 maximum complete A/AAAA answer set; excess fails closed rather than truncating (1–128)
CHORUS_OUTBOUND_MAX_HEADER_BYTES 16384 request and response header budget (1 KiB–64 KiB)
CHORUS_OUTBOUND_PRIVATE_ALLOWLIST [] JSON array of {origin,cidrs} exceptions for exact operator-controlled origins and private CIDRs
CHORUS_RATE_LIMIT_HMAC_KEY_FILE required readable file containing 32–4096 opaque bytes after trailing CR/LF removal; read once at startup and identical across replicas/restarts
CHORUS_APPROVAL_EXECUTION_SIGNING_KEY_FILE required readable file containing exactly one unencrypted Ed25519 PKCS8 PEM private key used to sign approval-execution attestations; Compose mounts an owner-only host file at a fixed secret path
CHORUS_TRUSTED_PROXY_CIDRS [] JSON string array of at most 64 explicit proxy CIDRs; forwarding headers are ignored outside these networks
CHORUS_MAX_FORWARDED_HOPS 16 maximum trusted forwarding hops (1–64)
CHORUS_MAX_FORWARDED_HEADER_BYTES 4096 combined X-Forwarded-For / X-Real-IP bytes (128–32,768)
CHORUS_RATE_LIMIT_SUBJECT_SLOTS 4096 fixed HMAC slots per internal authority scope (64–1,048,576)
CHORUS_RATE_LIMIT_GLOBAL_PER_MINUTE 20000 server-wide source-rotation budget (100–10,000,000)
CHORUS_RATE_LIMIT_PUBLIC_IP_PER_MINUTE 30 public-route client-IP budget (1–1,000,000)
CHORUS_RATE_LIMIT_AUTHENTICATED_IP_PER_MINUTE 300 protected-route client-IP budget (1–1,000,000)
CHORUS_RATE_LIMIT_AUTHENTICATED_AUTHORITY_PER_MINUTE 100 independent API-key and identity budget; administrators receive 10x unless the API key has an explicit override (1–1,000,000)
CHORUS_RATE_LIMIT_FEDERATION_PEER_PER_MINUTE 100 independent post-proof peer budget (1–1,000,000)
CHORUS_MAX_BODY_BYTES 1048576 aggregate streamed body cap for ordinary Hono routes (1 KiB–16 MiB)
CHORUS_MAX_UPLOAD_BODY_BYTES 67108864 multipart artifact/workspace envelope cap (1 KiB–256 MiB)
CHORUS_RPC_MAX_BATCH_ITEMS 32 JSON-RPC batch item cap (1–256)
CHORUS_RPC_MAX_JSON_DEPTH 32 whole-payload nesting cap (4–128)
CHORUS_RPC_MAX_NOTIFICATIONS 8 read-only notifications per payload (0–64); mutating notifications are rejected
CHORUS_RPC_MAX_COST 100 aggregate conservative method/parameter cost (1–10,000)
CHORUS_RPC_MAX_RESPONSE_BYTES 1048576 projected and actual serialized response cap (4 KiB–16 MiB)
EMBEDDED_MCP_ENABLED false set to exactly true to mount stateless, live-bearer-authenticated /mcp
EMBEDDED_MCP_ALLOWED_HOSTS loopback authorities for PORT comma-separated exact host[:port] authorities; schemes, paths, credentials, and wildcards are invalid
EMBEDDED_MCP_ALLOWED_ORIGINS loopback HTTP origins for PORT comma-separated exact browser origins, including scheme and port
EMBEDDED_MCP_MAX_BODY_BYTES 1048576 streamed JSON request limit (1 KiB–16 MiB)
EMBEDDED_MCP_GLOBAL_RATE_LIMIT 600 process-local global requests per minute
EMBEDDED_MCP_RATE_LIMIT 100 process-local requests per API key per minute
EMBEDDED_MCP_MAX_RATE_LIMIT_KEYS 4096 maximum live per-key limiter buckets; overflow shares a fail-closed bucket
FEDERATION_ENABLED false set to exactly true to mount the v2-only inbound /federation/* authority
CHORUS_FEDERATION_PUBLIC_ORIGIN required when enabled exact canonical public HTTP(S) origin whose authority is signed; HTTPS outside loopback
CHORUS_FEDERATION_KEY_ENCRYPTION_KEY_FILE required when enabled owner-only file containing 32–4096 raw bytes used to encrypt rotating peer keys at rest
CHORUS_FEDERATION_KEY_ENCRYPTION_KEY_HOST_FILE required by Compose when enabled host path to the 0400/0600 key file mounted at CHORUS_FEDERATION_KEY_ENCRYPTION_KEY_FILE; resolved from project .env by deployment preflight
CHORUS_FEDERATION_PROOF_TTL_SECONDS 60 outbound proof lifetime, 1–300 seconds
CHORUS_FEDERATION_PREVIOUS_KEY_OVERLAP_SECONDS 300 default current/previous rotation overlap, 0–86,400 seconds
MEMORY_GC_INTERVAL_MINUTES 5 memory GC cadence (index.ts:174)
ARTIFACT_GC_INTERVAL_MINUTES 15 artifact GC cadence, only if S3 configured (index.ts:260)

The measured R013 production topology does not inherit SIWE values from an operator shell, image default, or unbound env file. Its exact services.chorus.siwe contract fixes Base chain 8453, projects CHORUS_URL, SIWE_PUBLIC_URL, SIWE_ALLOWED_CHAIN_IDS, and SIWE_RPC_URL_8453 into Compose, cross-binds the same values into the candidate interface manifest, and requires a siwe_runtime rehearsal proof.

Authenticated administrators can inspect the redacted effective embedded policy through GET /admin/config: transport mode, live-auth/filesystem flags, exact allowlists, and numeric budgets are reported, but no Bearer material is returned.

The outbound policy is shared by webhook delivery, federation, configured SIWE/ERC RPC, and ERC-8004 registration metadata. It accepts only normalized HTTP(S), evaluates every A/AAAA answer against the vendored IANA special-purpose registries, rejects mixed public/private answers, pins the approved addresses for the connection, preserves the original Host/SNI, and never follows redirects or proxy environment variables. CHORUS_OUTBOUND_PRIVATE_ALLOWLIST is deliberately narrow: each entry needs an exact origin plus 1–32 CIDRs within RFC1918, RFC6598, loopback, or ULA. Link-local and cloud metadata destinations are hard-denied and cannot be enabled by this setting. Malformed JSON, unknown fields, non-origin URLs, or out-of-class CIDRs abort configuration.

The rate-limit key file is mandatory and read once before any database connection. Its post-trim bytes are the HMAC key directly (not hex/base64 decoded), so every replica must mount the same stable secret. Missing, unreadable, shorter than 32-byte, or larger than 4096-byte files abort startup. The deployment preflight additionally requires an owner-only regular secret file.

The approval-execution signing key is also mandatory and loaded before the database connection. Startup accepts one bounded BEGIN PRIVATE KEY PKCS8 PEM envelope and rejects malformed, encrypted, non-Ed25519, multiple, missing, or unreadable keys. The Compose preflight additionally requires mode 0400/0600 and validates the key structurally without printing private material.

Embeddings (src/memory/embedding-config.ts)

Section titled “Embeddings (src/memory/embedding-config.ts)”

Disabled unless EMBEDDING_PROVIDER is set.

Var Default Purpose
EMBEDDING_PROVIDER — (off) openai / ollama / openrouter (embedding-config.ts:27)
EMBEDDING_DIMENSIONS 1024 vector width (embedding-config.ts:30)
EMBEDDING_API_KEY — required for openai/openrouter; throws if missing (embedding-config.ts:35)
EMBEDDING_MODEL provider default (embedding-config.ts:36)
EMBEDDING_BASE_URL provider default (embedding-config.ts:37)

The memory vector index has a fixed width of 1024. Startup constructs the configured provider and aborts before any worker starts unless the provider also reports exactly 1024 dimensions. This prevents a width mismatch from turning every durable embedding request into failed work.

Var Default Purpose
MEMORY_QUOTA_DEFAULT parse default per-namespace memory cap (memory/quota.ts:126)
MEMORY_DECAY_HALF_LIFE_DAYS decay default decay half-life (memory/decay.ts:52)
MEMORY_DECAY_FLOOR decay default decay floor (memory/decay.ts:56)
MEMORY_BODY_CACHE_MAX_BYTES tiering default L2 body LRU cap (memory/tiering.ts:16)
MEMORY_HYBRID_ENABLED false hybrid keyword+vector retrieval (memory/hybrid.ts:130)
MEMORY_HYBRID_KEYWORD_WEIGHT default weight hybrid keyword weight (memory/hybrid.ts:140)
MEMORY_RERANKER_ENABLED false post-retrieval rerank (reranker-config.ts:48)
MEMORY_RERANKER_PROVIDER openrouter openrouter / tei / cohere (reranker-config.ts:44)
MEMORY_RERANKER_MODEL / _BASE_URL / _API_KEY per-provider (reranker-config.ts:50-52)
MEMORY_RERANKER_TIMEOUT_MS 5000 throws if non-positive (reranker-config.ts:53)
MEMORY_RERANKER_TOP_K 10 (reranker-config.ts:54)
MEMORY_SELROUTE_ENABLED / _PROVIDER / _MODEL / _API_KEY / _BASE_URL off LLM query router (query-router-config.ts:18-25)
MEMORY_LLM_EXTRACTION_ENABLED false boot-owned durable LLM triple extraction worker
MEMORY_LLM_EXTRACTION_MODEL openai/gpt-4o-mini OpenRouter model (llm-extractor-config.ts)
MEMORY_LLM_EXTRACTION_BASE_URL https://openrouter.ai/api/v1 OpenRouter-compatible base URL
MEMORY_LLM_EXTRACTION_API_KEY — required when extraction is enabled; a missing key warns and leaves the worker disabled
MEMORY_LLM_EXTRACTION_MAX_TRIPLES 10 maximum triples per memory revision; integer from 1 through 100

Signal extraction (src/signals/extraction.ts)

Section titled “Signal extraction (src/signals/extraction.ts)”
Var Default Purpose
EXTRACTION_ENABLED_TYPES "" (none) comma list of signal→memory extraction types (extraction.ts:35)
EXTRACTION_DEFAULT_SCOPE agent (extraction.ts:40)

Two independent prefixes: LLM_* (heavy synthesis — library_ask, library_eval) and LLM_AUDIT_* (hot-path judgments — falls back to LLM_* when unset). Each prefix reads the same shape; the provider is disabled silently (returns null) if any required var is missing.

Var (per ${prefix}) Default Purpose
${prefix}_PROVIDER_TYPE openai openai/openai-compatible or codex/codex-responses (provider.ts:48)
${prefix}_BASE_URL — (required) endpoint (provider.ts:159)
${prefix}_MODEL — (required) model id
${prefix}_API_KEY — (required) key
${prefix}_PROVIDER openai-compatible provider label
${prefix}_CODEX_AUTH_FILE — Codex path only: seeded auth JSON in a private runtime-owned writable directory. Refresh creates sibling lock/temp files and atomically replaces the file, so do not use a read-only secrets mount.
LLM_REASONING_OVERHEAD 4 multiplies max_completion_tokens (provider.ts:82)

Storage is off unless S3_ENDPOINT is set. Any SigV4 + path-style S3-compatible backend works; the bundled docker-compose ships Garage (set S3_REGION=garage to match its config). Chorus uses abortable, signed provider requests for put/get/delete/HEAD, bounded ListObjectsV2 inventory pages, presigned GET, and bucket HEAD/PUT.

Var Default Purpose
S3_ENDPOINT — (off) S3-compatible endpoint, e.g. http://garage:3900 (storage.ts:218)
S3_ACCESS_KEY / S3_SECRET_KEY "" credentials (storage.ts:223-224)
S3_BUCKET chorus-artifacts (storage.ts:225)
S3_REGION us-east-1 SigV4 region; set to garage for the bundled Garage backend (storage.ts:226)
S3_REQUEST_TIMEOUT_MS 30000 abortable deadline for bucket, GET, HEAD, DELETE, and signed inventory requests; valid range 1–900000 ms
S3_UPLOAD_TIMEOUT_MS 270000 abortable direct-provider PUT deadline; valid range 1–900000 ms
ARTIFACT_MAX_SIZE_MB 50 upload cap; also read by workspace (routes.ts:46, workspace/utils.ts:8)
CHORUS_LOCAL_UPLOAD_MAX_BYTES 52428800 regular-file descriptor read ceiling (0–1073741824) for standalone local/stdio MCP and CLI shims; 0 permits empty files only, and the receiving HTTP upload independently enforces the server cap
ARTIFACT_QUOTA_DEFAULT_MB quota default per-namespace artifact cap (quota.ts:91)
OBJECT_STORAGE_RECONCILE_INTERVAL_MS 60000 durable operation/inventory reconciliation cadence; valid range 100–86400000 ms

General provider operations default to 30 seconds and direct uploads to 270 seconds. Guarded application uploads use the stricter four-minute foreground deadline inside the five-minute reconciliation grace, preserving at least 30 seconds for ownership handoff. Signed path-style inventory listing rejects a provider response above 8 MiB.

Standalone local/stdio MCP and CLI shims accept regular files only. They open one descriptor, reject oversize files from descriptor metadata before allocation, read fixed chunks, detect growth, truncation, rewrite, inode, or metadata changes, and always close the descriptor.

Var Default Purpose
SSE_MAX_STREAMS_PER_IDENTITY 5 concurrent stream cap per replica
SSE_STREAM_PAGE_SIZE 100 maximum durable events scanned per catch-up page
SSE_MAX_PENDING_EVENTS 2048 maximum high-water lag before explicit slow-consumer disconnect
SSE_DURABLE_POLL_MS 250 cross-replica durable high-water poll interval
SSE_KEEPALIVE_MS 30000 keepalive comment interval
CHORUS_SSE_AUTH_MODE ticket safe default; query_token_compat is an unsafe warned transition mode
SIGNAL_STREAM_RETENTION_INTERVAL_MS 60000 physical retention sweep cadence; bounded integer ≥ 1000 ms
SIGNAL_STREAM_RETENTION_BATCH_SIZE 500 maximum expired rows deleted from one table in one page
SIGNAL_STREAM_RETENTION_MAX_PAGES_PER_SWEEP 8 maximum continuation pages drained from each table per sweep

Approvals, tasks, executor kinds, library, time

Section titled “Approvals, tasks, executor kinds, library, time”
Var Default Purpose
APPROVAL_REAPER_INTERVAL_SECONDS 60 approval-gate reaper cadence (approvals/reaper.ts:20)
APPROVAL_EXECUTION_TOKEN_TTL_SECONDS 3600 one-time execution-token TTL, sampled at gate creation and fingerprint-bound (whole 60–604800 seconds; must cover the execution lease)
APPROVAL_EXECUTION_LEASE_SECONDS 300 default durable execution-attempt lease, sampled once at gate creation and committed inside the fingerprinted action payload; integer from 30 to 3600 seconds
TASK_CLAIM_TTL_MINUTES 15 integer task/run lease TTL in minutes; allowed range 1–240 (4 h), with invalid or out-of-range values rejected rather than silently defaulted
EXECUTOR_KINDS_EXTENSION "" extra executor kinds beyond builtin hermes (config/executor-kinds.ts:16,52)
CHORUS_LIBRARY_MAX_DEPTH 5 library tree depth (library/validation.ts:5)
CHORUS_ALLOW_TIME_OVERRIDE unset → false gates now override in the command catalog (commands/catalog.ts:117); forced true only by the bench harness
Var Default Purpose
AUTH_REQUEST_ENABLED false enables public POST /auth-request (identity/routes.ts:91)
CHORUS_INSTANCE_NAME Chorus Instance agent-card + bootstrap banner (agent-card/routes.ts:21)
CHORUS_INSTANCE_DESCRIPTION A Chorus Protocol instance agent-card (agent-card/routes.ts:23)
CHORUS_BUILD_COMMIT unknown server_commit in health; set by Dockerfile ARG GIT_SHA (version.ts:14)
VERCEL_GIT_COMMIT_SHA / GITHUB_SHA / npm_package_gitHead — commit fallbacks (version.ts:17-19)
npm_package_version 0.2.0 version string (version.ts:11)
CHORUS_BOOTSTRAP_SECRET_OUTPUT_MODE redacted raw prints newly generated API keys and webhook signing secrets once on the creating replica; generated credentials are omitted from the durable bootstrap summary (bootstrap/schema.ts:15)

Standalone MCP package (packages/chorus-mcp)

Section titled “Standalone MCP package (packages/chorus-mcp)”

These configure the standalone chorus-mcp client, not the server.

Var Default Purpose
CHORUS_URL http://localhost:3000 target server (mcp/index.ts:17)
CHORUS_API_KEY "" required for stdio transport — exits 1 if missing (mcp/index.ts:18,55-58)
CHORUS_MCP_TRANSPORT stdio (or http if CHORUS_MCP_LISTEN_PORT set) (mcp/index.ts:19)
CHORUS_MCP_LISTEN_HOST 127.0.0.1 (mcp/index.ts:20)
CHORUS_MCP_LISTEN_PORT 3097 (mcp/index.ts:21)
CHORUS_MCP_ALLOWED_HOSTS exact loopback authorities for the listen port comma-separated host[:port] authorities; required for 0.0.0.0 / :: binds
CHORUS_MCP_ALLOWED_ORIGINS exact loopback HTTP origins for the listen port comma-separated full origins; required for 0.0.0.0 / :: binds
CHORUS_MCP_MAX_BODY_BYTES 1048576 streamed JSON request limit (1 KiB–16 MiB)
CHORUS_MCP_GLOBAL_RATE_LIMIT 600 process-local global requests per minute
CHORUS_MCP_RATE_LIMIT 100 process-local requests per bearer key per minute
CHORUS_MCP_MAX_RATE_LIMIT_KEYS 4096 maximum live per-key limiter buckets
CHORUS_MCP_TREE_MODE runtime runtime / dev / ignore (mcp/index.ts:23)

HTTP mode is stateless: every message revalidates its Bearer key and server compatibility. A known protocol or schema major mismatch is blocked with HTTP 412. Same-major drift or unavailable admin-gated compatibility metadata is reported as degraded and allowed; inspect X-Chorus-MCP-Compatibility. Remote HTTP omits artifact/workspace tools that accept service-host filesystem paths; stdio mode retains them for explicitly local use.

Surface Vars
CLI (packages/cli) CHORUS_URL, CHORUS_API_KEY (override the default profile; config.ts:73-75), HOME (config dir; config.ts:30)
GitHub adapter CHORUS_ADAPTER_RING → CHORUS_RING (default dev), CHORUS_ADAPTER_CREATED_BY (default github-adapter), GITHUB_TOKEN (commands/adapter/github.ts:39-43)
Dispatcher CHORUS_API_KEY — required, throws if missing (dispatcher/daemon.ts:639-640)
Console (SvelteKit) PUBLIC_CHORUS_URL → CHORUS_URL, CONSOLE_API_KEY → CHORUS_API_KEY (hooks.server.ts:19,23)

The LongMemEval bench harness (src/bench/longmemeval.ts, dev-only) reads its own LONGMEMEVAL_EMBEDDING_MODE/_DIMENSIONS/_MODEL/_API_KEY/_BASE_URL (longmemeval.ts:290-328).

From src/index.ts top-level await (lens-config-ops §2):

  • DB unreachable after 3 retries ([1s,2s,4s] backoff) → process.exit(1) (hard fail).
  • Any migration catalog, checksum, ledger, transaction, or schema error → startup rejects before workers/listener (hard fail).
  • Configured bootstrap missing, invalid, or unsuccessful → startup rejects before workers or the HTTP listener start (hard fail).
  • Fresh configured bootstrap without an explicit is_admin: true identity → rejects before authority records are created. Chorus never silently promotes the first configured identity.
  • Configured bootstrap contention/failure → replicas use a renewable digest + generation lease. A same-digest failure stays durably locked; change the config to advance generation and retry. SurrealDB’s clock—not a replica clock—decides lease expiry, lease durations are bounded, stale owners cannot finish, and persisted completion summaries never contain raw keys.
  • Existing configured authority → bootstrap never demotes an existing administrator and will fail before mutation if the central-admin graph or a configured identity’s active membership and live API key is incomplete. Repair that graph explicitly before retrying with a changed config.
  • Quota init / S3 bucket check failures → warn, continue (soft fail).