Skip to main content

The full path

What each stop does

StopResponsibility
AuthHeaderMiddlewareValidates the UCAN delegation (signature, expiry, audience, capability). Resolves the user’s DID and attaches RuntimeUserContext. Failure → 401, agent never runs.
SubscriptionMiddlewareOnly when the credits plugin is loaded. Checks user balance. Empty + DISABLE_CREDITS !== 'true' → 402.
ThrottlerGuardPer-user rate limit, registered as a global Nest guard (APP_GUARD), not an HTTP middleware. Nest runs middleware before guards, so it still gates after auth and subscription. Breach → 429.
MessagesControllerReads the inbound message, looks up the session (creates on first contact), hands off to the agent builder. Returns SSE.
createMainAgentBuilds the per-request RuntimeContext, reads cached registries, runs getRequestTools / getRequestSubAgents, composes the prompt, returns a LangChain agent compiled against the per-user checkpointer.
CheckpointerLoads { messages, loadedPlugins, userContext, ... } for this thread_id (= session id) from per-user SQLite (synced to Matrix in the background).
LLM invocationComposed prompt + bound tools + state messages go to the model resolved for the main role (provider from LLM_PROVIDER, or a hooks.resolveModel override). Plugin middleware fires (beforeModel, wrapModelCall, afterModel).
Tool callsThe agent loop dispatches plugin tools, sub-agent tools, meta-tools, and browser tools. Each emits a typed event so the client can render “Agent called X”.
Save state + streamThe final state is checkpointed; the assistant message streams over SSE. WS events for intermediate steps have already shipped.

Where each plugin hook fires

HookFires during
getTools, getSubAgents, getMiddlewares, getSharedStateRead from boot cache during agent build
getRequestTools, getRequestSubAgentsPer-request agent build
middlewares[].beforeModel / wrapModelCall / afterModelAround each LLM invocation
middlewares[].wrapToolCallAround each tool call
Tool / sub-agent handlerWhen the LLM calls the tool
getNestModules controllersAny HTTP request to a plugin route

Failure modes

What failsEffect
UCAN validation401. Agent never runs.
Credit check402. Agent never runs.
Rate limit429. Agent never runs.
Checkpointer loadError logged; falls back to empty state. Turn proceeds.
LLMPropagates to the client by default. A middleware can catch it by wrapping the call in wrapModelCall with try/catch.
Tool handlerOne retry on validation error; otherwise the error becomes a ToolMessage the agent sees.
Sub-agent initPromise.allSettled — log and skip; rest of turn continues.

Contexts

What RuntimeContext carries.

Meta-tools

How load_capability mutates loadedPlugins mid-turn.
Source: packages/oracle-runtime/src/graph/ and packages/oracle-runtime/src/modules/messages/.