Configuration Reference
cycgraph exposes operational tuning through environment variables (read once at module load, Zod-validated) and constructor options (passed when wiring components). This page is the single reference for both.
Where to override. Env vars are easiest for ops; constructor options are easiest for tests and embedded deployments. They never conflict — env vars set the defaults, constructor options override per-instance.
Runtime config (env vars)
Section titled “Runtime config (env vars)”All values are validated against RuntimeConfigSchema in @cycgraph/orchestrator/runtime-config. Out-of-bounds values throw at module load rather than producing a broken cache size or negative timeout.
| Env var | Default | Bounds | Purpose |
|---|---|---|---|
AGENT_CONFIG_CACHE_TTL_MS | 300000 (5 min) | 1s – 1h | TTL for cached agent configs in the factory |
MAX_AGENT_CONFIG_CACHE_SIZE | 100 | 1 – 10,000 | Max cached agent configs |
FALLBACK_CONFIG_CACHE_TTL_MS | 30000 (30s) | 1s – 1h | Shorter TTL for fallback configs so DB recovery is detected sooner |
AGENT_TIMEOUT_MS | 120000 (2 min) | 1s – 1h | Timeout for a single agent LLM invocation |
MAX_MEMORY_PROMPT_BYTES | 51200 (50 KB) | 1 KB – 10 MB | Max serialized memory injected into the system prompt |
MAX_MEMORY_VALUE_BYTES | 1048576 (1 MB) | 1 KB – 100 MB | Max bytes for a single memory value — reducer drops oversized values into state.memory_drops |
MAX_VISITED_NODES | 1000 | 10 – 1,000,000 | Ring-buffer cap on state.visited_nodes |
MAX_SUPERVISOR_HISTORY | 100 | 10 – 100,000 | Ring-buffer cap on state.supervisor_history |
MAX_MEMORY_DROPS | 50 | 1 – 10,000 | Ring-buffer cap on state.memory_drops |
FILTREX_CACHE_SIZE | 256 | 8 – 100,000 | LRU cap on the filtrex expression compile cache |
When to tune
Section titled “When to tune”| Symptom | Likely lever |
|---|---|
Workflow logs say memory_dropped every run | Raise MAX_MEMORY_VALUE_BYTES, or trim the agent’s output. Confirm in state.memory_drops. |
| LLM 504s under load | Increase AGENT_TIMEOUT_MS. Verify it’s the LLM that’s slow, not your network. |
| OOM on large graphs with deep visited paths | Lower MAX_VISITED_NODES (ring buffer). |
| Memory grows over hours of supervisor loops | Lower MAX_SUPERVISOR_HISTORY. |
| Cold start latency dominated by graph load | Increase FILTREX_CACHE_SIZE if you have many distinct edge conditions. |
GraphRunner options
Section titled “GraphRunner options”Passed to new GraphRunner(graph, state, options). Source: runner/graph-runner.ts.
| Option | Type | Default | Purpose |
|---|---|---|---|
persistence | PersistenceProvider | in-memory | Graph + state storage backend |
eventLog | EventLogWriter | in-memory | Append-only event log + checkpoints |
usageRecorder | UsageRecorder | noop | Cost / token recorder |
toolResolver | ToolResolver | none | MCP tool resolution (MCPConnectionManager recommended) |
contextCompressor | ContextCompressor | none | Compress memory before prompt injection |
memoryRetriever | MemoryRetriever | none | Pull facts from the hierarchical memory graph. Only fires for nodes that declare a memory_query directive. |
memoryWriter | MemoryWriter | none | Persist facts produced by reflection nodes. Required for reflection nodes to function. |
factSanitizer | FactSanitizer | none | Pre-write hook applied to every reflection fact. Return null to drop, or a modified fact to substitute. Fails closed: a thrown sanitizer drops the fact (see factSanitizerFailMode). |
factSanitizerFailMode | 'drop' | 'pass' | 'drop' | What to do when factSanitizer throws. 'drop' (default) discards the fact so unredacted PII is never persisted; 'pass' writes the original fact (fail open). |
rateLimiter | RateLimiter | none | Awaited before every LLM call (agent / supervisor / evaluator) to pace a run inside a provider’s budget. The implementation may delay (throttle) or throw (hard ceiling — surfaces as the node’s error, follows its failure_policy). Abortable; propagated into subgraphs. |
compaction_interval | number | 1000 | Events between automatic event-log compactions (checkpoint + delete-behind, recovery-safe) when an eventLog is wired. Defaults on so a long run can’t grow the log unbounded; set 0 to retain full history and compact manually via compactEvents(). |
persistDeltaFn | (patch: StatePatch) => Promise<void> | none | Differential persistence — when set with persistStateFn, the runner sends patches here and full snapshots to persistStateFn. A failed write rolls back the delta baseline so no patch is lost. |
middleware | RunnerMiddleware[] | [] | beforeNodeExecute / afterReduce hooks |
allow_implicit_completion | boolean | false | When a non-end node has no outgoing edge whose condition matches, the runner fails the run with NoMatchingEdgeError (a dead-end is almost always a routing bug). Set true to restore the legacy behavior of silently completing the workflow at that node. |
A pre-flight wiring check runs at the start of every run(): a graph containing a reflection node with no memoryWriter, or a node declaring MCP tool sources with no toolResolver, fails immediately (before any node executes) instead of mid-run. A memory_query directive with no memoryRetriever logs a warning.
The agent factory fails closed on an unknown agent_id (throws AgentNotFoundError). Opt into the legacy default-agent fallback with configureAgentFactory(registry, { allowDefaultFallback: true }) — see Agents.
MCPConnectionManager options
Section titled “MCPConnectionManager options”Source: mcp/connection-manager.ts.
| Option | Type | Default | Purpose |
|---|---|---|---|
cache_ttl_ms | number | 300000 (5 min) | TTL for cached tool manifests. 0 disables. |
default_tool_timeout_ms | number | 30000 (30s) | Per-tool execution timeout. Overridable per-server via MCPServerEntry.tool_timeout_ms. |
default_max_concurrent_calls | number | 0 (unlimited) | Default cap on concurrent tool calls per MCP server. Overridable per-server via MCPServerEntry.max_concurrent_calls. A FIFO semaphore bounds in-flight calls so a wide fan-out (evolution / voting / map candidates all hitting one server) can’t overwhelm it. |
tool_circuit_breaker | ToolCircuitBreakerOptions | null | enabled with defaults | Per-tool breaker. Pass null to disable entirely. |
ToolCircuitBreakerOptions
Section titled “ToolCircuitBreakerOptions”| Option | Default | Purpose |
|---|---|---|
failure_threshold | 5 | Consecutive failures that open the breaker |
success_threshold | 2 | Consecutive successes in half_open to close |
cooldown_ms | 30000 (30s) | Window the breaker stays open before transitioning to half_open |
Snapshot metrics via manager.getToolCircuitMetrics() — wire to a /metrics endpoint or middleware.
DrizzleEventLogWriter options
Section titled “DrizzleEventLogWriter options”Source: @cycgraph/orchestrator-postgres.
| Option | Default | Purpose |
|---|---|---|
retain_checkpoints | 3 | How many checkpoints per run to keep. Older ones are pruned inside the same transaction as each new write. Minimum 1 enforced. |
InMemoryMemoryIndex options
Section titled “InMemoryMemoryIndex options”Source: @cycgraph/memory.
| Option | Default | Purpose |
|---|---|---|
expectedDimensions | unset | Strict dimension check — every embedding indexed or queried must match. Mismatch throws EmbeddingDimensionMismatchError. Wire from EmbeddingProvider.dimensions. |
silenceScaleWarning | false | Suppress the one-shot console warning when the brute-force index crosses 10K entries. Set true only for stress tests. |
Validation behavior
Section titled “Validation behavior”Misconfiguration fails loud, not silent:
- Setting
MAX_MEMORY_VALUE_BYTES=0would silently drop every memory update. The Zod schema rejects it at startup with a descriptive error. - Setting
retain_checkpoints=0would orphan the run from any usable replay anchor.DrizzleEventLogWriterthrows in its constructor. - A 512-dim
EmbeddingProvidertalking to a 1536-dimpgvectorschema produced silently wrong cosine scores. WithexpectedDimensionsset, the first query throws.
Every default above is also the recommended starting point — change one knob at a time, watch for the symptom listed in When to tune.