CreateAgentParamsAn optional checkpoint saver to persist the agent's state.
An optional schema for the context. It allows to pass in a typed context object into the agent
invocation and allows to access it in hooks such as prompt and middleware.
As opposed to the agent state, defined in stateSchema, the context is not persisted between
agent invocations.
const agent = createAgent({
llm: model,
tools: [getWeather],
contextSchema: z.object({
capital: z.string(),
}),
prompt: (state, config) => {
return [
new SystemMessage(`You are a helpful assistant. The capital of France is ${config.context.capital}.`),
];
},
});
const result = await agent.invoke({
messages: [
new SystemMessage("You are a helpful assistant."),
new HumanMessage("What is the capital of France?"),
],
}, {
context: {
capital: "Paris",
},
});An optional description for the agent. This can be used to describe the agent to the underlying supervisor LLM.
Use to specify how to expose the agent name to the underlying supervisor LLM.
undefined: Relies on the LLM provider AIMessage#name. Currently, only OpenAI supports this."inline": Add the agent name directly into the content field of the AIMessage using XML-style tags.
Example: "How can I help you" -> "<name>agent_name</name><content>How can I help you?</content>"Middleware instances to run during agent execution. Each middleware can define its own state schema and hook into the agent lifecycle.
Defines a model to use for the agent. You can either pass in an instance of a LangChain chat model or a string. If a string is provided the agent initializes a ChatModel based on the provided model name and provider. It supports various model providers and allows for runtime configuration of model parameters.
const agent = createAgent({
model: "anthropic:claude-3-7-sonnet-latest",
// ...
});import { ChatOpenAI } from "@langchain/openai";
const agent = createAgent({
model: new ChatOpenAI({ model: "gpt-4o" }),
// ...
});An optional name for the agent.
An optional schema for the final agent output.
If provided, output will be formatted to match the given schema and returned in the 'structuredResponse' state key.
If not provided, structuredResponse will not be present in the output state.
Can be passed in as:
const agent = createAgent({
responseFormat: z.object({
capital: z.string(),
}),
// ...
});
const agent = createAgent({
responseFormat: {
type: "json_schema",
schema: {
type: "object",
properties: {
capital: { type: "string" },
},
required: ["capital"],
},
},
// ...
});
import { providerStrategy, toolStrategy } from "langchain";
const agent = createAgent({
responseFormat: providerStrategy(
z.object({
capital: z.string(),
})
),
// or
responseFormat: [
toolStrategy({ ... }),
toolStrategy({ ... }),
]
// ...
});
Note: The graph will make a separate call to the LLM to generate the structured response after the agent loop is finished. This is not the only strategy to get structured responses, see more options in this guide.
An optional abort signal that indicates that the overall operation should be aborted.
An optional schema for the agent state. It allows you to define custom state properties that persist across agent invocations and can be accessed in hooks, middleware, and throughout the agent's execution. The state is persisted when using a checkpointer and can be updated by middleware or during execution.
As opposed to the context (defined in contextSchema), the state is persisted between agent invocations
when using a checkpointer, making it suitable for maintaining conversation history, user preferences,
or any other data that should persist across multiple interactions.
import { z } from "zod";
import { createAgent } from "@langchain/langgraph";
const agent = createAgent({
model: "openai:gpt-4o",
tools: [getWeather],
stateSchema: z.object({
userPreferences: z.object({
temperatureUnit: z.enum(["celsius", "fahrenheit"]).default("celsius"),
location: z.string().optional(),
}).optional(),
conversationCount: z.number().default(0),
}),
prompt: (state, config) => {
const unit = state.userPreferences?.temperatureUnit || "celsius";
return [
new SystemMessage(`You are a helpful assistant. Use ${unit} for temperature.`),
];
},
});
const result = await agent.invoke({
messages: [
new HumanMessage("What's the weather like?"),
],
userPreferences: {
temperatureUnit: "fahrenheit",
location: "New York",
},
conversationCount: 1,
});An optional store to persist the agent's state.
Stream transformer factories baked into the compiled graph. These run
automatically for every streamEvents(..., { version: "v3" }) call, after the built-in
agent transformers (tool calls, middleware) and before any call-site
transformers passed via
streamEvents(input, { version: "v3", transformers }).
Use this to add domain-specific streaming projections that should always
be available on the agent's run stream. The projection values are
accessible via run.extensions.
import { StreamChannel } from "@langchain/langgraph";
const costTracker = () => ({
init: () => ({ cost: StreamChannel.remote<number>("cost") }),
process(event) {
// track token costs...
return true;
},
});
const agent = createAgent({
model: "openai:gpt-4o",
tools: [myTool],
streamTransformers: [costTracker],
});
const run = await agent.streamEvents({ messages }, { version: "v3" });
for await (const c of run.extensions.cost) {
console.log("cost delta:", c);
}An optional system message for the model.
Use a string for simple, static system prompts. This is the most common use case
and works well with template literals for dynamic content. When a string is provided,
it's converted to a single text block internally.
Use a SystemMessage when you need advanced features that require structured content:
SystemMessage with array content to enable per-block
cache control settings (e.g., cache_control: { type: "ephemeral" }). This allows you
to have different cache settings for different parts of your system prompt.SystemMessage instances.const agent = createAgent({
model: "anthropic:claude-sonnet-4-5",
systemPrompt: "You are a helpful assistant.",
// ...
});const userRole = "premium";
const agent = createAgent({
model: "anthropic:claude-sonnet-4-5",
systemPrompt: `You are a helpful assistant for ${userRole} users.`,
// ...
});import { SystemMessage } from "@langchain/core/messages";
const agent = createAgent({
model: "anthropic:claude-sonnet-4-5",
systemPrompt: new SystemMessage({
content: [
{
type: "text",
text: "You are a helpful assistant.",
},
{
type: "text",
text: "Today's date is 2024-06-01.",
cache_control: { type: "ephemeral" },
},
],
}),
// ...
});import { SystemMessage } from "@langchain/core/messages";
const agent = createAgent({
model: "anthropic:claude-sonnet-4-5",
systemPrompt: new SystemMessage("You are a helpful assistant."),
// ...
});A list of tools or a ToolNode.
import { tool } from "langchain";
const weatherTool = tool(() => "Sunny!", {
name: "get_weather",
description: "Get the weather for a location",
schema: z.object({
location: z.string().describe("The location to get weather for"),
}),
});
const agent = createAgent({
tools: [weatherTool],
// ...
});Determines the version of the graph to create.
Can be one of
"v1": The tool node processes the full AIMessage containing all tool calls. All tool
calls are executed concurrently via Promise.all inside a single graph node.
Choose v1 when your tools invoke sub-graphs or other long-running async work
and you need true parallelism — the Promise.all approach is unaffected by
LangGraph's per-task checkpoint serialisation.
"v2": Each tool call is dispatched as an independent graph task using the Send API.
Tasks are scheduled in parallel by LangGraph, but when tools invoke sub-graphs
the underlying checkpoint writes can cause effective serialisation, making
concurrent tool calls execute sequentially. v2 is the better choice when you
need per-tool-call checkpointing, independent fault isolation, or interrupt()
support inside individual tool calls.