Appearance
Inference dependency
Chat does not run inference. It depends on three things that must be configured on the runtime side:
system.agents— handles$prompt, owns sessions and memory.system.inference— provider routing and the actual model call.system.factotum— reads provider credentials from the local home.
If any are missing or misconfigured, Chat's prompts fail with the dependency-probe error described in Overview: Chat and inference.
Required state
For a healthy Chat:
bash
matrix invoke system.agents $introspect '{}'
# Expect: ok=true, accepts includes $prompt, $sessionList, session_state.readbash
matrix invoke system.inference status.get '{}'
# Expect: ok=true, effective: { provider: <name>, model: <name>, ... }bash
matrix invoke system.factotum factotum.list '{}'
# Expect: list of credential records, including the provider Chat needs.If effective.provider is empty, no inference will happen. If the provider is set but system.factotum has no matching credentials, the provider driver will fail at call time and system.agents will surface the error to Chat as an $activity error frame.
Configuring inference
There are two configuration surfaces (operator picks one):
Inference Settings webapp
/apps/inference-settings/ — UI for editing the inference config. Writes to a runtime-managed config file. After saving, the change takes effect on the next system.inference reload.
Direct edit
The inference config file lives at <host-home>/credentials/inference-config.json (or wherever system.inference is configured to read it). Format:
json
{
"providers": {
"anthropic": { "model": "claude-3-5-sonnet-20240620" },
"openai": { "model": "gpt-4-turbo" }
},
"effective": {
"provider": "anthropic",
"model": "claude-3-5-sonnet-20240620"
}
}The exact schema lives in @open-matrix/inference. After editing, restart the inference runtime so it re-reads.
OAuth providers
Per the auto-memory note "OAuth tokens are NOT API keys" (2026-04-02): Codex, ChatGPT, and Claude consumer plans use OAuth JWT, not static API keys. The user must complete an OAuth flow locally; system.factotum reads ~/.codex/auth.json or the equivalent.
To pair Codex:
- Run
codex auth(or the equivalent in the codex CLI) on the local machine. ~/.codex/auth.jsonis written.system.factotumpicks it up;system.inferencecan route to the Codex provider.
@open-matrix/factotum is the single actor that touches credentials. Chat sees only the effective.provider from system.inference status.get.
What Chat does when inference is missing
- User sends prompt.
system.agentsreceives$prompt, opens a session.system.agentscallssystem.inferencefor tokens.system.inference status.getshowseffective.provider === ''.system.agents(or the inference path) fails.- After
PROMPT_DEPENDENCY_PROBE_DELAY_MS(~2s), Chat probessystem.inference status.getitself and sees the empty effective provider. - Chat appends "Dependency Unavailable" to the transcript with provider-config guidance.
Pre-flight check
Before letting users in, validate:
bash
matrix invoke system.runtimes runtimes.registered '{}' \
| jq '.runtimes[] | .app' | sort -u
# Expect: agents, chat, host-control, inference, system, etc.If agents or inference is missing, bring them up before exposing Chat to users.
See also
Source:
projects/matrix-3/packages/chat/src/ChatApp.ts:3296, 3336-3384,projects/matrix-3/packages/inference/,projects/matrix-3/packages/factotum/.