Skip to main content

Where each hook plugs in

The runtime never reaches inside your plugin. Every contribution flows through one of these channels.

The ten contribution channels at a glance

The first four are declarative properties (data the runtime reads); the rest are hooks (methods the runtime calls).
ChannelWhat it contributesWhen called
manifestThe agent-facing interface — title, summary, whenToUse, examples, visibilityBoot (validation + Tier-1 composition)
configSchemaA Zod object merged into the global env schemaBoot (env validation)
dependsOn / softDependsOnPlugin ordering constraintsBoot (topo sort)
autoDetect(env)Decide whether to load based on envBoot (resolution)
getTools(ctx) / getRequestTools(rtCtx)LLM-callable toolsBoot cache + per-request
getSubAgents(ctx) / getRequestSubAgents(rtCtx)Focused inner agents (auto-wrapped as tools)Boot cache + per-request
getMiddlewares(ctx)LangChain AgentMiddleware objects (beforeAgent / beforeModel / wrapModelCall / afterModel / wrapToolCall / afterAgent hooks)Boot cache
getNestModules(ctx?)Nest modules (HTTP routes, services)Boot, once
getAuthExcludedRoutes()Routes that skip UCAN authBoot, once
getSharedState()Read-only accessors other plugins can consumeBoot, once
A middleware can declare any of the six LangChain hooks above. There is no onError middleware hook — to handle an LLM or tool error inside a middleware, wrap the call in wrapModelCall / wrapToolCall with try/catch. Boot-time hooks (getTools, getSubAgents, getMiddlewares) are called once and the results are cached for every request. The per-request variants run on every agent build — use them only when the contribution depends on live state (e.g. loadedPlugins, current user, rtCtx.shared.*).

Two contexts

ContextHoldsHooks that receive it
PluginContextconfig, identity, availablePlugins, loggergetTools, getSubAgents, getMiddlewares, getNestModules
RuntimeContextEverything in PluginContext plus user, session, history, secrets, matrix, ucan, llm, emit, shared, abortSignal, loadedPluginsgetRequestTools, getRequestSubAgents, all handlers, all middleware hooks
A tool registered via boot-time getTools still gets a fresh RuntimeContext when its handler fires. “Boot-time” refers to registration, not execution. See Contexts for the field list.

Error semantics

Hook throws…Effect
autoDetect, manifest validation, configSchema, getNestModules, getAuthExcludedRoutes, getSharedStateBoot fails. Loud failures because misconfiguration in production is worse than no plugin.
getTools / getSubAgents / getMiddlewares (boot warm or per-request)Logged with plugin name; plugin’s contribution skipped for that build. Other plugins continue.
Tool / sub-agent handlerBecomes an error ToolMessage the agent sees; one retry on validation errors.
Middleware hookPropagates as a turn error.

Write a plugin

Scaffold and ship one.

Manifest

The agent-facing interface.
Source: packages/oracle-runtime/src/plugin-api/oracle-plugin.ts.