Middleware
The middleware interface — the single extension mechanism for Agent Express.
A middleware can implement any subset of 5 onion hooks, all with the same
(ctx, next) pattern. Code before await next() runs on the way in;
code after runs on the way out.
agent: wraps the agent lifetime (init → … → dispose)session: wraps onerun()callturn: wraps one user → assistant cyclemodel: wraps one LLM calltool: wraps one tool execution
Plus 1 declarative property:
state: session state field declarations with defaults and optional reducers
Example
Section titled “Example”const costTracker: Middleware = { name: "cost-tracker", state: { totalCost: { default: 0, reducer: (prev, delta) => prev + delta } }, model: async (ctx, next) => { const response = await next() ctx.state.totalCost = response.usage.inputTokens * 0.001 return response },}Properties
Section titled “Properties”name:
string
Middleware name for debugging and tracing.
state?
Section titled “state?”
optionalstate?:StateSchema
Session state field declarations with defaults and optional reducers.
Methods
Section titled “Methods”agent()?
Section titled “agent()?”
optionalagent(ctx,next):Promise<void>
Wraps the agent lifetime. Code before next() = init; code after = dispose.
Register tools via ctx.registerTool() before calling next().
Use try { await next() } finally { cleanup } for guaranteed resource cleanup.
Parameters
Section titled “Parameters”() => Promise<void>
Returns
Section titled “Returns”Promise<void>
model()?
Section titled “model()?”
optionalmodel(ctx,next):Promise<ModelResponse>
Wraps a single LLM call. Can modify messages, change model, skip call, or transform response.
Parameters
Section titled “Parameters”() => Promise<ModelResponse>
Returns
Section titled “Returns”Promise<ModelResponse>
session()?
Section titled “session()?”
optionalsession(ctx,next):Promise<void>
Wraps a session (one run() call). Code before next() = session start; after = session end.
Parameters
Section titled “Parameters”() => Promise<void>
Returns
Section titled “Returns”Promise<void>
tool()?
Section titled “tool()?”
optionaltool(ctx,next):Promise<ToolResult>
Wraps a single tool execution. Can modify args, deny, skip, or transform result.
Parameters
Section titled “Parameters”() => Promise<ToolResult>
Returns
Section titled “Returns”Promise<ToolResult>
turn()?
Section titled “turn()?”
optionalturn(ctx,next):Promise<void>
Wraps a turn (one user message → assistant response cycle).
Parameters
Section titled “Parameters”() => Promise<void>
Returns
Section titled “Returns”Promise<void>