Skip to content

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 one run() call
  • turn: wraps one user → assistant cycle
  • model: wraps one LLM call
  • tool: wraps one tool execution

Plus 1 declarative property:

  • state: session state field declarations with defaults and optional reducers
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
},
}

name: string

Middleware name for debugging and tracing.


optional state?: StateSchema

Session state field declarations with defaults and optional reducers.

optional agent(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.

AgentContext

() => Promise<void>

Promise<void>


optional model(ctx, next): Promise<ModelResponse>

Wraps a single LLM call. Can modify messages, change model, skip call, or transform response.

ModelContext

() => Promise<ModelResponse>

Promise<ModelResponse>


optional session(ctx, next): Promise<void>

Wraps a session (one run() call). Code before next() = session start; after = session end.

SessionContext

() => Promise<void>

Promise<void>


optional tool(ctx, next): Promise<ToolResult>

Wraps a single tool execution. Can modify args, deny, skip, or transform result.

ToolContext

() => Promise<ToolResult>

Promise<ToolResult>


optional turn(ctx, next): Promise<void>

Wraps a turn (one user message → assistant response cycle).

TurnContext

() => Promise<void>

Promise<void>