Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.risolu.to/llms.txt

Use this file to discover all available pages before exploring further.

Risoluto’s configuration is layered with this merge order (last wins):
  1. Built-in defaults — sensible out-of-the-box configuration
  2. Persistent overlay~/.risoluto/config/overlay.yaml (or $DATA_DIR/config/overlay.yaml)
  3. Environment variables and $SECRET:name resolution at runtime

Managing Configuration

# View effective (merged) config
curl -s http://127.0.0.1:4000/api/v1/config

# View overlay only
curl -s http://127.0.0.1:4000/api/v1/config/overlay

# Update overlay (deep merge)
curl -s -X PUT http://127.0.0.1:4000/api/v1/config/overlay \
  -H 'Content-Type: application/json' \
  -d '{"codex":{"model":"gpt-5.4","reasoningEffort":"high"}}'

# Patch a single path
curl -s -X PATCH http://127.0.0.1:4000/api/v1/config/overlay/agent.maxConcurrentAgents \
  -H 'Content-Type: application/json' \
  -d '{"value": 5}'

# Delete an overlay key
curl -s -X DELETE http://127.0.0.1:4000/api/v1/config/overlay/codex.personality

# View config schema (JSON Schema)
curl -s http://127.0.0.1:4000/api/v1/config/schema
Overlay changes via the API or dashboard are persisted to disk and survive restarts. You never need to restart Risoluto after a config change — the orchestrator reloads automatically.

Configuration Sections

