Overview
RuntimeContext is the runtime-side bag a plugin’s code sees on every request. Built fresh per LangGraph invocation by buildRuntimeContext(runConfig, ambient, state).
Full shape
Fields
user
user
The authenticated user. Validated by
AuthHeaderMiddleware before the request reaches any plugin code.did— IXO DID (did:ixo:ixo1...).matrixUserId— e.g.@did-ixo-ixo1abc:ixo.world.ucanDelegation— UCAN envelope fromx-ucan-delegationheader.timezone— optional, fromx-timezoneheader.currentTime— optional, ISO timestamp.
session
session
id— the thread ID (Matrix rooteventId).client—'portal' | 'matrix' | 'slack'.wsId— optional WebSocket connection ID.requestId— correlation ID.roomId— optional Matrix room ID for the active conversation.
history
history
messages— readonly array ofBaseMessage(LangChain). The full thread history loaded by the checkpointer.recent(n)— convenience method returning the most recentnmessages.userContext— enrichment object fromstate.userContext(typically populated by the Memory plugin).state—ReadonlyState, a typed view over the LangGraph annotation state. See State schema.
config
config
Same merged + validated env as
PluginContext.config. Typed by your plugin’s own schema:availablePlugins
availablePlugins
The names of every plugin that survived boot resolution. Fixed.
loadedPlugins
loadedPlugins
The names of
on-demand plugins the agent has loaded for this thread via load_capability. Plus implicitly all always plugins. Per-thread, monotonically growing across turns.secrets
secrets
Per-room secrets, JWE-encrypted, 24h cache.
getIndex()— returns theSecretIndex(metadata only, no values).getValues(keys)— returns plaintext for the requested keys.
SecretsService. Returns nothing if the encryption key isn’t provisioned.blobStore
blobStore
Short-TTL, user-namespaced store for content the LLM must never relay verbatim — UCAN invocation CARs, JWTs, signed envelopes. A producing tool stores the value and returns a short opaque ID; a consuming tool looks it up server-side and forwards it on. The model only ever sees the ID.
put({ userDid, name, value, ttlSeconds? })— store a value, returns a freshblob_<16 hex>ID. TTL defaults to 1h and is clamped to the service max (24h). PassuserDidfrom a trusted source (e.g.rtCtx.user.did) — never from LLM-supplied tool args.get({ userDid, blobId })— retrieve a blob scoped to the requesting user. Returnsnullif it doesn’t exist, has expired, or belongs to a different user (cross-user reads always miss).isValidBlobId(value)— cheap format check (blob_<16 hex>); use it in a tool’s input handler to reject malformed IDs before paying for a lookup.
matrix
matrix
Scoped Matrix operations.
postToRoom(roomId, content)— post a message; returns the event ID.getRoomState(roomId)— snapshot of state events.getEventById(roomId, eventId)— fetch a specific event.
ucan
ucan
UCAN authorisation helpers.
requireCapability(resource, action)— throws if the user’s delegation doesn’t include this capability.hasCapability(resource, action)— boolean check.mintInvocation({ did, capability }, opts?)— mint a downstream invocation signed by the oracle’s signing mnemonic.resolveServiceDid(serviceUrl)— look up a downstream service’s DID document; returnsidornull.hasSigningKey()—trueonce the oracle has loaded its Ed25519 signing mnemonic. Gate registration of mint-capable tools on this: without a key, minting is a no-op, so the tool should surface an error rather than pretend it worked.createInvocationFromDelegation(delegationCar, serviceUrl, capability, options?)— mint an invocation from a directly-supplied delegation CAR (rather than the user’s cached one), targeted at a specific service route. Returns{ invocation }on success or{ error }with a surfaced-verbatim reason (missing signing key, audience mismatch, did:web unreachable, …).
llm
llm
get(role, params?)— returns aBaseChatModelfor the given role.
role is one of 'main' | 'subagent' | 'utility' or any custom string mapped in your provider config. The framework’s provider config maps roles to specific OpenRouter / Nebius / OpenAI models.Plugins should use this rather than instantiating LangChain models directly — the provider config handles auth headers, base URLs, and per-role model selection.emit
emit
Typed event emitter. Bundled clients (Portal, Slack) consume these events; render them into UI. See the API endpoints reference for the WebSocket event protocol.Available events:
toolCall, actionCall, renderComponent, reasoning, browserToolCall, router, messageCacheInvalidation. Payload types are currently Record<string, unknown> and may be tightened in future versions.logger
logger
Same as
PluginContext.logger. Plugin-scoped, auto-prefixed with the plugin name.abortSignal
abortSignal
Propagates from the incoming HTTP request / graph invocation. Pass it to
fetch calls so client disconnects abort upstream work.shared
shared
toolCallId
toolCallId
The identifier of the inbound tool call that triggered this handler, when available.
undefined for direct / test invocations.Used by tools that return a LangGraph Command and need to append a matching ToolMessage to the state update.Lifetime
Built fresh per graph invocation bybuildRuntimeContext(runConfig, ambient, state). Lives for the duration of that single turn. Don’t store references to rtCtx for use across turns — its inner services (Matrix client, secrets cache) may be invalid by the next call.