langchain
Version:
Typescript bindings for langchain
185 lines (183 loc) • 8.2 kB
TypeScript
import { ClientTool, ServerTool } from "./tools.js";
import { AfterAgentHook, AfterModelHook, AgentMiddleware, BeforeAgentHook, BeforeModelHook, WrapModelCallHook, WrapToolCallHook } from "./middleware/types.js";
import { InferInteropZodOutput, InteropZodDefault, InteropZodObject, InteropZodOptional } from "@langchain/core/utils/types";
//#region src/agents/middleware.d.ts
/**
* Creates a middleware instance with automatic schema inference.
*
* @param config - Middleware configuration
* @param config.name - The name of the middleware
* @param config.stateSchema - The schema of the middleware state
* @param config.contextSchema - The schema of the middleware context
* @param config.wrapModelCall - The function to wrap model invocation
* @param config.wrapToolCall - The function to wrap tool invocation
* @param config.beforeModel - The function to run before the model call
* @param config.afterModel - The function to run after the model call
* @param config.beforeAgent - The function to run before the agent execution starts
* @param config.afterAgent - The function to run after the agent execution completes
* @returns A middleware instance
*
* @example
* ```ts
* const authMiddleware = createMiddleware({
* name: "AuthMiddleware",
* stateSchema: z.object({
* isAuthenticated: z.boolean().default(false),
* }),
* contextSchema: z.object({
* userId: z.string(),
* }),
* beforeModel: async (state, runtime, controls) => {
* if (!state.isAuthenticated) {
* return controls.terminate(new Error("Not authenticated"));
* }
* },
* });
* ```
*/
declare function createMiddleware<TSchema extends InteropZodObject | undefined = undefined, TContextSchema extends InteropZodObject | InteropZodOptional<InteropZodObject> | InteropZodDefault<InteropZodObject> | undefined = undefined>(config: {
/**
* The name of the middleware
*/
name: string;
/**
* The schema of the middleware state. Middleware state is persisted between multiple invocations. It can be either:
* - A Zod object
* - A Zod optional object
* - A Zod default object
* - Undefined
*/
stateSchema?: TSchema;
/**
* The schema of the middleware context. Middleware context is read-only and not persisted between multiple invocations. It can be either:
* - A Zod object
* - A Zod optional object
* - A Zod default object
* - Undefined
*/
contextSchema?: TContextSchema;
/**
* Additional tools registered by the middleware.
*/
tools?: (ClientTool | ServerTool)[];
/**
* Wraps tool execution with custom logic. This allows you to:
* - Modify tool call parameters before execution
* - Handle errors and retry with different parameters
* - Post-process tool results
* - Implement caching, logging, authentication, or other cross-cutting concerns
* - Return Command objects for advanced control flow
*
* The handler receives a ToolCallRequest containing the tool call, state, and runtime,
* along with a handler function to execute the actual tool.
*
* @param request - The tool call request containing toolCall, state, and runtime.
* @param handler - The function that executes the tool. Call this with a ToolCallRequest to get the result.
* @returns The tool result as a ToolMessage or a Command for advanced control flow.
*
* @example
* ```ts
* wrapToolCall: async (request, handler) => {
* console.log(`Calling tool: ${request.tool.name}`);
* console.log(`Tool description: ${request.tool.description}`);
*
* try {
* // Execute the tool
* const result = await handler(request);
* console.log(`Tool ${request.tool.name} succeeded`);
* return result;
* } catch (error) {
* console.error(`Tool ${request.tool.name} failed:`, error);
* // Could return a custom error message or retry
* throw error;
* }
* }
* ```
*
* @example Authentication
* ```ts
* wrapToolCall: async (request, handler) => {
* // Check if user is authorized for this tool
* if (!request.runtime.context.isAuthorized(request.tool.name)) {
* return new ToolMessage({
* content: "Unauthorized to call this tool",
* tool_call_id: request.toolCall.id,
* });
* }
* return handler(request);
* }
* ```
*/
wrapToolCall?: WrapToolCallHook<TSchema, NormalizeContextSchema<TContextSchema>>;
/**
* Wraps the model invocation with custom logic. This allows you to:
* - Modify the request before calling the model
* - Handle errors and retry with different parameters
* - Post-process the response
* - Implement custom caching, logging, or other cross-cutting concerns
*
* The request parameter contains: model, messages, systemPrompt, tools, state, and runtime.
*
* @param request - The model request containing all the parameters needed.
* @param handler - The function that invokes the model. Call this with a ModelRequest to get the response.
* @returns The response from the model (or a modified version).
*
* @example
* ```ts
* wrapModelCall: async (request, handler) => {
* // Modify request before calling
* const modifiedRequest = { ...request, systemPrompt: "You are helpful" };
*
* try {
* // Call the model
* return await handler(modifiedRequest);
* } catch (error) {
* // Handle errors and retry with fallback
* const fallbackRequest = { ...request, model: fallbackModel };
* return await handler(fallbackRequest);
* }
* }
* ```
*/
wrapModelCall?: WrapModelCallHook<TSchema, NormalizeContextSchema<TContextSchema>>;
/**
* The function to run before the agent execution starts. This function is called once at the start of the agent invocation.
* It allows to modify the state of the agent before any model calls or tool executions.
*
* @param state - The middleware state
* @param runtime - The middleware runtime
* @returns The modified middleware state or undefined to pass through
*/
beforeAgent?: BeforeAgentHook<TSchema, NormalizeContextSchema<TContextSchema>>;
/**
* The function to run before the model call. This function is called before the model is invoked and before the `wrapModelCall` hook.
* It allows to modify the state of the agent.
*
* @param state - The middleware state
* @param runtime - The middleware runtime
* @returns The modified middleware state or undefined to pass through
*/
beforeModel?: BeforeModelHook<TSchema, NormalizeContextSchema<TContextSchema>>;
/**
* The function to run after the model call. This function is called after the model is invoked and before any tools are called.
* It allows to modify the state of the agent after the model is invoked, e.g. to update tool call parameters.
*
* @param state - The middleware state
* @param runtime - The middleware runtime
* @returns The modified middleware state or undefined to pass through
*/
afterModel?: AfterModelHook<TSchema, NormalizeContextSchema<TContextSchema>>;
/**
* The function to run after the agent execution completes. This function is called once at the end of the agent invocation.
* It allows to modify the final state of the agent after all model calls and tool executions are complete.
*
* @param state - The middleware state
* @param runtime - The middleware runtime
* @returns The modified middleware state or undefined to pass through
*/
afterAgent?: AfterAgentHook<TSchema, NormalizeContextSchema<TContextSchema>>;
}): AgentMiddleware<TSchema, TContextSchema, any>;
type NormalizeContextSchema<TContextSchema extends InteropZodObject | InteropZodOptional<InteropZodObject> | InteropZodDefault<InteropZodObject> | undefined = undefined> = TContextSchema extends InteropZodObject ? InferInteropZodOutput<TContextSchema> : TContextSchema extends InteropZodDefault<any> ? InferInteropZodOutput<TContextSchema> : TContextSchema extends InteropZodOptional<any> ? Partial<InferInteropZodOutput<TContextSchema>> : never;
//#endregion
export { createMiddleware };
//# sourceMappingURL=middleware.d.ts.map