KeyTypeDefaultDescription
server.portnumber4000HTTP server port
polling.intervalMsnumber15000Tracker polling interval in milliseconds
KeyTypeDefaultDescription
tracker.kindstring"linear"Tracker provider ("linear" or "github")
tracker.apiKeystring""Tracker API key (prefer $SECRET:LINEAR_API_KEY)
tracker.endpointstring"https://api.linear.app/graphql"Tracker GraphQL endpoint
tracker.projectSlugstringnullLinear project slug to watch
tracker.ownerstring""GitHub owner (when kind: "github")
tracker.repostring""GitHub repo (when kind: "github")
tracker.activeStatesstring[]["Backlog", "Todo", "In Progress"]States that trigger agent dispatch
tracker.terminalStatesstring[]["Done", "Canceled"]States that mark issues as complete
KeyTypeDefaultDescription
agent.maxConcurrentAgentsnumber10Maximum simultaneous agent workers
agent.maxConcurrentAgentsByStateobject{}Per-state concurrency limits (e.g. {"In Progress": 3})
agent.maxTurnsnumber20Max conversation turns per agent run
agent.maxRetryBackoffMsnumber300000Maximum retry backoff (5 min)
agent.maxContinuationAttemptsnumber5Max continuation turns after initial run
agent.successStatestringnullLinear state to transition to on success
agent.stallTimeoutMsnumber1200000Agent stall detection timeout (20 min)
agent.preflightCommandsstring[][]Shell commands to run before each agent turn
KeyTypeDefaultDescription
codex.commandstring"codex app-server"Command to start the Codex agent
codex.modelstring"gpt-5.4"Model identifier
codex.reasoningEffortenum"high"none, minimal, low, medium, high, xhigh
codex.personalitystring"friendly"Agent personality/tone
codex.selfReviewbooleanfalseEnable agent self-review before completing
codex.structuredOutputbooleanfalseEnable structured output mode
codex.approvalPolicystring|objectreject allTool call approval policy
codex.threadSandboxstring"workspace-write"Thread-level sandbox policy
codex.turnSandboxPolicyobject{type: "workspaceWrite"}Per-turn sandbox policy
Timeouts:
KeyTypeDefaultDescription
codex.readTimeoutMsnumber5000JSON-RPC read timeout
codex.turnTimeoutMsnumber3600000Max duration per turn (1 hour)
codex.drainTimeoutMsnumber2000Drain timeout on shutdown
codex.startupTimeoutMsnumber30000Container startup timeout (30s)
codex.stallTimeoutMsnumber300000Per-turn stall detection (5 min)
Authentication:
KeyTypeDefaultDescription
codex.auth.modeenum"api_key"api_key or openai_login
codex.auth.sourceHomestring"~/.codex"Path to Codex auth credentials
KeyTypeDefaultDescription
codex.sandbox.imagestring"risoluto-codex:latest"Docker image for worker containers
codex.sandbox.networkstring""Docker network name
codex.sandbox.extraMountsstring[][]Extra bind mounts
codex.sandbox.envPassthroughstring[][]Env vars forwarded to containers
codex.sandbox.egressAllowliststring[][]Allowed egress domains
Resources:
KeyTypeDefaultDescription
codex.sandbox.resources.memorystring"4g"Memory limit
codex.sandbox.resources.memoryReservationstring"1g"Guaranteed memory
codex.sandbox.resources.memorySwapstring"4g"Swap limit
codex.sandbox.resources.cpusstring"2.0"CPU limit
codex.sandbox.resources.tmpfsSizestring"512m"tmpfs mount size
Security:
KeyTypeDefaultDescription
codex.sandbox.security.noNewPrivilegesbooleantrue--security-opt=no-new-privileges
codex.sandbox.security.dropCapabilitiesbooleantrueDrop all Linux capabilities
codex.sandbox.security.gvisorbooleanfalseEnable gVisor runtime
codex.sandbox.security.seccompProfilestring""Custom seccomp profile path
Logging:
KeyTypeDefaultDescription
codex.sandbox.logs.driverstring"json-file"Docker log driver
codex.sandbox.logs.maxSizestring"50m"Max log file size
codex.sandbox.logs.maxFilenumber3Max number of log files
KeyTypeDefaultDescription
workspace.rootstring"../risoluto-workspaces"Root directory for issue workspaces
workspace.strategyenum"directory"Isolation strategy: directory (clone) or worktree (git worktree)
workspace.branchPrefixstring"risoluto/"Branch name prefix for agent branches
Hooks:
KeyTypeDefaultDescription
workspace.hooks.afterCreatestringnullShell command after workspace creation
workspace.hooks.beforeRunstringnullShell command before each agent run
workspace.hooks.afterRunstringnullShell command after each agent run
workspace.hooks.beforeRemovestringnullShell command before workspace removal
workspace.hooks.timeoutMsnumber60000Hook execution timeout (1 min)
Risoluto supports two notification config shapes. The single-Slack shape is the legacy path; the channels array is the current multi-channel path and is what you should use for anything beyond a single Slack webhook.Legacy single-Slack:
KeyTypeDefaultDescription
notifications.slack.webhookUrlstringSlack incoming webhook URL
notifications.slack.verbosityenum"critical"off, critical, verbose
Multi-channel array:
KeyTypeDefaultDescription
notifications.channels[]array[]Delivery channels, evaluated in order
notifications.channels[].namestringUnique channel label used in notification metadata
notifications.channels[].enabledbooleantrueDisable without removing the entry
notifications.channels[].minSeverityenum"info"info, warning, critical — only notifications at or above this severity are delivered
notifications.channels[].typeenumslack, webhook, or desktop
Slack channel (type: slack):
KeyTypeDefaultDescription
webhookUrlstringSlack incoming webhook URL (prefer $SECRET:SLACK_WEBHOOK_URL)
verbosityenum"critical"off, critical, verbose
Webhook channel (type: webhook):
KeyTypeDefaultDescription
urlstringHTTPS endpoint to POST notification payloads to
headersobject{}Extra HTTP headers (e.g. Authorization: Bearer ...)
Desktop channel (type: desktop): no extra fields — surfaces notifications in the dashboard notification tray only.
notifications:
  channels:
    - name: ops-slack
      type: slack
      minSeverity: warning
      webhookUrl: $SECRET:SLACK_WEBHOOK_URL
    - name: oncall-pager
      type: webhook
      minSeverity: critical
      url: https://events.example.com/risoluto
      headers:
        Authorization: Bearer $SECRET:PAGER_TOKEN
    - name: dashboard-only
      type: desktop
