const logging = defineMiddleware({
before: async (context) => {
console.log("Tool:", context.toolName);
},
after: async (context) => {
console.log("Completed:", context.toolName);
},
});
const timing = defineMiddleware.before(async (context) => {
context.state.set("startTime", Date.now());
});
Define middleware with result passing support
Allows middleware to inspect and transform results from tool handlers.
const logResult = defineMiddleware.withResult<ToolResult>({
after: async (context, result) => {
console.log("Result:", result.data);
return result; // Keep original result
},
});
const addTimestamp = defineMiddleware.withResult<ToolResult>({
after: async (context, result) => {
return {
...result,
_meta: { ...result._meta, timestamp: Date.now() },
};
},
});
const cache = defineMiddleware.withResult<ToolResult>({
before: async (context) => {
const cached = await getFromCache(context.toolName, context.input);
if (cached) {
context.state.set("response", cached);
}
},
after: async (context, result) => {
if (!context.state.get("response")) {
await saveToCache(context.toolName, context.input, result);
}
return result;
},
});
Create middleware that only runs after the chain
Automatically calls next() before the hook.
Create middleware that only runs before the chain
Automatically calls next() after the hook.
Create middleware with full control and type enforcement
The return type (Promise
Use this pattern for:
Define middleware with automatic next() handling
Prevents the common mistake of forgetting to call
await next().