ReAct (Reasoning + Acting) agent implementation combining language models with tools and middleware.
function createAgent<
T extends Record<string, any> = Record<string, any>,
StateSchema extends AnyAnnotationRoot | InteropZodObject | undefined = undefined,
ContextSchema extends AnyAnnotationRoot | InteropZodObject = AnyAnnotationRoot,
TMiddleware extends readonly AgentMiddleware[] = readonly AgentMiddleware[]
>(
params: CreateAgentParams<T, StateSchema, ContextSchema>
): ReactAgent<T, StateSchema, ContextSchema, TMiddleware>;
interface CreateAgentParams<
StructuredResponseType extends Record<string, any> = Record<string, any>,
StateSchema extends AnyAnnotationRoot | InteropZodObject | undefined = undefined,
ContextSchema extends AnyAnnotationRoot | InteropZodObject = AnyAnnotationRoot
> {
model: string | LanguageModelLike;
tools?: (ServerTool | ClientTool)[];
systemPrompt?: string | SystemMessage;
stateSchema?: StateSchema;
contextSchema?: ContextSchema;
checkpointer?: BaseCheckpointSaver | boolean;
store?: BaseStore;
responseFormat?: InteropZodType<StructuredResponseType> | JsonSchemaFormat | ResponseFormat;
middleware?: readonly AgentMiddleware[];
name?: string;
description?: string;
includeAgentName?: "inline" | undefined;
signal?: AbortSignal;
version?: "v1" | "v2";
}Key Parameters:
model: String ("openai:gpt-4o") or model instancetools: Array of ServerTool or ClientToolsystemPrompt: String or SystemMessage (for cache control)stateSchema: Custom state schema (persisted with checkpointer)contextSchema: Runtime context schema (not persisted)checkpointer: State persistence (boolean for default or BaseCheckpointSaver instance)store: Long-term memory storageresponseFormat: Zod schema, JSON schema, or tool/provider strategy for structured outputmiddleware: Array of middleware instancesversion: "v1" (parallel tool execution) or "v2" (distributed via Send API)Example:
import { createAgent, tool } from "langchain";
import { z } from "zod";
const search = tool(
({ query }) => `Results for: ${query}`,
{
name: "search",
description: "Search for information",
schema: z.object({ query: z.string() }),
}
);
// Basic agent
const agent = createAgent({
model: "openai:gpt-4o",
tools: [search],
systemPrompt: "You are a search assistant.",
});
// With custom state
const statefulAgent = createAgent({
model: "openai:gpt-4o",
tools: [search],
stateSchema: z.object({
userPreferences: z.object({
language: z.string().default("en"),
}).optional(),
}),
});
// With structured output
const extractorAgent = createAgent({
model: "openai:gpt-4o",
responseFormat: z.object({
name: z.string(),
email: z.string(),
}),
});class ReactAgent<
StructuredResponseFormat extends Record<string, any> | ResponseFormatUndefined = Record<string, any>,
StateSchema extends AnyAnnotationRoot | InteropZodObject | undefined = undefined,
ContextSchema extends AnyAnnotationRoot | InteropZodObject = AnyAnnotationRoot,
TMiddleware extends readonly AgentMiddleware[] = readonly AgentMiddleware[]
> {
invoke(
state: UserInput<StateSchema> & InferMiddlewareInputStates<TMiddleware>,
config?: InvokeConfiguration<InferContextInput<ContextSchema> & InferMiddlewareContextInputs<TMiddleware>>
): Promise<MergedAgentState<StateSchema, StructuredResponseFormat, TMiddleware>>;
stream<TStreamMode extends StreamMode | StreamMode[] | undefined>(
state: UserInput<StateSchema> & InferMiddlewareInputStates<TMiddleware>,
config?: StreamConfiguration<InferContextInput<ContextSchema> & InferMiddlewareContextInputs<TMiddleware>, TStreamMode>
): Promise<IterableReadableStream<StreamOutputMap<TStreamMode, ...>>>;
drawMermaidPng(params?: DrawMermaidParams): Promise<Uint8Array>;
drawMermaid(params?: DrawMermaidParams): Promise<string>;
}
interface DrawMermaidParams {
withStyles?: boolean;
curveStyle?: string;
nodeColors?: Record<string, string>;
wrapLabelNWords?: number;
backgroundColor?: string;
}Example:
// Invoke
const result = await agent.invoke({
messages: [{ role: "user", content: "Search for AI news" }],
});
// Stream with values mode
const stream = await agent.stream(
{ messages: [{ role: "user", content: "Search" }] },
{ streamMode: "values" }
);
for await (const chunk of stream) {
console.log(chunk);
}
// With checkpointing
import { MemorySaver } from "@langchain/langgraph";
const persistentAgent = createAgent({
model: "openai:gpt-4o",
tools: [search],
checkpointer: new MemorySaver(),
});
await persistentAgent.invoke(
{ messages: [{ role: "user", content: "My name is Alice" }] },
{ configurable: { thread_id: "user-123" } }
);
const result = await persistentAgent.invoke(
{ messages: [{ role: "user", content: "What's my name?" }] },
{ configurable: { thread_id: "user-123" } }
);
// Agent remembers: "Your name is Alice"interface BuiltInState {
messages: BaseMessage[];
__interrupt__?: Interrupt[];
jumpTo?: JumpToTarget;
}
type UserInput<TStateSchema extends AnyAnnotationRoot | InteropZodObject | undefined = undefined> =
InferSchemaInput<TStateSchema> & { messages: Array<BaseMessage | { role: string; content: string }> };
type JumpToTarget = "model_request" | "tools";
type MergedAgentState<StateSchema, StructuredResponseFormat, TMiddleware extends readonly AgentMiddleware[]> =
BuiltInState & InferSchemaInput<StateSchema> & InferMiddlewareStates<TMiddleware> & {
structuredResponse?: StructuredResponseFormat;
};interface InvokeConfiguration<TContext = unknown> {
context?: TContext;
configurable?: Record<string, any>;
store?: BaseStore;
signal?: AbortSignal;
recursionLimit?: number;
}
interface StreamConfiguration<TContext = unknown, TStreamMode = unknown, TEncoding = unknown>
extends InvokeConfiguration<TContext> {
streamMode?: TStreamMode;
encoding?: TEncoding;
}
type StreamMode = "values" | "updates" | "messages" | "debug";type ResponseFormat =
| InteropZodType<any>
| InteropZodType<any>[]
| JsonSchemaFormat
| JsonSchemaFormat[]
| ToolStrategy<any>
| TypedToolStrategy<any>
| ProviderStrategy<any>;
type ResponseFormatUndefined = symbol;
interface JsonSchemaFormat {
type: "json_schema";
schema: Record<string, any>;
name?: string;
strict?: boolean;
}
function toolStrategy<T extends Record<string, any>>(
schema: InteropZodType<T>,
options?: ToolStrategyOptions
): ToolStrategy<T>;
function providerStrategy<T extends Record<string, any>>(
schema: InteropZodType<T>
): ProviderStrategy<T>;
interface ToolStrategyOptions {
name?: string;
description?: string;
}Structured Output Examples:
import { createAgent, toolStrategy, providerStrategy } from "langchain";
import { z } from "zod";
const schema = z.object({
title: z.string(),
summary: z.string(),
});
// Zod schema (simplest)
const agent1 = createAgent({
model: "openai:gpt-4o",
responseFormat: schema,
});
// JSON Schema
const agent2 = createAgent({
model: "openai:gpt-4o",
responseFormat: {
type: "json_schema",
schema: {
type: "object",
properties: {
title: { type: "string" },
summary: { type: "string" },
},
required: ["title", "summary"],
},
},
});
// Tool strategy (for models without native structured output)
const agent3 = createAgent({
model: "anthropic:claude-3-sonnet",
responseFormat: toolStrategy(schema, {
name: "extract_info",
description: "Extract title and summary",
}),
});
// Provider strategy (uses model's native structured output)
const agent4 = createAgent({
model: "openai:gpt-4o",
responseFormat: providerStrategy(schema),
});
// Union types
const personSchema = z.object({ type: z.literal("person"), name: z.string() });
const companySchema = z.object({ type: z.literal("company"), name: z.string() });
const agent5 = createAgent({
model: "openai:gpt-4o",
responseFormat: [personSchema, companySchema],
});class MultipleToolsBoundError extends Error {}
class MultipleStructuredOutputsError extends Error {}
class StructuredOutputParsingError extends Error {}
class ToolInvocationError extends Error {}