See the Notifications guide for event types and severity levels.
KeyTypeDefaultDescription
webhook.webhookUrlstringHTTPS-only webhook URL (enables webhook mode)
webhook.webhookSecretstringHMAC signing secret for verification
webhook.pollingBaseMsnumber15000Polling interval when webhook is healthy
webhook.pollingStretchMsnumber120000Polling interval stretched when webhook active
webhook.healthCheckIntervalMsnumber300000Health check interval (5 min)
KeyTypeDefaultDescription
github.tokenstringGitHub Personal Access Token
github.apiBaseUrlstring"https://api.github.com"GitHub API endpoint (for GHES)
Route issues to different repositories based on tracker metadata. Each entry in repos is a destination that the orchestrator matches against the incoming issue before launching a worker. See the Multi-repo recipe for a worked example.
KeyTypeDefaultDescription
repos[]array[]Repository routing entries
repos[].repoUrlstringGit URL used to clone or fetch the workspace
repos[].defaultBranchstring"main"Branch agents branch from
repos[].identifierPrefixstring | nullnullMatch issues whose identifier starts with this prefix (e.g. "ENG-")
repos[].labelstring | nullnullMatch issues that carry this label
repos[].githubOwnerstring | nullnullGitHub owner used when the orchestrator opens the PR
repos[].githubRepostring | nullnullGitHub repo name used for the PR
repos[].githubTokenEnvstring | nullnullName of the env var holding the PR-creation token for this repo
Controls the opt-in auto-merge engine. Defaults to disabled, so no PR is auto-merged until you turn enabled on.
KeyTypeDefaultDescription
mergePolicy.enabledbooleanfalseMaster switch. When false, Risoluto never requests an auto-merge
mergePolicy.allowedPathsstring[][]Path prefixes; when non-empty, every changed file in the PR must match at least one entry
mergePolicy.maxChangedFilesnumber | nullnullMaximum number of changed files. null disables the cap
mergePolicy.maxDiffLinesnumber | nullnullMaximum combined additions + deletions. null disables the cap
mergePolicy.requireLabelsstring[][]Labels that must all be present on the PR before auto-merge is attempted
mergePolicy.excludeLabelsstring[][]Labels that block auto-merge when any are present
Override the default issue lifecycle stages and transitions. Only needed if your tracker uses non-standard states or you want to gate specific transitions.
KeyTypeDefaultDescription
stateMachine.stages[]array[]Ordered stage list
stateMachine.stages[].namestringStage label that must match a tracker state name
stateMachine.stages[].kindenumOne of backlog, todo, active, gate, terminal
stateMachine.transitionsobject{}Map of stage name to an array of allowed next stage names
stateMachine:
  stages:
    - { name: Backlog, kind: backlog }
    - { name: Ready, kind: todo }
    - { name: In Progress, kind: active }
    - { name: Review, kind: gate }
    - { name: Done, kind: terminal }
  transitions:
    Ready: [In Progress]
    In Progress: [Review, Ready]
    Review: [Done, In Progress]

Secrets Management

Secrets are stored in an AES-256-GCM encrypted store, separate from config:
curl -s -X POST http://127.0.0.1:4000/api/v1/secrets/SLACK_WEBHOOK_URL \
  -H 'Content-Type: application/json' \
  -d '{"value":"https://hooks.slack.com/services/..."}'
Keep secrets out of committed files. Use $SECRET:name references in config or environment variable expansion like $LINEAR_API_KEY.

Environment Variables

VariableRequiredDefaultDescription
LINEAR_API_KEYYesLinear API key
LINEAR_PROJECT_SLUGYesLinear project to watch
MASTER_KEYYesEncryption key for secrets store
OPENAI_API_KEYNoOpenAI API key (alternative to Codex auth)
GITHUB_TOKENNoGitHub PAT for PR creation
DATA_DIRNo~/.risolutoRoot directory for archives and config
RISOLUTO_BINDNo127.0.0.1HTTP bind address
RISOLUTO_WRITE_TOKENNoBearer token for remote API writes
RISOLUTO_READ_TOKENNoBearer token required for remote reads when RISOLUTO_BIND is non-loopback. Unset when binding to 127.0.0.1/::1
LOG_LEVELNoinfoLog verbosity
DISPATCH_MODENolocallocal or remote dispatch mode
DISPATCH_URLNoData plane URL (when DISPATCH_MODE=remote)
DISPATCH_SHARED_SECRETNoShared secret for control/data plane auth

What’s Next

Dashboard

Explore the real-time dashboard views.

Security

Harden your deployment with network controls and sandbox policies.
Last modified on April 10, 2026