Skip to content

Repo, providers, and ratchet

Smithers is configured through a small set of supervisor ops, persisted to <repo-root>/.smithers/smithers-config.json. There is no separate "settings page" — every knob is an op invocation.

Configure the GitHub repo

bash
matrix invoke smithers smithers.configure '{ "repo": "owner/name" }'

Or from the workbench: the Status Bar exposes a repo input. Either path calls onSmithersConfigure (SmithersSupervisor.ts:3147+) which validates the repo string, persists it via _persistConfig, and pushes it to GitHubAdapter.github.set-repo.

After change, GitHubAdapter clears its issue cache and refetches on next github.list-issues.

Inspect current config

bash
matrix invoke smithers smithers.config '{}'

Returns:

ts
{
  repo: string,
  maxConcurrentIssues: number,
  llmConfigs: Array<{ provider, model, label }>,  // configured LLM providers
  ratchetCount: number,
  containerMode: 'docker' | 'podman' | 'none',
}

LLM providers

Smithers does not configure providers directly — it asks @open-matrix/inference-catalog (which talks to system.inference). At supervisor bootstrap (SmithersSupervisor.ts:556-587):

ts
const adapter = createPiAiFromEnv();
this._piaiConfig = adapter?.config ?? null;
if (this._piaiConfig) {
  this._llmConfigs.push({
    provider: this._piaiConfig.provider,
    model: this._piaiConfig.model,
    apiKey: this._piaiConfig.apiKey,
    api: (this._piaiConfig as any).api,
    label: this._piaiConfig.provider === 'openai-codex' ? 'codex' : 'claude',
  });
}

So provider selection = inference-catalog config change. Add a Codex API key, restart Smithers — it shows up as a provider option. Add a Claude API key, restart — same. Both can be present; sequential fallback (maxRoundsPerProvider) drives selection.

maxConcurrentIssues

Default 3 (SMITHERS_DEFAULTS.limits.maxConcurrentIssues). Override:

bash
matrix invoke smithers smithers.configure '{ "maxConcurrentIssues": 5 }'

Increasing this lets more issues run in parallel. Each issue holds its own session, container (if Path B), and LLM credit; do not raise it past what your providers and Docker host can sustain.

Ratchet

The ratchet is read-only from the user's perspective; it grows by sign-off success. Read it:

bash
matrix invoke smithers smithers.ratchet '{}'
# returns { count, entries: [...] }

Each entry has a constraint id, the issue that satisfied it, and the evidence. The Governance route in the workbench renders this list. A future Smithers convergence run on any issue will treat ratcheted constraints as invariants — they are pre-approved and the agent only has to maintain them.

There is no "unratchet" op. The ratchet is monotonic by design (per DESIGN.md §1.7).

Architecture-doc constraints

ArchitectureDocWatcher (src/actors/ArchitectureDocWatcher.ts) watches a configured set of architecture docs and emits constraints when they change. Read its current set:

bash
matrix invoke smithers smithers.arch-constraints '{}'

These constraints are added to the projection for every convergence run, so changes to architecture docs propagate into the agent prompt automatically.

Container vs local mode

SmithersConfig.container (src/config/defaults.ts:99-105):

ts
container: {
  enabled: true,
  runtime: 'docker',
  image: 'smithers-agent:latest',
  workspacePath: '/workspace',
}

To disable containers entirely, pass runtime: 'none'mergeConfig (src/config/defaults.ts:172-174) will set enabled: false derived from that. With containers off, every coding agent runs in-process via Path A; with containers on, the supervisor prefers Path B SDK workers in containers.

Smithers reads this from matrix.json props at mount time, not from a runtime op — change it by editing the manifest or by passing props through the runner CLI.

Escalation policy

The default EscalationPolicy is hard-coded in src/actors/EscalationPolicy.ts. There is no user-facing override op. To change behaviour, fork the package and modify the policy class — its decision points (continue, fallback-provider, escalate-human, mark-error) are documented in Convergence loop and review barrier.

Auto-dispatch

smithers.auto (SmithersSupervisor.ts:2120+) toggles automatic dispatch — Smithers periodically scans pending workstream-requests and ready issues with the configured label, and starts convergence on them.

bash
matrix invoke smithers smithers.auto '{ "enabled": true, "intervalMs": 60000 }'

Default interval is 60s (autoDispatchIntervalMs). The supervisor logs auto-dispatch decisions in _autoDispatchLog; read with smithers.error-log (which combines auto-log + dispatch errors).

What is NOT configurable

  • The convergence phases. Hard-coded.
  • Sign-off forcing. Hard-coded — every constraint must be argued.
  • Review barrier (no piecemeal approvals). Hard-coded.
  • The shell tool. CodingAgent exposes exactly one tool (buildShellTool).
  • The session storage path. <host-home>/.matrix/sessions/ — managed by system.agents, not Smithers.

See also

Source: projects/matrix-3/packages/smithers/src/actors/SmithersSupervisor.ts:556-587 (LLM resolution), :3147-3192 (configure / config), projects/matrix-3/packages/smithers/src/config/defaults.ts.