# Technical Documentation: langchain-ai/langgraphjs

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/langchain-ai/langgraphjs)

### Overview (`.changeset/README.md`)

# Changesets

Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
with multi-package repos, or single-package repos to help you version and publish your code. You can
find the full documentation for it [in our repository](https://github.com/changesets/changesets)

We have a quick list of common questions to get you started engaging with this project in
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)

---

### Overview (`examples/ai-elements/README.md`)

# AI Elements — Tool-Calling Agent Example

A self-contained chat interface built with [AI Elements](https://elements.ai-sdk.dev/) components and `@langchain/react`. It demonstrates how to build a production-quality agentic UI using AI Elements' composable component library.

## What it shows

- **Tool call rendering** — each tool invocation is displayed with `Tool` + `ToolHeader` + `ToolContent` + `ToolInput` + `ToolOutput`, updating live as the agent streams tool input and then the result.
- **Reasoning display** — when the model emits reasoning tokens, a collapsible `Reasoning` block auto-opens during streaming and collapses when done.
- **Streaming messages** — `Message` + `MessageContent` + `MessageResponse` renders streaming markdown via Streamdown with full GFM support.
- **Loading skeleton** — a `Shimmer` placeholder appears between the user's message and the first assistant token.
- **Conversation scroll** — `Conversation` + `ConversationContent` + `ConversationScrollButton` auto-scrolls and shows a jump-to-bottom button when you scroll up.
- **Message actions** — `MessageActions` + `MessageAction` with a copy button appears below the last assistant message once streaming completes.
- **Prompt input** — `PromptInput` + `PromptInputBody` + `PromptInputTextarea` + `PromptInputFooter` + `PromptInputSubmit` provides a full-featured input bar.
- **Suggestions** — `Suggestions` + `Suggestion` shows preset prompts before the first message.

## Agent

The backing LangGraph agent (`packages/agents/src/agents/ai-elements.ts`) is a `createReactAgent` with two simulated tools:

| Tool          | Description                                                 |
| ------------- | ----------------------------------------------------------- |
| `get_weather` | Returns deterministic simulated weather data for any city   |
| `web_search`  | Returns three simulated search result objects for any query |

No external API keys are required for the tools.

## Setup

Create a `.env` file in this folder (optional — defaults are provided):

```bash
VITE_LANGGRAPH_API_URL=http://localhost:2024   # default when running locally
VITE_LANGGRAPH_ASSISTANT_ID=ai_elements         # matches langgraph.json
```

## Run

Start the LangGraph agent server first:

```bash
bun run dev --filter=@langchain/playground-agents
```

Then start this preview app:

```bash
bun run dev --filter=@langchain/playground-preview-ai-elements
```

Open [http://localhost:4600](http://localhost:4600).

## AI Elements components used

| Component                                                                                         | Source file                                   |
| ------------------------------------------------------------------------------------------------- | --------------------------------------------- |
| `Conversation`, `ConversationContent`, `ConversationScrollButton`                                 | `src/components/ai-elements/conversation.tsx` |
| `Message`, `MessageContent`, `MessageResponse`, `MessageActions`, `MessageAction`                 | `src/components/ai-elements/message.tsx`      |
| `PromptInput`, `PromptInputBody`, `PromptInputTextarea`, `PromptInputFooter`, `PromptInputSubmit` | `src/components/ai-elements/prompt-input.tsx` |
| `Tool`, `ToolHeader`, `ToolContent`, `ToolInput`, `ToolOutput`                                    | `src/components/ai-elements/tool.tsx`         |
| `Reasoning`, `ReasoningTrigger`, `ReasoningContent`                                               | `src/components/ai-elements/reasoning.tsx`    |
| `Suggestions`, `Suggestion`                                                                       | `src/components/ai-elements/suggestion.tsx`   |
| `Shimmer`                                                                                         | `src/components/ai-elements/shimmer.tsx`      |

Components live in `src/components/ai-elements/` and are owned by this package (shadcn/AI Elements registry style — copy-paste, not a node_modules import).

## Vite path alias

AI Elements components use bare `src/` imports (e.g. `import { cn } from "src/lib/utils"`). The `vite.config.ts` maps `src` → `./src` to resolve these correctly in both dev and production builds.

---

### Overview (`examples/assistant-ui-claude/README.md`)

# Assistant-UI Claude Example

This example combines:

- `@assistant-ui/react` for the Claude-style chat surface
- `@langchain/react` for streaming LangGraph state on the frontend
- a basic `langchain` agent on the backend

## What it shows

- A Claude-inspired assistant-ui thread and composer
- A local single-agent graph powered by `langchain`
- How to bridge `@langchain/react` state into assistant-ui with `useExternalStoreRuntime`

## Setup

Create a local `.env` file in this folder with:

```bash
OPENAI_API_KEY=your_openai_api_key
OPENAI_MODEL=gpt-4.1-mini
```

Optional overrides:

```bash
LANGGRAPH_API_URL=http://localhost:2024
VITE_LANGGRAPH_API_URL=http://localhost:2024
VITE_LANGGRAPH_ASSISTANT_ID=assistant-ui-claude
```

## Run

```bash
pnpm --filter @examples/assistant-ui-claude dev
```

Then open the Vite URL shown in the terminal, usually
[http://localhost:5173](http://localhost:5173).

The frontend talks directly to the LangGraph dev server at
`http://localhost:2024`, which serves the local `assistant-ui-claude` graph from
`langgraph.json`.

---

### Overview (`examples/streaming/README.md`)

# In-Process Streaming Examples

Runnable examples demonstrating `graph.streamEvents(..., { version: "v3" })` — the ergonomic in-process
streaming API for LangGraph.

## Setup

```bash
# From the monorepo root
pnpm install

# Set your API key
export ANTHROPIC_API_KEY=sk-...
```

## Examples

Each example is a self-contained script that can be run with `npx tsx`.

### `basic.ts` — Protocol event iteration

The simplest starting point. Iterates all `ProtocolEvent` objects from a tool-calling
graph and awaits the final output.

```bash
npx tsx src/basic.ts
```

Shows: `for await (const event of run)`, `await run.output`

### `messages.ts` — Streaming text tokens

Demonstrates the `.messages` projection. Each yielded `ChatModelStream` exposes
`.text` as both an `AsyncIterable<string>` (for token-by-token streaming) and a
`PromiseLike<string>` (for the full text). Also shows `.usage` for token counts.

```bash
npx tsx src/messages.ts
```

Shows: `run.messages`, `message.text`, `message.usage`

### `subgraphs.ts` — Recursive subgraph observation

A research pipeline with two sequential subgraphs (researcher → analyst). Shows
three ways to observe the subgraph tree:

1. Flat event stream — all events, dispatched by `event.method`
2. Subgraph discovery — `run.subgraphs` yields `SubgraphRunStream` per child
3. Concurrent consumption — messages and subgraphs consumed in parallel

```bash
npx tsx src/subgraphs.ts
```

Shows: `run.subgraphs`, `sub.messages`, `sub.name`, `sub.index`, recursive walking

### `custom-reducer.ts` — Domain-specific projections

Extends `streamEvents(..., { version: "v3" })` with a custom `StreamTransformer` that counts tool calls and
tracks token usage. The transformer is passed via the `transformers` option; its
projections appear on `run.extensions`.

```bash
npx tsx src/custom-reducer.ts
```

Shows: `StreamTransformer`, `graph.streamEvents(input, { version: "v3", transformers: [...] })`, `run.extensions`

### `parallel.ts` — Concurrent projection consumption

All projections on `GraphRunStream` share local stream channels, so
multiple `for await` loops can run concurrently without interference. This
example streams messages, counts state snapshots, and counts raw protocol
events in parallel via `Promise.all`.

```bash
npx tsx src/parallel.ts
```

Shows: `Promise.all([run.messages, run.values, run])`, independent cursors

### `human-in-the-loop.ts` — Interrupt, inspect, resume

Demonstrates the `streamEvents(..., { version: "v3" })` interrupt/resume lifecycle using a planner →
approval → executor graph. Turn 1 runs until `interrupt()` is called; the
example inspects `run.interrupted` and `run.interrupts`, then resumes with
`Command({ resume })` in turn 2.

```bash
npx tsx src/human-in-the-loop.ts
```

Shows: `interrupt()`, `run.interrupted`, `run.interrupts`, `Command({ resume })`, multi-turn `streamEvents(..., { version: "v3" })`

### `a2a.ts` — A2A protocol over a deployed server

End-to-end deployment example for custom stream transformers. The research
pipeline is compiled with an A2A transformer (`createA2ATransformer`) that emits
A2A-formatted status updates and artifacts. The graph is deployed via the
LangGraph dev server, and the SDK client subscribes to the `custom` channel
to receive only A2A events.

```bash
npx tsx src/a2a.ts
```

Shows: `.compile({ transformers: [createA2ATransformer] })`, `streamStateV2()`, SDK `client.runs.stream()`, `streamMode: ["custom"]`

## Agents

The example agents live in `src/agents/` and `src/a2a/`:

| Agent | File | Description |
|-------|------|-------------|
| Simple tool graph | `agents/simple-tool-graph.ts` | Single ReAct loop with search + calculator |
| Research pipeline | `agents/research-pipeline.ts` | Two sequential subgraphs with separate tools |
| Approval graph | `agents/approval-graph.ts` | Planner → human approval → executor with interrupt/resume |
| A2A research | `a2a/agent.ts` | Research pipeline with A2A stream transformer at compile time |

## API Surface

All examples use the `GraphRunStream` returned by
`graph.streamEvents(..., { version: "v3" })`:

```typescript
const run = await graph.streamEvents(input, { ...options, version: "v3" });

// Iterate all protocol events
for await (const event of run) { ... }

// Stream AI messages with text/reasoning/usage projections
for await (const msg of run.messages) {
  for await (const token of msg.text) { process.stdout.write(token); }
  const fullText = await msg.text;
  const usage = await msg.usage;
}

// Observe subgraphs recursively
for await (const sub of run.subgraphs) {
  console.log(sub.name, sub.path);
  for await (const msg of sub.messages) { ... }
}

// Final output
const state = await run.output;

// State snapshots per step
for await (const snapshot of run.values) { ... }

// Messages from a specific node
for await (const msg of run.messagesFrom("agent")) { ... }

// Custom transformers
const run = await graph.streamEvents(input, {
  version: "v3",
  transformers: [myTransformer],
});
const custom = await run.extensions.myProjection;

// Human-in-the-loop
const run1 = await graph.streamEvents(input, { ...config, version: "v3" });
for await (const msg of run1.messages) { ... }
await run1.output;
if (run1.interrupted) {
  console.log(run1.interrupts);
  const run2 = await graph.streamEvents(
    new Command({ resume: userDecision }),
    { ...config, version: "v3" }
  );
}
```

## Coming Soon

Additional examples will be added for:

- `createAgent` — `AgentRunStream` with typed `run.toolCalls`
- `createDeepAgent` — `DeepAgentRunStream` with `run.subagents`
- Cancellation — `run.abort()`, `AbortSignal` passthrough

---

### Overview (`examples/ui-multimodal/README.md`)

# React + TypeScript + Vite

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Currently, two official plugins are available:

- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs)
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/)

## React Compiler

The React Compiler is enabled on this template. See [this documentation](https://react.dev/learn/react-compiler) for more information.

Note: This will impact Vite dev & build performances.

## Expanding the ESLint configuration

If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:

```js
export default defineConfig([
  globalIgnores(['dist']),
  {
    files: ['**/*.{ts,tsx}'],
    extends: [
      // Other configs...

      // Remove tseslint.configs.recommended and replace with this
      tseslint.configs.recommendedTypeChecked,
      // Alternatively, use this for stricter rules
      tseslint.configs.strictTypeChecked,
      // Optionally, add this for stylistic rules
      tseslint.configs.stylisticTypeChecked,

      // Other configs...
    ],
    languageOptions: {
      parserOptions: {
        project: ['./tsconfig.node.json', './tsconfig.app.json'],
        tsconfigRootDir: import.meta.dirname,
      },
      // other options...
    },
  },
])
```

You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:

```js
// eslint.config.js
import reactX from 'eslint-plugin-react-x'
import reactDom from 'eslint-plugin-react-dom'

export default defineConfig([
  globalIgnores(['dist']),
  {
    files: ['**/*.{ts,tsx}'],
    extends: [
      // Other configs...
      // Enable lint rules for React
      reactX.configs['recommended-typescript'],
      // Enable lint rules for React DOM
      reactDom.configs.recommended,
    ],
    languageOptions: {
      parserOptions: {
        project: ['./tsconfig.node.json', './tsconfig.app.json'],
        tsconfigRootDir: import.meta.dirname,
      },
      // other options...
    },
  },
])
```

---

### Overview (`examples/ui-react/README.md`)

# React + TypeScript + Vite

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Currently, two official plugins are available:

- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs)
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/)

## React Compiler

The React Compiler is enabled on this template. See [this documentation](https://react.dev/learn/react-compiler) for more information.

Note: This will impact Vite dev & build performances.

## Expanding the ESLint configuration

If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:

```js
export default defineConfig([
  globalIgnores(['dist']),
  {
    files: ['**/*.{ts,tsx}'],
    extends: [
      // Other configs...

      // Remove tseslint.configs.recommended and replace with this
      tseslint.configs.recommendedTypeChecked,
      // Alternatively, use this for stricter rules
      tseslint.configs.strictTypeChecked,
      // Optionally, add this for stylistic rules
      tseslint.configs.stylisticTypeChecked,

      // Other configs...
    ],
    languageOptions: {
      parserOptions: {
        project: ['./tsconfig.node.json', './tsconfig.app.json'],
        tsconfigRootDir: import.meta.dirname,
      },
      // other options...
    },
  },
])
```

You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:

```js
// eslint.config.js
import reactX from 'eslint-plugin-react-x'
import reactDom from 'eslint-plugin-react-dom'

export default defineConfig([
  globalIgnores(['dist']),
  {
    files: ['**/*.{ts,tsx}'],
    extends: [
      // Other configs...
      // Enable lint rules for React
      reactX.configs['recommended-typescript'],
      // Enable lint rules for React DOM
      reactDom.configs.recommended,
    ],
    languageOptions: {
      parserOptions: {
        project: ['./tsconfig.node.json', './tsconfig.app.json'],
        tsconfigRootDir: import.meta.dirname,
      },
      // other options...
    },
  },
])
```

---

### Overview (`internal/bench/README.md`)

# LangGraph Benchmarks

This package contains benchmarks for the LangGraph.js.

## Running the tests

```bash
yarn test
```

---

### Overview (`libs/checkpoint-mongodb/README.md`)

# @langchain/langgraph-checkpoint-mongodb

Implementation of a [LangGraph.js](https://github.com/langchain-ai/langgraphjs) CheckpointSaver that uses a MongoDB instance.

## Usage

```ts
import { MongoClient } from "mongodb";
import { MongoDBSaver } from "@langchain/langgraph-checkpoint-mongodb";

const writeConfig = {
  configurable: {
    thread_id: "1",
    checkpoint_ns: ""
  }
};
const readConfig = {
  configurable: {
    thread_id: "1"
  }
};


const client = new MongoClient(process.env.MONGODB_URL);

const checkpointer = new MongoDBSaver({ client });

// NOTE: you need to call .setup() the first time you're using your checkpointer
await checkpointer.setup();

const checkpoint = {
  v: 1,
  ts: "2024-07-31T20:14:19.804150+00:00",
  id: "1ef4f797-8335-6428-8001-8a1503f9b875",
  channel_values: {
    my_key: "meow",
    node: "node"
  },
  channel_versions: {
    __start__: 2,
    my_key: 3,
    "start:node": 3,
    node: 3
  },
  versions_seen: {
    __input__: {},
    __start__: {
      __start__: 1
    },
    node: {
      "start:node": 2
    }
  },
  pending_sends: [],
}

// store checkpoint
await checkpointer.put(writeConfig, checkpoint, {}, {});

// load checkpoint
await checkpointer.get(readConfig);

// list checkpoints
for await (const checkpoint of checkpointer.list(readConfig)) {
  console.log(checkpoint);
}

await client.close();
```

## TTL (Time-To-Live) Support

Automatically expire old checkpoints using MongoDB's TTL indexes:

```ts
import { MongoClient } from "mongodb";
import { MongoDBSaver } from "@langchain/langgraph-checkpoint-mongodb";

const client = new MongoClient(process.env.MONGODB_URL);

// Create checkpointer with 1-hour TTL (in seconds)
const checkpointer = new MongoDBSaver({
  client,
  ttl: 3600,
});

// Create TTL indexes (call during deployment/startup)
await checkpointer.setup();
```

When TTL is enabled:
- An `upserted_at` timestamp is added to each document on every write
- MongoDB automatically deletes documents after the TTL expires
- Each update resets the expiration timer

The `setup()` method creates the required TTL indexes. Call it during application startup or deployment. It is idempotent and handles concurrent calls safely.

---

### Overview (`libs/checkpoint-postgres/README.md`)

# @langchain/langgraph-checkpoint-postgres

Implementation of a [LangGraph.js](https://github.com/langchain-ai/langgraphjs) CheckpointSaver that uses a Postgres DB.

## Usage

```ts
import { PostgresSaver } from "@langchain/langgraph-checkpoint-postgres";

const writeConfig = {
  configurable: {
    thread_id: "1",
    checkpoint_ns: ""
  }
};
const readConfig = {
  configurable: {
    thread_id: "1"
  }
};

// you can optionally pass a configuration object as the second parameter
const checkpointer = PostgresSaver.fromConnString("postgresql://...", {
  schema: "schema_name" // defaults to "public"
});

// You must call .setup() the first time you use the checkpointer:
await checkpointer.setup();

const checkpoint = {
  v: 1,
  ts: "2024-07-31T20:14:19.804150+00:00",
  id: "1ef4f797-8335-6428-8001-8a1503f9b875",
  channel_values: {
    my_key: "meow",
    node: "node"
  },
  channel_versions: {
    __start__: 2,
    my_key: 3,
    "start:node": 3,
    node: 3
  },
  versions_seen: {
    __input__: {},
    __start__: {
      __start__: 1
    },
    node: {
      "start:node": 2
    }
  },
  pending_sends: [],
}

// store checkpoint
await checkpointer.put(writeConfig, checkpoint, {}, {});

// load checkpoint
await checkpointer.get(readConfig);

// list checkpoints
for await (const checkpoint of checkpointer.list(readConfig)) {
  console.log(checkpoint);
}
```

## Usage with existing connection pool

```ts
import { PostgresSaver } from "@langchain/langgraph-checkpoint-postgres";
import pg from "pg";

// You can use any existing postgres connection pool
// we create a new pool here for the sake of the example
const pool = new pg.Pool({
  connectionString: "postgresql://..."
});

const checkpointer = new PostgresSaver(pool, undefined, {
  schema: "schema_name"
});

await checkpointer.setup();

// ...
```

## Edge & serverless runtimes (Cloudflare Workers, etc.)

`PostgresSaver` uses [node-postgres (`pg`)](https://node-postgres.com/) under the hood, which opens a raw TCP/TLS connection via Node's `net`/`tls` modules. Some serverless/edge runtimes, most notably **Cloudflare Workers**, do not support raw outbound TCP connections from arbitrary code, so a direct connection (including the initial `await checkpointer.setup()`) will hang. This is the root cause for issues where the runtime reports that the Worker "had hung and would never generate a response".

This is a database-driver/runtime limitation, **not** a persistence-flush problem. LangGraph awaits all pending checkpoint writes before `invoke()`/`stream()` resolves (see the [base checkpoint package README](../checkpoint/README.md#when-are-checkpoints-persisted)), so as long as you `await` the run you do not need `ctx.waitUntil()` to keep the runtime alive for persistence.

To use Postgres checkpointing from Cloudflare Workers, route the connection through [Cloudflare Hyperdrive](https://developers.cloudflare.com/hyperdrive/), which exposes a `pg`-compatible connection string:

```ts
// wrangler.toml / wrangler.jsonc must enable `nodejs_compat` and bind a Hyperdrive instance:
//   compatibility_flags = ["nodejs_compat"]
//   [[hyperdrive]]
//   binding = "HYPERDRIVE"
//   id = "<your-hyperdrive-id>"

import { PostgresSaver } from "@langchain/langgraph-checkpoint-postgres";

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const checkpointer = PostgresSaver.fromConnString(
      env.HYPERDRIVE.connectionString
    );
    // ... compile and `await graph.invoke(...)` here ...
    // Persistence is complete once `invoke`/`stream` resolves.
    return new Response("ok");
  },
};
```

Alternatively, implement a thin `BaseCheckpointSaver` on top of an HTTP/WebSocket Postgres driver such as [`@neondatabase/serverless`](https://github.com/neondatabase/serverless) that is designed for edge runtimes.

> Note: standard Node.js, Deno, and Bun deployments are unaffected — `PostgresSaver` works there out of the box.

## Testing

Spin up testing PostgreSQL

```bash
docker-compose up -d && docker-compose logs -f
```

Then use the following connection string to initialize your checkpointer:

```ts
const testCheckpointer = PostgresSaver.fromConnString(
  "postgresql://user:password@localhost:5434/testdb"
);
```

---

### Overview (`libs/checkpoint-redis/README.md`)

# @langchain/langgraph-checkpoint-redis

Redis checkpoint and store implementation for LangGraph.

## Overview

This package provides Redis-based implementations for:

1. **Checkpoint Savers**: Store and manage LangGraph checkpoints using Redis
    - **RedisSaver**: Standard checkpoint saver that maintains full checkpoint history
    - **ShallowRedisSaver**: Memory-optimized saver that only keeps the latest checkpoint per thread
2. **RedisStore**: Redis-backed key-value store with optional vector search capabilities

## Installation

```bash
npm install @langchain/langgraph-checkpoint-redis
```

## Dependencies

### Redis Requirements

This library requires Redis with the following modules:

- **RedisJSON** - For storing and manipulating JSON data
- **RediSearch** - For search and indexing capabilities

#### Redis 8.0+

If you're using Redis 8.0 or higher, both RedisJSON and RediSearch modules are included by default.

#### Redis < 8.0

For Redis versions lower than 8.0, you'll need to:

- Use [Redis Stack](https://redis.io/docs/stack/), which bundles Redis with these modules
- Or install the modules separately in your Redis instance

## Usage

### Standard Checkpoint Saver

```typescript
import { RedisSaver } from "@langchain/langgraph-checkpoint-redis";

const checkpointer = await RedisSaver.fromUrl(
    "redis://localhost:6379",
    {
        defaultTTL: 60, // TTL in minutes
        refreshOnRead: true
    }
);

// Indices are automatically created by fromUrl()

// Use with your graph
const config = {configurable: {thread_id: "1"}};

// Metadata must include required fields
const metadata = {
    source: "update",  // "update" | "input" | "loop" | "fork"
    step: 0,
    parents: {}
};

await checkpointer.put(config, checkpoint, metadata, {});
const loaded = await checkpointer.get(config);
```

### Shallow Checkpoint Saver

The `ShallowRedisSaver` is a memory-optimized variant that only keeps the latest checkpoint per thread:

```typescript
import { ShallowRedisSaver } from "@langchain/langgraph-checkpoint-redis/shallow";

// Create a shallow saver that only keeps the latest checkpoint
const shallowSaver = await ShallowRedisSaver.fromUrl("redis://localhost:6379");

// Use it the same way as RedisSaver
const config = {
    configurable: {
        thread_id: "my-thread",
        checkpoint_ns: "my-namespace"
    }
};

const metadata = {
    source: "update",
    step: 0,
    parents: {}
};

await shallowSaver.put(config, checkpoint, metadata, versions);

// Only the latest checkpoint is kept - older ones are automatically cleaned up
const latest = await shallowSaver.getTuple(config);
```

Key differences from RedisSaver:

- **Storage**: Only keeps the latest checkpoint per thread (no history)
- **Performance**: Reduced storage usage and faster operations
- **Inline storage**: Channel values are stored inline (no separate blob storage)
- **Automatic cleanup**: Old checkpoints and writes are automatically removed

### RedisStore

The `RedisStore` provides a key-value store with optional vector search capabilities:

```typescript
import { RedisStore } from "@langchain/langgraph-checkpoint-redis/store";

// Basic key-value store
const store = await RedisStore.fromConnString("redis://localhost:6379");

// Store with vector search
const vectorStore = await RedisStore.fromConnString("redis://localhost:6379", {
    index: {
        dims: 1536,  // Embedding dimensions
        embed: embeddings,  // Your embeddings instance
        distanceType: "cosine",  // or "l2", "ip"
        fields: ["text"],  // Fields to embed
    },
    ttl: {
        defaultTTL: 60,  // TTL in minutes
        refreshOnRead: true,
    }
});

// Put and get items
await store.put(["namespace", "nested"], "key1", {text: "Hello world"});
const item = await store.get(["namespace", "nested"], "key1");

// Search with namespace filtering
const results = await store.search(["namespace"], {
    filter: {category: "docs"},
    limit: 10,
});

// Vector search
const semanticResults = await vectorStore.search(["namespace"], {
    query: "semantic search query",
    filter: {type: "article"},
    limit: 5,
});

// Batch operations
const ops = [
    {type: "get", namespace: ["ns"], key: "key1"},
    {type: "put", namespace: ["ns"], key: "key2", value: {data: "value"}},
    {type: "search", namespacePrefix: ["ns"], limit: 10},
    {type: "list_namespaces", matchConditions: [{matchType: "prefix", path: ["ns"]}], limit: 10},
];
const results = await store.batch(ops);
```

## TTL Support

Both checkpoint savers and stores support Time-To-Live (TTL) functionality:

```typescript
const ttlConfig = {
    defaultTTL: 60,  // Default TTL in minutes
    refreshOnRead: true,  // Refresh TTL when items are read
};

const checkpointer = await RedisSaver.fromUrl("redis://localhost:6379", ttlConfig);
```

## Edge & serverless runtimes (Cloudflare Workers, etc.)

The Redis savers and store use [node-redis](https://github.com/redis/node-redis) (`createClient`/`createCluster`), which opens a raw TCP/TLS socket via Node's `net`/`tls` modules. Some serverless/edge runtimes, most notably **Cloudflare Workers**, do not support raw outbound TCP connections, so connecting (and the initial index setup) will hang. This is the root cause for issues where the runtime reports that the Worker "had hung and would never generate a response".

This is a client/runtime limitation, **not** a persistence-flush problem. LangGraph awaits all pending checkpoint writes before `invoke()`/`stream()` resolves (see the [base checkpoint package README](../checkpoint/README.md#when-are-checkpoints-persisted)), so as long as you `await` the run you do not need `ctx.waitUntil()` to keep the runtime alive for persistence.

Cloudflare Hyperdrive only supports Postgres/MySQL, so it cannot front Redis. To use Redis-backed persistence from Cloudflare Workers, use an HTTP-based Redis service such as [Upstash Redis](https://upstash.com/docs/redis/sdks/ts/overview) (`@upstash/redis`, which speaks REST and works in Workers) behind a small custom `BaseCheckpointSaver` implementation, rather than `RedisSaver`/`ShallowRedisSaver`.

> Note: standard Node.js, Deno, and Bun deployments are unaffected — the Redis savers work there out of the box.

## Development

### Running Tests

```bash
# Run tests (uses TestContainers)
yarn test

# Run tests in watch mode
yarn test:watch

# Run integration tests
yarn test:int
```

## License

MIT

---

### Overview (`libs/checkpoint-sqlite/README.md`)

# @langchain/langgraph-checkpoint-sqlite

Implementation of a [LangGraph.js](https://github.com/langchain-ai/langgraphjs) CheckpointSaver that uses a SQLite DB.

## Usage

```ts
import { SqliteSaver } from "@langchain/langgraph-checkpoint-sqlite";

const writeConfig = {
  configurable: {
    thread_id: "1",
    checkpoint_ns: ""
  }
};
const readConfig = {
  configurable: {
    thread_id: "1"
  }
};

const checkpointer = SqliteSaver.fromConnString(":memory:");
const checkpoint = {
  v: 1,
  ts: "2024-07-31T20:14:19.804150+00:00",
  id: "1ef4f797-8335-6428-8001-8a1503f9b875",
  channel_values: {
    my_key: "meow",
    node: "node"
  },
  channel_versions: {
    __start__: 2,
    my_key: 3,
    "start:node": 3,
    node: 3
  },
  versions_seen: {
    __input__: {},
    __start__: {
      __start__: 1
    },
    node: {
      "start:node": 2
    }
  },
  pending_sends: [],
}

// store checkpoint
await checkpointer.put(writeConfig, checkpoint, {}, {})

// load checkpoint
await checkpointer.get(readConfig)

// list checkpoints
for await (const checkpoint of checkpointer.list(readConfig)) {
  console.log(checkpoint);
}
```

---

### Overview (`libs/checkpoint-validation/README.md`)

# @langchain/langgraph-checkpoint-validation

The checkpointer validation tool is used to validate that custom checkpointer implementations conform to LangGraph's requirements. LangGraph uses [checkpointers](https://langchain-ai.github.io/langgraphjs/concepts/persistence/#checkpointer-libraries) for persisting workflow state, providing the ability to "rewind" your workflow to some earlier point in time, and continue execution from there.

The tool requires Node.js 20, 22, or 24 and later.

The overall process for using this tool is as follows:

1. Write your custom checkpointer implementation.
2. Add a file to your project that defines a [`CheckpointerTestInitializer`](./src/types.ts) as its default export.
3. Run the checkpointer validation tool to test your checkpointer and determine whether it meets LangGraph's requirements.
4. Iterate on your custom checkpointer as required, until tests pass.

The tool can be executed from the terminal as a CLI, or you can use it as a library to integrate it into your test suite.

## Writing a CheckpointerTestInitializer

The `CheckpointerTestInitializer` interface ([example](./src/tests/postgres_initializer.ts)) is used by the test harness to create instances of your custom checkpointer, and any infrastructure that it requires for testing purposes.

If you intend to execute the tool via the CLI, your `CheckpointerTestInitializer` **must** be the default export of the module in which it is defined.

**Synchronous vs Asynchronous initializer functions**: You may return promises from any functions defined in your `CheckpointerTestInitializer` according to your needs and the test harness will behave accordingly.

**IMPORTANT**: You must take care to write your `CheckpointerTestInitializer` such that instances of your custom checkpointer are isolated from one another with respect to persisted state, or else some tests (particularly the ones that exercise the `list` method) will fail. That is, state written by one instance of your checkpointer MUST NOT be readable by another instance of your checkpointer. That said, there will only ever be one instance of your checkpointer live at any given time, so **you may use shared storage, provided it is cleared when your checkpointer is created or destroyed.** The structure of the `CheckpointerTestInitializer` interface should make this relatively easy to achieve, per the sections below.


### (Required) `checkpointerName`: Define a name for your checkpointer

`CheckpointerTestInitializer` requires you to define a `checkpointerName` field (of type `string`) for use in the test output.

### `beforeAll`: Set up required infrastructure

If your checkpointer requires some external infrastructure to be provisioned, you may wish to provision this via the **optional** `beforeAll` function. This function executes exactly once, at the very start of the testing lifecycle. If defined, it is the first function that will be called from your `CheckpointerTestInitializer`.

**Timeout duration**: If your `beforeAll` function may take longer than 10 seconds to execute, you can assign a custom timeout duration (as milliseconds) to the optional `beforeAllTimeout` field of your `CheckpointerTestInitializer`.

**State isolation note**: Depending on the cost/performance/requirements of your checkpointer infrastructure, it **may** make more sense for you to provision it during the `createCheckpointer` step, so you can provide each checkpointer instance with its own isolated storage backend. However as mentioned above, you may also provision a single shared storage backend, provided you clear any stored data during the `createCheckpointer` or `destroyCheckpointer` step.

### `afterAll`: Tear down required infrastructure

If you set up infrastructure during the `beforeAll` step, you may need to tear it down once the tests complete their execution. You can define this teardown logic in the optional `afterAll` function. Much like `beforeAll` this function will execute exactly one time, after all tests have finished executing.

**IMPORTANT**: If you kill the test runner early this function may not be called. To avoid manual clean-up, give preference to test infrastructure management tools like [TestContainers](https://testcontainers.com/guides/getting-started-with-testcontainers-for-nodejs/), as these tools are designed to detect when this happens and clean up after themselves once the controlling process dies.

### (Required) `createCheckpointer`: Construct your checkpointer

`CheckpointerTestInitializer` requires you to define a `createCheckpointer()` function that returns an instance of your custom checkpointer.

**State isolation note:** If you're provisioning storage during this step, make sure that it is "fresh" storage for each instance of your checkpointer. Otherwise if you are using a shared storage setup, be sure to clear it either in this function, or in the `destroyCheckpointer` function (described in the section below).

### `destroyCheckpointer`: Destroy your checkpointer

If your custom checkpointer requires an explicit teardown step (for example, to clean up database connections), you can define this in the **optional** `destroyCheckpointer(checkpointer: CheckpointerT)` function.

**State isolation note:** If you are using a shared storage setup, be sure to clear it either in this function, or in the `createCheckpointer` function (described in the section above).

## CLI usage

You may use this tool's CLI either via `npx`, `yarn dlx`, or by installing globally and executing it via the `validate-checkpointer` command.

The only required argument to the tool is the import path for your `CheckpointerTestInitializer`. Relative paths must begin with a leading `./` (or `.\`, for Windows), otherwise the path will be interpreted as a module name rather than a relative path.

You may optionally pass one or more test filters as positional arguments after the import path argument (separated by spaces). Valid values are `getTuple`, `list`, `put`, and `putWrites`. If present, only the test suites specified in the filter list will be executed. This is useful for working through smaller sets of test failures as you're validating your checkpointer.

TypeScript imports **are** supported, so you may pass a path directly to your TypeScript source file.

### NPX & Yarn execution

NPX:

```bash
npx @langchain/langgraph-checkpoint-validation ./src/my_initializer.ts
```

Yarn:

```bash
yarn dlx @langchain/langgraph-checkpoint-validation ./src/my_initializer.ts
```

### Global install

NPM:

```bash
npm install @langchain/langgraph-checkpoint-validation
validate-checkpointer ./src/my_initializer.ts
```

## Usage in existing Jest-like test suite

This package exports a test definition function that may be used in any Jest-compatible test framework (including Vitest). If you wish to integrate this tooling into your existing test suite, you can simply import and invoke it from within a test file, as shown below.

```ts
import { validate } from "@langchain/langgraph-validation";

validate(MyCheckpointerInitializer);
```

---

### Overview (`libs/checkpoint/README.md`)

# @langchain/langgraph-checkpoint

This library defines the base interface for [LangGraph.js](https://github.com/langchain-ai/langgraphjs) checkpointers. Checkpointers provide persistence layer for LangGraph. They allow you to interact with and manage the graph's state. When you use a graph with a checkpointer, the checkpointer saves a _checkpoint_ of the graph state at every superstep, enabling several powerful capabilities like human-in-the-loop, "memory" between interactions and more.

## Key concepts

### Checkpoint

Checkpoint is a snapshot of the graph state at a given point in time. Checkpoint tuple refers to an object containing checkpoint and the associated config, metadata and pending writes.

### Thread

Threads enable the checkpointing of multiple different runs, making them essential for multi-tenant chat applications and other scenarios where maintaining separate states is necessary. A thread is a unique ID assigned to a series of checkpoints saved by a checkpointer. When using a checkpointer, you must specify a `thread_id` and optionally `checkpoint_id` when running the graph.

- `thread_id` is simply the ID of a thread. This is always required
- `checkpoint_id` can optionally be passed. This identifier refers to a specific checkpoint within a thread. This can be used to kick of a run of a graph from some point halfway through a thread.

You must pass these when invoking the graph as part of the configurable part of the config, e.g.

```ts
{ configurable: { thread_id: "1" } }  // valid config
{ configurable: { thread_id: "1", checkpoint_id: "0c62ca34-ac19-445d-bbb0-5b4984975b2a" } }  // also valid config
```

### Serde

`@langchain/langgraph-checkpoint` also defines protocol for serialization/deserialization (serde) and provides an default implementation that handles a range of types.

### Pending writes

When a graph node fails mid-execution at a given superstep, LangGraph stores pending checkpoint writes from any other nodes that completed successfully at that superstep, so that whenever we resume graph execution from that superstep we don't re-run the successful nodes.

### When are checkpoints persisted

By default (`durability: "async"`) checkpoint writes are dispatched in the background while the graph keeps executing, which keeps runs fast. Regardless of the `durability` mode, LangGraph **awaits all outstanding checkpointer writes before `invoke()` / `stream()` resolves**, `invoke()` fully drains the underlying stream, and the stream awaits every pending checkpointer promise before it completes.

In practice this means:

- If you `await graph.invoke(...)` (or fully consume `for await (... of graph.stream(...))`), persistence is guaranteed to be complete by the time the call returns. You do **not** need to keep the process/runtime alive for any trailing background writes.
- On serverless/edge runtimes (e.g. Cloudflare Workers) you therefore do not need `ctx.waitUntil()` to flush checkpoints, just make sure you `await` the run before returning a response. The only way to orphan writes is to start a stream and never consume it (e.g. piping `graph.stream()` into a detached, un-awaited task).

> Note: this guarantees the *write was issued and awaited*, not that your database driver works in a given runtime. See the runtime-compatibility notes in the [Postgres](../checkpoint-postgres/README.md#edge--serverless-runtimes-cloudflare-workers-etc) and [Redis](../checkpoint-redis/README.md#edge--serverless-runtimes-cloudflare-workers-etc) checkpointer READMEs.

## Interface

Each checkpointer should conform to `BaseCheckpointSaver` interface and must implement the following methods:

- `.put` - Store a checkpoint with its configuration and metadata.
- `.putWrites` - Store intermediate writes linked to a checkpoint (i.e. pending writes).
- `.getTuple` - Fetch a checkpoint tuple using for a given configuration (`thread_id` and `thread_ts`).
- `.list` - List checkpoints that match a given configuration and filter criteria.

## Usage

```ts
import { MemorySaver } from "@langchain/langgraph-checkpoint";

const writeConfig = {
  configurable: {
    thread_id: "1",
    checkpoint_ns: ""
  }
};
const readConfig = {
  configurable: {
    thread_id: "1"
  }
};

const checkpointer = new MemorySaver();
const checkpoint = {
  v: 1,
  ts: "2024-07-31T20:14:19.804150+00:00",
  id: "1ef4f797-8335-6428-8001-8a1503f9b875",
  channel_values: {
    my_key: "meow",
    node: "node"
  },
  channel_versions: {
    __start__: 2,
    my_key: 3,
    "start:node": 3,
    node: 3
  },
  versions_seen: {
    __input__: {},
    __start__: {
      __start__: 1
    },
    node: {
      "start:node": 2
    }
  },
  pending_sends: [],
}

// store checkpoint
await checkpointer.put(writeConfig, checkpoint, {}, {})

// load checkpoint
await checkpointer.get(readConfig)

// list checkpoints
for await (const checkpoint of checkpointer.list(readConfig)) {
  console.log(checkpoint);
}
```

---

### Overview (`libs/create-langgraph/README.md`)

# create-langgraph

[](https://www.npmjs.com/package/create-langgraph)
[](https://opensource.org/licenses/MIT)

The official scaffolding tool for [LangGraph.js](https://langchain-ai.github.io/langgraphjs/) projects. Quickly bootstrap new LangGraph applications from curated templates or generate configuration files for existing projects.

## Quick Start

Create a new LangGraph project with a single command:

```bash
# Using npm
npm init langgraph@latest

# Using yarn
yarn create langgraph

# Using pnpm
pnpm create langgraph

# Using pnpm
pnpm create langgraph

# Using bun
bunx create-langgraph
```

Follow the interactive prompts to select a template and configure your project.

## Templates

Choose from a variety of production-ready templates:

| Template                                                                             | Description                                                     |
| ------------------------------------------------------------------------------------ | --------------------------------------------------------------- |
| [**New LangGraph Project**](https://github.com/langchain-ai/new-langgraphjs-project) | A simple, minimal chatbot with memory                           |
| [**ReAct Agent**](https://github.com/langchain-ai/react-agent-js)                    | A flexible agent that can be extended with many tools           |
| [**Memory Agent**](https://github.com/langchain-ai/memory-agent-js)                  | A ReAct-style agent with persistent memory across conversations |
| [**Retrieval Agent**](https://github.com/langchain-ai/retrieval-agent-template-js)   | An agent with retrieval-based question-answering                |
| [**Data-enrichment Agent**](https://github.com/langchain-ai/data-enrichment-js)      | An agent that performs web searches and organizes findings      |

### Using a Specific Template

Skip the interactive prompt by specifying a template directly:

```bash
npx create-langgraph@latest my-project --template react-agent-js
```

Available template IDs:

- `new-langgraph-project-js`
- `react-agent-js`
- `memory-agent-js`
- `retrieval-agent-js`
- `data-enrichment-js`

## Commands

### `create-langgraph [path]`

Creates a new LangGraph project at the specified path.

```bash
npx create-langgraph@latest my-awesome-agent
```

**Options:**

- `-t, --template <template>` — Use a specific template (skips interactive selection)

**What it does:**

1. Downloads the selected template from GitHub
2. Extracts it to your target directory
3. Optionally initializes a Git repository
4. Provides next steps for getting started

### `create-langgraph config [path]`

Scans your project for LangGraph agents and generates a `langgraph.json` configuration file.

```bash
# In your project directory
npx create-langgraph@latest config

# Or specify a path
npx create-langgraph@latest config ./my-project
```

This command is useful when:

- You have an existing project and want to add LangGraph Platform support
- You've added new agents and need to update your configuration
- You want to automatically detect all agents in your codebase

## Agent Detection

The `config` command automatically detects LangGraph agents defined using these patterns:

### ESM (ES Modules)

```typescript
// Using createAgent
export const agent = createAgent({ model, tools });

// Using StateGraph
export const graph = new StateGraph(annotation).compile();

// Using workflow builder pattern
export const app = workflow.compile();
```

### CommonJS

```javascript
// Using module.exports
module.exports.agent = createAgent({ model, tools });
module.exports.graph = workflow.compile();

// Using exports shorthand
exports.myAgent = createAgent({ model, tools });
```

### What Gets Detected

The scanner looks for:

- `createAgent()` function calls
- `new StateGraph(...).compile()` patterns
- `workflow.compile()` or `builder.compile()` patterns

**Important:** Only **exported** agents are included in the generated configuration. Unexported agents will be listed as warnings so you can add the `export` keyword if needed.

## Generated Configuration

The `config` command generates a `langgraph.json` file like this:

```json
{
  "node_version": "20",
  "graphs": {
    "agent": "./src/agent.ts:agent",
    "searchAgent": "./src/search.ts:searchAgent"
  },
  "env": ".env"
}
```

The configuration includes:

- **node_version** — Detected from your current Node.js version
- **graphs** — Map of agent names to their file paths and export names
- **env** — Path to `.env` file (if one exists)

## Project Structure

After scaffolding, your project will have this structure:

```txt
my-project/
├── src/
│   └── agent.ts       # Your LangGraph agent
├── langgraph.json     # LangGraph configuration
├── package.json
├── tsconfig.json
└── .env.example       # Environment variables template
```

## Next Steps After Creating a Project

```bash
# Navigate to your project
cd my-project

# Install dependencies
npm install  # or yarn, pnpm, bun

# Start the LangGraph development server
npx @langchain/langgraph-cli@latest dev
```

The development server provides:

- A local API server for your agents
- Hot reloading during development
- Built-in debugging tools

## Analytics

This CLI collects anonymous usage analytics to help improve the tool. The following information is collected:

- Operating system and version
- Node.js version
- CLI version
- Command executed

**No personal information, project details, or code is ever collected.**

To opt out of analytics, set the environment variable:

```bash
export LANGGRAPH_CLI_NO_ANALYTICS=1
```

## Requirements

- Node.js 18 or later
- npm, yarn, pnpm, or bun

## Related Packages

- [@langchain/langgraph](https://www.npmjs.com/package/@langchain/langgraph) — The core LangGraph library
- [@langchain/langgraph-cli](https://www.npmjs.com/package/@langchain/langgraph-cli) — CLI tools for running LangGraph projects

## License

MIT © [LangChain](https://langchain.com)

---

### Overview (`libs/langgraph-api/README.md`)

# LangGraph.js API

In-memory implementation of the LangGraph.js API.

## Tests

1. Build the latest code changes to test: `pnpm build`
1. Start a local server: `pnpm dev`
1. Run the tests: `pnpm test`

---

### Overview (`libs/langgraph-cli/README.md`)

# LangGraph.js CLI

The official command-line interface for LangGraph.js, providing tools to create, develop, and deploy LangGraph.js applications.

## Installation

The `@langchain/langgraph-cli` is a CLI binary that can be run via `npx` or installed via your package manager of choice:

```bash
npx @langchain/langgraph-cli
```

## Commands

### `langgraphjs dev`

Run LangGraph.js API server in development mode with hot reloading.

```bash
npx @langchain/langgraph-cli dev
```

### `langgraphjs build`

Build a Docker image for your LangGraph.js application.

```bash
npx @langchain/langgraph-cli build
```

### `langgraphjs up`

Run LangGraph.js API server in Docker.

```bash
npx @langchain/langgraph-cli up
```

### `langgraphjs dockerfile`

Generate a Dockerfile for custom deployments

```bash
npx @langchain/langgraph-cli dockerfile <save path>
```

## Configuration

The CLI uses a `langgraph.json` configuration file with these key settings:

```json5
{
  // Required: Graph definitions
  graphs: {
    graph: "./src/graph.ts:graph",
  },

  // Optional: Node version (supported: "20", "22", "24")
  node_version: "24",

  // Optional: Environment variables
  env: ".env",

  // Optional: Additional Dockerfile commands
  dockerfile_lines: [],
}
```

See the [full documentation](https://langchain-ai.github.io/langgraph/cloud/reference/cli) for detailed configuration options.

---

### Overview (`libs/langgraph-core/README.md`)

<div align="center">
  <a href="https://www.langchain.com/langgraph">
    <picture>
      <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/langchain-ai/langgraphjs/HEAD/.github/images/logo-dark.svg">
      <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/langchain-ai/langgraphjs/HEAD/.github/images/logo-light.svg">
      <img alt="LangGraph Logo" src="https://raw.githubusercontent.com/langchain-ai/langgraphjs/HEAD/.github/images/logo-dark.svg" width="50%">
    </picture>
  </a>
</div>

<div align="center">
  <h3>Low-level orchestration framework for building stateful agents.</h3>
</div>

<div align="center">
  <a href="https://docs.langchain.com/oss/javascript/langgraph/overview" target="_blank"><img src="https://img.shields.io/badge/docs-latest-blue" alt="Docs"></a>
  <a href="https://www.npmjs.com/package/@langchain/langgraph" target="_blank"><img src="https://img.shields.io/npm/v/@langchain/langgraph?logo=npm" alt="Version"></a>
  <a href="https://www.npmjs.com/package/@langchain/langgraph" target="_blank"><img src="https://img.shields.io/npm/dm/@langchain/langgraph" alt="npm - Downloads"></a>
  <a href="https://github.com/langchain-ai/langgraphjs/issues" target="_blank"><img src="https://img.shields.io/github/issues-raw/langchain-ai/langgraphjs" alt="Open Issues"></a>
</div>

LangGraph — used by Replit, Uber, LinkedIn, GitLab and more — is a low-level orchestration framework for building controllable agents. While langchain provides integrations and composable components to streamline LLM application development, the LangGraph library enables agent orchestration — offering customizable architectures, long-term memory, and human-in-the-loop to reliably handle complex tasks.

```bash
npm install @langchain/langgraph @langchain/core
```

> [!TIP]
> If you're looking to quickly build agents, check out **[Deep Agents](https://docs.langchain.com/oss/javascript/deepagents/overview)** — a higher-level package built on LangGraph for agents that can plan, use subagents, and leverage file systems for complex tasks.

For an equivalent Python library, check out [LangGraph](https://github.com/langchain-ai/langgraph) and the [Python docs](https://docs.langchain.com/oss/python/langgraph/overview).

## Why use LangGraph?

LangGraph provides low-level supporting infrastructure for *any* long-running, stateful workflow or agent:

- **[Durable execution](https://docs.langchain.com/oss/javascript/langgraph/durable-execution)** — Build agents that persist through failures and can run for extended periods, automatically resuming from exactly where they left off.
- **[Human-in-the-loop](https://docs.langchain.com/oss/javascript/langgraph/interrupts)** — Seamlessly incorporate human oversight by inspecting and modifying agent state at any point during execution.
- **[Comprehensive memory](https://docs.langchain.com/oss/javascript/langgraph/memory)** — Create truly stateful agents with both short-term working memory for ongoing reasoning and long-term persistent memory across sessions.
- **[Debugging with LangSmith](https://www.langchain.com/langsmith)** — Gain deep visibility into complex agent behavior with visualization tools that trace execution paths, capture state transitions, and provide detailed runtime metrics.
- **[Production-ready deployment](https://docs.langchain.com/langsmith/deployments)** — Deploy sophisticated agent systems confidently with scalable infrastructure designed to handle the unique challenges of stateful, long-running workflows.

> [!TIP]
> For developing, debugging, and deploying AI agents and LLM applications, see [LangSmith](https://docs.langchain.com/langsmith/home).

## LangGraph’s ecosystem

While LangGraph can be used standalone, it also integrates seamlessly with any LangChain product, giving developers a full suite of tools for building agents. To improve your LLM application development, pair LangGraph with:

- [Deep Agents (JS)](https://docs.langchain.com/oss/javascript/deepagents/overview) — Build agents that can plan, use subagents, and leverage file systems for complex tasks. A higher-level package built on top of LangGraph.
- [LangChain](https://docs.langchain.com/oss/javascript/langchain/overview) – Provides integrations and composable components to streamline LLM application development.
- [LangSmith](http://www.langchain.com/langsmith) — Helpful for agent evals and observability. Debug poor-performing LLM app runs, evaluate agent trajectories, gain visibility in production, and improve performance over time.

## Additional resources

- [LangChain Forum](https://forum.langchain.com/): Connect with the community and share all of your technical questions, ideas, and feedback.
- [LangChain Academy](https://academy.langchain.com/courses/intro-to-langgraph): Learn the basics of LangGraph in our free, structured course.
- [Streaming Cookbook](https://github.com/langchain-ai/streaming-cookbook): Documentation and examples around LangGraphs's streaming capabilities.
- [API Reference](https://reference.langchain.com/javascript/langchain-langgraph): Detailed reference on core classes, methods, how to use the graph and checkpointing APIs, and higher-level prebuilt components.
- [Built with LangGraph](https://www.langchain.com/built-with-langgraph): Hear how industry leaders use LangGraph to ship powerful, production-ready AI applications.

## Acknowledgements

LangGraph is inspired by [Pregel](https://research.google/pubs/pub37252/) and [Apache Beam](https://beam.apache.org/). The public interface draws inspiration from [NetworkX](https://networkx.org/documentation/latest/). LangGraph is built by LangChain Inc, the creators of LangChain, but can be used without LangChain.

---

### Overview (`libs/langgraph-cua/README.md`)

# 🤖 LangGraph.js Computer Use Agent (CUA)

> [!TIP]
> Looking for the Python version? [Check out the repo here](https://github.com/langchain-ai/langgraph-cua-py).

A TypeScript library for creating computer use agent (CUA) systems using [LangGraph.js](https://github.com/langchain-ai/langgraphjs). A CUA is a type of agent which has the ability to interact with a computer to perform tasks.

Short demo video:
<video src="https://github.com/user-attachments/assets/7fd0ab05-fecc-46f5-961b-6624cb254ac2" controls></video>

> [!TIP]
> This demo used the following prompt:
>
> ```
> I want to contribute to the LangGraph.js project. Please find the GitHub repository, and inspect the read me,
> along with some of the issues and open pull requests. Then, report back with a plan of action to contribute.
> ```

This library is built on top of [LangGraph.js](https://github.com/langchain-ai/langgraphjs), a powerful framework for building agent applications, and comes with out-of-box support for [streaming](https://langchain-ai.github.io/langgraph/how-tos/#streaming), [short-term and long-term memory](https://langchain-ai.github.io/langgraph/concepts/memory/) and [human-in-the-loop](https://langchain-ai.github.io/langgraph/concepts/human_in_the_loop/).

## Installation

You will need to explicitly install LangGraph, Core, and OpenAI since these are peer dependencies of this package.

```bash
yarn add @langchain/langgraph-cua @langchain/langgraph @langchain/core @langchain/openai
```

## Quickstart

This project by default uses [Scrapybara](https://scrapybara.com/) for accessing a virtual machine to run the agent. To use LangGraph CUA, you'll need both OpenAI and Scrapybara API keys.

```bash
export OPENAI_API_KEY=<your_api_key>
export SCRAPYBARA_API_KEY=<your_api_key>
```

Then, create the graph by importing the `createCua` function from the `@langchain/langgraph-cua` module.

```typescript
import "dotenv/config";
import { createCua } from "@langchain/langgraph-cua";

const cuaGraph = createCua();

// Define the input messages
const messages = [
  {
    role: "system",
    content:
      "You're an advanced AI computer use assistant. The browser you are using " +
      "is already initialized, and visiting google.com.",
  },
  {
    role: "user",
    content:
      "I want to contribute to the LangGraph.js project. Please find the GitHub repository, and inspect the read me, " +
      "along with some of the issues and open pull requests. Then, report back with a plan of action to contribute.",
  },
];

async function main() {
  // Stream the graph execution
  const stream = await cuaGraph.stream(
    { messages },
    {
      streamMode: "updates",
      subgraphs: true,
    }
  );

  // Process the stream updates
  for await (const update of stream) {
    console.log(update);
  }

  console.log("Done");
}

main().catch(console.error);
```

The above example will invoke the graph, passing in a request for it to do some research into LangGraph.js from the standpoint of a new contributor. The code will log the stream URL, which you can open in your browser to view the CUA stream.

You can find more examples inside the [`examples` directory](/libs/langgraph-cua/examples).

## How to customize

The `createCua` function accepts a few configuration parameters. These are the same configuration parameters that the graph accepts, along with `recursionLimit`.

You can either pass these parameters when calling `createCua`, or at runtime when invoking the graph by passing them to the `config` object.

### Configuration Parameters

- `scrapybaraApiKey`: The API key to use for Scrapybara. If not provided, it defaults to reading the `SCRAPYBARA_API_KEY` environment variable.
- `timeoutHours`: The number of hours to keep the virtual machine running before it times out.
- `zdrEnabled`: Whether or not Zero Data Retention is enabled in the user's OpenAI account. If `true`, the agent will not pass the `previous_response_id` to the model, and will always pass it the full message history for each request. If `false`, the agent will pass the `previous_response_id` to the model, and only the latest message in the history will be passed. Default `false`.
- `recursionLimit`: The maximum number of recursive calls the agent can make. Default is 100. This is greater than the standard default of 25 in LangGraph, because computer use agents are expected to take more iterations.
- `authStateId`: The ID of the authentication state. If defined, it will be used to authenticate with Scrapybara. Only applies if 'environment' is set to 'web'.
- `environment`: The environment to use. Default is `web`. Options are `web`, `ubuntu`, and `windows`.
- `prompt`: The prompt to pass to the model. This will be passed as the system message.
- `nodeBeforeAction`: A custom node to run before the computer action. This function will receive the current state and config as parameters.
- `nodeAfterAction`: A custom node to run after the computer action. This function will receive the current state and config as parameters.
- `stateModifier`: Optional state modifier for customizing the agent's state.

### System Prompts

Including a system prompt with your CUA graph is recommended, and can save the agent time in its initial steps by providing context into its environment and objective. Below is the recommended system prompt from Scrapybara:

<details><summary>System Prompt</summary>
    
    You have access to an Ubuntu VM with internet connectivity. You can install Ubuntu applications using the bash tool (prefer curl over wget).  

    ### Handling HTML and Large Text Output  
    - To read an HTML file, open it in Chromium using the address bar.  

    ### Interacting with Web Pages and Forms  
    - Zoom out or scroll to ensure all content is visible.  
    - When interacting with input fields:  
    - Clear the field first using `Ctrl+A` and `Delete`.  
    - Take an extra screenshot after pressing "Enter" to confirm the input was submitted correctly.  
    - Move the mouse to the next field after submission.  

    ### Efficiency and Authentication  
    - Computer function calls take time; optimize by stringing together related actions when possible.  
    - You are allowed to take actions on authenticated sites on behalf of the user.  
    - Assume the user has already authenticated if they request access to a site.  
    - For logging into additional sites, ask the user to use Auth Contexts or the Interactive Desktop.  

    ### Handling Black Screens  
    - If the first screenshot shows a black screen:  
    - Click the center of the screen.  
    - Take another screenshot.  

    ### Best Practices  
    - If given a complex task, break it down into smaller steps and ask for details only when necessary.  
    - Read web pages thoroughly by scrolling down until sufficient information is gathered.  
    - Explain each action you take and why.  
    - Avoid asking for confirmation on routine actions (e.g., pressing "Enter" after typing a URL). Seek clarification only for ambiguous or critical actions (e.g., deleting files or submitting sensitive information).  
    - If a user's request implies the need for external information, assume they want you to search for it and provide the answer directly.  

    ### Date Context  
    Today's date is {todays_date}


If you choose to use this prompt, ensure you're populating the `{todays_date}` placeholder with the current date.

</details>

### Node Before/After Action

LangGraph CUA allows you to customize the agent's behavior by providing custom nodes that run before and after computer actions. These nodes give you fine-grained control over the agent's workflow.

```typescript
import { createCua, CUAState, CUAUpdate } from "@langchain/langgraph-cua";
import { LangGraphRunnableConfig } from "@langchain/langgraph";

// Custom node that runs before a computer action
async function customNodeBefore(
  state: CUAState,
  config: LangGraphRunnableConfig
): Promise<CUAUpdate> {
  console.log("Running before computer action");
  // You can modify the state here
  return {};
}

// Custom node that runs after a computer action
async function customNodeAfter(
  state: CUAState,
  config: LangGraphRunnableConfig
): Promise<CUAUpdate> {
  console.log("Running after computer action");
  // You can process the results of the computer action here
  return {};
}

const cuaGraph = createCua({
  nodeBeforeAction: customNodeBefore,
  nodeAfterAction: customNodeAfter,
});
```

These custom nodes allow you to:

- Perform validation or preprocessing before a computer action
- Modify or analyze the results after a computer action
- Implement custom logic that integrates with your application (e.g. for Generative UI)

### State Modifier

The `stateModifier` parameter allows you to customize the agent's state by extending the default state annotation. This gives you the ability to add custom fields to the state object.

```typescript
import { createCua, CUAAnnotation } from "@langchain/langgraph-cua";
import { Annotation } from "@langchain/langgraph";

// Create a custom state annotation that extends the default CUA state
const CustomStateAnnotation = Annotation.Root({
  ...CUAAnnotation.spec,
  // Add your custom fields here
  customField: Annotation.Field({
    default: "default value",
  }),
});

const cuaGraph = createCua({
  stateModifier: CustomStateAnnotation,
});
```

By using state modifiers, you can:

- Store additional context or metadata in the agent's state
- Customize the default behavior of the agent
- Implement domain-specific functionality

### Screenshot Upload

The `uploadScreenshot` parameter allows you to upload screenshots to a storage service (e.g., an image hosting service) and return the URL. This is useful, because storing screenshots in the state object can quickly consume your LangGraph server's disk space.

```typescript
import { createCua } from "@langgraph/cua";

const cuaGraph = createCua({
  uploadScreenshot: async (base64Screenshot) => {
    // Upload screenshot to storage service
    const publicImageUrl = await uploadToS3(base64Screenshot);
    return publicImageUrl;
  },
});
```


## Auth States

LangGraph CUA integrates with Scrapybara's [auth states API](https://docs.scrapybara.com/auth-states) to persist browser authentication sessions. This allows you to authenticate once (e.g., logging into Amazon) and reuse that session in future runs.

### Using Auth States

Pass an `authStateId` when creating your CUA graph:

```typescript
import { createCua } from "@langgraph/cua";

const cuaGraph = createCua({ authStateId: "<your_auth_state_id>" });
```

The graph stores this ID in the `authenticatedId` state field. If you change the `authStateId` in future runs, the graph will automatically reauthenticate.

### Managing Auth States with Scrapybara SDK

#### Save an Auth State

```typescript
import { ScrapybaraClient } from "scrapybara";

const client = new ScrapybaraClient({ apiKey: "<api_key>" });
const instance = await client.get("<instance_id>");
const authStateId = (await instance.saveAuth({ name: "example_site" })).authStateId;
```

#### Modify an Auth State

```typescript
import { ScrapybaraClient } from "scrapybara";

const client = new ScrapybaraClient({ apiKey: "<api_key>" });
const instance = await client.get("<instance_id>");
await instance.modifyAuth({ authStateId: "your_existing_auth_state_id", name: "renamed_auth_state" });
```

> [!NOTE]
> To apply changes to an auth state in an existing run, set the `authenticatedId` state field to `undefined` to trigger re-authentication.

## Zero Data Retention (ZDR)

LangGraph CUA supports Zero Data Retention (ZDR) via the `zdrEnabled` configuration parameter. When set to true, the graph will _not_ assume it can use the `previous_message_id`, and _all_ AI & tool messages will be passed to the OpenAI on each request.

## Development

To get started with development, first clone the repository:

```bash
git clone https://github.com/langchain-ai/langgraphjs.git
```

Install dependencies:

```bash
yarn install
```

Navigate into the `libs/langgraph-cua` directory:

```bash
cd libs/langgraph-cua
```

Set the required environment variables:

```bash
cp .env.example .env
```

Finally, you can then run the integration tests:

```bash
yarn test:single src/tests/cua.int.test.ts
```

---

### Overview (`libs/langgraph-supervisor/README.md`)

# 🤖 LangGraph Multi-Agent Supervisor

A JavaScript library for creating hierarchical multi-agent systems using [LangGraph](https://github.com/langchain-ai/langgraphjs). Hierarchical systems are a type of [multi-agent](https://langchain-ai.github.io/langgraphjs/concepts/multi_agent) architecture where specialized agents are coordinated by a central **supervisor** agent. The supervisor controls all communication flow and task delegation, making decisions about which agent to invoke based on the current context and task requirements.

## Features

- 🤖 **Create a supervisor agent** to orchestrate multiple specialized agents
- 🛠️ **Tool-based agent handoff mechanism** for communication between agents
- 📝 **Flexible message history management** for conversation control

This library is built on top of [LangGraph](https://github.com/langchain-ai/langgraphjs), a powerful framework for building agent applications, and comes with out-of-box support for [streaming](https://langchain-ai.github.io/langgraphjs/how-tos/#streaming), [short-term and long-term memory](https://langchain-ai.github.io/langgraphjs/concepts/memory/) and [human-in-the-loop](https://langchain-ai.github.io/langgraphjs/concepts/human_in_the_loop/)

## Installation

```bash
npm install @langchain/langgraph-supervisor @langchain/langgraph @langchain/core
```

## Quickstart

Here's a simple example of a supervisor managing two specialized agents:



```bash
npm install @langchain/langgraph-supervisor @langchain/langgraph @langchain/core @langchain/openai

export OPENAI_API_KEY=<your_api_key>
```

```
/* Detailed source-code truncated for AI context efficiency. */
```

## Message History Management

You can control how agent messages are added to the overall conversation history of the multi-agent system:

Include full message history from an agent:



```ts
const workflow = createSupervisor({
  agents: [agent1, agent2],
  outputMode: "full_history"
})
```

Include only the final agent response:



```ts
const workflow = createSupervisor({
  agents: [agent1, agent2],
  outputMode: "last_message"
})
```

## Multi-level Hierarchies

You can create multi-level hierarchical systems by creating a supervisor that manages multiple supervisors.

```ts
const researchTeam = createSupervisor({
  agents: [researchAgent, mathAgent],
  llm: model,
}).compile({ name: "research_team" })

const writingTeam = createSupervisor({
  agents: [writingAgent, publishingAgent],
  llm: model,
}).compile({ name: "writing_team" })

const topLevelSupervisor = createSupervisor({
  agents: [researchTeam, writingTeam],
  llm: model,
}).compile({ name: "top_level_supervisor" })
```

## Adding Memory

You can add [short-term](https://langchain-ai.github.io/langgraphjs/how-tos/persistence/) and [long-term](https://langchain-ai.github.io/langgraphjs/how-tos/cross-thread-persistence/) [memory](https://langchain-ai.github.io/langgraphjs/concepts/memory/) to your supervisor multi-agent system. Since `createSupervisor()` returns an instance of `StateGraph` that needs to be compiled before use, you can directly pass a [checkpointer](https://langchain-ai.github.io/langgraphjs/reference/classes/checkpoint.BaseCheckpointSaver.html) or a [store](https://langchain-ai.github.io/langgraphjs/reference/classes/checkpoint.BaseStore.html) instance to the `.compile()` method:

```ts
import { MemorySaver, InMemoryStore } from "@langchain/langgraph";

const checkpointer = new MemorySaver()
const store = new InMemoryStore()

const model = ...
const researchAgent = ...
const mathAgent = ...

const workflow = createSupervisor({
  agents: [researchAgent, mathAgent],
  llm: model,
  prompt: "You are a team supervisor managing a research expert and a math expert.",
})

// Compile with checkpointer/store
const app = workflow.compile({
  checkpointer,
  store
})
```

---

### Overview (`libs/langgraph-swarm/README.md`)

# 🤖 LangGraph Multi-Agent Swarm 

A JavaScript library for creating swarm-style multi-agent systems using [LangGraph](https://github.com/langchain-ai/langgraphjs). A swarm is a type of [multi-agent](https://langchain-ai.github.io/langgraphjs/concepts/multi_agent) architecture where agents dynamically hand off control to one another based on their specializations. The system remembers which agent was last active, ensuring that on subsequent interactions, the conversation resumes with that agent.



> [!NOTE]
> This library has been updated to support LangChain 1.0. However, it has **not** been tested with the new agents in `langchain`. The library currently only supports the prebuilt `createReactAgent` from LangGraph. This update allows users to migrate to LangChain 1.0 without changing their existing code. For users of the swarm package, we recommend continuing to use `createReactAgent` rather than the new `createAgent` pattern from LangChain for now.

## Features

- 🤖 **Multi-agent collaboration** - Enable specialized agents to work together and hand off context to each other
- 🛠️ **Customizable handoff tools** - Built-in tools for communication between agents

This library is built on top of [LangGraph](https://github.com/langchain-ai/langgraphjs), a powerful framework for building agent applications, and comes with out-of-box support for [streaming](https://langchain-ai.github.io/langgraphjs/how-tos/#streaming), [short-term and long-term memory](https://langchain-ai.github.io/langgraphjs/concepts/memory/) and [human-in-the-loop](https://langchain-ai.github.io/langgraphjs/concepts/human_in_the_loop/)

## Installation

```bash
npm install @langchain/langgraph-swarm @langchain/langgraph @langchain/core
```

## Quickstart

```bash
npm install @langchain/langgraph-swarm @langchain/langgraph @langchain/core @langchain/openai

export OPENAI_API_KEY=<your_api_key>
```

```
/* Detailed source-code truncated for AI context efficiency. */
```

## Memory

You can add [short-term](https://langchain-ai.github.io/langgraphjs/how-tos/persistence/) and [long-term](https://langchain-ai.github.io/langgraphjs/how-tos/cross-thread-persistence/) [memory](https://langchain-ai.github.io/langgraphjs/concepts/memory/) to your swarm multi-agent system. Since `createSwarm()` returns an instance of `StateGraph` that needs to be compiled before use, you can directly pass a [checkpointer](https://langchain-ai.github.io/langgraphjs/reference/classes/checkpoint.BaseCheckpointSaver.html) or a [store](https://langchain-ai.github.io/langgraphjs/reference/classes/checkpoint.BaseStore.html) instance to the `.compile()` method:

```ts
import { MemorySaver, InMemoryStore } from "@langchain/langgraph";

// short-term memory
const checkpointer = new MemorySaver()
// long-term memory
const store = new InMemoryStore()

alice = ...
bob = ...

const workflow = createSwarm({
  agents: [alice, bob],
  defaultActiveAgent: "Alice",
})

// Compile with checkpointer/store
const app = workflow.compile({
  checkpointer,
  store
})
```

> [!IMPORTANT]
> Adding [short-term memory](https://langchain-ai.github.io/langgraphjs/concepts/persistence/) is crucial for maintaining conversation state across multiple interactions. Without it, the swarm would "forget" which agent was last active and lose the conversation history. Make sure to always compile the swarm with a checkpointer if you plan to use it in multi-turn conversations; e.g., `workflow.compile(checkpointer=checkpointer)`.

## How to customize

You can customize multi-agent swarm by changing either the [handoff tools](#customizing-handoff-tools) implementation or the [agent implementation](#customizing-agent-implementation).

### Customizing handoff tools

By default, the agents in the swarm are assumed to use handoff tools created with the prebuilt `createHandoffTool`. You can also create your own, custom handoff tools. Here are some ideas on how you can modify the default implementation:

* change tool name and/or description
* add tool call arguments for the LLM to populate, for example a task description for the next agent
* change what data is passed to the next agent as part of the handoff: by default `create_handoff_tool` passes **full** message history (all of the messages generated in the swarm up to this point), as well as the contents of `Command.update` to the next agent

> [!IMPORTANT]
> If you want to change what messages are passed to the next agent, you **must** use a different state schema key for `messages` in your agent implementation (e.g., `alice_messages`). By default, all agent (subgraph) state updates are applied to the swarm (parent) graph state during the handoff. Since all of the agents by default are assumed to communicate over a single `messages` key, this means that the agent's messages are **automatically combined** into the parent graph's `messages`, unless an agent uses a different key for `messages`. See more on this in the [customizing agent implementation](#customizing-agent-implementation) section.

Here is an example of what a custom handoff tool might look like:

```
/* Detailed source-code truncated for AI context efficiency. */
```

> [!IMPORTANT]
> If you are implementing custom handoff tools that return `Command`, you need to ensure that:  
  (1) your agent has a tool-calling node that can handle tools returning `Command` (like LangGraph's prebuilt [`ToolNode`](https://langchain-ai.github.io/langgraphjs/reference/classes/langgraph_prebuilt.ToolNode.html))
  (2) both the swarm graph and the next agent graph have the [state schema](https://langchain-ai.github.io/langgraphjs/concepts/low_level/#annotation) containing the keys you want to update in `Command.update`

### Customizing agent implementation

By default, individual agents are expected to communicate over a single `messages` key that is shared by all agents and the overall multi-agent swarm graph. This means that **all** of the messages from **all** of the agents will be combined into a single, shared list of messages. This might not be desirable if you don't want to expose an agent's internal history of messages. To change this, you can customize the agent by taking the following steps:

1.  use custom [state schema](https://langchain-ai.github.io/langgraphjs/concepts/low_level#annotation) with a different key for messages, for example `alice_messages`
1.  write a wrapper that converts the parent graph state to the child agent state and back (see this [how-to](https://langchain-ai.github.io/langgraphjs/how-tos/subgraph-transform-state/) guide)

```ts
import { BaseMessage } from "@langchain/core/messages";
import { Annotation, StateGraph, messagesStateReducer } from "@langchain/langgraph";

export const AliceStateAnnotation = Annotation.Root({
  alice_messages: Annotation<BaseMessage[]>({
    reducer: messagesStateReducer,
    default: () => [],
  }),
});
import { SwarmState } from "@langchain/langgraph-swarm";

// see this guide to learn how you can implement a custom tool-calling agent
// https://langchain-ai.github.io/langgraphjs/how-tos/react-agent-from-scratch/
const alice = (
    new StateGraph(AliceStateAnnotation)
    .addNode("model", ...)
    .addNode("tools", ...)
    .addEdge(...)
    ...
    .compile()
)

// wrapper calling the agent
const callAlice = async (state: typeof SwarmState.State) => {
    // you can put any input transformation from parent state -> agent state
    // for example, you can invoke "alice" with "task_description" populated by the LLM
    const response = await alice.invoke({"alice_messages": state["messages"]})
    // you can put any output transformation from agent state -> parent state
    return { "messages": response.alice_messages }
}

const callBob = async (state: typeof SwarmState.State) => {
    ...
}
```

Then, you can create the swarm manually in the following way:

```ts
import { addActiveAgentRouter } from "@langchain/langgraph-swarm";

let workflow = (
    new StateGraph(SwarmState)
    .addNode("Alice", callAlice, { ends: ["Bob"] })
    .addNode("Bob", callBob, { ends: ["Alice"] })
)
// this is the router that enables us to keep track of the last active agent
workflow = addActiveAgentRouter(workflow, {
    routeTo: ["Alice", "Bob"],
    defaultActiveAgent: "Alice",
})

// compile the workflow
const app = workflow.compile()
```

---

### Overview (`libs/langgraph-ui/README.md`)

# LangGraph.js UI

Contains the logic for creating Generative UI bundles served via LangGraph API.

---

### Overview (`libs/sdk-angular/README.md`)

# @langchain/angular

Angular SDK for building AI-powered applications with [Deep Agents](https://docs.langchain.com/oss/javascript/deepagents/overview), [LangChain](https://docs.langchain.com/oss/javascript/langchain/overview) and [LangGraph](https://docs.langchain.com/oss/javascript/langgraph/overview).

The package ships a Signals-first API built on top of the v2 streaming
protocol. `injectStream` returns a small, always-on root handle
(`values`, `messages`, `isLoading`, `error`, …) and pushes anything
namespaced (subagents, subgraphs, media, submission queue, per-message
metadata) behind **ref-counted `inject*` selectors** so components
only pay for data they actually consume.

> **Upgrading from `0.x`?** See [`docs/v1-migration.md`](./docs/v1-migration.md)
> for the complete matrix of option, return-shape, and transport
> changes.

## Installation

```bash
npm install @langchain/angular @langchain/core
```

**Peer dependencies:** `@angular/core` (^18.0.0 – ^21.0.0),
`@langchain/core` (^1.1.27).

## Quick start

```typescript
import { Component } from "@angular/core";
import { injectStream } from "@langchain/angular";

@Component({
  standalone: true,
  template: `
    <div>
      @for (msg of stream.messages(); track msg.id ?? $index) {
        <div>{{ str(msg.content) }}</div>
      }

      <button
        [disabled]="stream.isLoading()"
        (click)="onSubmit()"
      >
        Send
      </button>
    </div>
  `,
})
export class ChatComponent {
  readonly stream = injectStream({
    assistantId: "agent",
    apiUrl: "http://localhost:2024",
  });

  str(v: unknown) {
    return typeof v === "string" ? v : JSON.stringify(v);
  }

  onSubmit() {
    void this.stream.submit({
      messages: [{ type: "human", content: "Hello!" }],
    });
  }
}
```

`injectStream` must be called from an **Angular injection context** —
the host's `DestroyRef` owns the stream, so navigating away destroys
the controller automatically.

## Features at a glance

- **Signals everywhere.** Messages, values, tool calls, interrupts,
  loading/error state — all Angular `Signal<T>`s you call as
  functions in templates.
- **One call, two transports.** Same option bag targets either the
  LangGraph Platform (SSE by default, `transport: "websocket"`
  opt-in) or a custom backend through an `AgentServerAdapter`.
- **Ref-counted selectors.** `injectMessages`, `injectValues`,
  `injectToolCalls`, media selectors, submission queue — the first
  consumer opens a subscription, the last one's `DestroyRef` closes
  it. Components pay only for what they render.
- **Human-in-the-loop.** Interrupts are first-class signals; resume
  or fork a specific pending interrupt with one call.
- **Headless tools.** Register browser-side tool implementations;
  the runtime dispatches matching interrupts and auto-resumes with
  the return value.
- **Subagent & subgraph discovery.** Lightweight snapshots at the
  root; scoped content (messages, tool calls, state) via the same
  selectors, targeted at a snapshot or namespace.
- **Forking without history preload.** Per-message metadata +
  `submit({ forkFrom })` replaces the legacy `branch` /
  `fetchStateHistory` trio.
- **DI-native.** `provideStream` for subtree sharing,
  `provideStreamDefaults` for app-wide config, `StreamService` for
  class-based wrappers.
- **Typed end-to-end.** Pass `typeof agent` as the first generic —
  state, tool args, and per-subagent state flow through to every
  selector.

## Public stream types

Use `StreamApi<T>` when you need to name the return type of
`injectStream`, `useStream`, `provideStream`, or `StreamService` in
Angular code. It is the Angular-facing alias for the Signals-first
handle.

`UseStreamResult<T>` is also exported as a React-compatible alias for
the same shape. Prefer it only in shared utilities that are designed to
accept stream handles from multiple framework packages.

## Documentation

In-depth guides live under [`docs/`](./docs):

- [`inject-stream.md`](./docs/inject-stream.md) — options + return-shape reference
- [`transports.md`](./docs/transports.md) — SSE, WebSocket, and custom `AgentServerAdapter`
- [`custom-transport.md`](./docs/custom-transport.md) — implementing `AgentServerAdapter` against your own backend, with a worked walkthrough of [`examples/ui-react-transport`](../../examples/ui-react-transport)
- [`selectors.md`](./docs/selectors.md) — scoped reads (`injectMessages`, `injectValues`, media, channels, …)
- [`interrupts.md`](./docs/interrupts.md) — handling and responding to interrupts
- [`branching.md`](./docs/branching.md) — forking via `injectMessageMetadata` + `submit({ forkFrom })`
- [`submission-queue.md`](./docs/submission-queue.md) — `injectSubmissionQueue` and `multitaskStrategy: "enqueue"`
- [`headless-tools.md`](./docs/headless-tools.md) — browser-side tool implementations
- [`subagents-subgraphs.md`](./docs/subagents-subgraphs.md) — discovery snapshots and scoped content
- [`dependency-injection.md`](./docs/dependency-injection.md) — `provideStream`, `provideStreamDefaults`, `StreamService`
- [`type-safety.md`](./docs/type-safety.md) — generics, agent inference, and public stream aliases
- [`testing.md`](./docs/testing.md) — `STREAM_INSTANCE` fakes and service overrides
- [`v1-migration.md`](./docs/v1-migration.md) — migrating from `0.x`

## Playground

For complete end-to-end examples, visit the
[LangChain UI Playground](https://docs.langchain.com/playground).

## License

MIT

---

### Overview (`libs/sdk-react/README.md`)

# @langchain/react

React SDK for building AI-powered applications with [Deep Agents](https://docs.langchain.com/oss/javascript/deepagents/overview), [LangChain](https://docs.langchain.com/oss/javascript/langchain/overview) and [LangGraph](https://docs.langchain.com/oss/javascript/langgraph/overview).

`@langchain/react` v1 ships a v2-native `useStream` hook together with a small family of companion selector hooks. The root hook gives you always-on access to thread state, messages, tool calls, and interrupts; the selector hooks open ref-counted subscriptions for the things that aren't needed on every view (per-subagent messages, media streams, submission queue, message metadata, raw channels, …).

## Highlights

- **v2-native streaming protocol.** Session-based transport with automatic re-attach on remount; no more `reconnectOnMount` / `joinStream` dance.
- **Selector-based subscriptions.** Namespaced data (subagents, subgraphs, media) streams only when a component actually mounts the matching selector hook, and releases on unmount.
- **Always-on root projections.** `values`, `messages`, `toolCalls`, and `interrupts` are live at the root with zero per-subscription cost.
- **Agent-brand type inference.** `useStream<typeof agent>()` unwraps state, tool calls, and subagent state maps from an agent brand.
- **Discriminated options.** The hosted Agent Server path and the custom-adapter path are two arms of a single typed union — mixing them is a compile-time error.
- **Multimodal media streams.** Built-in assembly for audio, images, video, and files.
- **Suspense integration.** `useSuspenseStream` hands the initial hydration phase to `<Suspense>` and non-streaming errors to Error Boundaries.

## Installation

```bash
npm install @langchain/react @langchain/core
```

**Peer dependencies:** `react` (^18 || ^19), `@langchain/core` (^1.1.27).

## Quick Start

```tsx
import { useStream } from "@langchain/react";

function Chat() {
  const { messages, submit, isLoading } = useStream({
    assistantId: "agent",
    apiUrl: "http://localhost:2024",
  });

  return (
    <div>
      {messages.map((msg, i) => (
        <div key={msg.id ?? i}>{String(msg.content)}</div>
      ))}

      <button
        disabled={isLoading}
        onClick={() =>
          void submit({
            messages: [{ type: "human", content: "Hello!" }],
          })
        }
      >
        Send
      </button>
    </div>
  );
}
```

## Mental model

`@langchain/react` v1 splits the surface into two layers:

1. **Root hook (`useStream`).** Owns the thread lifecycle, the transport, and a handful of always-on projections (`values`, `messages`, `toolCalls`, `interrupts`, `error`, `isLoading`, discovery maps). Mount it once per thread.
2. **Companion selector hooks.** Each one opens a ref-counted subscription when the first component mounts it and releases it when the last consumer unmounts. Use them for anything scoped to a namespace, a subagent / subgraph, a specific message, a specific extension channel, or a media stream.

```tsx
import {
  useStream,
  useMessages,
  useToolCalls,
  useSubmissionQueue,
} from "@langchain/react";

function Chat() {
  const stream = useStream({ assistantId: "agent", apiUrl: "/api" });

  // Root: free reads, no new subscription.
  const messages = useMessages(stream); // same as stream.messages

  // Scoped: opens a namespaced subscription on mount.
  const queue = useSubmissionQueue(stream);
}
```

## Documentation

Detailed guides live in [`./docs`](./docs/). Start with the two files most apps need first:

- **[`useStream`](./docs/use-stream.md)** — options, return shape, `submit()`, `stop()`, `respond()`, `hydrationPromise`.
- **[Companion selector hooks](./docs/selectors.md)** — `useValues`, `useMessages`, `useToolCalls`, `useMessageMetadata`, `useChannel`, `useExtension`, and friends.

Feature-specific guides:

- **[Transports](./docs/transports.md)** — SSE, WebSocket, `HttpAgentServerAdapter`, custom `AgentServerAdapter`.
- **[Custom transports](./docs/custom-transport.md)** — implementing `AgentServerAdapter` against your own backend, with a worked walkthrough of [`examples/ui-react-transport`](../../examples/ui-react-transport).
- **[Interrupts & headless tools](./docs/interrupts.md)** — pausing runs, `respond()`, `tools` + `onTool`.
- **[Fork / edit from a checkpoint](./docs/fork-from-checkpoint.md)** — `useMessageMetadata` + `submit({ forkFrom })`.
- **[Submission queue](./docs/submission-queue.md)** — `multitaskStrategy: "enqueue"` + `useSubmissionQueue`.
- **[Subagents & subgraphs](./docs/subagents.md)** — discovery maps, scoped selector subscriptions.
- **[Multimodal media](./docs/multimodal.md)** — `useAudio` / `useImages` / `useVideo` / `useFiles`, `useMediaURL`, players.
- **[`useSuspenseStream`](./docs/suspense.md)** — Suspense + Error Boundary integration.
- **[`StreamProvider` / `useStreamContext`](./docs/context.md)** — share one stream across a subtree.
- **[Type safety](./docs/type-safety.md)** — agent-brand inference, prop-drilling, type helpers.

## Migrating from v0 to v1

The `useStream` import name is unchanged, but the return shape, option bag, and protocol semantics all shifted. Most chat apps migrate in well under an hour — the full migration guide with line-by-line diffs lives in [`./docs/v1-migration.md`](./docs/v1-migration.md).

Legacy type aliases (`UseStream`, `UseSuspenseStream`, `UseStreamOptions`, `UseStreamTransport`, `QueueEntry`, `GetToolCallsType`, `SubagentStream`, …) and the legacy `FetchStreamTransport` class are **no longer re-exported** from `@langchain/react`. Apps still on the legacy surface can import directly from `@langchain/langgraph-sdk/ui` during their migration.

## Playground

For complete end-to-end examples with full agentic UIs, visit the [LangChain UI Playground](https://docs.langchain.com/playground).

## License

MIT

---

### Overview (`libs/sdk-svelte/README.md`)

# @langchain/svelte

Svelte 5 SDK for [Deep Agents](https://docs.langchain.com/oss/javascript/deepagents/overview), [LangChain](https://docs.langchain.com/oss/javascript/langchain/overview) and [LangGraph](https://docs.langchain.com/oss/javascript/langgraph/overview).

`useStream` binds a LangGraph agent into a Svelte 5 component. Reactive fields are exposed as getters on a stable handle (`stream.messages`, `stream.isLoading`, …) so templates and `$derived` expressions track updates automatically — no stores, no `$` prefix, no destructuring.

## Installation

```bash
npm install @langchain/svelte @langchain/core
```

**Peer dependencies:** `svelte` ^5.0.0, `@langchain/core` ^1.0.1

## Quick start

```svelte
<script lang="ts">
  import { useStream } from "@langchain/svelte";

  const stream = useStream({
    assistantId: "agent",
    apiUrl: "http://localhost:2024",
  });
</script>

{#each stream.messages as msg (msg.id)}
  <div>{msg.content}</div>
{/each}

<button
  disabled={stream.isLoading}
  onclick={() =>
    stream.submit({ messages: [{ type: "human", content: "Hello!" }] })}
>
  Send
</button>
```

> **Note:** Access fields through the live `stream` handle. Destructuring (`const { messages } = stream`) freezes the values at that moment — use `stream.messages` in templates instead.

## Highlights

- **v2-native streaming protocol.** Session-based transport with automatic re-attach on remount; no more `reconnectOnMount` / `joinStream` dance.
- **Always-on root projections.** `values`, `messages`, `toolCalls`, and `interrupts` are reactive at the root with zero extra subscription cost.
- **Selector composables for scoped data.** Per-subagent / per-subgraph messages, tool calls, and media stream only when a component actually mounts the matching composable, and release on unmount.
- **Discriminated option bag.** The hosted Agent Server path and the custom-adapter path are two arms of a single typed union — mixing them is a compile-time error.
- **Reactive `threadId`.** Pass `threadId: () => active` to drive in-place thread swaps without remounting.
- **Agent-brand type inference.** `useStream<typeof agent>()` unwraps state, tool calls, and subagent state maps from an agent brand.
- **Multimodal media streams.** Built-in assembly for audio, images, video, and files — plus opinionated playback helpers.
- **Headless tools.** Register local tool implementations that auto-resolve server-emitted tool-call interrupts without a round-trip through the UI.

## Documentation

In-depth guides live in [`docs/`](./docs/):

- [`useStream` — options, return shape, reactive `threadId`](./docs/use-stream.md)
- [Selector composables (`useMessages`, `useToolCalls`, `useValues`, …)](./docs/selector-composables.md)
- [Interrupts, `respond()`, `stop()`, `hydrationPromise`](./docs/interrupts.md)
- [Submission queue](./docs/submission-queue.md)
- [Stream context (`provideStream` / `getStream`)](./docs/stream-context.md)
- [Headless tools](./docs/headless-tools.md)
- [Custom transport (`AgentServerAdapter`, `HttpAgentServerAdapter`)](./docs/custom-transport.md)
- [Media (images, audio, video, files) & playback helpers](./docs/media.md)
- [Type safety](./docs/type-safety.md)

## Migrating from v0

`@langchain/svelte` **v1** targets the v2 streaming protocol. The `useStream` import stays the same, but the option bag, return shape, and how you subscribe to scoped data all change. Most chat apps migrate in well under an hour — the full guide with line-by-line diffs lives in [`docs/v1-migration.md`](./docs/v1-migration.md).

## Playground

For full end-to-end examples, see the [LangChain UI Playground](https://docs.langchain.com/playground).

## License

MIT

---

### Overview (`libs/sdk-vue/README.md`)

# @langchain/vue

Vue SDK for building AI-powered applications with [Deep Agents](https://docs.langchain.com/oss/javascript/deepagents/overview), [LangChain](https://docs.langchain.com/oss/javascript/langchain/overview) and [LangGraph](https://docs.langchain.com/oss/javascript/langgraph/overview).

The package ships a Composition-API–first binding built on top of
the v2 streaming protocol. `useStream` returns a small, always-on
root handle (`values`, `messages`, `isLoading`, `error`, …) and
pushes anything namespaced (subagents, subgraphs, media, submission
queue, per-message metadata) behind **ref-counted `use*` selectors**
so components only pay for the data they actually consume.

> **Upgrading from `0.x`?** See [`docs/v1-migration.md`](./docs/v1-migration.md)
> for the complete matrix of option, return-shape, and transport
> changes.

## Highlights

- **v2-native streaming protocol.** Session-based transport with
  automatic re-attach on remount — no `reconnectOnMount` /
  `joinStream` dance.
- **Composition-API first.** Everything is a `ShallowRef` /
  `ComputedRef`, auto-disposed via `onScopeDispose` when the scope
  unmounts.
- **Selector-based subscriptions.** Namespaced data (subagents,
  subgraphs, media) streams only when a component actually mounts
  the matching selector composable, and releases on unmount.
- **Discriminated transports.** Hosted Agent Server and custom
  adapters are two arms of a single typed union — mixing them is a
  compile-time error.
- **Agent-brand type inference.** `useStream<typeof agent>()`
  unwraps state, tool calls, and subagent state maps from an agent
  brand.
- **Multimodal media streams.** Built-in assembly for audio,
  images, video, and files, with ready-to-use `<img>` / `<audio>` /
  `<video>` players.
- **`<Suspense>` friendly.** `hydrationPromise` lets you gate
  `async setup()` on initial hydration.

## Installation

```bash
npm install @langchain/vue @langchain/core
```

**Peer dependencies:** `vue` (^3.4.0), `@langchain/core` (^1.0.1).

## Quick start

```vue
<script setup lang="ts">
import { useStream } from "@langchain/vue";

const stream = useStream({
  assistantId: "agent",
  apiUrl: "http://localhost:2024",
});

function onSubmit() {
  void stream.submit({ messages: [{ type: "human", content: "Hello!" }] });
}
</script>

<template>
  <div>
    <div v-for="(msg, i) in stream.messages" :key="msg.id ?? i">
      {{ typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content) }}
    </div>

    <button :disabled="stream.isLoading" @click="onSubmit">
      Send
    </button>
  </div>
</template>
```

Reactive fields on the handle are Vue refs (`ShallowRef` /
`ComputedRef`). In `<script setup>`, read them with `.value`:
`stream.messages.value`, `stream.isLoading.value`. In `<template>`,
Vue auto-unwraps refs, so prefer the shorter
`stream.messages` / `stream.isLoading` form.

## Documentation

In-depth guides live in [`docs/`](./docs):

- [API reference](./docs/api-reference.md) — `useStream` options and
  return shape.
- [Selectors](./docs/selectors.md) — ref-counted readers for
  namespaced / scoped data.
- [Transports](./docs/transports.md) — SSE, WebSocket, and custom
  `AgentServerAdapter` implementations.
- [Custom transports](./docs/custom-transport.md) — implementing
  `AgentServerAdapter` against your own backend, with a worked
  walkthrough of [`examples/ui-react-transport`](../../examples/ui-react-transport).
- [Interrupts & headless tools](./docs/interrupts.md) — pausing a
  run, responding to interrupts, registering browser-side tools.
- [Forking from a message](./docs/forking.md) — edit / retry flows
  with `useMessageMetadata` + `submit({ forkFrom })`.
- [Submission queue](./docs/submission-queue.md) — inspecting and
  cancelling enqueued submits.
- [Subagents & subgraphs](./docs/subagents.md) — rendering
  per-subagent messages, tool calls, and state via scoped selectors.
- [Multimodal media](./docs/multimodal.md) — audio / image / video /
  file streams with built-in players.
- [Sharing a stream](./docs/sharing-streams.md) — `provideStream`,
  `useStreamContext`, and the `LangChainPlugin` app-level defaults.
- [Suspense-style hydration](./docs/suspense.md) — gating
  `async setup()` on `hydrationPromise`.
- [Type safety](./docs/type-safety.md) — brand inference, generics,
  and the exported helper types.
- [Testing](./docs/testing.md) — mounting components with mock
  streams or real dev servers.
- [Migrating from 0.x](./docs/v1-migration.md) — full diff of
  options, return shape, and transport classes.

## Playground

For complete end-to-end examples with full agentic UIs, visit the
[LangChain UI Playground](https://docs.langchain.com/playground).

## License

MIT

---

### Overview (`libs/sdk/README.md`)

# `@langchain/langgraph-sdk`

The JavaScript / TypeScript SDK for talking to a LangGraph API server.
Use it to create and manage assistants, threads, runs, cron
schedules, and the KV store — and, most importantly, to **stream**
graph executions in real time.

📚 **[Full documentation](./docs/README.md)**

## Install

```bash
pnpm add @langchain/langgraph-sdk @langchain/core
# or: npm install @langchain/langgraph-sdk @langchain/core
# or: yarn add @langchain/langgraph-sdk @langchain/core
```

## Quick start

```ts
import { Client } from "@langchain/langgraph-sdk";

const client = new Client({ apiUrl: "http://localhost:2024" });

// Open a thread-centric stream (the recommended way to stream).
const thread = client.threads.stream({ assistantId: "my-agent" });

await thread.run.start({
  input: { messages: [{ role: "user", content: "hello" }] },
});

for await (const message of thread.messages) {
  for await (const token of message.text) {
    process.stdout.write(token);
  }
}

console.log(await thread.output);
await thread.close();
```

With no `apiUrl`, the SDK points at `http://localhost:2024` (the
default `langgraph dev` URL).

## What's in the SDK

| Sub-client          | Purpose                                            | Docs                                                            |
| ------------------- | -------------------------------------------------- | --------------------------------------------------------------- |
| `client.threads`    | Create threads, manage state, and **stream** runs. | [Threads](./docs/threads.md) · [Streaming](./docs/streaming.md) |
| `client.assistants` | CRUD for assistants (schemas, graphs, versions).   | [Assistants](./docs/assistants.md)                              |
| `client.runs`       | Trigger / join / cancel runs without streaming.    | [Runs (legacy)](./docs/runs.md)                                 |
| `client.crons`      | Schedule recurring runs.                           | [Crons](./docs/crons.md)                                        |
| `client.store`      | Namespaced KV + semantic store.                    | [Store](./docs/store.md)                                        |

### Streaming

`client.threads.stream(...)` returns a [`ThreadStream`](./docs/streaming.md)
with typed, lazy projections for every aspect of a run:

- `thread.messages` / `thread.toolCalls` — assembled chat output.
- `thread.values` / `thread.output` — graph state and final answer.
- `thread.interrupts` / `thread.interrupted` — human-in-the-loop.
- `thread.subgraphs` / `thread.subagents` — nested / deep-agent work.
- `thread.extensions.<name>` — typed custom server projections.
- `thread.audio` / `thread.images` / `thread.video` / `thread.files`
  — media.

> **Deprecated.** The generator-based streaming APIs on
> `client.runs.*` (`stream`, `joinStream`) and `client.threads.joinStream`
> are preserved for backwards compatibility only. New code should use
> `client.threads.stream(...)`. See
> [Runs (legacy)](./docs/runs.md) for migration guidance.

### Transports

Streaming defaults to Server-Sent Events (SSE) over HTTP. You can
switch to WebSocket per-call or globally, or plug in a custom
`AgentServerAdapter`:

```ts
const thread = client.threads.stream({
  assistantId: "my-agent",
  transport: "websocket",
});
```

See [Transports](./docs/transports.md) for full details.

## Framework adapters

If you're building a UI, use the framework-specific packages that
wrap this SDK:

- [`@langchain/langgraph-sdk/react`](../sdk-react/docs/README.md)
- [`@langchain/langgraph-sdk/vue`](../sdk-vue/docs/README.md)
- [`@langchain/langgraph-sdk/svelte`](../sdk-svelte/docs/README.md)
- [`@langchain/langgraph-sdk/angular`](../sdk-angular/docs/README.md)

Use the SDK directly when you need low-level control, run it from a
non-browser environment (Node.js server, edge workers, scripts), or
integrate into a framework that does not yet have a first-party
adapter.

## Architecture

The client code is organized into sub-client modules under
`src/client/`:

| Path                 | Module                                                    |
| -------------------- | --------------------------------------------------------- |
| `client/assistants/` | `AssistantsClient`                                        |
| `client/threads/`    | `ThreadsClient` (includes the v2 `stream(...)` primitive) |
| `client/runs/`       | `RunsClient` (legacy streaming + CRUD)                    |
| `client/crons/`      | `CronsClient`                                             |
| `client/store/`      | `StoreClient`                                             |
| `client/stream/`     | `ThreadStream`, assemblers, transports                    |
| `client/base.ts`     | `BaseClient`, shared config & helpers                     |
| `client/index.ts`    | Main `Client` class & re-exports                          |

## Change log

See [CHANGELOG.md](https://github.com/langchain-ai/langgraphjs/blob/main/libs/sdk/CHANGELOG.md).

---

### Overview (`internal/environment_tests/test-exports-cf/README.md`)

# test-exports-cf

This package was generated with `wrangler init` with the purpose of testing compatibility with Cloudlfare Workers.

---

### Overview (`internal/environment_tests/test-exports-vercel/README.md`)

This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.

[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.

The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.

This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.

---

### Overview (`libs/sdk-angular/docs/README.md`)

# Angular SDK docs

This folder contains guides for using `@langchain/angular` to build
LangGraph-powered Angular applications. The docs cover the main stream API,
Angular dependency injection patterns, selectors, transports, and common
interactive agent workflows.

## Core usage

- [`inject-stream.md`](./inject-stream.md) explains the primary `injectStream`
  API, including options, return values, and lifecycle behavior.
- [`dependency-injection.md`](./dependency-injection.md) covers
  `provideStream`, `injectStream`, stream defaults, and `StreamService`.
- [`type-safety.md`](./type-safety.md) describes agent-brand inference, stream
  aliases, and type helpers.
- [`testing.md`](./testing.md) shows how to test streams, selectors, and
  services.

## Streaming features

- [`selectors.md`](./selectors.md) explains selector targets, scoped messages,
  media selectors, and cleanup behavior.
- [`submission-queue.md`](./submission-queue.md) covers queued submissions,
  multitask strategies, and thread swaps.
- [`interrupts.md`](./interrupts.md) shows how to read and resume interrupts.
- [`headless-tools.md`](./headless-tools.md) covers tool handlers and lifecycle
  events that run outside the visible UI.

## Agent workflows

- [`branching.md`](./branching.md) explains how to fork from a message using
  checkpoint IDs.
- [`subagents-subgraphs.md`](./subagents-subgraphs.md) covers subagent and
  subgraph discovery, rendering, and namespace targeting.

## Connectivity and migration

- [`transports.md`](./transports.md) compares the built-in LangGraph Platform
  transports and custom adapters.
- [`custom-transport.md`](./custom-transport.md) is the detailed guide for
  pointing `injectStream` at a custom backend — `HttpAgentServerAdapter`,
  server-side protocol handling, lazy thread binding, and implementing
  `AgentServerAdapter` directly.
- [`v1-migration.md`](./v1-migration.md) explains how to migrate from earlier
  Angular SDK APIs to v1.

---

### Overview (`libs/sdk-react/docs/README.md`)

# React SDK docs

This folder contains guides for using `@langchain/react` to build
LangGraph-powered React applications. The docs cover the core stream hooks,
context sharing, selectors, transports, and interactive agent patterns such as
interrupts, media, and subagents.

## Core usage

- [`use-stream.md`](./use-stream.md) explains the primary `useStream` hook,
  including options, return values, submissions, stopping, and hydration.
- [`context.md`](./context.md) covers `StreamProvider`, `useStreamContext`,
  type inference, nested providers, and custom adapters.
- [`suspense.md`](./suspense.md) describes `useSuspenseStream` and how it
  differs from `useStream`.
- [`type-safety.md`](./type-safety.md) explains agent-brand inference, custom
  state types, stream prop drilling, and helper types.

## Streaming features

- [`selectors.md`](./selectors.md) covers companion selector hooks for reading
  root or scoped stream data.
- [`submission-queue.md`](./submission-queue.md) explains multitask strategies,
  queued runs, cancellation, and thread switches.
- [`interrupts.md`](./interrupts.md) shows how to read, resume, and respond to
  interrupts, including headless tools.
- [`multimodal.md`](./multimodal.md) covers media handles, media hooks, and
  audio/video helpers.

## Agent workflows

- [`fork-from-checkpoint.md`](./fork-from-checkpoint.md) explains editing or
  retrying from a checkpoint.
- [`subagents.md`](./subagents.md) covers subagent discovery snapshots,
  rendering subagent content, and subgraphs.

## Connectivity

- [`transports.md`](./transports.md) compares built-in SSE, WebSocket,
  header-based auth, and custom adapters.
- [`custom-transport.md`](./custom-transport.md) is the detailed guide for
  pointing `useStream` at a custom backend — `HttpAgentServerAdapter`,
  server-side protocol handling, lazy thread binding, and implementing
  `AgentServerAdapter` directly.

---

### Overview (`libs/sdk-svelte/docs/README.md`)

# Svelte SDK docs

This folder contains guides for using `@langchain/svelte` to build
LangGraph-powered Svelte applications. The docs cover the main stream
composable, stream context, selectors, custom transports, and interactive agent
workflows.

## Core usage

- [`use-stream.md`](./use-stream.md) explains the primary `useStream`
  composable, including options, return shape, and reactive `threadId` values.
- [`stream-context.md`](./stream-context.md) covers providing and reading a
  stream through Svelte context.
- [`type-safety.md`](./type-safety.md) explains agent-brand inference, custom
  state types, typed stream handles, and helper types.
- [`v1-migration.md`](./v1-migration.md) explains how to migrate from
  `@langchain/svelte` v0 to v1.

## Streaming features

- [`selector-composables.md`](./selector-composables.md) covers selector
  composables, per-subagent views, per-message metadata, and raw event access.
- [`submission-queue.md`](./submission-queue.md) explains the submission queue
  exposed by the stream.
- [`interrupts.md`](./interrupts.md) shows how to handle targeted interrupts,
  stop runs, and use `hydrationPromise`.
- [`media.md`](./media.md) covers media URLs and audio/video helpers.

## Agent workflows and connectivity

- [`headless-tools.md`](./headless-tools.md) covers tool implementations and
  lifecycle events for headless tools.
- [`custom-transport.md`](./custom-transport.md) is the detailed guide for
  pointing `useStream` at a custom backend in Svelte apps —
  `HttpAgentServerAdapter`, server-side protocol handling, lazy thread
  binding, and implementing `AgentServerAdapter` directly.

---

### Overview (`libs/sdk-vue/docs/README.md`)

# Vue SDK docs

This folder contains guides for using `@langchain/vue` to build
LangGraph-powered Vue applications. The docs cover the stream composables,
context sharing, selectors, transports, testing, and advanced agent workflows.

## Core usage

- [`api-reference.md`](./api-reference.md) documents `useStream` options,
  return values, and related APIs.
- [`sharing-streams.md`](./sharing-streams.md) covers `provideStream`,
  `useStreamContext`, app-level defaults, and multi-agent layouts.
- [`suspense.md`](./suspense.md) explains suspense-style hydration and
  `hydrationPromise`.
- [`type-safety.md`](./type-safety.md) explains agent-brand inference, custom
  state shapes, stream prop drilling, and helper types.
- [`testing.md`](./testing.md) shows how to test with provided streams.

## Streaming features

- [`selectors.md`](./selectors.md) covers selector composables, target
  arguments, examples, and cleanup behavior.
- [`submission-queue.md`](./submission-queue.md) explains queued submissions and
  thread switching.
- [`interrupts.md`](./interrupts.md) shows how to handle interrupts (including
  script vs template payload access and HITL), resume a specific interrupt,
  stop runs, and use headless tools.
- [`multimodal.md`](./multimodal.md) covers multimodal media selectors, helper
  APIs, examples, and subagent scoping.

## Agent workflows

- [`forking.md`](./forking.md) explains forking from a message for branching
  workflows.
- [`subagents.md`](./subagents.md) covers subagent and subgraph rendering,
  listing, and discovery.

## Connectivity and migration

- [`transports.md`](./transports.md) compares built-in SSE, WebSocket, and
  custom adapter options.
- [`custom-transport.md`](./custom-transport.md) is the detailed guide for
  pointing `useStream` at a custom backend — `HttpAgentServerAdapter`,
  server-side protocol handling, lazy thread binding, and implementing
  `AgentServerAdapter` directly.
- [`v1-migration.md`](./v1-migration.md) explains how to migrate to
  `@langchain/vue` v1.

---

### Overview (`libs/sdk/docs/README.md`)

# `@langchain/langgraph-sdk`

The JavaScript / TypeScript SDK for talking to a LangGraph API server. Use
it to create and manage assistants, threads, runs, cron schedules, and the
KV store — and, most importantly, to **stream** graph executions in real
time.

If you're building a UI on top of LangGraph, the framework-specific
packages are thin wrappers around this SDK:

- [`@langchain/react`](../../sdk-react/docs/use-stream.md)
- [`@langchain/vue`](../../sdk-vue/docs/api-reference.md)
- [`@langchain/svelte`](../../sdk-svelte/docs/use-stream.md)
- [`@langchain/angular`](../../sdk-angular/docs/inject-stream.md)

Use the SDK directly when you need low-level control, run it from a
non-browser environment (Node.js server, edge workers, scripts), or
integrate into a framework that is not yet covered by a first-party
adapter.

## Table of contents

1. [Getting started](./getting-started.md) — install, create a `Client`,
   make your first request.
2. [Configuration](./configuration.md) — `apiUrl`, `apiKey`, headers,
   timeouts, retries, request hooks, and the `streamProtocol` flag.
3. **Streaming (recommended)**
   - [Overview](./streaming.md) — the `ThreadStream` primitive returned
     by `client.threads.stream(...)`.
   - [Messages & tokens](./streaming-messages.md) — stream text and
     reasoning deltas from chat models.
   - [Interrupts & human-in-the-loop](./streaming-interrupts.md) —
     pause, inspect, and resume runs.
   - [Subgraphs](./streaming-subgraphs.md) —
     observe nested work in fan-out graphs.
   - [Subagents](./streaming-subagents.md) —
     observe deepagents-specific `task`-tool workers.
   - [Custom transformers (extensions)](./streaming-extensions.md) —
     consume `custom:<name>` projections with end-to-end typing.
   - [Media blocks](./streaming-media.md) — audio, image, video, and
     file streams.
   - [Advanced: raw subscriptions](./streaming-advanced.md) —
     `subscribe()`, `onEvent()`, `state.*`, channel filters.
   - [Transports](./transports.md) — SSE, WebSocket, and custom
     `AgentServerAdapter`s.
4. **Sub-clients**
   - [Assistants](./assistants.md) — `client.assistants`.
   - [Threads](./threads.md) — `client.threads` (CRUD, state, history).
   - [Runs (legacy)](./runs.md) — `client.runs` **(deprecated for
     streaming; use [`client.threads.stream`](./streaming.md)
     instead)**.
   - [Cron jobs](./crons.md) — `client.crons`.
   - [KV store](./store.md) — `client.store`.

## Which API do I use for streaming?

The SDK ships with two generations of streaming APIs. **New code should
always use the v2 `client.threads.stream(...)` primitive.** The legacy
generators on `client.runs.*` are preserved for backwards compatibility
only.

- **Stream a run with typed projections:** [`client.threads.stream(...)`](./streaming.md) ✅ **recommended**
- **Stream messages token-by-token:** [`thread.messages`](./streaming-messages.md) ✅
- **Human-in-the-loop:** [`thread.interrupts` + `thread.input.respond(...)`](./streaming-interrupts.md) ✅
- **Subgraph tree:** [`thread.subgraphs`](./streaming-subgraphs.md) ✅
- **Deep-agent subagents:** [`thread.subagents`](./streaming-subagents.md) ✅
- **Custom server-side projections:** [`thread.extensions.<name>`](./streaming-extensions.md) ✅
- **Re-attach to an in-flight run:** `client.threads.stream(threadId, { assistantId })` ✅
- **`client.runs.stream(...)` / `runs.joinStream()`:** ⚠️ Legacy — see [Runs (legacy)](./runs.md) for migration guidance

## Quick peek

```ts
import { Client } from "@langchain/langgraph-sdk";

const client = new Client({ apiUrl: "http://localhost:2024" });

const thread = client.threads.stream({ assistantId: "my-agent" });

await thread.run.start({
  input: { messages: [{ role: "user", content: "hello" }] },
});

for await (const message of thread.messages) {
  for await (const token of message.text) {
    process.stdout.write(token);
  }
}

console.log(await thread.output);
await thread.close();
```

Continue with [Getting started](./getting-started.md).

---

### Docs Index (`docs/docs/index.md`)

---
hide_comments: true
title: LangGraph
---

{!README.md!}

---

### Docs Llms Txt Overview (`docs/docs/llms-txt-overview.md`)

# LLMs-txt Overview

## Overview

Below you can find a list of documentation files in the [`llms.txt`](https://llmstxt.org/) format, specifically `llms.txt` and `llms-full.txt`. These files allow large language models (LLMs) and agents to access programming documentation and APIs, particularly useful within integrated development environments (IDEs).

| Language Version | llms.txt                                                                                                   | llms-full.txt                                                                                                        |
|------------------|------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------|
| LangGraph Python | [https://langchain-ai.github.io/langgraph/llms.txt](https://langchain-ai.github.io/langgraph/llms.txt)     | [https://langchain-ai.github.io/langgraph/llms-full.txt](https://langchain-ai.github.io/langgraph/llms-full.txt)     |
| LangGraph JS     | [https://langchain-ai.github.io/langgraphjs/llms.txt](https://langchain-ai.github.io/langgraphjs/llms.txt) | [https://langchain-ai.github.io/langgraphjs/llms-full.txt](https://langchain-ai.github.io/langgraphjs/llms-full.txt) |
| LangChain Python | [https://python.langchain.com/llms.txt](https://python.langchain.com/llms.txt)                             | N/A                                                                                                                  |
| LangChain JS     | [https://js.langchain.com/llms.txt](https://js.langchain.com/llms.txt)                                     | N/A                                                                                                                  |

!!! info "Review the output"

    Even with access to up-to-date documentation, current state-of-the-art models may not always generate correct code. Treat the generated code as a starting point, and always review it before shipping
    code to production.

## Differences Between `llms.txt` and `llms-full.txt`

- **`llms.txt`** is an index file containing links with brief descriptions of the content. An LLM or agent must follow these links to access detailed information.

- **`llms-full.txt`** includes all the detailed content directly in a single file, eliminating the need for additional navigation.

A key consideration when using `llms-full.txt` is its size. For extensive documentation, this file may become too large to fit into an LLM's context window.

## Using `llms.txt` via an MCP Server

As of March 9, 2025, IDEs [do not yet have robust native support for `llms.txt`](https://x.com/jeremyphoward/status/1902109312216129905?t=1eHFv2vdNdAckajnug0_Vw&s=19). However, you can still use `llms.txt` effectively through an MCP server.

### 🚀 Use the `mcpdoc` Server

We provide an **MCP server** that was designed to serve documentation for LLMs and IDEs:

👉 **[langchain-ai/mcpdoc GitHub Repository](https://github.com/langchain-ai/mcpdoc)**

This MCP server allows integrating `llms.txt` into tools like **Cursor**, **Windsurf**, **Claude**, and **Claude Code**.

📘 **Setup instructions and usage examples** are available in the repository.

## Using `llms-full.txt`

The LangGraph `llms-full.txt` file typically contains several hundred thousand tokens, exceeding the context window limitations of most LLMs. To effectively use this file:

1. **With IDEs (e.g., Cursor, Windsurf)**:
    - Add the `llms-full.txt` as custom documentation. The IDE will automatically chunk and index the content, implementing Retrieval-Augmented Generation (RAG).

2. **Without IDE support**:
    - Use a chat model with a large context window.
    - Implement a RAG strategy to manage and query the documentation efficiently.

---

### Docs Agents Overview (`docs/docs/agents/overview.md`)

---
title: Overview
---

# Agent development with LangGraph

**LangGraph** provides both low-level primitives and high-level prebuilt components for building agent-based applications. This section focuses on the **prebuilt**, **reusable** components designed to help you construct agentic systems quickly and reliably—without the need to implement orchestration, memory, or human feedback handling from scratch.

## What is an agent?

An _agent_ consists of three components: a **large language model (LLM)**, a set of **tools** it can use, and a **prompt** that provides instructions.

The LLM operates in a loop. In each iteration, it selects a tool to invoke, provides input, receives the result (an observation), and uses that observation to inform the next action. The loop continues until a stopping condition is met — typically when the agent has gathered enough information to respond to the user.

<figure markdown="1">
{: style="max-height:400px"}
<figcaption>Agent loop: the LLM selects tools and uses their outputs to fulfill a user request.</figcaption>
</figure>

## Key features

LangGraph includes several capabilities essential for building robust, production-ready agentic systems:

- [**Memory integration**](./memory.md): Native support for _short-term_ (session-based) and _long-term_ (persistent across sessions) memory, enabling stateful behaviors in chatbots and assistants.
- [**Human-in-the-loop control**](./human-in-the-loop.md): Execution can pause _indefinitely_ to await human feedback—unlike websocket-based solutions limited to real-time interaction. This enables asynchronous approval, correction, or intervention at any point in the workflow.
- [**Streaming support**](./streaming.md): Real-time streaming of agent state, model tokens, tool outputs, or combined streams.
- [**Deployment tooling**](./deployment.md): Includes infrastructure-free deployment tools. [**LangGraph Platform**](https://langchain-ai.github.io/langgraph/concepts/langgraph_platform/) supports testing, debugging, and deployment.
  - **[Studio](https://langchain-ai.github.io/langgraph/concepts/langgraph_studio/)**: A visual IDE for inspecting and debugging workflows.
  - Supports multiple [**deployment options**](https://langchain-ai.github.io/langgraph/tutorials/deployment/) for production.

## High-level building blocks

LangGraph comes with a set of prebuilt components that implement common agent behaviors and workflows. These abstractions are built on top of the LangGraph framework, offering a faster path to production while remaining flexible for advanced customization.

Using LangGraph for agent development allows you to focus on your application's logic and behavior, instead of building and maintaining the supporting infrastructure for state, memory, and human feedback.

## Package ecosystem

The high-level components are organized into several packages, each with a specific focus.

| Package                  | Description                                                                 | Installation                                       |
| ------------------------ | --------------------------------------------------------------------------- | -------------------------------------------------- |
| `langgraph`              | Prebuilt components to [**create agents**](./agents.md)                     | `npm install @langchain/langgraph @langchain/core` |
| `langgraph-supervisor`   | Tools for building [**supervisor**](./multi-agent.md#supervisor) agents     | `npm install @langchain/langgraph-supervisor`      |
| `langgraph-swarm`        | Tools for building a [**swarm**](./multi-agent.md#swarm) multi-agent system | `npm install @langchain/langgraph-swarm`           |
| `langchain-mcp-adapters` | Interfaces to [**MCP servers**](./mcp.md) for tool and resource integration | `npm install @langchain/mcp-adapters`              |
| `agentevals`             | Utilities to [**evaluate agent performance**](./evals.md)                   | `npm install agentevals`                           |

## Visualize an agent graph

Use the following tool to visualize the graph generated by [`createReactAgent`](/langgraphjs/reference/functions/langgraph_prebuilt.createReactAgent.html) and to view an outline of the corresponding code. It allows you to explore the infrastructure of the agent as defined by the presence of:

- [`tools`](./tools.md): A list of tools (functions, APIs, or other callable objects) that the agent can use to perform tasks.
- `preModelHook`: A function that is called before the model is invoked. It can be used to condense messages or perform other preprocessing tasks.
- `postModelHook`: A function that is called after the model is invoked. It can be used to implement guardrails, human-in-the-loop flows, or other postprocessing tasks.
- [`responseFormat`](./agents.md#structured-output): A data structure used to constrain the type of the final output (via Zod schemas).

<div class="agent-layout">
  <div class="agent-graph-features-container">
    <div class="agent-graph-features">
      <h3 class="agent-section-title">Features</h3>
      <label><input type="checkbox" id="tools" checked> <code>tools</code></label>
      <label><input type="checkbox" id="preModelHook"> <code>preModelHook</code></label>
      <label><input type="checkbox" id="postModelHook"> <code>postModelHook</code></label>
      <label><input type="checkbox" id="responseFormat"> <code>responseFormat</code></label>
    </div>
  </div>

  <div class="agent-graph-container">
    <h3 class="agent-section-title">Graph</h3>
    <img id="agent-graph-img" src="../assets/react_agent_graphs/0001.svg" alt="graph image" style="max-width: 100%;"/>
  </div>
</div>

The following code snippet shows how to create the above agent (and underlying graph) with [`createReactAgent`](/langgraphjs/reference/functions/langgraph_prebuilt.createReactAgent.html):

<div class="language-typescript">
  <pre><code id="agent-code" class="language-typescript"></code></pre>
</div>

<script>
function getCheckedValue(id) {
  return document.getElementById(id).checked ? "1" : "0";
}

function getKey() {
  return [
    getCheckedValue("responseFormat"),
    getCheckedValue("postModelHook"),
    getCheckedValue("preModelHook"),
    getCheckedValue("tools")
  ].join("");
}

function dedent(strings, ...values) {
  const str = String.raw({ raw: strings }, ...values)
  const [space] = str.split("\n").filter(Boolean).at(0).match(/^(\s*)/)
  const spaceLen = space.length
  return str.split("\n").map(line => line.slice(spaceLen)).join("\n").trim()
}

Object.assign(dedent, {
  offset: (size) => (strings, ...values) => {
    return dedent(strings, ...values).split("\n").map(line => " ".repeat(size) + line).join("\n")
  }
})




function generateCodeSnippet({ tools, pre, post, response }) {
  const lines = []

  lines.push(dedent`
    import { createReactAgent } from "@langchain/langgraph/prebuilt";
    import { ChatOpenAI } from "@langchain/openai";
  `)

  if (tools) lines.push(`import { tool } from "@langchain/core/tools";`);  
  if (response || tools) lines.push(`import { z } from "zod";`);

  lines.push("", dedent`
    const agent = createReactAgent({
      llm: new ChatOpenAI({ model: "o4-mini" }),
  `)

  if (tools) {
    lines.push(dedent.offset(2)`
      tools: [
        tool(() => "Sample tool output", {
          name: "sampleTool",
          schema: z.object({}),
        }),
      ],
    `)
  }

  if (pre) {
    lines.push(dedent.offset(2)`
      preModelHook: (state) => ({ llmInputMessages: state.messages }),
    `)
  }

  if (post) {
    lines.push(dedent.offset(2)`
      postModelHook: (state) => state,
    `)
  }

  if (response) {
    lines.push(dedent.offset(2)`
      responseFormat: z.object({ result: z.string() }),
    `)
  }

  lines.push(`});`);

  return lines.join("\n");
}

function render() {
  const key = getKey();
  document.getElementById("agent-graph-img").src = `../assets/react_agent_graphs/${key}.svg`;

  const state = {
    tools: document.getElementById("tools").checked,
    pre: document.getElementById("preModelHook").checked,
    post: document.getElementById("postModelHook").checked,
    response: document.getElementById("responseFormat").checked
  };

  document.getElementById("agent-code").textContent = generateCodeSnippet(state);
}

function initializeWidget() {
  render(); // no need for `await` here
  document.querySelectorAll(".agent-graph-features input").forEach((input) => {
    input.addEventListener("change", render);
  });
}

// Init for both full reload and SPA nav (used by MkDocs Material)
window.addEventListener("DOMContentLoaded", initializeWidget);
document$.subscribe(initializeWidget);
</script>

---

### Docs Concepts Index (`docs/docs/concepts/index.md`)

---
title: Concepts
description: Conceptual Guide for LangGraph.js
---

# Conceptual Guide

This guide provides explanations of the key concepts behind the LangGraph framework and AI applications more broadly.

We recommend that you go through at least the [Quick Start](../tutorials/quickstart.ipynb) before diving into the conceptual guide. This will provide practical context that will make it easier to understand the concepts discussed here.

The conceptual guide does not cover step-by-step instructions or specific implementation examples — those are found in the [Tutorials](../tutorials/index.md) and [How-to guides](../how-tos/index.md). For detailed reference material, please see the [API reference](https://langchain-ai.github.io/langgraphjs/reference/).

## LangGraph

### High Level

- [Why LangGraph?](high_level.md): A high-level overview of LangGraph and its goals.

### Concepts

- [LangGraph Glossary](low_level.md): LangGraph workflows are designed as graphs, with nodes representing different components and edges representing the flow of information between them. This guide provides an overview of the key concepts associated with LangGraph graph primitives.
- [Common Agentic Patterns](agentic_concepts.md): An agent uses an LLM to pick its own control flow to solve more complex problems! Agents are a key building block in many LLM applications. This guide explains the different types of agent architectures and how they can be used to control the flow of an application.
- [Multi-Agent Systems](multi_agent.md): Complex LLM applications can often be broken down into multiple agents, each responsible for a different part of the application. This guide explains common patterns for building multi-agent systems.
- [Breakpoints](breakpoints.md): Breakpoints allow pausing the execution of a graph at specific points. Breakpoints allow stepping through graph execution for debugging purposes.
- [Human-in-the-Loop](human_in_the_loop.md): Explains different ways of integrating human feedback into a LangGraph application.
- [Time Travel](time-travel.md): Time travel allows you to replay past actions in your LangGraph application to explore alternative paths and debug issues.
- [Persistence](persistence.md): LangGraph has a built-in persistence layer, implemented through checkpointers. This persistence layer helps to support powerful capabilities like human-in-the-loop, memory, time travel, and fault-tolerance.
- [Memory](memory.md): Memory in AI applications refers to the ability to process, store, and effectively recall information from past interactions. With memory, your agents can learn from feedback and adapt to users' preferences.
- [Streaming](streaming.md): Streaming is crucial for enhancing the responsiveness of applications built on LLMs. By displaying output progressively, even before a complete response is ready, streaming significantly improves user experience (UX), particularly when dealing with the latency of LLMs.
- [Functional API](functional_api.md): An alternative to [Graph API (StateGraph)](low_level.md#stategraph) for development in LangGraph.
- [FAQ](faq.md): Frequently asked questions about LangGraph.

## LangGraph Platform

LangGraph Platform is a commercial solution for deploying agentic applications in production, built on the open-source LangGraph framework.

The LangGraph Platform offers a few different deployment options described in the [deployment options guide](./deployment_options.md).

!!! tip

    * LangGraph is an MIT-licensed open-source library, which we are committed to maintaining and growing for the community.
    * You can always deploy LangGraph applications on your own infrastructure using the open-source LangGraph project without using LangGraph Platform.

### High Level

- [Why LangGraph Platform?](./langgraph_platform.md): The LangGraph platform is an opinionated way to deploy and manage LangGraph applications. This guide provides an overview of the key features and concepts behind LangGraph Platform.
- [Deployment Options](./deployment_options.md): LangGraph Platform offers four deployment options: [Self-Hosted Lite](./self_hosted.md#self-hosted-lite), [Self-Hosted Enterprise](./self_hosted.md#self-hosted-enterprise), [bring your own cloud (BYOC)](./bring_your_own_cloud.md), and [Cloud SaaS](./langgraph_cloud.md). This guide explains the differences between these options, and which Plans they are available on.
- [Plans](./plans.md): LangGraph Platforms offer three different plans: Developer, Plus, Enterprise. This guide explains the differences between these options, what deployment options are available for each, and how to sign up for each one.
- [Template Applications](./template_applications.md): Reference applications designed to help you get started quickly when building with LangGraph.

### Components

The LangGraph Platform comprises several components that work together to support the deployment and management of LangGraph applications:

- [LangGraph Server](./langgraph_server.md): The LangGraph Server is designed to support a wide range of agentic application use cases, from background processing to real-time interactions.
- [LangGraph Studio](./langgraph_studio.md): LangGraph Studio is a specialized IDE that can connect to a LangGraph Server to enable visualization, interaction, and debugging of the application locally.
- [LangGraph CLI](./langgraph_cli.md): LangGraph CLI is a command-line interface that helps to interact with a local LangGraph
- [Python/JS SDK](./sdk.md): The Python/JS SDK provides a programmatic way to interact with deployed LangGraph Applications.
- [Remote Graph](../how-tos/use-remote-graph.md): A RemoteGraph allows you to interact with any deployed LangGraph application as though it were running locally.

### LangGraph Server

- [Application Structure](./application_structure.md): A LangGraph application consists of one or more graphs, a LangGraph API Configuration file (`langgraph.json`), a file that specifies dependencies, and environment variables.
- [Assistants](./assistants.md): Assistants are a way to save and manage different configurations of your LangGraph applications.
- [Web-hooks](./langgraph_server.md#webhooks): Webhooks allow your running LangGraph application to send data to external services on specific events.
- [Cron Jobs](./langgraph_server.md#cron-jobs): Cron jobs are a way to schedule tasks to run at specific times in your LangGraph application.
- [Double Texting](./double_texting.md): Double texting is a common issue in LLM applications where users may send multiple messages before the graph has finished running. This guide explains how to handle double texting with LangGraph Deploy.
- [Authentication & Access Control](./auth.md): Learn about options for authentication and access control when deploying the LangGraph Platform.

### Deployment Options

- [Self-Hosted Lite](./self_hosted.md): A free (up to 1 million nodes executed), limited version of LangGraph Platform that you can run locally or in a self-hosted manner
- [Cloud SaaS](./langgraph_cloud.md): Hosted as part of LangSmith.
- [Bring Your Own Cloud](./bring_your_own_cloud.md): We manage the infrastructure, so you don't have to, but the infrastructure all runs within your cloud.
- [Self-Hosted Enterprise](./self_hosted.md): Completely managed by you.

---

### Docs How Tos Index (`docs/docs/how-tos/index.md`)

---
title: How-to Guides
description: How to accomplish common tasks in LangGraph.js
---

# How-to guides

Here you’ll find answers to “How do I...?” types of questions. These guides are **goal-oriented** and concrete; they're meant to help you complete a specific task. For conceptual explanations see the [Conceptual guide](../concepts/index.md). For end-to-end walk-throughs see [Tutorials](../tutorials/index.md). For comprehensive descriptions of every class and function see the [API Reference](https://langchain-ai.github.io/langgraphjs/reference/).

## Installation

- [How to install and manage dependencies](manage-ecosystem-dependencies.ipynb)
- [How to use LangGraph.js in web environments](use-in-web-environments.ipynb)

## LangGraph

### Controllability

LangGraph.js is known for being a highly controllable agent framework.
These how-to guides show how to achieve that controllability.

- [How to create branches for parallel execution](branching.ipynb)
- [How to create map-reduce branches for parallel execution](map-reduce.ipynb)
- [How to defer node execution](defer-node-execution.ipynb)
- [How to combine control flow and state updates with Command](command.ipynb)
- [How to create and control loops with recursion limits](recursion-limit.ipynb)

### Persistence

LangGraph.js makes it easy to persist state across graph runs. The guides below shows how to add persistence to your graph.

- [How to add thread-level persistence to your graph](persistence.ipynb)
- [How to add thread-level persistence to subgraphs](subgraph-persistence.ipynb)
- [How to add cross-thread persistence](cross-thread-persistence.ipynb)
- [How to use a Postgres checkpointer for persistence](persistence-postgres.ipynb)

See the below guides for how-to add persistence to your workflow using the [Functional API](../concepts/functional_api.md):

- [How to add thread-level persistence (functional API)](persistence-functional.ipynb)
- [How to add cross-thread persistence (functional API)](cross-thread-persistence-functional.ipynb)

### Memory

LangGraph makes it easy to manage conversation [memory](../concepts/memory.md) in your graph. These how-to guides show how to implement different strategies for that.

- [How to manage conversation history](manage-conversation-history.ipynb)
- [How to delete messages](delete-messages.ipynb)
- [How to add summary of the conversation history](add-summary-conversation-history.ipynb)
- [How to add long-term memory (cross-thread)](cross-thread-persistence.ipynb)
- [How to use semantic search for long-term memory](semantic-search.ipynb)

### Human-in-the-loop

[Human-in-the-loop](/langgraphjs/concepts/human_in_the_loop) functionality allows
you to involve humans in the decision-making process of your graph. These how-to guides show how to implement human-in-the-loop workflows in your graph.

Key workflows:

- [How to wait for user input](wait-user-input.ipynb): A basic example that shows how to implement a human-in-the-loop workflow in your graph using the `interrupt` function.
- [How to review tool calls](review-tool-calls.ipynb): Incorporate human-in-the-loop for reviewing/editing/accepting tool call requests before they executed using the `interrupt` function.

Other methods:

- [How to add static breakpoints](breakpoints.ipynb): Use for debugging purposes. For [**human-in-the-loop**](/langgraphjs/concepts/human_in_the_loop) workflows, we recommend the [`interrupt` function](/langgraphjs/reference/functions/langgraph.interrupt-1.html) instead.
- [How to edit graph state](edit-graph-state.ipynb): Edit graph state using `graph.update_state` method. Use this if implementing a **human-in-the-loop** workflow via **static breakpoints**.
- [How to add dynamic breakpoints with `NodeInterrupt`](dynamic_breakpoints.ipynb): **Not recommended**: Use the [`interrupt` function](/langgraphjs/concepts/human_in_the_loop) instead.

See the below guides for how-to implement human-in-the-loop workflows with the [Functional API](../concepts/functional_api.md):

- [How to wait for user input (Functional API)](wait-user-input-functional.ipynb)
- [How to review tool calls (Functional API)](review-tool-calls-functional.ipynb)

### Time Travel

[Time travel](../concepts/time-travel.md) allows you to replay past actions in your LangGraph application to explore alternative paths and debug issues. These how-to guides show how to use time travel in your graph.

- [How to view and update past graph state](time-travel.ipynb)

### Streaming

LangGraph is built to be streaming first.
These guides show how to use different streaming modes.

- [How to stream the full state of your graph](stream-values.ipynb)
- [How to stream state updates of your graph](stream-updates.ipynb)
- [How to stream LLM tokens](stream-tokens.ipynb)
- [How to stream LLM tokens without LangChain models](streaming-tokens-without-langchain.ipynb)
- [How to stream custom data](streaming-content.ipynb)
- [How to configure multiple streaming modes](stream-multiple.ipynb)
- [How to stream events from within a tool](streaming-events-from-within-tools.ipynb)
- [How to stream from the final node](streaming-from-final-node.ipynb)

### Tool calling

- [How to call tools using ToolNode](tool-calling.ipynb)
- [How to force an agent to call a tool](force-calling-a-tool-first.ipynb)
- [How to handle tool calling errors](tool-calling-errors.ipynb)
- [How to pass runtime values to tools](pass-run-time-values-to-tools.ipynb)
- [How to update graph state from tools](update-state-from-tools.ipynb)

### Subgraphs

[Subgraphs](../concepts/low_level.md#subgraphs) allow you to reuse an existing graph from another graph. These how-to guides show how to use subgraphs:

- [How to add and use subgraphs](subgraph.ipynb)
- [How to view and update state in subgraphs](subgraphs-manage-state.ipynb)
- [How to transform inputs and outputs of a subgraph](subgraph-transform-state.ipynb)

### Multi-agent

- [How to build a multi-agent network](multi-agent-network.ipynb)
- [How to add multi-turn conversation in a multi-agent application](multi-agent-multi-turn-convo.ipynb)

See the [multi-agent tutorials](../tutorials/index.md#multi-agent-systems) for implementations of other multi-agent architectures.

See the below guides for how-to implement multi-agent workflows with the [Functional API](../concepts/functional_api.md):

- [How to build a multi-agent network (functional API)](multi-agent-network-functional.ipynb)
- [How to add multi-turn conversation in a multi-agent application (functional API)](multi-agent-multi-turn-convo-functional.ipynb)

### State management

- [How to define graph state](define-state.ipynb)
- [Have a separate input and output schema](input_output_schema.ipynb)
- [Pass private state between nodes inside the graph](pass_private_state.ipynb)

### Other

- [How to add runtime configuration to your graph](configuration.ipynb)
- [How to add node retries](node-retry-policies.ipynb)
- [How to cache expensive nodes](node-caching.ipynb)
- [How to let an agent return tool results directly](dynamically-returning-directly.ipynb)
- [How to have an agent respond in structured format](respond-in-format.ipynb)
- [How to manage agent steps](managing-agent-steps.ipynb)

### Prebuilt ReAct Agent

- [How to create a ReAct agent](create-react-agent.ipynb)
- [How to add memory to a ReAct agent](react-memory.ipynb)
- [How to add a system prompt to a ReAct agent](react-system-prompt.ipynb)
- [How to add Human-in-the-loop to a ReAct agent](react-human-in-the-loop.ipynb)
- [How to return structured output from a ReAct agent](react-return-structured-output.ipynb)

See the below guide for how-to build ReAct agents with the [Functional API](../concepts/functional_api.md):

- [How to create a ReAct agent from scratch (Functional API)](react-agent-from-scratch-functional.ipynb)

## LangGraph Platform

This section includes how-to guides for LangGraph Platform.

LangGraph Platform is a commercial solution for deploying agentic applications in production, built on the open-source LangGraph framework. It provides four deployment options to fit a range of needs: a free tier, a self-hosted version, a cloud SaaS, and a Bring Your Own Cloud (BYOC) option. You can explore these options in detail in the [deployment options guide](../concepts/deployment_options.md).

!!! tip

    * LangGraph is an MIT-licensed open-source library, which we are committed to maintaining and growing for the community.
    * You can always deploy LangGraph applications on your own infrastructure using the open-source LangGraph project without using LangGraph Platform.

### Application Structure

Learn how to set up your app for deployment to LangGraph Platform:

- [How to set up app for deployment (requirements.txt)](/langgraphjs/cloud/deployment/setup)
- [How to set up app for deployment (pyproject.toml)](/langgraphjs/cloud/deployment/setup_pyproject)
- [How to set up app for deployment (JavaScript)](/langgraphjs/cloud/deployment/setup_javascript)
- [How to customize Dockerfile](/langgraphjs/cloud/deployment/custom_docker)
- [How to test locally](/langgraphjs/cloud/deployment/test_locally)
- [How to integrate LangGraph into your React application](/langgraphjs/cloud/how-tos/use_stream_react)

### Deployment

LangGraph applications can be deployed using LangGraph Cloud, which provides a range of services to help you deploy, manage, and scale your applications.

- [How to deploy to LangGraph cloud](/langgraphjs/cloud/deployment/cloud)
- [How to deploy to a self-hosted environment](./deploy-self-hosted.md)
- [How to interact with the deployment using RemoteGraph](./use-remote-graph.md)

### Authentication & Access Control

- [How to add custom authentication](./auth/custom_auth.md)

### Modifying the API

- [How to add custom routes](./http/custom_routes.md)
- [How to add custom middleware](./http/custom_middleware.md)

### Assistants

[Assistants](../concepts/assistants.md) are a configured instance of a template.

- [How to configure agents](/langgraphjs/cloud/how-tos/configuration_cloud)
- [How to version assistants](/langgraphjs/cloud/how-tos/assistant_versioning)

### Threads

- [How to copy threads](/langgraphjs/cloud/how-tos/copy_threads)
- [How to check status of your threads](/langgraphjs/cloud/how-tos/check_thread_status)

### Runs

LangGraph Cloud supports multiple types of runs besides streaming runs.

- [How to run an agent in the background](/langgraphjs/cloud/how-tos/background_run)
- [How to run multiple agents in the same thread](/langgraphjs/cloud/how-tos/same-thread)
- [How to create cron jobs](/langgraphjs/cloud/how-tos/cron_jobs)
- [How to create stateless runs](/langgraphjs/cloud/how-tos/stateless_runs)

### Streaming

Streaming the results of your LLM application is vital for ensuring a good user experience, especially when your graph may call multiple models and take a long time to fully complete a run. Read about how to stream values from your graph in these how to guides:

- [How to stream values](/langgraphjs/cloud/how-tos/stream_values)
- [How to stream updates](/langgraphjs/cloud/how-tos/stream_updates)
- [How to stream messages](/langgraphjs/cloud/how-tos/stream_messages)
- [How to stream events](/langgraphjs/cloud/how-tos/stream_events)
- [How to stream in debug mode](/langgraphjs/cloud/how-tos/stream_debug)
- [How to stream multiple modes](/langgraphjs/cloud/how-tos/stream_multiple)

### Frontend & Generative UI

With LangGraph Platform you can integrate LangGraph agents into your React applications and colocate UI components with your agent code.

- [How to integrate LangGraph into your React application](/langgraphjs/cloud/how-tos/use_stream_react)
- [How to implement Generative User Interfaces with LangGraph](/langgraphjs/cloud/how-tos/generative_ui_react)

### Human-in-the-loop

When creating complex graphs, leaving every decision up to the LLM can be dangerous, especially when the decisions involve invoking certain tools or accessing specific documents. To remedy this, LangGraph allows you to insert human-in-the-loop behavior to ensure your graph does not have undesired outcomes. Read more about the different ways you can add human-in-the-loop capabilities to your LangGraph Cloud projects in these how-to guides:

- [How to add a breakpoint](/langgraphjs/cloud/how-tos/human_in_the_loop_breakpoint)
- [How to wait for user input](/langgraphjs/cloud/how-tos/human_in_the_loop_user_input)
- [How to edit graph state](/langgraphjs/cloud/how-tos/human_in_the_loop_edit_state)
- [How to replay and branch from prior states](/langgraphjs/cloud/how-tos/human_in_the_loop_time_travel)
- [How to review tool calls](/langgraphjs/cloud/how-tos/human_in_the_loop_review_tool_calls)

### Double-texting

Graph execution can take a while, and sometimes users may change their mind about the input they wanted to send before their original input has finished running. For example, a user might notice a typo in their original request and will edit the prompt and resend it. Deciding what to do in these cases is important for ensuring a smooth user experience and preventing your graphs from behaving in unexpected ways. The following how-to guides provide information on the various options LangGraph Cloud gives you for dealing with double-texting:

- [How to use the interrupt option](/langgraphjs/cloud/how-tos/interrupt_concurrent)
- [How to use the rollback option](/langgraphjs/cloud/how-tos/rollback_concurrent)
- [How to use the reject option](/langgraphjs/cloud/how-tos/reject_concurrent)
- [How to use the enqueue option](/langgraphjs/cloud/how-tos/enqueue_concurrent)

### Webhooks

- [How to integrate webhooks](/langgraphjs/cloud/how-tos/webhooks)

### Cron Jobs

- [How to create cron jobs](/langgraphjs/cloud/how-tos/cron_jobs)

### LangGraph Studio

LangGraph Studio is a built-in UI for visualizing, testing, and debugging your agents.

- [How to connect to a LangGraph Cloud deployment](/langgraphjs/cloud/how-tos/test_deployment)
- [How to connect to a local deployment](/langgraphjs/cloud/how-tos/test_local_deployment)
- [How to test your graph in LangGraph Studio](/langgraphjs/cloud/how-tos/invoke_studio)
- [How to interact with threads in LangGraph Studio](/langgraphjs/cloud/how-tos/threads_studio)

## Troubleshooting

These are the guides for resolving common errors you may find while building with LangGraph. Errors referenced below will have an `lc_error_code` property corresponding to one of the below codes when they are thrown in code.

- [GRAPH_RECURSION_LIMIT](../troubleshooting/errors/GRAPH_RECURSION_LIMIT.ipynb)
- [INVALID_CONCURRENT_GRAPH_UPDATE](../troubleshooting/errors/INVALID_CONCURRENT_GRAPH_UPDATE.ipynb)
- [INVALID_GRAPH_NODE_RETURN_VALUE](../troubleshooting/errors/INVALID_GRAPH_NODE_RETURN_VALUE.ipynb)
- [MULTIPLE_SUBGRAPHS](../troubleshooting/errors/MULTIPLE_SUBGRAPHS.ipynb)
- [UNREACHABLE_NODE](../troubleshooting/errors/UNREACHABLE_NODE.ipynb)

---

### Docs Tutorials Index (`docs/docs/tutorials/index.md`)

---
title: Tutorials
---

# Tutorials

Welcome to the LangGraph.js Tutorials! These notebooks introduce LangGraph through building various language agents and applications.

## Quick Start

Learn the basics of LangGraph through a comprehensive quick start in which you will build an agent from scratch.

- [Quick Start](quickstart.ipynb)
- [Common Workflows](workflows/index.md): Overview of the most common workflows using LLMs implemented with LangGraph.
- [LangGraph Cloud Quick Start](/langgraphjs/cloud/quick_start/): In this tutorial, you will build and deploy an agent to LangGraph Cloud.

## Use cases

Learn from example implementations of graphs designed for specific scenarios and that implement common design patterns.

#### Chatbots

- [Customer support with a small model](chatbots/customer_support_small_model.ipynb)

#### RAG

- [Agentic RAG](rag/langgraph_agentic_rag.ipynb)
- [Corrective RAG](rag/langgraph_crag.ipynb)
- [Self-RAG](rag/langgraph_self_rag.ipynb)

#### Multi-Agent Systems

- [Collaboration](multi_agent/multi_agent_collaboration.ipynb): Enabling two agents to collaborate on a task
- [Supervision](multi_agent/agent_supervisor.ipynb): Using an LLM to orchestrate and delegate to individual agents
- [Hierarchical Teams](multi_agent/hierarchical_agent_teams.ipynb): Orchestrating nested teams of agents to solve problems

#### Planning Agents

- [Plan-and-Execute](plan-and-execute/plan-and-execute.ipynb): Implementing a basic planning and execution agent

#### Reflection & Critique

- [Basic Reflection](reflection/reflection.ipynb): Prompting the agent to reflect on and revise its outputs
- [Rewoo](rewoo/rewoo.ipynb): Reducing re-planning by saving observations as variables

### Evaluation

- [Agent-based](chatbot-simulation-evaluation/agent-simulation-evaluation.ipynb): Evaluate chatbots via simulated user interactions

---

### Docs Versions Index (`docs/docs/versions/index.md`)

# LangGraph Over Time

As LangGraph.js continues to evolve and improve, breaking changes are sometimes necessary to enhance functionality, performance, or developer experience. This page serves as a guide to the version history of LangGraph.js, documenting significant changes and providing assistance for upgrading between versions.

## Version History

### v0.4.x (Latest)

- (Breaking) Cleanup of the `Interrupt` interface: removing `when`, `ns` in favour of `id` and `values`.
- (Breaking) Removed `writes` from checkpoints. You will need to upgrade your checkpointer packages.
- (Breaking) Allow async serialization and deserialization of values from checkpointers.
- (Breaking) Removed unused support for SharedValue and managed values.
- Improved type-inference of configurable fields (0.4.0) and `streamMode: "updates"` (0.4.4). 
- Added support for `context` property and `Runtime` type.
- Added support for `deleteThread` in checkpointers.
- Added support for `durability` property superseding `checkpointDuring`.
- Added support for dynamic model choice in `createReactAgent` (0.4.3).
- Added support for partially applying tool calls in `createReactAgent["postModelHook"]` (0.4.3).
- Numerous bugfixes.

### v0.3.0

- (Breaking) Interrupts are now properly propagated in `"values"` stream mode and in `.invoke()`.
- (Breaking) Return type of `.stream()` is now strictly typed.
- Added support for [node / task caching](/langgraphjs/how-tos/node-caching/).
- Added support for [deferred nodes](/langgraphjs/how-tos/defer-node-execution/).
- Added support for `preModelHook` and `postModelHook` in `createReactAgent`.
- Added support for `addSequence` and shorthand object syntax for `addNode`.
- Added `pushMessage()` method to allow manually pushing messages to `"messages"` stream mode.
- Added `isInterrupted()` method to check if the state contains an interrupt.
- Numerous bugfixes.

### v0.2.0

- (Breaking) [`@langchain/core`](https://www.npmjs.com/package/@langchain/core) is now a peer dependency and requires explicit installation.
- Added support for [dynamic breakpoints](/langgraphjs/how-tos/dynamic_breakpoints/).
- Added support for [separate input and output schema](/langgraphjs/how-tos/input_output_schema/).
- Allow using an array to specify destination nodes from a conditional edge as shorthand for object.
- Numerous bugfixes.

### v0.1.0

- (Breaking) Changed checkpoint representations to support namespacing for subgraphs and pending writes.
- (Breaking) `MessagesState` was changed to [`MessagesAnnotation`](/langgraphjs/reference/variables/langgraph.MessagesAnnotation.html).
- Added [`Annotation`](/langgraphjs/reference/modules/langgraph.Annotation.html), a more streamlined way to declare state. Removes the need for separate type and channel declarations.
- Split checkpointer implementations into different libraries for easier inheritance.
- Major internal architecture refactor to use more robust patterns.
- Deprecated `MessageGraph` in favor of [`StateGraph`](/langgraphjs/reference/classes/langgraph.StateGraph.html) + [`MessagesAnnotation`](/langgraphjs/reference/variables/langgraph.MessagesAnnotation.html).
- Numerous bugfixes.

## Upgrading

When upgrading LangGraph.js, please refer to the specific version sections below for detailed instructions on how to adapt your code to the latest changes.

### Upgrading to v0.3.0

- If a node is interrupted, it will now be present in the `"values"` stream mode and in `.invoke()` under the `__interrupts` key. You can use the `isInterrupted()` method to check if the state contains an interrupt and handle it appropriately.
- The return type of `.stream()` is no longer `IterableReadableStream<any>`, which means you may need to fix any type errors.

### Upgrading to v0.2.0

- You will now need to install `@langchain/core` explicitly. See [this page](https://langchain-ai.github.io/langgraphjs/how-tos/manage-ecosystem-dependencies/) for more information.

### Upgrading to v0.1.0

- Old saved checkpoints will no longer be valid, and you will need to update to use a new prebuilt checkpointer.
- We recommend switching to the new `Annotation` syntax when declaring graph state.

## Deprecation Notices

This section will list any deprecated features or APIs, along with their planned removal dates and recommended alternatives.

#### `MessageGraph`

Use [`MessagesAnnotation`](/langgraphjs/reference/variables/langgraph.MessagesAnnotation.html) with [`StateGraph`](/langgraphjs/reference/classes/langgraph.StateGraph.html).

#### `createFunctionCallingExecutor`

Use [`createReactAgent`](/langgraphjs/reference/functions/langgraph_prebuilt.createReactAgent.html) with a model that supports tool calling.

#### `ToolExecutor`

Use [`ToolNode`](/langgraphjs/reference/classes/langgraph_prebuilt.ToolNode.html) instead.

## Full changelog

For the most up-to-date information on LangGraph.js versions and changes, please refer to our [GitHub repository](https://github.com/langchain-ai/langgraphjs) and [release notes](https://github.com/langchain-ai/langgraphjs/releases).

---

### Libs Sdk Docs Getting Started (`libs/sdk/docs/getting-started.md`)

# Getting started

## Install

```bash
npm add @langchain/langgraph-sdk @langchain/core
# or
pnpm add @langchain/langgraph-sdk @langchain/core
# or
yarn add @langchain/langgraph-sdk @langchain/core
```

`@langchain/core` is a required peer dependency. Install it alongside
the SDK unless you already depend on `@langchain/langgraph` (which
peers the same package).

The SDK targets modern runtimes (Node ≥ 18, evergreen browsers, Deno,
Bun, Cloudflare Workers, Vercel Edge). No additional polyfills are
required in environments that ship `fetch`, `ReadableStream`, and
`AbortController`.

## Create a client

```ts
import { Client } from "@langchain/langgraph-sdk";

const client = new Client({
  apiUrl: "http://localhost:2024",
});
```

With zero arguments, the client defaults to `http://localhost:8123`
(the LangGraph dev server) and picks up an API key from the
`LANGGRAPH_API_KEY`, `LANGSMITH_API_KEY`, or `LANGCHAIN_API_KEY`
environment variables. See [Configuration](./configuration.md) for the
full option bag.

## Your first request

### Discover an assistant

A fresh LangGraph project auto-creates one assistant per graph
registered in `langgraph.json`. List them:

```ts
const assistants = await client.assistants.search({ limit: 10 });
const agent = assistants[0];
console.log(agent.assistant_id, agent.graph_id);
```

### Stream a run (recommended)

Use `client.threads.stream(...)` — the v2 thread-centric streaming API:

```ts
const thread = client.threads.stream({ assistantId: agent.assistant_id });

await thread.run.start({
  input: { messages: [{ role: "user", content: "what's 42 * 17?" }] },
});

for await (const message of thread.messages) {
  for await (const token of message.text) {
    process.stdout.write(token);
  }
  process.stdout.write("\n");
}

console.log("final state:", await thread.output);
await thread.close();
```

`thread.messages`, `thread.values`, `thread.toolCalls`, `thread.subgraphs`,
and `thread.extensions.<name>` are lazy — only the projections you
actually touch are streamed across the wire. Everything is covered in
detail in [Streaming](./streaming.md).

### Call a non-streaming API

Every sub-client also exposes plain async methods for CRUD-style work:

```ts
const thread = await client.threads.create({ metadata: { topic: "math" } });
await client.threads.update(thread.thread_id, {
  metadata: { topic: "algebra" },
});
await client.store.putItem(["notes"], "first", {
  body: "thread opened",
});
```

See the sub-client guides under the [main index](./README.md#sub-clients).

## TypeScript support

Every response shape is fully typed. The `Client` constructor accepts
three type parameters for graph-specific state:

```ts
type State = { messages: BaseMessage[]; summary?: string };
type Update = Partial<State>;
type CustomEvent = { kind: "progress"; pct: number };

const client = new Client<State, Update, CustomEvent>({ apiUrl: "..." });

const state = await client.threads.getState<State>(threadId);
//    ^? ThreadState<State>
```

For streaming, use the generic on `threads.stream()` to type server-side
transformer projections end-to-end:

```ts
type Extensions = InferExtensions<[typeof myTransformer]>;
const thread = client.threads.stream<Extensions>({ assistantId: "agent" });
//    ^? ThreadStream<Extensions>
```

See [Custom transformers](./streaming-extensions.md) for details.

## What to read next

- [Configuration](./configuration.md) — tune `Client` for your
  environment.
- [Streaming](./streaming.md) — the recommended streaming primitive
  and its lazy projections.
- [Threads](./threads.md) — CRUD, state, history, checkpoints,
  pruning, and more.

---

### Docs Troubleshooting Errors Index (`docs/docs/troubleshooting/errors/index.md`)

# Error reference

This page contains guides around resolving common errors you may find while building with LangChain.
Errors referenced below will have an `lc_error_code` property corresponding to one of the below codes when they are thrown in code.

- [GRAPH_RECURSION_LIMIT](/langgraphjs/troubleshooting/errors/GRAPH_RECURSION_LIMIT)
- [INVALID_CONCURRENT_GRAPH_UPDATE](/langgraphjs/troubleshooting/errors/INVALID_CONCURRENT_GRAPH_UPDATE)
- [INVALID_GRAPH_NODE_RETURN_VALUE](/langgraphjs/troubleshooting/errors/INVALID_GRAPH_NODE_RETURN_VALUE)
- [MULTIPLE_SUBGRAPHS](/langgraphjs/troubleshooting/errors/MULTIPLE_SUBGRAPHS)
- [UNREACHABLE_NODE](/langgraphjs/troubleshooting/errors/UNREACHABLE_NODE)

---

### Docs Tutorials Workflows Index (`docs/docs/tutorials/workflows/index.md`)

# Workflows and Agents

This guide reviews common patterns for agentic systems. In describing these systems, it can be useful to make a distinction between "workflows" and "agents". One way to think about this difference is nicely explained [here](https://www.anthropic.com/research/building-effective-agents) by Anthropic:

> Workflows are systems where LLMs and tools are orchestrated through predefined code paths.
> Agents, on the other hand, are systems where LLMs dynamically direct their own processes and tool usage, maintaining control over how they accomplish tasks.

Here is a simple way to visualize these differences:



When building agents and workflows, LangGraph [offers a number of benefits](https://langchain-ai.github.io/langgraphjs/concepts/high_level/) including persistence, streaming, and support for debugging as well as deployment.

## Set up

!!! note Compatibility

    The Functional API requires `@langchain/langgraph>=0.2.24`.

You can use [any chat model](https://js.langchain.com/docs/integrations/chat/) that supports structured outputs and tool calling. Below, we show the process of installing the packages, setting API keys, and testing structured outputs / tool calling for Anthropic.

??? "Install dependencies"

    ```bash
    yarn add @langchain/langgraph @langchain/anthropic @langchain/core
    ```

Initialize an LLM

```ts
import { ChatAnthropic } from "@langchain/anthropic";

process.env.ANTHROPIC_API_KEY = "<your_anthropic_key>";

const llm = new ChatAnthropic({
  model: "claude-3-5-sonnet-latest",
});
```

## Building Blocks: The Augmented LLM

LLM have [augmentations](https://www.anthropic.com/research/building-effective-agents) that support building workflows and agents. These include [structured outputs](https://js.langchain.com/docs/concepts/structured_outputs/) and [tool calling](https://js.langchain.com/docs/concepts/tool_calling/), as shown in this image from the Anthropic [blog](https://www.anthropic.com/research/building-effective-agents):



```ts
import { tool } from "@langchain/core/tools";
import { z } from "zod";

const searchQuerySchema = z.object({
  searchQuery: z.string().describe("Query that is optimized web search."),
  justification: z.string("Why this query is relevant to the user's request."),
});

// Augment the LLM with schema for structured output
const structuredLlm = llm.withStructuredOutput(searchQuerySchema, {
  name: "searchQuery",
});

// Invoke the augmented LLM
const output = await structuredLlm.invoke(
  "How does Calcium CT score relate to high cholesterol?"
);

const multiply = tool(
  async ({ a, b }) => {
    return a * b;
  },
  {
    name: "multiply",
    description: "multiplies two numbers together",
    schema: z.object({
      a: z.number("the first number"),
      b: z.number("the second number"),
    }),
  }
);

// Augment the LLM with tools
const llmWithTools = llm.bindTools([multiply]);

// Invoke the LLM with input that triggers the tool call
const message = await llmWithTools.invoke("What is 2 times 3?");

console.log(message.tool_calls);
```

## Prompt chaining

In prompt chaining, each LLM call processes the output of the previous one.

As noted in the [Anthropic blog](https://www.anthropic.com/research/building-effective-agents):

> Prompt chaining decomposes a task into a sequence of steps, where each LLM call processes the output of the previous one. You can add programmatic checks (see "gate” in the diagram below) on any intermediate steps to ensure that the process is still on track.

> When to use this workflow: This workflow is ideal for situations where the task can be easily and cleanly decomposed into fixed subtasks. The main goal is to trade off latency for higher accuracy, by making each LLM call an easier task.



=== "Graph API"

    ```
/* Detailed source-code truncated for AI context efficiency. */
```

    **LangSmith Trace**

    https://smith.langchain.com/public/a0281fca-3a71-46de-beee-791468607b75/r

=== "Functional API"

    ```
/* Detailed source-code truncated for AI context efficiency. */
```

    **LangSmith Trace**

    https://smith.langchain.com/public/332fa4fc-b6ca-416e-baa3-161625e69163/r

## Parallelization

With parallelization, LLMs work simultaneously on a task:

> LLMs can sometimes work simultaneously on a task and have their outputs aggregated programmatically. This workflow, parallelization, manifests in two key variations: Sectioning: Breaking a task into independent subtasks run in parallel. Voting: Running the same task multiple times to get diverse outputs.

> When to use this workflow: Parallelization is effective when the divided subtasks can be parallelized for speed, or when multiple perspectives or attempts are needed for higher confidence results. For complex tasks with multiple considerations, LLMs generally perform better when each consideration is handled by a separate LLM call, allowing focused attention on each specific aspect.



=== "Graph API"

    ```
/* Detailed source-code truncated for AI context efficiency. */
```

    **LangSmith Trace**

    https://smith.langchain.com/public/3be2e53c-ca94-40dd-934f-82ff87fac277/r

    **Resources:**

    **Documentation**

    See our documentation on parallelization [here](https://langchain-ai.github.io/langgraphjs/how-tos/branching/).

=== "Functional API"

    ```
/* Detailed source-code truncated for AI context efficiency. */
```

    **LangSmith Trace**

    https://smith.langchain.com/public/623d033f-e814-41e9-80b1-75e6abb67801/r

## Routing

Routing classifies an input and directs it to a followup task. As noted in the [Anthropic blog](https://www.anthropic.com/research/building-effective-agents):

> Routing classifies an input and directs it to a specialized followup task. This workflow allows for separation of concerns, and building more specialized prompts. Without this workflow, optimizing for one kind of input can hurt performance on other inputs.

> When to use this workflow: Routing works well for complex tasks where there are distinct categories that are better handled separately, and where classification can be handled accurately, either by an LLM or a more traditional classification model/algorithm.



=== "Graph API"

    ```
/* Detailed source-code truncated for AI context efficiency. */
```

    **LangSmith Trace**

    https://smith.langchain.com/public/c4580b74-fe91-47e4-96fe-7fac598d509c/r

    **Examples**

    [Here](https://langchain-ai.github.io/langgraphjs/tutorials/rag/langgraph_adaptive_rag_local/) is RAG workflow that routes questions. See our video [here](https://www.youtube.com/watch?v=bq1Plo2RhYI).

=== "Functional API"

    ```
/* Detailed source-code truncated for AI context efficiency. */
```

    **LangSmith Trace**

    https://smith.langchain.com/public/5e2eb979-82dd-402c-b1a0-a8cceaf2a28a/r

## Orchestrator-Worker

With orchestrator-worker, an orchestrator breaks down a task and delegates each sub-task to workers. As noted in the [Anthropic blog](https://www.anthropic.com/research/building-effective-agents):

> In the orchestrator-workers workflow, a central LLM dynamically breaks down tasks, delegates them to worker LLMs, and synthesizes their results.

> When to use this workflow: This workflow is well-suited for complex tasks where you can’t predict the subtasks needed (in coding, for example, the number of files that need to be changed and the nature of the change in each file likely depend on the task). Whereas it’s topographically similar, the key difference from parallelization is its flexibility—subtasks aren't pre-defined, but determined by the orchestrator based on the specific input.



=== "Graph API"

    ```ts
    import { z } from "zod";

    // Schema for structured output to use in planning
    const sectionSchema = z.object({
      name: z.string().describe("Name for this section of the report."),
      description: z.string().describe(
        "Brief overview of the main topics and concepts to be covered in this section."
      ),
    });

    const sectionsSchema = z.object({
      sections: z.array(sectionSchema).describe("Sections of the report."),
    });

    // Augment the LLM with schema for structured output
    const planner = llm.withStructuredOutput(sectionsSchema);
    ```

    **Creating Workers in LangGraph**

    Because orchestrator-worker workflows are common, LangGraph **has the `Send` API to support this**. It lets you dynamically create worker nodes and send each one a specific input. Each worker has its own state, and all worker outputs are written to a *shared state key* that is accessible to the orchestrator graph. This gives the orchestrator access to all worker output and allows it to synthesize them into a final output. As you can see below, we iterate over a list of sections and `Send` each to a worker node. See further documentation [here](https://langchain-ai.github.io/langgraphjs/how-tos/map-reduce/) and [here](https://langchain-ai.github.io/langgraphjs/concepts/low_level/#send).

    ```
/* Detailed source-code truncated for AI context efficiency. */
```

    **LangSmith Trace**

    https://smith.langchain.com/public/78cbcfc3-38bf-471d-b62a-b299b144237d/r

    **Resources:**

    **Examples**

    [Here](https://github.com/langchain-ai/report-mAIstro) is a project that uses orchestrator-worker for report planning and writing. See our video [here](https://www.youtube.com/watch?v=wSxZ7yFbbas).

=== "Functional API"

    ```
/* Detailed source-code truncated for AI context efficiency. */
```

    **LangSmith Trace**

    https://smith.langchain.com/public/75a636d0-6179-4a12-9836-e0aa571e87c5/r

## Evaluator-optimizer

In the evaluator-optimizer workflow, one LLM call generates a response while another provides evaluation and feedback in a loop:

> In the evaluator-optimizer workflow, one LLM call generates a response while another provides evaluation and feedback in a loop.

> When to use this workflow: This workflow is particularly effective when we have clear evaluation criteria, and when iterative refinement provides measurable value. The two signs of good fit are, first, that LLM responses can be demonstrably improved when a human articulates their feedback; and second, that the LLM can provide such feedback. This is analogous to the iterative writing process a human writer might go through when producing a polished document.



=== "Graph API"

    ```
/* Detailed source-code truncated for AI context efficiency. */
```

    **LangSmith Trace**

    https://smith.langchain.com/public/86ab3e60-2000-4bff-b988-9b89a3269789/r

    **Resources:**

    **Examples**

    [Here](https://github.com/langchain-ai/research-rabbit) is an assistant that uses evaluator-optimizer to improve a report. See our video [here](https://www.youtube.com/watch?v=XGuTzHoqlj8).

    [Here](https://langchain-ai.github.io/langgraphjs/tutorials/rag/langgraph_adaptive_rag_local/) is a RAG workflow that grades answers for hallucinations or errors. See our video [here](https://www.youtube.com/watch?v=bq1Plo2RhYI).

=== "Functional API"

    ```
/* Detailed source-code truncated for AI context efficiency. */
```

    **LangSmith Trace**

    https://smith.langchain.com/public/f66830be-4339-4a6b-8a93-389ce5ae27b4/r

## Agent

Agents are typically implemented as an LLM performing actions (via tool-calling) based on environmental feedback in a loop. As noted in the [Anthropic blog](https://www.anthropic.com/research/building-effective-agents):

> Agents can handle sophisticated tasks, but their implementation is often straightforward. They are typically just LLMs using tools based on environmental feedback in a loop. It is therefore crucial to design toolsets and their documentation clearly and thoughtfully.

> When to use agents: Agents can be used for open-ended problems where it’s difficult or impossible to predict the required number of steps, and where you can’t hardcode a fixed path. The LLM will potentially operate for many turns, and you must have some level of trust in its decision-making. Agents' autonomy makes them ideal for scaling tasks in trusted environments.



```ts
import { tool } from "@langchain/core/tools";
import { z } from "zod";

// Define tools
const multiply = tool(
  async ({ a, b }: { a: number; b: number }) => {
    return a * b;
  },
  {
    name: "multiply",
    description: "Multiply two numbers together",
    schema: z.object({
      a: z.number().describe("first number"),
      b: z.number().describe("second number"),
    }),
  }
);

const add = tool(
  async ({ a, b }: { a: number; b: number }) => {
    return a + b;
  },
  {
    name: "add",
    description: "Add two numbers together",
    schema: z.object({
      a: z.number().describe("first number"),
      b: z.number().describe("second number"),
    }),
  }
);

const divide = tool(
  async ({ a, b }: { a: number; b: number }) => {
    return a / b;
  },
  {
    name: "divide",
    description: "Divide two numbers",
    schema: z.object({
      a: z.number().describe("first number"),
      b: z.number().describe("second number"),
    }),
  }
);

// Augment the LLM with tools
const tools = [add, multiply, divide];
const toolsByName = Object.fromEntries(tools.map((tool) => [tool.name, tool]));
const llmWithTools = llm.bindTools(tools);
```

=== "Graph API"

    ```
/* Detailed source-code truncated for AI context efficiency. */
```

    **LangSmith Trace**

    https://smith.langchain.com/public/051f0391-6761-4f8c-a53b-22231b016690/r

    **Examples**

    [Here](https://github.com/langchain-ai/memory-agent) is a project that uses a tool calling agent to create / store long-term memories.

=== "Functional API"

    ```
/* Detailed source-code truncated for AI context efficiency. */
```

    **LangSmith Trace**

    https://smith.langchain.com/public/42ae8bf9-3935-4504-a081-8ddbcbfc8b2e/r

#### Pre-built

LangGraph also provides a **pre-built method** for creating an agent as defined above (using the [`createReactAgent`](/langgraphjs/reference/functions/langgraph_prebuilt.createReactAgent.html) function):

https://langchain-ai.github.io/langgraphjs/how-tos/create-react-agent/

```ts
import { createReactAgent } from "@langchain/langgraph/prebuilt";

// Pass in:
// (1) an LLM instance
// (2) the tools list (which is used to create the tool node)
const prebuiltAgent = createReactAgent({
  llm: llmWithTools,
  tools,
});

// invoke
const result = await prebuiltAgent.invoke({
  messages: [
    {
      role: "user",
      content: "Add 3 and 4.",
    },
  ],
});
console.log(result.messages);
```

**LangSmith Trace**

https://smith.langchain.com/public/abab6a44-29f6-4b97-8164-af77413e494d/r

## What LangGraph provides

By constructing each of the above in LangGraph, we get a few things:

### Persistence: Human-in-the-Loop

LangGraph persistence layer supports interruption and approval of actions (e.g., Human In The Loop). See [Module 3 of LangChain Academy](https://github.com/langchain-ai/langchain-academy/tree/main/module-3).

### Persistence: Memory

LangGraph persistence layer supports conversational (short-term) memory and long-term memory. See [Modules 2](https://github.com/langchain-ai/langchain-academy/tree/main/module-2) [and 5](https://github.com/langchain-ai/langchain-academy/tree/main/module-5) of LangChain Academy:

### Streaming

LangGraph provides several ways to stream workflow / agent outputs or intermediate state. See [Module 3 of LangChain Academy](https://github.com/langchain-ai/langchain-academy/blob/main/module-3/streaming-interruption.ipynb).

### Deployment

LangGraph provides an easy on-ramp for deployment, observability, and evaluation. See [module 6](https://github.com/langchain-ai/langchain-academy/tree/main/module-6) of LangChain Academy.

---

### Docs Requirements (`docs/docs-requirements.txt`)

mkdocs
mkdocstrings
mkdocs-jupyter
mkdocs-redirects
mkdocs-minify-plugin
mkdocs-open-in-new-tab
mkdocs-rss-plugin
mkdocs-typedoc
mkdocs-exclude-search
markdown-include
markdown-callouts

---

### Mkdocs.Yml (`docs/mkdocs.yml`)

site_name: ""
site_description: Build language agents as graphs
site_url: https://langchain-ai.github.io/langgraphjs/
repo_url: https://github.com/langchain-ai/langgraphjs
theme:
  name: material
  custom_dir: overrides
  logo_dark_mode: static/wordmark_light.svg
  logo_light_mode: static/wordmark_dark.svg
  favicon: static/favicon.png
  features:
    - announce.dismiss
    - content.code.annotate
    - content.code.copy
    - content.code.select
    - content.tabs.link
    - content.tooltips
    - header.autohide
    - navigation.expand
    - navigation.footer
    - navigation.indexes
    - navigation.instant
    - navigation.instant.prefetch
    - navigation.instant.progress
    - navigation.sections
    - navigation.path
    - navigation.prune
    - navigation.tabs
    - navigation.top
    - navigation.tracking
    - search.highlight
    - search.share
    - search.suggest
    - toc.follow
  palette:
    - scheme: default
      primary: white
      accent: gray
      toggle:
        icon: material/brightness-7
        name: Switch to dark mode
    - scheme: slate
      primary: grey
      accent: white
      toggle:
        icon: material/brightness-4
        name: Switch to light mode
  font:
    text: "Public Sans"
    code: "Roboto Mono"
plugins:
  - search:
      separator: '[\s\u200b\-_,:!=\[\]()"`/]+|\.(?!\d)|&[lg]t;|(?!\b)(?=[A-Z][a-z])'
  - autorefs
  - open-in-new-tab
  - exclude-search:
      exclude:
        - tutorials/quickstart.ipynb
        - tutorials/deployment.md
        - tutorials/langgraph-platform/local-server.md
        - concepts/template_applications.md  # TODO: make tutorial
        - cloud/quick_start.md
        - how-tos/index.md
        - how-tos#installation
        - how-tos/manage-ecosystem-dependencies.ipynb
        - how-tos/use-in-web-environments.ipynb
        - how-tos#langgraph
        - how-tos#controllability
        - how-tos/map-reduce.ipynb
        - how-tos/branching.ipynb
        - how-tos/command.ipynb
        - how-tos/recursion-limit.ipynb
        - how-tos/defer-node-execution.ipynb
        - how-tos#persistence
        - how-tos/persistence.ipynb
        - how-tos/persistence-functional.ipynb
        - how-tos/subgraph-persistence.ipynb
        - how-tos/cross-thread-persistence.ipynb
        - how-tos/cross-thread-persistence-functional.ipynb
        - how-tos/persistence-postgres.ipynb
        - how-tos#memory
        - how-tos/manage-conversation-history.ipynb
        - how-tos/delete-messages.ipynb
        - how-tos/add-summary-conversation-history.ipynb
        - how-tos/semantic-search.ipynb
        - how-tos#human-in-the-loop
        - how-tos/breakpoints.ipynb
        - how-tos/dynamic_breakpoints.ipynb
        - how-tos/edit-graph-state.ipynb
        - how-tos/wait-user-input.ipynb
        - how-tos/wait-user-input-functional.ipynb
        - how-tos/time-travel.ipynb
        - how-tos/review-tool-calls.ipynb
        - how-tos/review-tool-calls-functional.ipynb
        - how-tos#streaming
        - how-tos/stream-values.ipynb
        - how-tos/stream-updates.ipynb
        - how-tos/stream-tokens.ipynb
        - how-tos/streaming-tokens-without-langchain.ipynb
        - how-tos/streaming-content.ipynb
        - how-tos/stream-multiple.ipynb
        - how-tos/streaming-events-from-within-tools.ipynb
        - how-tos/streaming-from-final-node.ipynb
        - how-tos#tool-calling
        - how-tos/tool-calling.ipynb
        - how-tos/force-calling-a-tool-first.ipynb
        - how-tos/tool-calling-errors.ipynb
        - how-tos/pass-run-time-values-to-tools.ipynb
        - how-tos/update-state-from-tools.ipynb
        - how-tos#subgraphs
        - how-tos/subgraph.ipynb
        - how-tos/subgraphs-manage-state.ipynb
        - how-tos/subgraph-transform-state.ipynb
        - how-tos#multi-agent
        - how-tos/multi-agent-network.ipynb
        - how-tos/multi-agent-network-functional.ipynb
        - how-tos/multi-agent-multi-turn-convo.ipynb
        - how-tos/multi-agent-multi-turn-convo-functional.ipynb
        - how-tos#state-management
        - how-tos/define-state.ipynb
        - how-tos/input_output_schema.ipynb
        - how-tos/pass_private_state.ipynb
        - how-tos#other
        - how-tos/configuration.ipynb
        - how-tos/node-retry-policies.ipynb
        - how-tos/node-caching.ipynb
        - how-tos/dynamically-returning-directly.ipynb
        - how-tos/respond-in-format.ipynb
        - how-tos/managing-agent-steps.ipynb
        - how-tos#prebuilt-react-agent
        - how-tos/create-react-agent.ipynb
        - how-tos/react-memory.ipynb
        - how-tos/react-system-prompt.ipynb
        - how-tos/react-human-in-the-loop.ipynb
        - how-tos/react-return-structured-output.ipynb
        - how-tos/react-agent-from-scratch-functional.ipynb
        - how-tos#langgraph-platform
        - how-tos#application-structure
        - cloud/deployment/setup.md
        - cloud/deployment/setup_pyproject.md
        - cloud/deployment/setup_javascript.md
        - cloud/deployment/semantic_search.md
        - cloud/deployment/custom_docker.md
        - cloud/deployment/test_locally.md
        - cloud/deployment/graph_rebuild.md
        - how-tos#deployment
        - cloud/deployment/cloud.md
        - how-tos/deploy-self-hosted.md
        - how-tos/use-remote-graph.md
        - how-tos#authentication-access-control
        - how-tos/auth/custom_auth.md
        - cloud/how-tos/auth/openapi_security_new.md
        - how-tos#assistants
        - cloud/how-tos/configuration_cloud.md
        - cloud/how-tos/assistant_versioning.md
        - how-tos#threads
        - cloud/how-tos/use_threads.md
        - cloud/how-tos/copy_threads.md
        - cloud/how-tos/check_thread_status.md
        - how-tos#runs
        - cloud/how-tos/background_run.md
        - cloud/how-tos/same-thread.md
        - cloud/how-tos/cron_jobs.md
        - how-tos#streaming
        - cloud/how-tos/stateless_runs.md
        - cloud/how-tos/stream_values.md
        - cloud/how-tos/stream_updates.md
        - cloud/how-tos/stream_messages.md
        - cloud/how-tos/stream_events.md
        - cloud/how-tos/stream_debug.md
        - cloud/how-tos/stream_multiple.md
        - how-tos#frontend-generative-ui
        - cloud/how-tos/use_stream_react.md
        - cloud/how-tos/generative_ui_react.md
        - how-tos#human-in-the-loop
        - cloud/how-tos/human_in_the_loop_breakpoint.md
        - cloud/how-tos/human_in_the_loop_user_input.md
        - cloud/how-tos/human_in_the_loop_edit_state.md
        - cloud/how-tos/human_in_the_loop_time_travel.md
        - cloud/how-tos/human_in_the_loop_review_tool_calls.md
        - how-tos#double-texting
        - cloud/how-tos/interrupt_concurrent.md
        - cloud/how-tos/rollback_concurrent.md
        - cloud/how-tos/reject_concurrent.md
        - cloud/how-tos/enqueue_concurrent.md
        - how-tos#webhooks
        - cloud/how-tos/webhooks.md
        - how-tos#cron-jobs
        - cloud/how-tos/cron_jobs.md
        - how-tos#modifying-the-api
        - cloud/how-tos/http/custom_middleware.md
        - cloud/how-tos/http/custom_routes.md
        - how-tos#langgraph-studio
        - cloud/how-tos/test_deployment.md
        - cloud/how-tos/test_local_deployment.md
        - cloud/how-tos/invoke_studio.md
        - cloud/how-tos/threads_studio.md
        - cloud/how-tos/datasets_studio.md
        - concepts/index.md
        - concepts#langgraph
        - concepts/high_level.md
        - concepts/low_level.md
        - concepts/agentic_concepts.md
        - concepts/multi_agent.md
        - concepts/human_in_the_loop.md
        - concepts/persistence.md
        - concepts/memory.md
        - concepts/streaming.md
        - concepts/functional_api.md
        - concepts#langgraph-platform
        - concepts#high-level
        - concepts/langgraph_platform.md
        - concepts/deployment_options.md
        - concepts/plans.md
        - concepts#components
        - concepts/langgraph_server.md
        - concepts/langgraph_studio.md
        - concepts/langgraph_cli.md
        - concepts/sdk.md
        - concepts#langgraph-server
        - concepts/application_structure.md
        - concepts/assistants.md
        - concepts/double_texting.md
        - concepts/auth.md
        - concepts#deployment-options
        - concepts/self_hosted.md
        - concepts/langgraph_cloud.md
        - concepts/bring_your_own_cloud.md
        - tutorials/index.md
        - tutorials#quick-start
        - tutorials/workflows/index.md
        - tutorials/chatbots/customer_support_small_model.ipynb
        - tutorials#rag
        - tutorials/rag/langgraph_agentic_rag.ipynb
        - tutorials/rag/langgraph_crag.ipynb
        - tutorials/rag/langgraph_self_rag.ipynb
        - tutorials#agent-architectures
        - tutorials#multi-agent-systems
        - tutorials/multi_agent/multi_agent_collaboration.ipynb
        - tutorials/multi_agent/agent_supervisor.ipynb
        - tutorials/multi_agent/hierarchical_agent_teams.ipynb
        - tutorials#planning-agents
        - tutorials/plan-and-execute/plan-and-execute.ipynb
        - tutorials#reflection-critique
        - tutorials/reflection/reflection.ipynb
        - tutorials/rewoo/rewoo.ipynb
        - tutorials#evaluation
        - tutorials/chatbot-simulation-evaluation/agent-simulation-evaluation.ipynb
        - adopters.md
        - llms-txt-overview.md
        - concepts/faq.md
        - troubleshooting/errors/
        - troubleshooting/errors/index.md
        - troubleshooting/errors/GRAPH_RECURSION_LIMIT.ipynb
        - troubleshooting/errors/INVALID_CONCURRENT_GRAPH_UPDATE.ipynb
        - troubleshooting/errors/INVALID_GRAPH_NODE_RETURN_VALUE.ipynb
        - troubleshooting/errors/MULTIPLE_SUBGRAPHS.ipynb
        - troubleshooting/errors/UNREACHABLE_NODE.ipynb
        - agents/overview.md
        - agents/agents.md
        - agents/run_agents.md
        - agents/streaming.md
        - agents/models.md
        - agents/tools.md
        - agents/mcp.md
        - agents/context.md
        - agents/memory.md
        - agents/human-in-the-loop.md
        - agents/multi-agent.md
        - agents/evals.md
        - agents/deployment.md
        - agents/ui.md
        # NOTE: prebuilt.md is auto-generated by `make generate-prebuilt-page`
        - agents/prebuilt.md    

nav:
  - LangGraph:
    - Introduction: index.md
  - "API reference":
      - "reference/index.html"
      - LangGraph Platform:
          - Server API: "cloud/reference/api/api_ref.md"
          - CLI: "cloud/reference/cli.md"
          - SDK (Python): "cloud/reference/sdk/python_sdk_ref.md"
          - SDK (JS/TS): "cloud/reference/sdk/js_ts_sdk_ref.md"
          - RemoteGraph: reference/remote_graph.md
          - Environment variables: "cloud/reference/env_var.md"
  - "Versions":
      - "versions/index.md"

markdown_extensions:
  - abbr
  - admonition
  - pymdownx.details
  - attr_list
  - def_list
  - footnotes
  - md_in_html
  - toc:
      permalink: true
  - pymdownx.arithmatex:
      generic: true
  - pymdownx.betterem:
      smart_enable: all
  - pymdownx.caret
  - pymdownx.details
  - pymdownx.emoji:
      emoji_generator: !!python/name:material.extensions.emoji.to_svg
      emoji_index: !!python/name:material.extensions.emoji.twemoji
  - pymdownx.highlight:
      anchor_linenums: true
      line_spans: __span
      use_pygments: true
      pygments_lang_class: true
  - pymdownx.inlinehilite
  - pymdownx.keys
  - pymdownx.magiclink:
      normalize_issue_symbols: true
      repo_url_shorthand: true
      user: langchain-ai
      repo: langgraphjs
  - pymdownx.mark
  - pymdownx.smartsymbols
  - pymdownx.snippets:
      auto_append:
        - includes/mkdocs.md
  - pymdownx.superfences:
      custom_fences:
        - name: mermaid
          class: mermaid
          format: !!python/name:pymdownx.superfences.fence_code_format
  - pymdownx.tabbed:
      alternate_style: true
      combine_header_slug: true
  - pymdownx.tasklist:
      custom_checkbox: true
  - markdown_include.include:
      base_path: ../
  - github-callouts
extra_css:
  - css/mkdocstrings.css
  - css/agent_graph_widget.css
hooks:
  - _scripts/notebook_hooks.py
extra:
  scope: /langgraphjs/
  consent:
    title: Cookie consent
    actions:
      - accept
      - reject
    description: >- 
      We use cookies to recognize your repeated visits and preferences, as well
      as to measure the effectiveness of our documentation and whether users
      find what they're searching for. <strong>Clicking "Accept" makes our
      documentation better. Thank you!</strong> ❤️
  social:
    - icon: fontawesome/brands/python
      link: https://langchain-ai.github.io/langgraph/
    - icon: fontawesome/brands/github
      link: https://github.com/langchain-ai/langgraphjs
    - icon: fontawesome/brands/twitter
      link: https://x.com/langchain_js

validation:
  # https://www.mkdocs.org/user-guide/configuration/
  # We're `ignoring` nav.omitted_files because we are going to rely
  # on files being properly links to from the index pages of:
  # - tutorials
  # - concepts
  # - how-tos
  # - reference
  omitted_files: ignore
  # absolute_links: warn
  unrecognized_links: warn
  anchors: info
  # this is needed to handle headers with anchors for nav
  not_found: info
copyright: >
  Copyright &copy; 2025 LangChain, Inc | <a href="#__consent">Consent Preferences</a>

---

### Package.Json (`docs/package.json`)

{
  "name": "docs",
  "type": "module",
  "private": true,
  "description": "Dependencies for LangGraph docs.",
  "scripts": {
    "build": "typedoc --options typedoc.jsonc"
  },
  "devDependencies": {
    "typedoc": "patch:typedoc@npm:3.0.28.11#./patches/typedoc@3.0.28.11.patch"
  }
}

---

### Docs Adopters (`docs/docs/adopters.md`)

# 🦜🕸️ LangGraph Adopters

This list of companies using LangGraph and their success stories is compiled from public sources. If your company uses LangGraph, we'd love for you to share your story and add it to the list. You’re also welcome to contribute updates based on publicly available information from other companies, such as blog posts or press releases.


| Company | Industry | Use case | Reference |
| --- | --- | --- | --- |
| [AirTop](https://www.airtop.ai/) | Software & Technology (GenAI Native) | Browser automation for AI agents | [Case study, 2024](https://blog.langchain.dev/customers-airtop/) |
| [AppFolio](https://www.appfolio.com/) | Real Estate | Copilot for domain-specific task | [Case study, 2024](https://blog.langchain.dev/customers-appfolio/) |
| [Athena Intelligence](https://www.athenaintel.com/) | Software & Technology (GenAI Native) | Research & summarization | [Case study, 2024](https://blog.langchain.dev/customers-athena-intelligence/) |
| [Captide](https://www.captide.co/) | Software & Technology (GenAI Native) | Data extraction | [Case study, 2025](https://blog.langchain.dev/how-captide-is-redefining-equity-research-with-agentic-workflows-built-on-langgraph-and-langsmith/) |
| [Elastic](https://www.elastic.co/) | Software & Technology | Copilot for domain-specific task | [Blog post, 2025](https://www.elastic.co/blog/elastic-security-generative-ai-features) |
| [GitLab](https://about.gitlab.com/) | Software & Technology | Code generation | [Duo workflow docs](https://handbook.gitlab.com/handbook/engineering/architecture/design-documents/duo_workflow/) |
| [Infor](https://infor.com/) | Software & Technology | GenAI embedded product experiences; customer support; copilot | [Case study, 2025](https://blog.langchain.dev/customers-infor/) |
| [Komodo Health](https://www.komodohealth.com/) | Healthcare | Copilot for domain-specific task | [Blog post](https://www.komodohealth.com/perspectives/new-gen-ai-assistant-empowers-the-enterprise/) |
| [LinkedIn](https://www.linkedin.com/) | Social Media | Code generation; Search & discovery | [Blog post, 2025](https://www.linkedin.com/blog/engineering/ai/practical-text-to-sql-for-data-analytics); [Blog post, 2024](https://www.linkedin.com/blog/engineering/generative-ai/behind-the-platform-the-journey-to-create-the-linkedin-genai-application-tech-stack) |
| [Minimal](https://gominimal.ai/) | E-commerce | Customer support | [Case study, 2025](https://blog.langchain.dev/how-minimal-built-a-multi-agent-customer-support-system-with-langgraph-langsmith/) |
| [OpenRecovery](https://www.openrecovery.com/) | Healthcare | Copilot for domain-specific task | [Case study, 2024](https://blog.langchain.dev/customers-openrecovery/) |
| [Rakuten](https://www.rakuten.com/) | E-commerce / Fintech | Copilot for domain-specific task | [Blog post, 2025](https://rakuten.today/blog/from-ai-hype-to-real-world-tools-rakuten-teams-up-with-langchain.html) |
| [Replit](https://replit.com/) | Software & Technology | Code generation | [Blog post, 2024](https://blog.langchain.dev/customers-replit/); [Breakout agent story, 2024](https://www.langchain.com/breakoutagents/replit); [Fireside chat video, 2024](https://www.youtube.com/watch?v=ViykMqljjxU) |
| [Rexera](https://www.rexera.com/) | Real Estate (GenAI Native) | Copilot for domain-specific task | [Case study, 2024](https://blog.langchain.dev/customers-rexera/) |
| [Tradestack](https://www.tradestack.uk/) | Software & Technology (GenAI Native) | Copilot for domain-specific task | [Case study, 2024](https://blog.langchain.dev/customers-tradestack/) |
| [Uber](https://www.uber.com/) | Transportation | Developer productivity; Code generation | [Presentation, 2024](https://dpe.org/sessions/ty-smith-adam-huda/this-year-in-ubers-ai-driven-developer-productivity-revolution/); [Video, 2024](https://www.youtube.com/watch?v=8rkA5vWUE4Y) |
| [Unify](https://www.unifygtm.com/) | Software & Technology (GenAI Native) | Copilot for domain-specific task | [Blog post, 2024](https://blog.langchain.dev/unify-launches-agents-for-account-qualification-using-langgraph-and-langsmith/) |
| [Vizient](https://www.vizientinc.com/) | Healthcare | Copilot for domain-specific task | [Case study, 2025](https://blog.langchain.dev/p/3d2cd58c-13a5-4df9-bd84-7d54ed0ed82c/) |

---

### Docs Llms (`docs/docs/llms.txt`)

# LangGraph

## Quickstart

These guides are designed to help you get started with LangGraph.

- [LangGraph Quickstart](https://docs.langchain.com/oss/javascript/langgraph/tutorials/quickstart/): Build a chatbot that can use tools and keep track of conversation history. Add human-in-the-loop capabilities and explore how time-travel works.
- [Common Workflows](https://docs.langchain.com/oss/javascript/langgraph/tutorials/workflows/): Overview of the most common workflows using LLMs implemented with LangGraph.
- [LangGraph Server Quickstart](https://docs.langchain.com/oss/javascript/langgraph/tutorials/langgraph-platform/local-server/): Launch a LangGraph server locally and interact with it using REST API and LangGraph Studio Web UI.
- [Deploy with LangGraph Cloud Quickstart](https://docs.langchain.com/oss/javascript/langgraph/cloud/quick_start/): Deploy a LangGraph app using LangGraph Cloud.

## Concepts

These guides provide explanations of the key concepts behind the LangGraph framework.

- [Why LangGraph?](https://docs.langchain.com/oss/javascript/langgraph/concepts/high_level/): Motivation for LangGraph, a library for building agentic applications with LLMs.
- [LangGraph Glossary](https://docs.langchain.com/oss/javascript/langgraph/concepts/low_level/): LangGraph workflows are designed as graphs, with nodes representing different components and edges representing the flow of information between them. This guide provides an overview of the key concepts associated with LangGraph graph primitives.
- [Common Agentic Patterns](https://docs.langchain.com/oss/javascript/langgraph/concepts/agentic_concepts/): An agent uses an LLM to pick its own control flow to solve more complex problems! Agents are a key building block in many LLM applications. This guide explains the different types of agent architectures and how they can be used to control the flow of an application.
- [Multi-Agent Systems](https://docs.langchain.com/oss/javascript/langgraph/concepts/multi_agent/): Complex LLM applications can often be broken down into multiple agents, each responsible for a different part of the application. This guide explains common patterns for building multi-agent systems.
- [Breakpoints](https://docs.langchain.com/oss/javascript/langgraph/concepts/breakpoints/): Breakpoints allow pausing the execution of a graph at specific points. Breakpoints allow stepping through graph execution for debugging purposes.
- [Human-in-the-Loop](https://docs.langchain.com/oss/javascript/langgraph/concepts/human_in_the_loop/): Explains different ways of integrating human feedback into a LangGraph application.
- [Time Travel](https://docs.langchain.com/oss/javascript/langgraph/concepts/time-travel/): Time travel allows you to replay past actions in your LangGraph application to explore alternative paths and debug issues.
- [Persistence](https://docs.langchain.com/oss/javascript/langgraph/concepts/persistence/): LangGraph has a built-in persistence layer, implemented through checkpointers. This persistence layer helps to support powerful capabilities like human-in-the-loop, memory, time travel, and fault-tolerance.
- [Memory](https://docs.langchain.com/oss/javascript/langgraph/concepts/memory/): Memory in AI applications refers to the ability to process, store, and effectively recall information from past interactions. With memory, your agents can learn from feedback and adapt to users' preferences.
- [Streaming](https://docs.langchain.com/oss/javascript/langgraph/concepts/streaming/): Streaming is crucial for enhancing the responsiveness of applications built on LLMs. By displaying output progressively, even before a complete response is ready, streaming significantly improves user experience (UX), particularly when dealing with the latency of LLMs.
- [Functional API](https://docs.langchain.com/oss/javascript/langgraph/concepts/functional_api/): `@entrypoint` and `@task` decorators that allow you to add LangGraph functionality to an existing codebase.
- [FAQ](https://docs.langchain.com/oss/javascript/langgraph/concepts/faq/): Frequently asked questions about LangGraph.

## How-tos

Here you'll find answers to "How do I...?" types of questions. 

These guides are **goal-oriented** and concrete. 

They're meant to help you complete a specific task.

### Fine-grained Control

These guides demonstrate LangGraph features that grant fine-grained control over the execution of your graph.

- [How to create map-reduce branches for parallel execution](https://docs.langchain.com/oss/javascript/langgraph/how-tos/map-reduce/)
- [How to update state and jump to nodes in graphs and subgraphs](https://docs.langchain.com/oss/javascript/langgraph/how-tos/command/)
- [How to defer node execution](https://docs.langchain.com/oss/javascript/langgraph/how-tos/defer-node-execution/)
- [How to add runtime configuration to your graph](https://docs.langchain.com/oss/javascript/langgraph/how-tos/configuration/)

### Persistence
 
Persistence makes it easy to persist state across graph runs (per-thread persistence) and across threads (cross-thread persistence). 

These how-to guides show how to add persistence to your graph.

- [How to add thread-level persistence to your graph](https://docs.langchain.com/oss/javascript/langgraph/how-tos/persistence/)
- [How to add thread-level persistence to a subgraph](https://docs.langchain.com/oss/javascript/langgraph/how-tos/subgraph-persistence/)
- [How to add cross-thread persistence to your graph](https://docs.langchain.com/oss/javascript/langgraph/how-tos/cross-thread-persistence/)
- [How to use Postgres checkpointer for persistence](https://docs.langchain.com/oss/javascript/langgraph/how-tos/persistence_postgres/)

See the below guides for how-to add persistence to your workflow using the [Functional API](https://docs.langchain.com/oss/javascript/langgraph/concepts/functional_api/):

- [How to add thread-level persistence (functional API)](https://docs.langchain.com/oss/javascript/langgraph/how-tos/persistence-functional/)
- [How to add cross-thread persistence (functional API)](https://docs.langchain.com/oss/javascript/langgraph/how-tos/cross-thread-persistence-functional/)

### Memory

LangGraph makes it easy to manage conversation memory in your graph. These how-to guides show how to implement different strategies for that.

- [How to manage conversation history](https://docs.langchain.com/oss/javascript/langgraph/how-tos/memory/manage-conversation-history/)
- [How to delete messages](https://docs.langchain.com/oss/javascript/langgraph/how-tos/memory/delete-messages/)
- [How to add summary conversation memory](https://docs.langchain.com/oss/javascript/langgraph/how-tos/memory/add-summary-conversation-history/)
- [How to add long-term memory (cross-thread)](https://docs.langchain.com/oss/javascript/langgraph/how-tos/memory/cross-thread-persistence/)
- [How to use semantic search for long-term memory](https://docs.langchain.com/oss/javascript/langgraph/how-tos/memory/semantic-search/)

### Human-in-the-loop

Human-in-the-loop functionality allows you to involve humans in the decision-making process of your graph.

These how-to guides show how to implement human-in-the-loop workflows in your graph.

- [How to wait for user input](https://docs.langchain.com/oss/javascript/langgraph/how-tos/human_in_the_loop/wait-user-input/): A basic example that shows how to implement a human-in-the-loop workflow in your graph using the `interrupt` function.
- [How to review tool calls](https://docs.langchain.com/oss/javascript/langgraph/how-tos/human_in_the_loop/review-tool-calls/): Incorporate human-in-the-loop for reviewing/editing/accepting tool call requests before they executed using the `interrupt` function.
- [How to add static breakpoints](https://docs.langchain.com/oss/javascript/langgraph/how-tos/human_in_the_loop/breakpoints/): Use for debugging purposes. For human-in-the-loop workflows, we recommend the [`interrupt` function](https://docs.langchain.com/oss/javascript/langgraph/reference/types/#langgraph.types.interrupt) instead.
- [How to edit graph state](https://docs.langchain.com/oss/javascript/langgraph/how-tos/human_in_the_loop/edit-graph-state/): Edit graph state using `graph.update_state` method. Use this if implementing a **human-in-the-loop** workflow via **static breakpoints**.

See the below guides for how-to implement human-in-the-loop workflows with the Functional API.

- [How to wait for user input (Functional API)](https://docs.langchain.com/oss/javascript/langgraph/how-tos/wait-user-input-functional/)
- [How to review tool calls (Functional API)](https://docs.langchain.com/oss/javascript/langgraph/how-tos/review-tool-calls-functional/)

### Time Travel

[Time travel](https://docs.langchain.com/oss/javascript/langgraph/concepts/time-travel/) allows you to replay past actions in your LangGraph application to explore alternative paths and debug issues. These how-to guides show how to use time travel in your graph.

- [How to view and update past graph state](https://docs.langchain.com/oss/javascript/langgraph/how-tos/time-travel/)

### Streaming

[Streaming](https://docs.langchain.com/oss/javascript/langgraph/concepts/streaming/) is crucial for enhancing the responsiveness of applications built on LLMs. By displaying output progressively, even before a complete response is ready, streaming significantly improves user experience (UX), particularly when dealing with the latency of LLMs.

- [How to stream the full state of your graph](https://docs.langchain.com/oss/javascript/langgraph/how-tos/stream-values/)
- [How to stream state updates of your graph](https://docs.langchain.com/oss/javascript/langgraph/how-tos/stream-updates/)
- [How to stream LLM tokens](https://docs.langchain.com/oss/javascript/langgraph/how-tos/stream-tokens/)
- [How to stream LLM tokens without LangChain models](https://docs.langchain.com/oss/javascript/langgraph/how-tos/streaming-tokens-without-langchain/)
- [How to stream custom data](https://docs.langchain.com/oss/javascript/langgraph/how-tos/streaming-content/)
- [How to configure multiple streaming modes](https://docs.langchain.com/oss/javascript/langgraph/how-tos/stream-multiple/)
- [How to stream events from within a tool](https://docs.langchain.com/oss/javascript/langgraph/how-tos/streaming-events-from-within-tools/)
- [How to stream from the final node](https://docs.langchain.com/oss/javascript/langgraph/how-tos/streaming-from-final-node/)

### Tool calling

- [How to call tools using ToolNode](https://docs.langchain.com/oss/javascript/langgraph/how-tos/tool-calling/)
- [How to force an agent to call a tool](https://docs.langchain.com/oss/javascript/langgraph/how-tos/force-calling-a-tool-first/)
- [How to handle tool calling errors](https://docs.langchain.com/oss/javascript/langgraph/how-tos/tool-calling-errors/)
- [How to pass runtime values to tools](https://docs.langchain.com/oss/javascript/langgraph/how-tos/pass-run-time-values-to-tools/)
- [How to update graph state from tools](https://docs.langchain.com/oss/javascript/langgraph/how-tos/update-state-from-tools/)

### Subgraphs

[Subgraphs](https://docs.langchain.com/oss/javascript/langgraph/concepts/low_level/#subgraphs) allow you to reuse an existing graph from another graph. These how-to guides show how to use subgraphs:

- [How to add and use subgraphs](https://docs.langchain.com/oss/javascript/langgraph/how-tos/subgraph/)
- [How to view and update state in subgraphs](https://docs.langchain.com/oss/javascript/langgraph/how-tos/subgraphs-manage-state/)
- [How to transform inputs and outputs of a subgraph](https://docs.langchain.com/oss/javascript/langgraph/how-tos/subgraph-transform-state/)

### Multi-agent

- [How to build a multi-agent network](https://docs.langchain.com/oss/javascript/langgraph/how-tos/multi-agent-network/)
- [How to add multi-turn conversation in a multi-agent application](https://docs.langchain.com/oss/javascript/langgraph/how-tos/multi-agent-multi-turn-convo/)

See the [multi-agent tutorials](https://docs.langchain.com/oss/javascript/langgraph/tutorials/index/#multi-agent-systems) for implementations of other multi-agent architectures.

See the below guides for how-to implement multi-agent workflows with the [Functional API](https://docs.langchain.com/oss/javascript/langgraph/concepts/functional_api/):

- [How to build a multi-agent network (functional API)](https://docs.langchain.com/oss/javascript/langgraph/how-tos/multi-agent-network-functional/)
- [How to add multi-turn conversation in a multi-agent application (functional API)](https://docs.langchain.com/oss/javascript/langgraph/how-tos/multi-agent-multi-turn-convo-functional/)

### State management

- [How to define graph state](https://docs.langchain.com/oss/javascript/langgraph/how-tos/define-state/)
- [Have a separate input and output schema](https://docs.langchain.com/oss/javascript/langgraph/how-tos/input_output_schema/)
- [Pass private state between nodes inside the graph](https://docs.langchain.com/oss/javascript/langgraph/how-tos/pass_private_state/)

### Other

- [How to add runtime configuration to your graph](https://docs.langchain.com/oss/javascript/langgraph/how-tos/configuration/)
- [How to add node retries](https://docs.langchain.com/oss/javascript/langgraph/how-tos/node-retry-policies/)
- [How to cache expensive nodes](https://docs.langchain.com/oss/javascript/langgraph/how-tos/node-caching/)
- [How to let an agent return tool results directly](https://docs.langchain.com/oss/javascript/langgraph/how-tos/dynamically-returning-directly/)
- [How to have an agent respond in structured format](https://docs.langchain.com/oss/javascript/langgraph/how-tos/respond-in-format/)
- [How to manage agent steps](https://docs.langchain.com/oss/javascript/langgraph/how-tos/managing-agent-steps/)

### Prebuilt ReAct Agent

- [How to create a ReAct agent](https://docs.langchain.com/oss/javascript/langgraph/how-tos/create-react-agent/)
- [How to add memory to a ReAct agent](https://docs.langchain.com/oss/javascript/langgraph/how-tos/react-memory/)
- [How to add a system prompt to a ReAct agent](https://docs.langchain.com/oss/javascript/langgraph/how-tos/react-system-prompt/)
- [How to add Human-in-the-loop to a ReAct agent](https://docs.langchain.com/oss/javascript/langgraph/how-tos/react-human-in-the-loop/)
- [How to return structured output from a ReAct agent](https://docs.langchain.com/oss/javascript/langgraph/how-tos/react-return-structured-output/)

See the below guide for how-to build ReAct agents with the [Functional API](https://docs.langchain.com/oss/javascript/langgraph/concepts/functional_api/):

- [How to create a ReAct agent from scratch (Functional API)](https://docs.langchain.com/oss/javascript/langgraph/how-tos/react-agent-from-scratch-functional/)

## LangGraph Platform

This section includes how-to guides for LangGraph Platform.

LangGraph Platform is a commercial solution for deploying agentic applications in production, built on the open-source LangGraph framework. It provides four deployment options to fit a range of needs: a free tier, a self-hosted version, a cloud SaaS, and a Bring Your Own Cloud (BYOC) option. You can explore these options in detail in the [deployment options guide](https://docs.langchain.com/oss/javascript/langgraph/concepts/deployment_options/).

!!! tip

    * LangGraph is an MIT-licensed open-source library, which we are committed to maintaining and growing for the community.
    * You can always deploy LangGraph applications on your own infrastructure using the open-source LangGraph project without using LangGraph Platform.

### Application Structure

Learn how to set up your app for deployment to LangGraph Platform:

- [How to set up app for deployment (requirements.txt)](https://docs.langchain.com/oss/javascript/langgraph/cloud/deployment/setup/)
- [How to set up app for deployment (pyproject.toml)](https://docs.langchain.com/oss/javascript/langgraph/cloud/deployment/setup_pyproject/)
- [How to set up app for deployment (JavaScript)](https://docs.langchain.com/oss/javascript/langgraph/cloud/deployment/setup_javascript/)
- [How to customize Dockerfile](https://docs.langchain.com/oss/javascript/langgraph/cloud/deployment/custom_docker/)
- [How to test locally](https://docs.langchain.com/oss/javascript/langgraph/cloud/deployment/test_locally/)
- [How to integrate LangGraph into your React application](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/use_stream_react/)

### Deployment

LangGraph applications can be deployed using LangGraph Cloud, which provides a range of services to help you deploy, manage, and scale your applications.

- [How to deploy to LangGraph cloud](https://docs.langchain.com/oss/javascript/langgraph/cloud/deployment/cloud/)
- [How to deploy to a self-hosted environment](https://docs.langchain.com/oss/javascript/langgraph/how-tos/deploy-self-hosted/)
- [How to interact with the deployment using RemoteGraph](https://docs.langchain.com/oss/javascript/langgraph/how-tos/use-remote-graph/)

### Assistants

[Assistants](https://docs.langchain.com/oss/javascript/langgraph/concepts/assistants/) are a configured instance of a template.

- [How to configure agents](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/configuration_cloud/)
- [How to version assistants](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/assistant_versioning/)

### Threads

- [How to copy threads](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/copy_threads/)
- [How to check status of your threads](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/check_thread_status/)

### Runs

LangGraph Cloud supports multiple types of runs besides streaming runs.

- [How to run an agent in the background](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/background_run/)
- [How to run multiple agents in the same thread](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/same-thread/)
- [How to create cron jobs](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/cron_jobs/)
- [How to create stateless runs](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/stateless_runs/)

### Streaming

Streaming the results of your LLM application is vital for ensuring a good user experience, especially when your graph may call multiple models and take a long time to fully complete a run. Read about how to stream values from your graph in these how to guides:

- [How to stream values](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/stream_values/)
- [How to stream updates](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/stream_updates/)
- [How to stream messages](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/stream_messages/)
- [How to stream events](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/stream_events/)
- [How to stream in debug mode](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/stream_debug/)
- [How to stream multiple modes](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/stream_multiple/)

### Frontend & Generative UI

With LangGraph Platform you can integrate LangGraph agents into your React applications and colocate UI components with your agent code.

- [How to integrate LangGraph into your React application](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/use_stream_react/)
- [How to implement Generative User Interfaces with LangGraph](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/generative_ui_react/)

### Human-in-the-loop

When creating complex graphs, leaving every decision up to the LLM can be dangerous, especially when the decisions involve invoking certain tools or accessing specific documents. To remedy this, LangGraph allows you to insert human-in-the-loop behavior to ensure your graph does not have undesired outcomes. Read more about the different ways you can add human-in-the-loop capabilities to your LangGraph Cloud projects in these how-to guides:

- [How to add a breakpoint](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/human_in_the_loop_breakpoint/)
- [How to wait for user input](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/human_in_the_loop_user_input/)
- [How to edit graph state](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/human_in_the_loop_edit_state/)
- [How to replay and branch from prior states](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/human_in_the_loop_time_travel/)
- [How to review tool calls](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/human_in_the_loop_review_tool_calls/)

### Double-texting

Graph execution can take a while, and sometimes users may change their mind about the input they wanted to send before their original input has finished running. For example, a user might notice a typo in their original request and will edit the prompt and resend it. Deciding what to do in these cases is important for ensuring a smooth user experience and preventing your graphs from behaving in unexpected ways. The following how-to guides provide information on the various options LangGraph Cloud gives you for dealing with double-texting:

- [How to use the interrupt option](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/interrupt_concurrent/)
- [How to use the rollback option](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/rollback_concurrent/)
- [How to use the reject option](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/reject_concurrent/)
- [How to use the enqueue option](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/enqueue_concurrent/)

### Webhooks

- [How to integrate webhooks](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/webhooks/)

### Cron Jobs

- [How to create cron jobs](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/cron_jobs/)

### LangGraph Studio

LangGraph Studio is a built-in UI for visualizing, testing, and debugging your agents.

- [How to connect to a LangGraph Cloud deployment](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/test_deployment/)
- [How to connect to a local deployment](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/test_local_deployment/)
- [How to test your graph in LangGraph Studio](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/invoke_studio/)
- [How to interact with threads in LangGraph Studio](https://docs.langchain.com/oss/javascript/langgraph/cloud/how-tos/threads_studio/)

## Troubleshooting

These are the guides for resolving common errors you may find while building with LangGraph. Errors referenced below will have an `lc_error_code` property corresponding to one of the below codes when they are thrown in code.

- [GRAPH_RECURSION_LIMIT](https://docs.langchain.com/oss/javascript/langgraph/troubleshooting/errors/GRAPH_RECURSION_LIMIT/)
- [INVALID_CONCURRENT_GRAPH_UPDATE](https://docs.langchain.com/oss/javascript/langgraph/troubleshooting/errors/INVALID_CONCURRENT_GRAPH_UPDATE/)
- [INVALID_GRAPH_NODE_RETURN_VALUE](https://docs.langchain.com/oss/javascript/langgraph/troubleshooting/errors/INVALID_GRAPH_NODE_RETURN_VALUE/)
- [MULTIPLE_SUBGRAPHS](https://docs.langchain.com/oss/javascript/langgraph/troubleshooting/errors/MULTIPLE_SUBGRAPHS/)
- [UNREACHABLE_NODE](https://docs.langchain.com/oss/javascript/langgraph/troubleshooting/errors/UNREACHABLE_NODE/)

---

###  Scripts Third Party Packages.Yml (`docs/_scripts/third_party/packages.yml`)

#A list of third-party packages to surface on the third-party page.
packages:
  - name: "@langchain/langgraph-supervisor"
    repo: "langchain-ai/langgraphjs"
    monorepo_path: "libs/langgraph-supervisor"
    description: "Build supervisor multi-agent systems with LangGraph"
  - name: "@langchain/langgraph-swarm"
    repo: "langchain-ai/langgraphjs"
    monorepo_path: "libs/langgraph-swarm"
    description: "Build multi-agent swarms with LangGraph"
  - name: "@langchain/langgraph-cua"
    repo: "langchain-ai/langgraphjs"
    monorepo_path: "libs/langgraph-cua"
    description: "Build computer use agents with LangGraph"

---

### Docs Agents Agents (`docs/docs/agents/agents.md`)

# LangGraph quickstart

This guide shows you how to set up and use LangGraph's **prebuilt**, **reusable** components, which are designed to help you construct agentic systems quickly and reliably.

## Prerequisites

Before you start this tutorial, ensure you have the following:

- An [Anthropic](https://console.anthropic.com/settings/keys) API key

## 1. Install dependencies

If you haven't already, install LangGraph and LangChain:

```
npm install langchain @langchain/langgraph @langchain/anthropic
```

## 2. Create an agent

Use [`createReactAgent`](/langgraphjs/reference/functions/langgraph_prebuilt.createReactAgent.html) to instantiate an agent:

```ts
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { initChatModel } from "langchain/chat_models/universal";
import { tool } from "@langchain/core/tools";
import { z } from "zod";

const getWeather = tool( // (1)!
  async (input: { city: string }) => {
    return `It's always sunny in ${input.city}!`;
  },
  {
    name: "getWeather",
    schema: z.object({
      city: z.string().describe("The city to get the weather for"),
    }),
    description: "Get weather for a given city.",
  }
);

const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest"); // (2)!
const agent = createReactAgent({
  llm,
  tools: [getWeather], // (3)!
  prompt: "You are a helpful assistant", // (4)!
});

// Run the agent
await agent.invoke({
  messages: [{ role: "user", content: "what is the weather in sf" }],
});
```

1. Define a tool for the agent to use. For more advanced tool usage and customization, check the [tools](./tools.md) page.
2. Provide a language model for the agent to use. To learn more about configuring language models for the agents, check the [models](./models.md) page.
3. Provide a list of tools for the model to use.
4. Provide a system prompt (instructions) to the language model used by the agent.

## 3. Configure an LLM

Use [`initChatModel`](https://api.js.langchain.com/functions/langchain.chat_models_universal.initChatModel.html) to configure an LLM with specific parameters, such as temperature:

```ts
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { initChatModel } from "langchain/chat_models/universal";

// highlight-next-line
const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest", {
  // highlight-next-line
  temperature: 0,
});

const agent = createReactAgent({
  // highlight-next-line
  llm,
  tools: [getWeather],
});
```

See the [models](./models.md) page for more information on how to configure LLMs.

## 4. Add a custom prompt

Prompts instruct the LLM how to behave. They can be:

- **Static**: A string is interpreted as a **system message**
- **Dynamic**: a list of messages generated at **runtime** based on input or configuration

=== "Static prompt"

    Define a fixed prompt string or list of messages.

    ```ts
    import { createReactAgent } from "@langchain/langgraph/prebuilt";
    import { initChatModel } from "langchain/chat_models/universal";

    const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
    const agent = createReactAgent({
      llm,
      tools: [getWeather],
      // A static prompt that never changes
      // highlight-next-line
      prompt: "Never answer questions about the weather.",
    });

    await agent.invoke({
      messages: "what is the weather in sf",
    });
    ```

=== "Dynamic prompt"

    Define a function that returns a message list based on the agent's state and configuration:

    ```ts
    import { BaseMessageLike } from "@langchain/core/messages";
    import { RunnableConfig } from "@langchain/core/runnables";
    import { initChatModel } from "langchain/chat_models/universal";
    import { MessagesAnnotation } from "@langchain/langgraph";
    import { createReactAgent } from "@langchain/langgraph/prebuilt";

    const prompt = (
      state: typeof MessagesAnnotation.State,
      config: RunnableConfig
    ): BaseMessageLike[] => { // (1)!
      const userName = config.configurable?.userName;
      const systemMsg = `You are a helpful assistant. Address the user as ${userName}.`;
      return [{ role: "system", content: systemMsg }, ...state.messages];
    };

    const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
    const agent = createReactAgent({
      llm,
      tools: [getWeather],
      // highlight-next-line
      prompt,
    });

    await agent.invoke(
      { messages: [{ role: "user", content: "what is the weather in sf" }] },
      // highlight-next-line
      { configurable: { userName: "John Smith" } }
    );
    ```

    1. Dynamic prompts allow including non-message [context](./context.md) when constructing an input to the LLM, such as:

      - Information passed at runtime, like a `userId` or API credentials (using `config`).
      - Internal agent state updated during a multi-step reasoning process (using `state`).

      Dynamic prompts can be defined as functions that take `state` and `config` and return a list of messages to send to the LLM.

For more information, see [Context](./context.md).

## 5. Add memory

To allow multi-turn conversations with an agent, you need to enable [persistence](../concepts/persistence.md) by providing a `checkpointer` when creating an agent. At runtime you need to provide a config containing `thread_id` — a unique identifier for the conversation (session):

```ts
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { MemorySaver } from "@langchain/langgraph-checkpoint";
import { initChatModel } from "langchain/chat_models/universal";

// highlight-next-line
const checkpointer = new MemorySaver();

const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
const agent = createReactAgent({
  llm,
  tools: [getWeather],
  // highlight-next-line
  checkpointer, // (1)!
});

// Run the agent
// highlight-next-line
const config = { configurable: { thread_id: "1" } };
const sfResponse = await agent.invoke(
  { messages: [{ role: "user", content: "what is the weather in sf" }] },
  config // (2)!
);
const nyResponse = await agent.invoke(
  { messages: [{ role: "user", content: "what about new york?" }] },
  config
);
```

1. `checkpointer` allows the agent to store its state at every step in the tool calling loop. This enables [short-term memory](./memory.md#short-term-memory) and [human-in-the-loop](./human-in-the-loop.md) capabilities.
2. Pass configuration with `thread_id` to be able to resume the same conversation on future agent invocations.

When you enable the checkpointer, it stores agent state at every step in the provided checkpointer database (or in memory, if using `InMemorySaver`).

Note that in the above example, when the agent is invoked the second time with the same `thread_id`, the original message history from the first conversation is automatically included, together with the new user input.

For more information, see [Memory](./memory.md).

## 6. Configure structured output

To produce structured responses conforming to a schema, use the `responseFormat` parameter. The schema can be defined with a `zod` schema. The result will be accessible via the `structuredResponse` field.

```ts
import { z } from "zod";
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { initChatModel } from "langchain/chat_models/universal";

const WeatherResponse = z.object({
  conditions: z.string(),
});

const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
const agent = createReactAgent({
  llm,
  tools: [getWeather],
  // highlight-next-line
  responseFormat: WeatherResponse, // (1)!
});

const response = await agent.invoke({
  messages: [{ role: "user", content: "what is the weather in sf" }],
});
// highlight-next-line
response.structuredResponse;
```

1. When `responseFormat` is provided, a separate step is added at the end of the agent loop: agent message history is passed to an LLM with structured output to generate a structured response.

   To provide a system prompt to this LLM, use an object `{ prompt, schema }`, e.g., `responseFormat: { prompt, schema: WeatherResponse }`.

!!! Note "LLM post-processing"

    Structured output requires an additional call to the LLM to format the response according to the schema.

## Next steps

- [Deploy your agent locally](../tutorials/langgraph-platform/local-server.md)
- [Learn more about prebuilt agents](../agents/overview.md)
- [LangGraph Platform quickstart](../cloud/quick_start.md)

---

### Docs Agents Context (`docs/docs/agents/context.md`)

# Context

Agents often require more than a list of messages to function effectively. They need **context**.

Context includes *any* data outside the message list that can shape agent behavior or tool execution. This can be:

- Information passed at runtime, like a `user_id` or API credentials.
- Internal state updated during a multi-step reasoning process.
- Persistent memory or facts from previous interactions.

LangGraph provides **three** primary ways to supply context:

| Type                                                                         | Description                                   | Mutable? | Lifetime                |
|------------------------------------------------------------------------------|-----------------------------------------------|----------|-------------------------|
| [**Config**](#config-static-context)                                         | data passed at the start of a run             | ❌        | per run                 |
| [**State**](#state-mutable-context)                                          | dynamic data that can change during execution | ✅        | per run or conversation |
| [**Long-term Memory (Store)**](#long-term-memory-cross-conversation-context) | data that can be shared between conversations | ✅        | across conversations    |

You can use context to:

- Adjust the system prompt the model sees
- Feed tools with necessary inputs
- Track facts during an ongoing conversation

## Providing Runtime Context

Use this when you need to inject data into an agent at runtime.

### Config (static context)

Config is for immutable data like user metadata or API keys. Use
when you have values that don't change mid-run.

Specify configuration using a key called **"configurable"** which is reserved
for this purpose:

```ts
await agent.invoke(
  { messages: "hi!" },
  // highlight-next-line
  { configurable: { userId: "user_123" } }
)
```

### State (mutable context)

State acts as short-term memory during a run. It holds dynamic data that can evolve during execution, such as values derived from tools or LLM outputs.

```ts
const CustomState = Annotation.Root({
  ...MessagesAnnotation.spec,
  userName: Annotation<string>,
});

const agent = createReactAgent({
  // Other agent parameters...
  // highlight-next-line
  stateSchema: CustomState,
})

await agent.invoke(
  // highlight-next-line
  { messages: "hi!", userName: "Jane" }
)
```

!!! tip "Turning on memory"

    Please see the [memory guide](./memory.md) for more details on how to enable memory. This is a powerful feature that allows you to persist the agent's state across multiple invocations.
    Otherwise, the state is scoped only to a single agent run.



### Long-Term Memory (cross-conversation context)

For context that spans *across* conversations or sessions, LangGraph allows access to **long-term memory** via a `store`. This can be used to read or update persistent facts (e.g., user profiles, preferences, prior interactions). For more, see the [Memory guide](./memory.md).

## Customizing Prompts with Context

Prompts define how the agent behaves. To incorporate runtime context, you can dynamically generate prompts based on the agent's state or config.

Common use cases:

- Personalization
- Role or goal customization
- Conditional behavior (e.g., user is admin)

=== "Using config"

    ```ts
    import { BaseMessageLike } from "@langchain/core/messages";
    import { RunnableConfig } from "@langchain/core/runnables";
    import { initChatModel } from "langchain/chat_models/universal";
    import { MessagesAnnotation } from "@langchain/langgraph";
    import { createReactAgent } from "@langchain/langgraph/prebuilt";

    const prompt = (
      state: typeof MessagesAnnotation.State,
      // highlight-next-line
      config: RunnableConfig
    ): BaseMessageLike[] => {
      // highlight-next-line
      const userName = config.configurable?.userName;
      const systemMsg = `You are a helpful assistant. Address the user as ${userName}.`;
      return [{ role: "system", content: systemMsg }, ...state.messages];
    };

    const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
    const agent = createReactAgent({
      llm,
      tools: [getWeather],
      // highlight-next-line
      prompt
    });

    await agent.invoke(
      { messages: "hi!" },
      // highlight-next-line
      { configurable: { userName: "John Smith" } }
    );
    ```

=== "Using state"

    ```ts
    import { BaseMessageLike } from "@langchain/core/messages";
    import { RunnableConfig } from "@langchain/core/runnables";
    import { initChatModel } from "langchain/chat_models/universal";
    import { Annotation, MessagesAnnotation } from "@langchain/langgraph";
    import { createReactAgent } from "@langchain/langgraph/prebuilt";

    const CustomState = Annotation.Root({
      ...MessagesAnnotation.spec,
      // highlight-next-line
      userName: Annotation<string>,
    });

    const prompt = (
      // highlight-next-line
      state: typeof CustomState.State,
    ): BaseMessageLike[] => {
      // highlight-next-line
      const userName = state.userName;
      const systemMsg = `You are a helpful assistant. Address the user as ${userName}.`;
      return [{ role: "system", content: systemMsg }, ...state.messages];
    };

    const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
    const agent = createReactAgent({
      llm,
      tools: [getWeather],
      // highlight-next-line
      prompt,
      // highlight-next-line
      stateSchema: CustomState,
    });

    await agent.invoke(
      // highlight-next-line
      { messages: "hi!", userName: "John Smith" },
    );
    ```

## Tools

Tools can access context through:

* Use `RunnableConfig` for config access
* Use `runtime.state` (the second argument, typed as `ToolRuntime`) for agent state

!!! tip "Browser / web environments"

    When a tool runs inside a `ToolNode` (including in `createReactAgent`), the `ToolNode` forwards its input (the current graph state) to the tool via `runtime.state`. This works in every runtime, including web browsers.

    An older alternative, `getCurrentTaskInput()`, relies on [`AsyncLocalStorage`](https://nodejs.org/api/async_hooks.html), which is available in Node.js, Deno, and Cloudflare Workers, but **not** in web browsers. Prefer `runtime.state` for portability.

=== "Using config"

    ```ts
    import { RunnableConfig } from "@langchain/core/runnables";
    import { initChatModel } from "langchain/chat_models/universal";
    import { createReactAgent } from "@langchain/langgraph/prebuilt";
    import { tool } from "@langchain/core/tools";
    import { z } from "zod";

    const getUserInfo = tool(
      async (input: Record<string, any>, config: RunnableConfig) => {
        // highlight-next-line
        const userId = config.configurable?.userId;
        return userId === "user_123" ? "User is John Smith" : "Unknown user";
      },
      {
        name: "get_user_info",
        description: "Look up user info.",
        schema: z.object({}),
      }
    );

    const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
    const agent = createReactAgent({
      llm,
      tools: [getUserInfo],
    });

    await agent.invoke(
      { messages: "look up user information" },
      // highlight-next-line
      { configurable: { userId: "user_123" } }
    );
    ```

=== "Using state"

    ```ts
    import { initChatModel } from "langchain/chat_models/universal";
    import { createReactAgent } from "@langchain/langgraph/prebuilt";
    import { Annotation, MessagesAnnotation } from "@langchain/langgraph";
    import { tool, type ToolRuntime } from "@langchain/core/tools";
    import { z } from "zod";

    const CustomState = Annotation.Root({
      ...MessagesAnnotation.spec,
      // highlight-next-line
      userId: Annotation<string>(),
    });

    const getUserInfo = tool(
      async (
        input: Record<string, any>,
        // highlight-next-line
        runtime: ToolRuntime<typeof CustomState.State>,
      ) => {
        // Read the graph state directly from the second argument.
        // This works in web browsers too (no AsyncLocalStorage required).
        // highlight-next-line
        const userId = runtime.state.userId;
        return userId === "user_123" ? "User is John Smith" : "Unknown user";
      },
      {
        name: "get_user_info",
        description: "Look up user info.",
        schema: z.object({})
      }
    );

    const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
    const agent = createReactAgent({
      llm,
      tools: [getUserInfo],
      // highlight-next-line
      stateSchema: CustomState,
    });

    await agent.invoke(
      // highlight-next-line
      { messages: "look up user information", userId: "user_123" }
    );
    ```


## Update context from tools

Tools can modify the agent's state during execution. This is useful for persisting intermediate results or making information accessible to subsequent tools or prompts.

```
/* Detailed source-code truncated for AI context efficiency. */
```

For more details, see [how to update state from tools](../how-tos/update-state-from-tools.ipynb).

---

### Docs Agents Deployment (`docs/docs/agents/deployment.md`)

# Deployment

To deploy your LangGraph agent, create and configure a LangGraph app. This setup supports both local development and production deployments.

Features: 

* 🖥️ Local server for development
* 🧩 Studio Web UI for visual debugging
* ☁️ Cloud and 🔧 self-hosted deployment options
* 📊 LangSmith integration for tracing and observability

!!! info "Requirements" 

    - ✅ You **must** have a [LangSmith account](https://www.langchain.com/langsmith). You can sign up for **free** and get started with the free tier.

## Create a LangGraph app

```bash
npm install create-langgraph
create-langgraph path/to/your/app
```

Follow the prompts and select `New LangGraph Project`. This will create an empty LangGraph project. You can modify it by replacing the code in `src/agent/graph.ts` with your agent code. For example:

```ts
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { initChatModel } from "langchain/chat_models/universal";
import { tool } from "@langchain/core/tools";
import { z } from "zod";

const getWeather = tool(
  async (input: { city: string }) => {
    return `It's always sunny in ${input.city}!`;
  },
  {
    name: "getWeather",
    schema: z.object({
      city: z.string().describe("The city to get the weather for"),
    }),
    description: "Get weather for a given city.",
  }
);

const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
// make sure to export the graph that will be used in the LangGraph API server
// highlight-next-line
export const graph = createReactAgent({
  llm,
  tools: [getWeather],
  prompt: "You are a helpful assistant"
})
```

### Install dependencies

In the root of your new LangGraph app, install the dependencies:

```shell
yarn
# install these to use initChatModel with Anthropic
yarn add langchain
yarn add @langchain/anthropic
```

### Create an `.env` file

You will find a `.env.example` in the root of your new LangGraph app. Create
a `.env` file in the root of your new LangGraph app and copy the contents of the `.env.example` file into it, filling in the necessary API keys:

```bash
LANGSMITH_API_KEY=lsv2...
ANTHROPIC_API_KEY=sk-
```

## Launch LangGraph server locally

```shell
npx @langchain/langgraph-cli dev
```

This will start up the LangGraph API server locally. If this runs successfully, you should see something like:

>    Welcome to LangGraph.js!
> 
>    - 🚀 API: http://localhost:2024
>     
>    - 🎨 Studio UI: https://smith.langchain.com/studio/?baseUrl=http://127.0.0.1:2024

## LangGraph Studio Web UI

LangGraph Studio Web is a specialized UI that you can connect to LangGraph API server to enable visualization, interaction, and debugging of your application locally. Test your graph in the LangGraph Studio Web UI by visiting the URL provided in the output of the `npx @langchain/langgraph-cli dev` command.

>    - LangGraph Studio Web UI: https://smith.langchain.com/studio/?baseUrl=http://127.0.0.1:2024

## Deployment

Once your LangGraph app is running locally, you can deploy it using LangSmith Deployment or self-hosted options. Refer to the [deployment options guide](https://langchain-ai.github.io/langgraph/tutorials/deployment/) for detailed instructions on all supported deployment models.

---

### Docs Agents Evals (`docs/docs/agents/evals.md`)

# Evals

To evaluate your agent's performance you can use `LangSmith` [evaluations](https://docs.smith.langchain.com/evaluation). You would need to first define an evaluator function to judge the results from an agent, such as final outputs or trajectory. Depending on your evaluation technique, this may or may not involve a reference output:

```ts
const evaluator = async (params: {
  inputs: Record<string, unknown>;
  outputs: Record<string, unknown>;
  referenceOutputs?: Record<string, unknown>;
}) => {
  // compare agent outputs against reference outputs
  const outputMessages = params.outputs.messages;
  const referenceMessages = params.referenceOutputs.messages;
  const score = compareMessages(outputMessages, referenceMessages);
  return { key: "evaluator_score", score: score };
};
```

To get started, you can use prebuilt evaluators from `AgentEvals` package:

```bash
npm install agentevals @langchain/core
```

## Create evaluator

A common way to evaluate agent performance is by comparing its trajectory (the order in which it calls its tools) against a reference trajectory:

```ts
// highlight-next-line
import { createTrajectoryMatchEvaluator } from "agentevals";

const outputs = [
  {
    role: "assistant",
    tool_calls: [
      {
        function: {
          name: "get_weather",
          arguments: JSON.stringify({ city: "san francisco" }),
        },
      },
      {
        function: {
          name: "get_directions",
          arguments: JSON.stringify({ destination: "presidio" }),
        },
      },
    ],
  },
];

const referenceOutputs = [
  {
    role: "assistant",
    tool_calls: [
      {
        function: {
          name: "get_weather",
          arguments: JSON.stringify({ city: "san francisco" }),
        },
      },
    ],
  },
];

// Create the evaluator
const evaluator = createTrajectoryMatchEvaluator({
  // highlight-next-line
  trajectoryMatchMode: "superset",  // (1)!
})

// Run the evaluator
const result = await evaluator({
  outputs,
  referenceOutputs,
});
```

1. Specify how the trajectories will be compared. `superset` will accept output trajectory as valid if it's a superset of the reference one. Other options include: [strict](https://github.com/langchain-ai/agentevals?tab=readme-ov-file#strict-match), [unordered](https://github.com/langchain-ai/agentevals?tab=readme-ov-file#unordered-match) and [subset](https://github.com/langchain-ai/agentevals?tab=readme-ov-file#subset-and-superset-match)


As a next step, learn more about how to [customize trajectory match evaluator](https://github.com/langchain-ai/agentevals?tab=readme-ov-file#agent-trajectory-match).

### LLM-as-a-judge

You can use LLM-as-a-judge evaluator that uses an LLM to compare the trajectory against the reference outputs and output a score:

```ts
import {
  // highlight-next-line
  createTrajectoryLLMAsJudge,
  TRAJECTORY_ACCURACY_PROMPT_WITH_REFERENCE
} from "agentevals";

const evaluator = createTrajectoryLLMAsJudge({
  prompt: TRAJECTORY_ACCURACY_PROMPT_WITH_REFERENCE,
  model: "openai:o3-mini",
});
```

## Run evaluator

To run an evaluator, you will first need to create a [LangSmith dataset](https://docs.smith.langchain.com/evaluation/concepts#datasets). To use the prebuilt AgentEvals evaluators, you will need a dataset with the following schema:

- **input**: `{ messages: [...] }` input messages to call the agent with.
- **output**: `{ messages": [...] }` expected message history in the agent output. For trajectory evaluation, you can choose to keep only assistant messages.

```ts
import { evaluate } from "langsmith/evaluation";
import { createTrajectoryMatchEvaluator } from "agentevals";
import { createReactAgent } from "@langchain/langgraph/prebuilt";

const agent = createReactAgent({ ... })
const evaluator = createTrajectoryMatchEvaluator({ ... })
await evaluate(
  async (inputs) => await agent.invoke(inputs),
  {
    // replace with your dataset name
    data: "<Name of your dataset>",
    evaluators: [evaluator],
  }
);
```

---

### Docs Agents Human In The Loop (`docs/docs/agents/human-in-the-loop.md`)

# Human-in-the-loop

To review, edit and approve tool calls in an agent you can use LangGraph's built-in [human-in-the-loop](../concepts/human_in_the_loop.md) features, specifically the [`interrupt()`](/langgraphjs/reference/functions/langgraph.interrupt-1.html) primitive.

LangGraph allows you to pause execution **indefinitely** — for minutes, hours, or even days—until human input is received.

This is possible because the agent state is **checkpointed into a database**, which allows the system to persist execution context and later resume the workflow, continuing from where it left off.

For a deeper dive into the **human-in-the-loop** concept, see the [concept guide](../concepts/human_in_the_loop.md).

<figure markdown="1">
{: style="max-height:400px"}
<figcaption>
A human can review and edit the output from the agent before proceeding. This is particularly critical in applications where the tool calls requested may be sensitive or require human oversight.
</figcaption>
</figure>


## Review tool calls

To add a human approval step to a tool:

1. Use `interrupt()` in the tool to pause execution.
2. Resume with a `Command({ resume: ... })` to continue based on human input.

```ts
import { MemorySaver } from "@langchain/langgraph-checkpoint";
import { interrupt } from "@langchain/langgraph";
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { initChatModel } from "langchain/chat_models/universal";
import { tool } from "@langchain/core/tools";
import { z } from "zod";

// An example of a sensitive tool that requires human review / approval
const bookHotel = tool(
  async (input: { hotelName: string; }) => {
    let hotelName = input.hotelName;
    // highlight-next-line
    const response = interrupt(  // (1)!
      `Trying to call \`book_hotel\` with args {'hotel_name': ${hotelName}}. ` +
      `Please approve or suggest edits.`
    )
    if (response.type === "accept") {
      // proceed to execute the tool logic
    } else if (response.type === "edit") {
        hotelName = response.args["hotel_name"]
    } else {
        throw new Error(`Unknown response type: ${response.type}`)
    }
    return `Successfully booked a stay at ${hotelName}.`;
  },
  {
    name: "bookHotel",
    schema: z.object({
      hotelName: z.string().describe("Hotel to book"),
    }),
    description: "Book a hotel.",
  }
);

// highlight-next-line
const checkpointer = new MemorySaver();  // (2)!

const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
const agent = createReactAgent({
  llm,
  tools: [bookHotel],
  // highlight-next-line
  checkpointer  // (3)!
});
```

1. The [`interrupt` function](/langgraphjs/reference/functions/langgraph.interrupt-1.html) pauses the agent graph at a specific node. In this case, we call `interrupt()` at the beginning of the tool function, which pauses the graph at the node that executes the tool. The information inside `interrupt()` (e.g., tool calls) can be presented to a human, and the graph can be resumed with the user input (tool call approval, edit or feedback).
2. The `InMemorySaver` is used to store the agent state at every step in the tool calling loop. This enables [short-term memory](./memory.md#short-term-memory) and [human-in-the-loop](./human-in-the-loop.md) capabilities. In this example, we use `InMemorySaver` to store the agent state in memory. In a production application, the agent state will be stored in a database.
3. Initialize the agent with the `checkpointer`.

Run the agent with the `stream()` method, passing the `config` object to specify the thread ID. This allows the agent to resume the same conversation on future invocations.

```ts
const config = {
   configurable: {
      // highlight-next-line
      "thread_id": "1"
   }
}

for await (const chunk of await agent.stream(
  { messages: "book a stay at McKittrick hotel" },
  // highlight-next-line
  config
)) {
  console.log(chunk);
  console.log("\n");
};
```

> You should see that the agent runs until it reaches the `interrupt()` call, at which point it pauses and waits for human input.

Resume the agent with a `Command({ resume: ... })` to continue based on human input.

```ts
import { Command } from "@langchain/langgraph";

for await (const chunk of await agent.stream(
  new Command({ resume: { type: "accept" } }),  // (1)!
  // new Command({ resume: { type: "edit", args: { "hotel_name": "McKittrick Hotel" } } }),
  // highlight-next-line
  config
)) {
  console.log(chunk);
  console.log("\n");
};
```

1. The [`interrupt` function](/langgraphjs/reference/functions/langgraph.interrupt-1.html) is used in conjunction with the [`Command`](/langgraphjs/reference/classes/langgraph.Command.html) object to resume the graph with a value provided by the human.

## Additional resources

* [Human-in-the-loop in LangGraph](../concepts/human_in_the_loop.md)

---

### Docs Agents Mcp (`docs/docs/agents/mcp.md`)

# MCP Integration

[Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction) is an open protocol that standardizes how applications provide tools and context to language models. LangGraph agents can use tools defined on MCP servers through the `@langchain/mcp-adapters` library.



Install the `@langchain/mcp-adapters` library to use MCP tools in LangGraph:

```bash
npm install @langchain/mcp-adapters
```

## Use MCP tools

The `@langchain/mcp-adapters` package enables agents to use tools defined across one or more MCP servers.

```ts
// highlight-next-line
import { MultiServerMCPClient } from "@langchain/mcp-adapters";
import { initChatModel } from "langchain/chat_models/universal";
import { createReactAgent } from "@langchain/langgraph/prebuilt";

// highlight-next-line
const client = new MultiServerMCPClient({
  mcpServers: {
    "math": {
      command: "python",
      // Replace with absolute path to your math_server.py file
      args: ["/path/to/math_server.py"],
      transport: "stdio",
    },
    "weather": {
      // Ensure your start your weather server on port 8000
      url: "http://localhost:8000/sse",
      transport: "sse",
    }
  }
})

const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
const agent = createReactAgent({
  llm,
  // highlight-next-line
  tools: await client.getTools()
});
 
const mathResponse = await agent.invoke(
  { messages: [ { role: "user", content: "what's (3 + 5) x 12?" } ] }
);
const weatherResponse = await agent.invoke(
  { messages: [ { role: "user", content: "what is the weather in nyc?" } ] }
);
await client.close();
```

## Custom MCP servers

To create your own MCP servers, you can use the `mcp` library in Python (or `@modelcontextprotocol/sdk` in TypeScript). These libraries provide a simple way to define tools and run them as servers.

Install the MCP library:

```bash
pip install mcp
```
Use the following reference implementations to test your agent with MCP tool servers.

```python title="Example Math Server (stdio transport)"
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("Math")

@mcp.tool()
def add(a: int, b: int) -> int:
    """Add two numbers"""
    return a + b

@mcp.tool()
def multiply(a: int, b: int) -> int:
    """Multiply two numbers"""
    return a * b

if __name__ == "__main__":
    mcp.run(transport="stdio")
```

```python title="Example Weather Server (SSE transport)"
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("Weather")

@mcp.tool()
async def get_weather(location: str) -> str:
    """Get weather for location."""
    return "It's always sunny in New York"

if __name__ == "__main__":
    mcp.run(transport="sse")
```

## Additional resources

- [MCP documentation](https://modelcontextprotocol.io/introduction)
- [MCP Transport documentation](https://modelcontextprotocol.io/docs/concepts/transports)

---

### Docs Agents Memory (`docs/docs/agents/memory.md`)

# Memory

LangGraph supports two types of memory essential for building conversational agents:

- **[Short-term memory](#short-term-memory)**: Tracks the ongoing conversation by maintaining message history within a session.
- **[Long-term memory](#long-term-memory)**: Stores user-specific or application-level data across sessions.

This guide demonstrates how to use both memory types with agents in LangGraph. For a deeper
understanding of memory concepts, refer to the [LangGraph memory documentation](../concepts/memory.md).

<figure markdown="1">
{: style="max-height:400px"}
<figcaption>Both <strong>short-term</strong> and <strong>long-term</strong> memory require persistent storage to maintain continuity across LLM interactions. In production environments, this data is typically stored in a database.</figcaption>
</figure>

!!! note "Terminology"

    In LangGraph:

    - *Short-term memory* is also referred to as **thread-level memory**.
    - *Long-term memory* is also called **cross-thread memory**.

    A [thread](../concepts/persistence.md#threads) represents a sequence of related runs
    grouped by the same `thread_id`.

## Short-term memory

Short-term memory enables agents to track multi-turn conversations. To use it, you must:

1. Provide a `checkpointer` when creating the agent. The `checkpointer` enables [persistence](../concepts/persistence.md) of the agent's state.
2. Supply a `thread_id` in the config when running the agent. The `thread_id` is a unique identifier for the conversation session.

```ts
// highlight-next-line
import { MemorySaver } from "@langchain/langgraph-checkpoint";
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { initChatModel } from "langchain/chat_models/universal";
import { tool } from "@langchain/core/tools";
import { z } from "zod";

// highlight-next-line
const checkpointer = new MemorySaver();  // (1)!

const getWeather = tool(
  async (input: { city: string }) => {
    return `It's always sunny in ${input.city}!`;
  },
  {
    name: "getWeather",
    schema: z.object({
      city: z.string().describe("The city to get the weather for"),
    }),
    description: "Get weather for a given city.",
  }
);

const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
const agent = createReactAgent({
  llm,
  tools: [getWeather],
  // highlight-next-line
  checkpointer  // (2)!
});

// Run the agent
// highlight-next-line
const config = { configurable: { thread_id: "1" } };  // (3)!
const sfResponse = await agent.invoke(
  { messages: [ { role: "user", content: "what is the weather in sf" } ] },
  config  // (4)!
);
const nyResponse = await agent.invoke(
  { messages: [ { role: "user", content: "what about new york?" } ] },
  config
);
```

1. The `MemorySaver` is a checkpointer that stores the agent's state in memory. In a production setting, you would typically use a database or other persistent storage. Please review the [checkpointer documentation](https://langchain-ai.github.io/langgraphjs/reference/index.html) for more options. If you're deploying with **LangGraph Platform**, the platform will provide a production-ready checkpointer for you.
2. The `checkpointer` is passed to the agent. This enables the agent to persist its state across invocations. Please note that 
3. A unique `thread_id` is provided in the config. This ID is used to identify the conversation session. The value is controlled by the user and can be any string.
4. The agent will continue the conversation using the same `thread_id`. This will allow the agent to infer that the user is asking specifically about the **weather** in New York. 

When the agent is invoked the second time with the same `thread_id`, the original message history from the first conversation is automatically included, allowing the agent to infer that the user is asking specifically about the **weather** in New York.

!!! Note "LangGraph Platform providers a production-ready checkpointer"

    If you're using [LangGraph Platform](./deployment.md), during deployment your checkpointer will be automatically configured to use a production-ready database.

## Long-term memory

Use long-term memory to store user-specific or application-specific data across conversations. This is useful for applications like chatbots, where you want to remember user preferences or other information.

To use long-term memory, you need to:

1. [Configure a store](../how-tos/cross-thread-persistence.ipynb) to persist data across invocations.
2. Use the `config.store` to access the store from within tools or prompts.

### Reading

```
/* Detailed source-code truncated for AI context efficiency. */
```

1. The `InMemoryStore` is a store that stores data in memory. In a production setting, you would typically use a database or other persistent storage. Please review the [documentation](https://langchain-ai.github.io/langgraphjs/reference/index.html) for more options. If you're deploying with **LangGraph Platform**, the platform will provide a production-ready store for you.
2. For this example, we write some sample data to the store using the `put` method. Please see the [BaseStore.put](https://langchain-ai.github.io/langgraphjs/reference/classes/checkpoint.BaseStore.html#put) API reference for more details.
3. The first argument is the namespace. This is used to group related data together. In this case, we are using the `users` namespace to group user data.
4. A key within the namespace. This example uses a user ID for the key.
5. The data that we want to store for the given user.
6. You can access the store via `config.store` from anywhere in your nodes, tools and prompts. It contains the store that was passed to the agent when it was created.
7. The `get` method is used to retrieve data from the store. The first argument is the namespace, and the second argument is the key. This will return a `StoreValue` object, which contains the value and metadata about the value.
8. The `store` is passed to the agent. This enables the agent to access the store when running tools.

### Writing

```
/* Detailed source-code truncated for AI context efficiency. */
```

1. The `InMemoryStore` is a store that stores data in memory. In a production setting, you would typically use a database or other persistent storage. Please review the [store documentation](../reference/stores.md) for more options. If you're deploying with **LangGraph Platform**, the platform will provide a production-ready store for you.
2. The `UserInfo` class is an interface that defines the structure of the user information. We will specify the same schema below using a zod object, so that the LLM formats the response according to the schema.
3. The `saveUserInfo` is a tool that allows an agent to update user information. This could be useful for a chat application where the user wants to update their profile information.
4. You can access the store via `config.store` from anywhere in your nodes, tools and prompts. It contains the store that was passed to the agent when it was created.
5. The `put` method is used to store data in the store. The first argument is the namespace, and the second argument is the key. This will store the user information in the store.
6. The `userId` is passed in the config. This is used to identify the user whose information is being updated.

## Additional resources

* [Memory in LangGraph](../concepts/memory.md)

---

### Docs Agents Models (`docs/docs/agents/models.md`)

# Models

This page describes how to configure the chat model used by an agent.

## Tool calling support

To enable tool-calling agents, the underlying LLM must support [tool calling](https://js.langchain.com/docs/concepts/tool_calling/).

Compatible models can be found in the [LangChain integrations directory](https://js.langchain.com/docs/integrations/chat/).

## Using `initChatModel`

The [`initChatModel`](https://js.langchain.com/docs/how_to/chat_models_universal_init/) utility simplifies model initialization with configurable parameters:

```ts
import { initChatModel } from "langchain/chat_models/universal";

const llm = await initChatModel(
  "anthropic:claude-3-7-sonnet-latest",
  {
    temperature: 0,
    maxTokens: 2048
  }
);
```

Refer to the [API reference](https://api.js.langchain.com/functions/langchain.chat_models_universal.initChatModel.html) for advanced options.

## Using provider-specific LLMs 

If a model provider is not available via `initChatModel`, you can instantiate the provider's model class directly. The model must implement the [`BaseChatModel`](https://api.js.langchain.com/classes/_langchain_core.language_models_chat_models.BaseChatModel.html) interface and support tool calling:

```ts
import { ChatAnthropic } from "@langchain/anthropic";
import { createReactAgent } from "@langchain/langgraph/prebuilt";

// highlight-next-line
const llm = new ChatAnthropic({
  modelName: "claude-3-7-sonnet-latest",
  temperature: 0,
  maxTokens: 2048
});

const agent = createReactAgent({
  // highlight-next-line
  llm,
  // other parameters
});
```

!!! note "Illustrative example" 

    The example above uses `ChatAnthropic`, which is already supported by `initChatModel`. This pattern is shown to illustrate how to manually instantiate a model not available through `initChatModel`.

## Additional resources

- [Model integration directory](https://js.langchain.com/docs/integrations/chat/)
- [Universal initialization with `initChatModel`](https://js.langchain.com/docs/how_to/chat_models_universal_init/)

---

### Docs Agents Multi Agent (`docs/docs/agents/multi-agent.md`)

# Multi-agent

A single agent might struggle if it needs to specialize in multiple domains or manage many tools. To tackle this, you can break your agent into smaller, independent agents and composing them into a [multi-agent system](../concepts/multi_agent.md).

In multi-agent systems, agents need to communicate between each other. They do so via [handoffs](#handoffs) — a primitive that describes which agent to hand control to and the payload to send to that agent.

Two of the most popular multi-agent architectures are:

- [supervisor](#supervisor) — individual agents are coordinated by a central supervisor agent. The supervisor controls all communication flow and task delegation, making decisions about which agent to invoke based on the current context and task requirements.
- [swarm](#swarm) — agents dynamically hand off control to one another based on their specializations. The system remembers which agent was last active, ensuring that on subsequent interactions, the conversation resumes with that agent.

## Supervisor



Use [`langgraph-supervisor`](https://github.com/langchain-ai/langgraphjs/tree/main/libs/langgraph-supervisor) library to create a supervisor multi-agent system:

```bash
npm install @langchain/langgraph-supervisor
```

```
/* Detailed source-code truncated for AI context efficiency. */
```

## Swarm



Use [`langgraph-swarm`](https://github.com/langchain-ai/langgraphjs/tree/main/libs/langgraph-swarm) library to create a swarm multi-agent system:

```bash
npm install @langchain/langgraph-swarm
```

```ts
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { ChatAnthropic } from "@langchain/anthropic";
// highlight-next-line
import { createSwarm, createHandoffTool } from "@langchain/langgraph-swarm";

const transferToHotelAssistant = createHandoffTool({
  agentName: "hotel_assistant",
  description: "Transfer user to the hotel-booking assistant.",
});

const transferToFlightAssistant = createHandoffTool({
  agentName: "flight_assistant",
  description: "Transfer user to the flight-booking assistant.",
});


const llm = new ChatAnthropic({ modelName: "claude-3-5-sonnet-latest" });

const flightAssistant = createReactAgent({
  llm,
  tools: [bookFlight, transferToHotelAssistant],
  prompt: "You are a flight booking assistant",
  name: "flight_assistant",
});

const hotelAssistant = createReactAgent({
  llm,
  tools: [bookHotel, transferToFlightAssistant],
  prompt: "You are a hotel booking assistant",
  name: "hotel_assistant",
});

// highlight-next-line
const swarm = createSwarm({
  agents: [flightAssistant, hotelAssistant],
  defaultActiveAgent: "flight_assistant",
}).compile();

const stream = await swarm.stream({
  messages: [{
    role: "user",
    content: "first book a flight from BOS to JFK and then book a stay at McKittrick Hotel"
  }]
});

for await (const chunk of stream) {
  console.log(chunk);
  console.log("\n");
}
```

## Handoffs

A common pattern in multi-agent interactions is **handoffs**, where one agent *hands off* control to another. Handoffs allow you to specify:

- **destination**: target agent to navigate to
- **payload**: information to pass to that agent

This is used both by `langgraph-supervisor` (supervisor hands off to individual agents) and `langgraph-swarm` (an individual agent can hand off to other agents).

To implement handoffs with `createReactAgent`, you need to:

1. Create a special tool that can transfer control to a different agent

    ```ts
    const transferToBob = tool(
      async (_) => {
        return new Command({
          // name of the agent (node) to go to
          // highlight-next-line
          goto: "bob",
          // data to send to the agent
          // highlight-next-line
          update: { messages: ... },
          // indicate to LangGraph that we need to navigate to
          // agent node in a parent graph
          // highlight-next-line
          graph: Command.PARENT,
        });
      },
      {
        name: ...,
        schema: ...,
        description: ...
      }
    );
    ```

1. Create individual agents that have access to handoff tools:

    ```ts
    const flightAssistant = createReactAgent(
      ..., tools: [bookFlight, transferToHotelAssistant]
    )
    const hotelAssistant = createReactAgent(
      ..., tools=[bookHotel, transferToFlightAssistant]
    )
    ```

1. Define a parent graph that contains individual agents as nodes:

    ```ts
    import { StateGraph, MessagesAnnotation } from "@langchain/langgraph";

    const multiAgentGraph = new StateGraph(MessagesAnnotation)
      .addNode("flight_assistant", flightAssistant)
      .addNode("hotel_assistant", hotelAssistant)
      ...
    ```

Putting this together, here is how you can implement a simple multi-agent system with two agents — a flight booking assistant and a hotel booking assistant:

```
/* Detailed source-code truncated for AI context efficiency. */
```

1. Access agent's state
2. The `Command` primitive allows specifying a state update and a node transition as a single operation, making it useful for implementing handoffs.
3. Name of the agent or node to hand off to.
4. Take the agent's messages and **add** them to the parent's **state** as part of the handoff. The next agent will see the parent state.
5. Indicate to LangGraph that we need to navigate to agent node in a **parent** multi-agent graph.

!!! Note
    This handoff implementation assumes that:

    - each agent receives overall message history (across all agents) in the multi-agent system as its input
    - each agent outputs its internal messages history to the overall message history of the multi-agent system

    Check out LangGraph [supervisor](https://github.com/langchain-ai/langgraph-supervisor-py#customizing-handoff-tools) and [swarm](https://github.com/langchain-ai/langgraph-swarm-py#customizing-handoff-tools) documentation to learn how to customize handoffs.

---

### Docs Agents Prebuilt (`docs/docs/agents/prebuilt.md`)

# Community Agents

To share your project, simply open a Pull Request adding an entry for your package in our [packages.yml](https://github.com/langchain-ai/langgraph/blob/main/docs/_scripts/third_party_page/packages.yml) file.

[//]: # (This file is stub. Do not edit this file directly!)
[//]: # (1. Update the `packages.yml` file in the `docs/_scripts/third_party_page` directory.)
[//]: # (2. From the /docs directory, run `make build-prebuilt` to generate an updated version of this file for testing locally.)

---

### Docs Agents Run Agents (`docs/docs/agents/run_agents.md`)

# Running agents


Agents support execution using either `.invoke()` for full responses, or `.stream()` for **incremental** [streaming](#streaming-output) of the output. This section explains how to provide input, interpret output, enable streaming, and control execution limits.


## Basic usage

Agents can be executed using `.invoke()`:

```ts
import { createReactAgent } from "@langchain/langgraph/prebuilt";

const agent = createReactAgent(...);

// highlight-next-line
const response = await agent.invoke(
  { messages: [ { role: "user", content: "what is the weather in sf" } ] }
);
```

## Inputs and outputs

Agents use a language model that expects a list of `messages` as an input. Therefore, agent inputs and outputs are stored as a list of `messages` under the `messages` key in the agent [state](../concepts/low_level.md#working-with-messages-in-graph-state).

## Input format

Agent input must be an object with a `messages` key. Supported formats are:

| Format             | Example                                                                                                                       |
|--------------------|-------------------------------------------------------------------------------------------------------------------------------|
| String             | `{ messages: "Hello" }`  — Interpreted as a [HumanMessage](https://js.langchain.com/docs/concepts/messages/#humanmessage) |
| Message object | `{ messages: { "role": "user", "content": "Hello" } }`                                                                          |
| List of messages   | `{ messages: [ {"role": "user", "content": "Hello" } ] }`                                                                        |
| With custom state  | `{ messages: [ {"role": "user", "content": "Hello"} ], "user_name": "Alice" }` — If using a custom `stateSchema`               |

Messages are automatically converted into LangChain's internal message format. You can read
more about [LangChain messages](https://js.langchain.com/docs/concepts/messages/#langchain-messages) in the LangChain documentation.

!!! tip "Using custom agent state"

    You can provide additional fields defined in your agent's state schema directly in the input dictionary. This allows dynamic behavior based on runtime data or prior tool outputs.  
    See the [context guide](./context.md) for full details.

!!! note

    A string input for `messages` is converted to a [HumanMessage](https://js.langchain.com/docs/concepts/messages/#humanmessage). This behavior differs from the `prompt` parameter in `createReactAgent`, which is interpreted as a [SystemMessage](https://js.langchain.com/docs/concepts/messages/#systemmessage) when passed as a string.


## Output format

Agent output is a dictionary containing:

- `messages`: A list of all messages exchanged during execution (user input, assistant replies, tool invocations).
- Optionally, `structuredResponse` if [structured output](./agents.md#structured-output) is configured.
- If using a custom `stateSchema`, additional keys corresponding to your defined fields may also be present in the output. These can hold updated state values from tool execution or prompt logic.

See the [context guide](./context.md) for more details on working with custom state schemas and accessing context.

## Streaming output

Agents support streaming responses for more responsive applications. This includes:

- **Progress updates** after each step
- **LLM tokens** as they're generated
- **Custom tool messages** during execution

Streaming is available in both sync and async modes:

```ts
for await (
  const chunk of await agent.stream(
    { messages: [ { role: "user", content: "what is the weather in sf" } ] },
    { streamMode: "updates" },
  )
) {
  console.log(chunk);
}
```

!!! tip

    For full details, see the [streaming guide](./streaming.md).

## Max iterations

To control agent execution and avoid infinite loops, set a recursion limit. This defines the maximum number of steps the agent can take before raising a `GraphRecursionError`. You can configure `recursionLimit` at runtime or when defining agent via `.withConfig()`:

=== "Runtime"

    ```ts
    import { GraphRecursionError } from "@langchain/langgraph";
    import { createReactAgent } from "@langchain/langgraph/prebuilt";
    import { initChatModel } from "langchain/chat_models/universal";

    const maxIterations = 3;
    // highlight-next-line
    const recursionLimit = 2 * maxIterations + 1;
    const llm = await initChatModel("anthropic:claude-3-5-haiku-latest");
    const agent = createReactAgent({
      llm,
      tools: [getWeather]
    });

    try {
      const response = await agent.invoke(
        { messages: [ { role: "user", content: "what's the weather in sf" } ] },
        // highlight-next-line
        { recursionLimit }
      );
    } catch (error) {
      if (error instanceof GraphRecursionError) {
        console.log("Agent stopped due to max iterations.");
      } else {
        throw error;
      }
    }
    ```

=== "`.withConfig()`"

    ```ts
    import { GraphRecursionError } from "@langchain/langgraph";
    import { createReactAgent } from "@langchain/langgraph/prebuilt";
    import { initChatModel } from "langchain/chat_models/universal";

    const maxIterations = 3;
    // highlight-next-line
    const recursionLimit = 2 * maxIterations + 1;
    const llm = await initChatModel("anthropic:claude-3-5-haiku-latest");
    const agent = createReactAgent({
      llm,
      tools: [getWeather]
    });
    // highlight-next-line
    const agentWithRecursionLimit = agent.withConfig({ recursionLimit });

    try {
      const response = await agentWithRecursionLimit.invoke(
        { messages: [ { role: "user", content: "what's the weather in sf" } ] }
      );
    } catch (error) {
      if (error instanceof GraphRecursionError) {
        console.log("Agent stopped due to max iterations.");
      } else {
        throw error;
      }
    }
    ```

---

### Docs Agents Streaming (`docs/docs/agents/streaming.md`)

# Streaming

Streaming is key to building responsive applications. There are a few types of data you’ll want to stream:

1. [**Agent progress**](#agent-progress) — get updates after each node in the agent graph is executed.
2. [**LLM tokens**](#llm-tokens) — stream tokens as they are generated by the language model.
3. [**Custom updates**](#tool-updates) — emit custom data from tools during execution (e.g., "Fetched 10/100 records")

You can stream [more than one type of data](#stream-multiple-modes) at a time. 


<figure markdown="1">
{: style="max-height:300px"}
<figcaption>
Waiting is for pigeons.
</figcaption>
</figure>

## Agent progress

To stream agent progress, use the [`stream()`](/langgraphjs/reference/classes/langgraph.CompiledStateGraph.html#stream) method with `streamMode: "updates"`. This emits an event after every agent step.

For example, if you have an agent that calls a tool once, you should see the following updates:

* **LLM node**: AI message with tool call requests
* **Tool node**: Tool message with execution result
* **LLM node**: Final AI response

```ts
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { initChatModel } from "langchain/chat_models/universal";

const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
const agent = createReactAgent({
  llm,
  tools: [getWeather],
});
// highlight-next-line
for await (const chunk of await agent.stream(
  { messages: "what is the weather in sf" },
  // highlight-next-line
  { streamMode: "updates" }
)) {
  console.log(chunk);
  console.log("\n");
}
```

## LLM tokens

To stream tokens as they are produced by the LLM, use `streamMode: "messages"`:

```ts
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { initChatModel } from "langchain/chat_models/universal";

const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
const agent = createReactAgent({
  llm,
  tools: [getWeather],
});
// highlight-next-line
for await (const [token, metadata] of await agent.stream(
  { messages: "what is the weather in sf" },
  // highlight-next-line
  { streamMode: "messages" }
)) {
  console.log("Token", token);
  console.log("Metadata", metadata);
  console.log("\n");
}
```

## Tool updates

To stream updates from tools as they are executed, you can use `writer` object available via `config.writer`:

```ts
import { LangGraphRunnableConfig } from "@langchain/langgraph";
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { initChatModel } from "langchain/chat_models/universal";

const getWeather = tool(
  async (input: { city: string }, config: LangGraphRunnableConfig) => {
    // stream any arbitrary data
    // highlight-next-line
    config.writer?.(`Looking up data for city: ${input.city}`);
    return `It's always sunny in ${input.city}!`;
  },
  {
    name: "getWeather",
    schema: z.object({
      city: z.string().describe("The city to get the weather for"),
    }),
    description: "Get weather for a given city.",
  }
);

const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
const agent = createReactAgent({
  llm,
  tools: [getWeather],
});

for await (const chunk of await agent.stream(
  { messages: "what is the weather in sf" },
  // highlight-next-line
  { streamMode: "custom" }
)) {
  console.log(chunk);
  console.log("\n");
}
```

## Stream multiple modes

You can specify multiple streaming modes by passing stream mode as a list: `streamMode: ["updates", "messages", "custom"]`:

```ts
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { initChatModel } from "langchain/chat_models/universal";

const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
const agent = createReactAgent({
  llm,
  tools: [getWeather],
});

for await (const [streamMode, chunk] of await agent.stream(
  { messages: "what is the weather in sf" },
  // highlight-next-line
  { streamMode: ["updates", "messages", "custom"] }
)) {
  console.log(streamMode, chunk);
  console.log("\n");
}
```

## Additional resources

* [Streaming in LangGraph](https://langchain-ai.github.io/langgraphjs/how-tos/#streaming)

---

### Docs Agents Tools (`docs/docs/agents/tools.md`)

# Tools

[Tools](https://js.langchain.com/docs/concepts/tools/) are a way to encapsulate a function and its input schema in a way that can be passed to a chat model that supports tool calling. This allows the model to request the execution of this function with specific inputs.

You can either [define your own tools](#define-tools) or use [prebuilt integrations](#prebuilt-tools) that LangChain provides.

## Define tools

You create tools using the [`tool`](https://api.js.langchain.com/functions/_langchain_core.tools.tool-1.html) function:

```ts
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { initChatModel } from "langchain/chat_models/universal";
// highlight-next-line
import { tool } from "@langchain/core/tools";
import { z } from "zod";

const multiply = tool(
  async (input: { a: number; b: number }) => {
    return input.a * input.b;
  },
  {
    name: "multiply",
    schema: z.object({
      a: z.number().describe("First operand"),
      b: z.number().describe("Second operand"),
    }),
    description: "Multiply two numbers.",
  }
);

const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
const agent = createReactAgent({
  llm,
  tools: [multiply],
});
```

For additional customization, refer to the [custom tools guide](https://js.langchain.com/docs/how_to/custom_tools/).

## Hide arguments from the model

Some tools require runtime-only arguments (e.g., user ID or session context) that should not be controllable by the model.

You can put these arguments in the `state` or `config` of the agent, and access
this information inside the tool:

```ts
import { z } from "zod";
import { tool, type ToolRuntime } from "@langchain/core/tools";
// highlight-next-line
import { MessagesAnnotation } from "@langchain/langgraph";

const myTool = tool(
  async (
    input: {
      // This will be populated by an LLM
      toolArg: string;
    },
    // access runtime values from the second argument
    // highlight-next-line
    runtime: ToolRuntime<typeof MessagesAnnotation.State>
  ) => {
    // Fetch the current agent state
    // highlight-next-line
    const state = runtime.state;
    doSomethingWithState(state.messages);
    doSomethingWithConfig(runtime.config);
    // ...
  },
  {
    name: "myTool",
    schema: z.object({
      myToolArg: z.number().describe("Tool arg"),
    }),
    description: "My tool.",
  }
);
```

## Disable parallel tool calling

Some model providers support executing multiple tools in parallel, but
allow users to disable this feature.

For supported providers, you can disable parallel tool calling by setting `parallel_tool_calls: false` via the `model.bindTools()` method:

```ts
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { ChatOpenAI } from "@langchain/openai";
import { tool } from "@langchain/core/tools";
import { z } from "zod";

const add = tool(
  async (input: { a: number; b: number }) => {
    return input.a + input.b;
  },
  {
    name: "add",
    schema: z.object({
      a: z.number().describe("First operand"),
      b: z.number().describe("Second operand"),
    }),
    description: "Add two numbers.",
  }
);

const multiply = tool(
  async (input: { a: number; b: number }) => {
    return input.a * input.b;
  },
  {
    name: "multiply",
    schema: z.object({
      a: z.number().describe("First operand"),
      b: z.number().describe("Second operand"),
    }),
    description: "Multiply two numbers.",
  }
);

const llm = new ChatOpenAI({ model: "gpt-4.1" });

const tools = [add, multiply];
const agent = createReactAgent({
  // disable parallel tool calls
  // highlight-next-line
  llm: llm.bindTools(tools, { parallel_tool_calls: false }),
  tools,
});

const response = await agent.invoke({
  messages: [{ role: "user", content: "what's 3 + 5 and 4 * 7?" }],
});
```

## Return tool results directly

Use `returnDirect: true` to return tool results immediately and stop the agent loop:

```ts
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { initChatModel } from "langchain/chat_models/universal";
import { tool } from "@langchain/core/tools";
import { z } from "zod";

const add = tool(
  async (input: { a: number; b: number }) => {
    return input.a + input.b;
  },
  {
    name: "add",
    schema: z.object({
      a: z.number().describe("First operand"),
      b: z.number().describe("Second operand"),
    }),
    description: "Add two numbers.",
    // highlight-next-line
    returnDirect: true,
  }
);

const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
const agent = createReactAgent({
  llm,
  tools: [add],
});

const response = await agent.invoke({
  messages: [{ role: "user", content: "what's 3 + 5?" }],
});
```

## Force tool use

To force the agent to use specific tools, you can set the `tool_choice` option in `model.bindTools()`:

```ts
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { initChatModel } from "langchain/chat_models/universal";
import { tool } from "@langchain/core/tools";
import { z } from "zod";

const greet = tool(
  async (input: { userName: string }) => {
    return `Hello ${input.userName}!`;
  },
  {
    name: "greet",
    schema: z.object({
      userName: z.string().describe("Name of the user to greet"),
    }),
    description: "Greet user.",
    // highlight-next-line
    returnDirect: true,
  }
);

const llm = new ChatAnthropic({ model: "claude-3-7-sonnet-latest" });
const tools = [greet];

const agent = createReactAgent({
  // highlight-next-line
  llm: llm.bindTools(tools, { tool_choice: { type: "tool", name: "greet" } }),
  tools,
});

const response = await agent.invoke({
  messages: "Hi, I am Bob",
});
```

!!! Warning "Avoid infinite loops"

    Forcing tool usage without stopping conditions can create infinite loops. Use one of the following safeguards:

    - Mark the tool with [`returnDirect: True`](#return-tool-results-directly) to end the loop after execution.
    - Set [`recursionLimit`](../concepts/low_level.md#recursion-limit) to restrict the number of execution steps.

## Handle tool errors

By default, the agent will catch all exceptions raised during tool calls and will pass those as tool messages to the LLM. To control how the errors are handled, you can use the prebuilt [`ToolNode`](https://langchain-ai.github.io/langgraphjs/reference/classes/langgraph_prebuilt.ToolNode.html) — the node that executes tools inside `createReactAgent` — via its `handleToolErrors` parameter:

=== "Enable error handling (default)"

    ```ts
    import { createReactAgent } from "@langchain/langgraph/prebuilt";
    import { initChatModel } from "langchain/chat_models/universal";
    import { tool } from "@langchain/core/tools";
    import { z } from "zod";

    const multiply = tool(
      async (input: { a: number; b: number }) => {
        if (input.a === 42) {
          throw new Error("The ultimate error");
        }
        return input.a * input.b;
      },
      {
        name: "multiply",
        schema: z.object({
          a: z.number().describe("First operand"),
          b: z.number().describe("Second operand"),
        }),
        description: "Multiply two numbers.",
      }
    );

    // Run with error handling (default)
    const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
    const agent = createReactAgent({
      llm,
      tools: [multiply],
    });

    const response = await agent.invoke(
      { messages: [ { role: "user", content: "what's 42 x 7?" } ] }
    );
    ```

=== "Disable error handling"

    ```ts
    import { createReactAgent } from "@langchain/langgraph/prebuilt";
    import { initChatModel } from "langchain/chat_models/universal";
    import { tool } from "@langchain/core/tools";
    import { z } from "zod";
    import { ToolNode } from "@langchain/langgraph/prebuilt";

    const multiply = tool(
      async (input: { a: number; b: number }) => {
        if (input.a === 42) {
          throw new Error("The ultimate error");
        }
        return input.a * input.b;
      },
      {
        name: "multiply",
        schema: z.object({
          a: z.number().describe("First operand"),
          b: z.number().describe("Second operand"),
        }),
        description: "Multiply two numbers.",
      }
    );

    // highlight-next-line
    const toolNode = new ToolNode({
      tools: [multiply],
      // highlight-next-line
      handleToolErrors: false, // (1)!
    });

    const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
    const agentNoErrorHandling = createReactAgent({
      llm,
      tools: toolNode,
    });

    const response = await agentNoErrorHandling.invoke(
      { messages: [ { role: "user", content: "what's 42 x 7?" } ] }
    );
    ```

    1. This disables error handling (enabled by default).

## Prebuilt tools

You can use prebuilt tools from model providers by passing a dictionary with tool specs to the `tools` parameter of `createReactAgent`. For example, to use the `web_search_preview` tool from OpenAI:

```ts
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { initChatModel } from "langchain/chat_models/universal";

const llm = await initChatModel("openai:gpt-4o-mini");

const agent = createReactAgent({
  llm,
  tools: [{ type: "web_search_preview" }],
});

const response = await agent.invoke({
  messages: ["What was a positive news story from today?"],
});
```

Additionally, LangChain supports a wide range of prebuilt tool integrations for interacting with APIs, databases, file systems, web data, and more. These tools extend the functionality of agents and enable rapid development.

You can browse the full list of available integrations in the [LangChain integrations directory](https://js.langchain.com/docs/integrations/tools/).

Some commonly used tool categories include:

- **Search**: Exa, SerpAPI, Tavily
- **Code interpreters**: Python REPL
- **Databases**: SQL, MongoDB, Redis
- **Web data**: Web scraping and browsing
- **APIs**: Discord, Gmail, and others

These integrations can be configured and added to your agents using the same `tools` parameter shown in the examples above.

---

### Docs Agents Ui (`docs/docs/agents/ui.md`)

# UI

You can use a prebuilt chat UI for interacting with any LangGraph agent through the [Agent Chat UI](https://github.com/langchain-ai/agent-chat-ui). Using the [deployed version](https://agentchat.vercel.app) is the quickest way to get started, and allows you to interact with both local and deployed graphs.

## Run agent in UI

First, set up LangGraph API server [locally](./deployment.md#launch-langgraph-server-locally) or deploy your agent on [LangSmith Deployment](https://langchain-ai.github.io/langgraph/cloud/quick_start/).

Then, navigate to [Agent Chat UI](https://agentchat.vercel.app), or clone the repository and [run the dev server locally](https://github.com/langchain-ai/agent-chat-ui?tab=readme-ov-file#setup):

<video controls src="../assets/base-chat-ui.mp4" type="video/mp4"></video>

!!! Tip

    UI has out-of-box support for rendering tool calls, and tool result messages. To customize what messages are shown, see the [Hiding Messages in the Chat](https://github.com/langchain-ai/agent-chat-ui?tab=readme-ov-file#hiding-messages-in-the-chat) section in the Agent Chat UI documentation.

## Generative UI

You can also use generative UI in the Agent Chat UI.

Generative UI allows you to define [React](https://react.dev/) components, and push them to the UI from the LangGraph server. For more documentation on building generative UI LangGraph agents, read [these docs](https://langchain-ai.github.io/langgraph/cloud/how-tos/generative_ui_react/).

---

### Docs Concepts .Meta.Yml (`docs/docs/concepts/.meta.yml`)

tags:
  - concepts
  - conceptual guide
  - explanation

---

### Docs Concepts Agentic Concepts (`docs/docs/concepts/agentic_concepts.md`)

# Agent architectures

Many LLM applications implement a particular control flow of steps before and / or after LLM calls. As an example, [RAG](https://github.com/langchain-ai/rag-from-scratch) performs retrieval of relevant documents to a question, and passes those documents to an LLM in order to ground the model's response.

Instead of hard-coding a fixed control flow, we sometimes want LLM systems that can pick its own control flow to solve more complex problems! This is one definition of an [agent](https://blog.langchain.dev/what-is-an-agent/): _an agent is a system that uses an LLM to decide the control flow of an application._ There are many ways that an LLM can control application:

- An LLM can route between two potential paths
- An LLM can decide which of many tools to call
- An LLM can decide whether the generated answer is sufficient or more work is needed

As a result, there are many different types of [agent architectures](https://blog.langchain.dev/what-is-a-cognitive-architecture/), which given an LLM varying levels of control.



## Router

A router allows an LLM to select a single step from a specified set of options. This is an agent architecture that exhibits a relatively limited level of control because the LLM usually governs a single decision and can return a narrow set of outputs. Routers typically employ a few different concepts to achieve this.

### Structured Output

Structured outputs with LLMs work by providing a specific format or schema that the LLM should follow in its response. This is similar to tool calling, but more general. While tool calling typically involves selecting and using predefined functions, structured outputs can be used for any type of formatted response. Common methods to achieve structured outputs include:

1. Prompt engineering: Instructing the LLM to respond in a specific format.
2. Output parsers: Using post-processing to extract structured data from LLM responses.
3. Tool calling: Leveraging built-in tool calling capabilities of some LLMs to generate structured outputs.

Structured outputs are crucial for routing as they ensure the LLM's decision can be reliably interpreted and acted upon by the system. Learn more about [structured outputs in this how-to guide](https://js.langchain.com/docs/how_to/structured_output/).

## Tool calling agent

While a router allows an LLM to make a single decision, more complex agent architectures expand the LLM's control in two key ways:

1. Multi-step decision making: The LLM can control a sequence of decisions rather than just one.
2. Tool access: The LLM can choose from and use a variety of tools to accomplish tasks.

[ReAct](https://arxiv.org/abs/2210.03629) is a popular general purpose agent architecture that combines these expansions, integrating three core concepts.

1. `Tool calling`: Allowing the LLM to select and use various tools as needed.
2. `Memory`: Enabling the agent to retain and use information from previous steps.
3. `Planning`: Empowering the LLM to create and follow multi-step plans to achieve goals.

This architecture allows for more complex and flexible agent behaviors, going beyond simple routing to enable dynamic problem-solving across multiple steps. You can use it with [`createReactAgent`](/langgraphjs/reference/functions/langgraph_prebuilt.createReactAgent.html).

### Tool calling

Tools are useful whenever you want an agent to interact with external systems. External systems (e.g., APIs) often require a particular input schema or payload, rather than natural language. When we bind an API, for example, as a tool we given the model awareness of the required input schema. The model will choose to call a tool based upon the natural language input from the user and it will return an output that adheres to the tool's schema.

[Many LLM providers support tool calling](https://js.langchain.com/docs/integrations/chat/) and [tool calling interface](https://blog.langchain.dev/improving-core-tool-interfaces-and-docs-in-langchain/) in LangChain is simple: you can define a tool schema, and pass it into `ChatModel.bindTools([tool])`.



### Memory

Memory is crucial for agents, enabling them to retain and utilize information across multiple steps of problem-solving. It operates on different scales:

1. Short-term memory: Allows the agent to access information acquired during earlier steps in a sequence.
2. Long-term memory: Enables the agent to recall information from previous interactions, such as past messages in a conversation.

LangGraph provides full control over memory implementation:

- [`State`](./low_level.md#state): User-defined schema specifying the exact structure of memory to retain.
- [`Checkpointers`](./persistence.md): Mechanism to store state at every step across different interactions.

This flexible approach allows you to tailor the memory system to your specific agent architecture needs. For a practical guide on adding memory to your graph, see [this tutorial](/langgraphjs/how-tos/persistence).

Effective memory management enhances an agent's ability to maintain context, learn from past experiences, and make more informed decisions over time.

### Planning

In the ReAct architecture, an LLM is called repeatedly in a while-loop. At each step the agent decides which tools to call, and what the inputs to those tools should be. Those tools are then executed, and the outputs are fed back into the LLM as observations. The while-loop terminates when the agent decides it is not worth calling any more tools.

### ReAct implementation

There are several differences between this paper and the pre-built [`createReactAgent`](/langgraphjs/reference/functions/langgraph_prebuilt.createReactAgent.html) implementation:

- First, we use [tool-calling](#tool-calling) to have LLMs call tools, whereas the paper used prompting + parsing of raw output. This is because tool calling did not exist when the paper was written, but is generally better and more reliable.
- Second, we use messages to prompt the LLM, whereas the paper used string formatting. This is because at the time of writing, LLMs didn't even expose a message-based interface, whereas now that's the only interface they expose.
- Third, the paper required all inputs to the tools to be a single string. This was largely due to LLMs not being super capable at the time, and only really being able to generate a single input. Our implementation allows for using tools that require multiple inputs.
- Fourth, the paper only looks at calling a single tool at the time, largely due to limitations in LLMs performance at the time. Our implementation allows for calling multiple tools at a time.
- Finally, the paper asked the LLM to explicitly generate a "Thought" step before deciding which tools to call. This is the "Reasoning" part of "ReAct". Our implementation does not do this by default, largely because LLMs have gotten much better and that is not as necessary. Of course, if you wish to prompt it do so, you certainly can.

## Custom agent architectures

While routers and tool-calling agents (like ReAct) are common, [customizing agent architectures](https://blog.langchain.dev/why-you-should-outsource-your-agentic-infrastructure-but-own-your-cognitive-architecture/) often leads to better performance for specific tasks. LangGraph offers several powerful features for building tailored agent systems:

### Human-in-the-loop

Human involvement can significantly enhance agent reliability, especially for sensitive tasks. This can involve:

- Approving specific actions
- Providing feedback to update the agent's state
- Offering guidance in complex decision-making processes

Human-in-the-loop patterns are crucial when full automation isn't feasible or desirable. Learn more in our [human-in-the-loop guide](./human_in_the_loop.md).

### Parallelization

Parallel processing is vital for efficient multi-agent systems and complex tasks. LangGraph supports parallelization through its [Send](./low_level.md#send) API, enabling:

- Concurrent processing of multiple states
- Implementation of map-reduce-like operations
- Efficient handling of independent subtasks

For practical implementation, see our [map-reduce tutorial](/langgraphjs/how-tos/map-reduce/).

### Subgraphs

[Subgraphs](./low_level.md#subgraphs) are essential for managing complex agent architectures, particularly in [multi-agent systems](./multi_agent.md). They allow:

- Isolated state management for individual agents
- Hierarchical organization of agent teams
- Controlled communication between agents and the main system

Subgraphs communicate with the parent graph through overlapping keys in the state schema. This enables flexible, modular agent design. For implementation details, refer to our [subgraph how-to guide](../how-tos/subgraph.ipynb).

### Reflection

Reflection mechanisms can significantly improve agent reliability by:

1. Evaluating task completion and correctness
2. Providing feedback for iterative improvement
3. Enabling self-correction and learning

While often LLM-based, reflection can also use deterministic methods. For instance, in coding tasks, compilation errors can serve as feedback. This approach is demonstrated in [this video using LangGraph for self-corrective code generation](https://www.youtube.com/watch?v=MvNdgmM7uyc).

By leveraging these features, LangGraph enables the creation of sophisticated, task-specific agent architectures that can handle complex workflows, collaborate effectively, and continuously improve their performance.

---

### Docs Concepts Application Structure (`docs/docs/concepts/application_structure.md`)

# Application Structure

!!! info "Prerequisites"

    - [LangGraph Server](./langgraph_server.md)
    - [LangGraph Glossary](./low_level.md)

## Overview

A LangGraph application consists of one or more graphs, a LangGraph API Configuration file (`langgraph.json`), a file that specifies dependencies, and an optional .env file that specifies environment variables.

This guide shows a typical structure for a LangGraph application and shows how the required information to deploy a LangGraph application using the LangGraph Platform is specified.

## Key Concepts

To deploy using the LangGraph Platform, the following information should be provided:

1. A [LangGraph API Configuration file](#configuration-file) (`langgraph.json`) that specifies the dependencies, graphs, environment variables to use for the application.
2. The [graphs](#graphs) that implement the logic of the application.
3. A file that specifies [dependencies](#dependencies) required to run the application.
4. [Environment variable](#environment-variables) that are required for the application to run.

## File Structure

Below are examples of directory structures for Python and JavaScript applications:

=== "JS (package.json)"

    ```plaintext
    my-app/
    ├── src # all project code lies within here
    │   ├── utils # optional utilities for your graph
    │   │   ├── tools.ts # tools for your graph
    │   │   ├── nodes.ts # node functions for your graph
    │   │   └── state.ts # state definition of your graph
    │   └── agent.ts # code for constructing your graph
    ├── package.json # package dependencies
    ├── .env # environment variables
    └── langgraph.json # configuration file for LangGraph
    ```

=== "Python (requirements.txt)"

    ```plaintext
    my-app/
    ├── my_agent # all project code lies within here
    │   ├── utils # utilities for your graph
    │   │   ├── __init__.py
    │   │   ├── tools.py # tools for your graph
    │   │   ├── nodes.py # node functions for your graph
    │   │   └── state.py # state definition of your graph
    │   ├── requirements.txt # package dependencies
    │   ├── __init__.py
    │   └── agent.py # code for constructing your graph
    ├── .env # environment variables
    └── langgraph.json # configuration file for LangGraph
    ```

=== "Python (pyproject.toml)"

    ```plaintext
    my-app/
    ├── my_agent # all project code lies within here
    │   ├── utils # utilities for your graph
    │   │   ├── __init__.py
    │   │   ├── tools.py # tools for your graph
    │   │   ├── nodes.py # node functions for your graph
    │   │   └── state.py # state definition of your graph
    │   ├── __init__.py
    │   └── agent.py # code for constructing your graph
    ├── .env # environment variables
    ├── langgraph.json  # configuration file for LangGraph
    └── pyproject.toml # dependencies for your project
    ```

!!! note

    The directory structure of a LangGraph application can vary depending on the programming language and the package manager used.

## Configuration File

The `langgraph.json` file is a JSON file that specifies the dependencies, graphs, environment variables, and other settings required to deploy a LangGraph application.

The file supports specification of the following information:

| Key                | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `dependencies`     | **Required**. Array of dependencies for LangGraph API server. Dependencies can be one of the following: (1) `"."`, which will look for local Python packages, (2) `pyproject.toml`, `setup.py` or `requirements.txt` in the app directory `"./local_package"`, or (3) a package name.                                                                                                                                                                                                                                                        |
| `graphs`           | **Required**. Mapping from graph ID to path where the compiled graph or a function that makes a graph is defined. Example: <ul><li>`./your_package/your_file.py:variable`, where `variable` is an instance of `langgraph.graph.state.CompiledStateGraph`</li><li>`./your_package/your_file.py:make_graph`, where `make_graph` is a function that takes a config dictionary (`langchain_core.runnables.RunnableConfig`) and creates an instance of `langgraph.graph.state.StateGraph` / `langgraph.graph.state.CompiledStateGraph`.</li></ul> |
| `env`              | Path to `.env` file or a mapping from environment variable to its value.                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `node_version`     | Defaults to `20`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `dockerfile_lines` | Array of additional lines to add to Dockerfile following the import from parent image.                                                                                                                                                                                                                                                                                                                                                                                                                                                       |

!!! tip

    The LangGraph CLI defaults to using the configuration file **langgraph.json** in the current directory.

### Examples

=== "JavaScript"

    * The dependencies will be loaded from a dependency file in the local directory (e.g., `package.json`).
    * A single graph will be loaded from the file `./your_package/your_file.js` with the function `agent`.
    * The environment variable `OPENAI_API_KEY` is set inline.

    ```json
    {
        "dependencies": [
          "."
        ],
        "graphs": {
          "my_agent": "./your_package/your_file.js:agent"
        },
        "env": {
          "OPENAI_API_KEY": "secret-key"
        }
    }
    ```

=== "Python"

    * The dependencies involve a custom local package and the `langchain_openai` package.
    * A single graph will be loaded from the file `./your_package/your_file.py` with the variable `variable`.
    * The environment variables are loaded from the `.env` file.

    ```json
    {
        "dependencies": [
            "langchain_openai",
            "./your_package"
        ],
        "graphs": {
            "my_agent": "./your_package/your_file.py:agent"
        },
        "env": "./.env"
    }
    ```

## Dependencies

A LangGraph application may depend on other Python packages or JavaScript libraries (depending on the programming language in which the application is written).

You will generally need to specify the following information for dependencies to be set up correctly:

1. A file in the directory that specifies the dependencies (e.g., `requirements.txt`, `pyproject.toml`, or `package.json`).
2. A `dependencies` key in the [LangGraph configuration file](#configuration-file) that specifies the dependencies required to run the LangGraph application.
3. Any additional binaries or system libraries can be specified using `dockerfile_lines` key in the [LangGraph configuration file](#configuration-file).

## Graphs

Use the `graphs` key in the [LangGraph configuration file](#configuration-file) to specify which graphs will be available in the deployed LangGraph application.

You can specify one or more graphs in the configuration file. Each graph is identified by a name (which should be unique) and a path for either: (1) the compiled graph or (2) a function that makes a graph is defined.

## Environment Variables

If you're working with a deployed LangGraph application locally, you can configure environment variables in the `env` key of the [LangGraph configuration file](#configuration-file).

For a production deployment, you will typically want to configure the environment variables in the deployment environment.

## Related

Please see the following resources for more information:

- How-to guides for [Application Structure](../how-tos/index.md#application-structure).

---

### Docs Concepts Assistants (`docs/docs/concepts/assistants.md`)

# Assistants

!!! info "Prerequisites"

    - [LangGraph Server](./langgraph_server.md)

When building agents, it is fairly common to make rapid changes that _do not_ alter the graph logic. For example, simply changing prompts or the LLM selection can have significant impacts on the behavior of the agents. Assistants offer an easy way to make and save these types of changes to agent configuration. This can have at least two use cases:

- Assistants give developers a quick and easy way to modify and version agents for experimentation.
- Assistants can be modified via LangGraph Studio, offering a no-code way to configure agents (e.g., for business users).

Assistants build off the concept of ["configuration"](low_level.md#configuration).
While ["configuration"](low_level.md#configuration) is available in the open source LangGraph library as well, assistants are only present in [LangGraph Platform](langgraph_platform.md).
This is because Assistants are tightly coupled to your deployed graph, and so we can only make them available when we are also deploying the graphs.

## Configuring Assistants

In practice, an assistant is just an _instance_ of a graph with a specific configuration. Because of this, multiple assistants can reference the same graph but can contain different configurations, such as prompts, models, and other graph configuration options. The LangGraph Cloud API provides several endpoints for creating and managing assistants. See [this how-to](/langgraphjs/cloud/how-tos/configuration_cloud) for more details on how to create assistants.

## Versioning Assistants

Once you've created an assistant, you can save and version it to track changes to the configuration over time. You can think about this at three levels:

1) The graph lays out the general agent application logic
2) The agent configuration options represent parameters that can be changed
3) Assistant versions save and track specific settings of the agent configuration options

For example, let's imagine you have a general writing agent. You have created a general graph architecture that works well for writing. However, there are different types of writing, e.g. blogs vs tweets. In order to get the best performance on each use case, you need to make some minor changes to the models and prompts used. In this setup, you could create an assistant for each use case - one for blog writing and one for tweeting. These would share the same graph structure, but they may use different models and different prompts. Read [this how-to](/langgraphjs/cloud/how-tos/assistant_versioning) to learn how you can use assistant versioning through both the [Studio](/langgraphjs/cloud/how-tos/index/#langgraph-studio) and the SDK.




## Resources

For more information on assistants, see the following resources:

- [Assistants how-to guides](../how-tos/index.md#assistants)

---

### Docs Concepts Auth (`docs/docs/concepts/auth.md`)

# Authentication & Access Control

LangGraph Platform provides a flexible authentication and authorization system that can integrate with most authentication schemes.

## Core Concepts

### Authentication vs Authorization

While often used interchangeably, these terms represent distinct security concepts:

- [**Authentication**](#authentication) ("AuthN") verifies _who_ you are. This runs as middleware for every request.
- [**Authorization**](#authorization) ("AuthZ") determines _what you can do_. This validates the user's privileges and roles on a per-resource basis.

In LangGraph Platform, authentication is handled by your [`authenticate()`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#authenticate) handler, and authorization is handled by your [`on()`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#on) handlers.

### Default Security Models

LangGraph Platform provides different security defaults:

- LangGraph Cloud
- Self-Hosted

### LangGraph Cloud

- Uses LangSmith API keys by default
- Requires valid API key in `x-api-key` header
- Can be customized with your auth handler

!!! note "Custom auth"

    Custom auth **is supported** for all plans in LangGraph Cloud.

### Self-Hosted

- No default authentication
- Complete flexibility to implement your security model
- You control all aspects of authentication and authorization

!!! note "Custom auth"

    Custom auth is supported for **Enterprise** self-hosted plans.
    Self-hosted lite plans do not support custom auth natively.

## System Architecture

A typical authentication setup involves three main components:

1. **Authentication Provider** (Identity Provider/IdP)

   - A dedicated service that manages user identities and credentials
   - Handles user registration, login, password resets, etc.
   - Issues tokens (JWT, session tokens, etc.) after successful authentication
   - Examples: Auth0, Supabase Auth, Okta, or your own auth server

2. **LangGraph Backend** (Resource Server)

   - Your LangGraph application that contains business logic and protected resources
   - Validates tokens with the auth provider
   - Enforces access control based on user identity and permissions
   - Doesn't store user credentials directly

3. **Client Application** (Frontend)

   - Web app, mobile app, or API client
   - Collects time-sensitive user credentials and sends to auth provider
   - Receives tokens from auth provider
   - Includes these tokens in requests to LangGraph backend

Here's how these components typically interact:

```mermaid
sequenceDiagram
    participant Client as Client App
    participant Auth as Auth Provider
    participant LG as LangGraph Backend

    Client->>Auth: 1. Login (username/password)
    Auth-->>Client: 2. Return token
    Client->>LG: 3. Request with token
    Note over LG: 4. Validate token (authenticate())
    LG-->>Auth:  5. Fetch user info
    Auth-->>LG: 6. Confirm validity
    Note over LG: 7. Apply access control (on())
    LG-->>Client: 8. Return resources
```

Your [`authenticate()`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#authenticate) handler in LangGraph handles steps 4-6, while your [`on()`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#on) handlers implement step 7.

## Authentication

Authentication in LangGraph runs as middleware on every request. Your [`authenticate()`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#authenticate) handler receives request information and should:

1. Validate the credentials
2. Return user information containing the user's identity and user information if valid
3. Raise an [`HTTPException`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#class-httpexception) or an error if invalid

```typescript
import { Auth, HTTPException } from "@langchain/langgraph-sdk/auth";

// (1) Validate the credentials
const isValidKey = (key: string) => {
  return true;
};

export const auth = new Auth().authenticate(async (request: Request) => {
  const apiKey = request.headers.get("x-api-key");

  if (!apiKey || !isValidKey(apiKey)) {
    // (3) Raise an HTTPException
    throw new HTTPException(401, { message: "Invalid API key" });
  }

  // (2) Return user information containing the user's identity and user information if valid
  return {
    // required, unique user identifier
    identity: "user-123",
    // required, list of permissions
    permissions: [],
    // optional, assumed `true` by default
    is_authenticated: true,

    // You can add more custom fields if you want to implement other auth patterns
    role: "admin",
    org_id: "org-123",
  };
});
```

The returned user information is available:

- To your authorization handlers via `user` property in [`on()`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#on) callback.
- In your application via `config["configuration"]["langgraph_auth_user"]`

??? info "`Request` input parameter"

    The [`authenticate()`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#authenticate) handler accepts a [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request/Request) instance as an argument, but the `Request` object may not include the request body.

    You can still use the `Request` instance to extract other fields such as headers, query parameters etc.

## Authorization

After authentication, LangGraph calls your [`on()`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#on) handlers to control access to specific resources (e.g., threads, assistants, crons). These handlers can:

1. Add metadata to be saved during resource creation by mutating the `value["metadata"]` object directly. See the [supported actions table](#supported-actions) for the list of types the value can take for each action.
2. Filter resources by metadata during search/list or read operations by returning a [filter object](#filter-operations).
3. Raise an HTTP error if access is denied.

If you want to just implement simple user-scoped access control, you can use a single [`on()`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#on) handler for all resources and actions. If you want to have different control depending on the resource and action, you can use [resource-specific handlers](#resource-specific-handlers). See the [Supported Resources](#supported-resources) section for a full list of the resources that support access control.

```typescript
import { Auth, HTTPException } from "@langchain/langgraph-sdk/auth";

export const auth = new Auth()
  .authenticate(async (request: Request) => ({
    identity: "user-123",
    permissions: [],
  }))
  .on("*", ({ value, user }) => {
    // Create filter to restrict access to just this user's resources
    const filters = { owner: user.identity };

    // If the operation supports metadata, add the user identity
    // as metadata to the resource.
    if ("metadata" in value) {
      value.metadata ??= {};
      value.metadata.owner = user.identity;
    }

    // Return filters to restrict access
    // These filters are applied to ALL operations (create, read, update, search, etc.)
    // to ensure users can only access their own resources
    return filters;
  });
```

### Resource-Specific Handlers {#resource-specific-handlers}

You can register handlers for specific resources and actions by chaining the resource and action names together with the [`on()`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#on) method.
When a request is made, the most specific handler that matches that resource and action is called. Below is an example of how to register handlers for specific resources and actions. For the following setup:

1. Authenticated users are able to create threads, read thread, create runs on threads
2. Only users with the "assistants:create" permission are allowed to create new assistants
3. All other endpoints (e.g., e.g., delete assistant, crons, store) are disabled for all users.

!!! tip "Supported Handlers"

    For a full list of supported resources and actions, see the [Supported Resources](#supported-resources) section below.

```
/* Detailed source-code truncated for AI context efficiency. */
```

Notice that we are mixing global and resource-specific handlers in the above example. Since each request is handled by the most specific handler, a request to create a `thread` would match the `thread:create` handler but NOT the `*` handler. A request to `update` a thread, however would be handled by the global handler, since we don't have a more specific handler for that resource and action. Requests to create, update,

### Filter Operations {#filter-operations}

Authorization handlers can return `None`, a boolean, or a filter object.

- `null`, `void` and `true` mean "authorize access to all underlying resources"
- `False` means "deny access to all underlying resources (raises a 403 error)"
- A metadata filter object will restrict access to resources. Supports exact matches and operators.

???+ info "Filter object syntax"

    The following operators are supported:

    - Exact match shorthand: `{"field": "value"}`
    - Exact match: `{"field": {"$eq": "value"}}`
    - Contains: `{"field": {"$contains": "value"}}`

    A metadata filter object with multiple keys is treated using a logical `AND` filter. For example, `{"owner": org_id, "allowed_users": {"$contains": user_id}}` will only match resources with metadata whose "owner" is `org_id` and whose "allowed_users" list contains `user_id`.

## Common Access Patterns

Here are some typical authorization patterns:

### Single-Owner Resources

This common pattern lets you scope all threads, assistants, crons, and runs to a single user. It's useful for common single-user use cases like regular chatbot-style apps.

```typescript
import { Auth, HTTPException } from "@langchain/langgraph-sdk/auth";

export const auth = new Auth()
  .authenticate(async (request: Request) => ({
    identity: "user-123",
    permissions: ["threads:write", "threads:read"],
  }))
  .on("*", ({ value, user }) => {
    if ("metadata" in value) {
      value.metadata ??= {};
      value.metadata.owner = user.identity;
    }
    return { owner: user.identity };
  });
```

### Permission-based Access

This pattern lets you control access based on **permissions**. It's useful if you want certain roles to have broader or more restricted access to resources.

```typescript
import { Auth, HTTPException } from "@langchain/langgraph-sdk/auth";

export const auth = new Auth()
  .authenticate(async (request: Request) => ({
    identity: "user-123",
    // Define permissions in auth
    permissions: ["threads:write", "threads:read"],
  }))
  .on("threads:create", ({ value, user, permissions }) => {
    if (!permissions.includes("threads:write")) {
      throw new HTTPException(403, { message: "Unauthorized" });
    }

    if ("metadata" in value) {
      value.metadata ??= {};
      value.metadata.owner = user.identity;
    }
    return { owner: user.identity };
  })
  .on("threads:read", ({ user, permissions }) => {
    if (
      !permissions.includes("threads:read") &&
      !permissions.includes("threads:write")
    ) {
      throw new HTTPException(403, { message: "Unauthorized" });
    }

    return { owner: user.identity };
  });
```

## Supported Resources {#supported-resources}

LangGraph provides three levels of authorization handlers, from most general to most specific:

1. **Global Handler** (`on("*")`): Matches all resources and actions
2. **Resource Handler** (e.g., `on("threads")`, `on("assistants")`, `on("crons")`): Matches all actions for a specific resource
3. **Action Handler** (e.g., `on("threads:create")`, `on("threads:read")`): Matches a specific action on a specific resource

The most specific matching handler will be used. For example, `on("threads:create")` takes precedence over `on("threads")` for thread creation. If a more specific handler is registered, the more general handler will not be called for that resource and action.

#### Supported action events {#supported-actions}

| Resource       | Event                | Description                | Value Type                                                                                                         |
| -------------- | -------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| **Threads**    | `threads:create`     | Thread creation            | [`ThreadsCreate`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#threadscreate)       |
|                | `threads:read`       | Thread retrieval           | [`ThreadsRead`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#threadsread)           |
|                | `threads:update`     | Thread updates             | [`ThreadsUpdate`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#threadsupdate)       |
|                | `threads:delete`     | Thread deletion            | [`ThreadsDelete`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#threadsdelete)       |
|                | `threads:search`     | Listing threads            | [`ThreadsSearch`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#threadssearch)       |
|                | `threads:create_run` | Creating or updating a run | [`RunsCreate`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#threadscreate_run)      |
| **Assistants** | `assistants:create`  | Assistant creation         | [`AssistantsCreate`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#assistantscreate) |
|                | `assistants:read`    | Assistant retrieval        | [`AssistantsRead`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#assistantsread)     |
|                | `assistants:update`  | Assistant updates          | [`AssistantsUpdate`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#assistantsupdate) |
|                | `assistants:delete`  | Assistant deletion         | [`AssistantsDelete`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#assistantsdelete) |
|                | `assistants:search`  | Listing assistants         | [`AssistantsSearch`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#assistantssearch) |
| **Crons**      | `crons:create`       | Cron job creation          | [`CronsCreate`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#cronscreate)           |
|                | `crons:read`         | Cron job retrieval         | [`CronsRead`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#cronsread)               |
|                | `crons:update`       | Cron job updates           | [`CronsUpdate`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#cronsupdate)           |
|                | `crons:delete`       | Cron job deletion          | [`CronsDelete`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#cronsdelete)           |
|                | `crons:search`       | Listing cron jobs          | [`CronsSearch`](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/js_ts_sdk_ref/#cronssearch)           |

???+ note "About Runs"

    Runs are scoped to their parent thread for access control. This means permissions are typically inherited from the thread, reflecting the conversational nature of the data model. All run operations (reading, listing) except creation are controlled by the thread's handlers.
    There is a specific `threads:create_run` event for creating new runs because it had more arguments that you can view in the handler.

## Next Steps

For implementation details:

- See the how-to guide on implementing a [custom auth handlers](../how-tos/auth/custom_auth.md)

---

### Docs Concepts Breakpoints (`docs/docs/concepts/breakpoints.md`)

# Breakpoints

Breakpoints pause graph execution at specific points and enable stepping through execution step by step. Breakpoints are powered by LangGraph's [**persistence layer**](./persistence.md), which saves the state after each graph step. Breakpoints can also be used to enable [**human-in-the-loop**](./human_in_the_loop.md) workflows, though we recommend using the [`interrupt` function](./human_in_the_loop.md#interrupt) for this purpose.

## Requirements

To use breakpoints, you will need to:

1. [**Specify a checkpointer**](persistence.md#checkpoints) to save the graph state after each step.

2. [**Set breakpoints**](#setting-breakpoints) to specify where execution should pause.

3. **Run the graph** with a [**thread ID**](./persistence.md#threads) to pause execution at the breakpoint.

4. **Resume execution** using `invoke`/`stream` (see [**The `Command` primitive**](./human_in_the_loop.md#the-command-primitive)).

## Setting breakpoints

There are two places where you can set breakpoints:

1. **Before** or **after** a node executes by setting breakpoints at **compile time** or **run time**. We call these [**static breakpoints**](#static-breakpoints).

2. **Inside** a node using the [`NodeInterrupt` error](#nodeinterrupt-error).

### Static breakpoints

Static breakpoints are triggered either **before** or **after** a node executes. You can set static breakpoints by specifying `interruptBefore` and `interruptAfter` at **"compile" time** or **run time**.

=== "Compile time"

    ```typescript
    const graph = graphBuilder.compile({
        interruptBefore: ["nodeA"],
        interruptAfter: ["nodeB", "nodeC"],
        checkpointer: ..., // Specify a checkpointer
    });

    const threadConfig = {
        configurable: {
            thread_id: "someThread"
        }
    };

    // Run the graph until the breakpoint
    await graph.invoke(inputs, threadConfig);

    // Optionally update the graph state based on user input
    await graph.updateState(update, threadConfig);

    // Resume the graph
    await graph.invoke(null, threadConfig);
    ```

=== "Run time"

    ```typescript
    await graph.invoke(
        inputs,
        { 
            configurable: { thread_id: "someThread" },
            interruptBefore: ["nodeA"],
            interruptAfter: ["nodeB", "nodeC"]
        }
    );

    const threadConfig = {
        configurable: {
            thread_id: "someThread"
        }
    };

    // Run the graph until the breakpoint
    await graph.invoke(inputs, threadConfig);

    // Optionally update the graph state based on user input
    await graph.updateState(update, threadConfig);

    // Resume the graph
    await graph.invoke(null, threadConfig);
    ```

    !!! note

        You cannot set static breakpoints at runtime for **sub-graphs**.

        If you have a sub-graph, you must set the breakpoints at compilation time.

Static breakpoints can be especially useful for debugging if you want to step through the graph execution one
node at a time or if you want to pause the graph execution at specific nodes.

### `NodeInterrupt` error

We recommend that you [**use the `interrupt` function instead**](#the-interrupt-function) of the `NodeInterrupt` error if you're trying to implement
[human-in-the-loop](./human_in_the_loop.md) workflows. The `interrupt` function is easier to use and more flexible.

??? node "`NodeInterrupt` error"

    The developer can define some *condition* that must be met for a breakpoint to be triggered. This concept of [dynamic breakpoints](./low_level.md#dynamic-breakpoints) is useful when the developer wants to halt the graph under *a particular condition*. This uses a `NodeInterrupt`, which is a special type of error that can be thrown from within a node based upon some condition. As an example, we can define a dynamic breakpoint that triggers when the `input` is longer than 5 characters.

    ```typescript
    function myNode(state: typeof GraphAnnotation.State) {
        if (state.input.length > 5) {
            throw new NodeInterrupt(`Received input that is longer than 5 characters: ${state.input}`);
        }
        return state;
    }
    ```

    Let's assume we run the graph with an input that triggers the dynamic breakpoint and then attempt to resume the graph execution simply by passing in `null` for the input.

    ```typescript
    // Attempt to continue the graph execution with no change to state after we hit the dynamic breakpoint 
    for await (const event of await graph.stream(null, threadConfig)) {
        console.log(event);
    }
    ```

    The graph will *interrupt* again because this node will be *re-run* with the same graph state. We need to change the graph state such that the condition that triggers the dynamic breakpoint is no longer met. So, we can simply edit the graph state to an input that meets the condition of our dynamic breakpoint (< 5 characters) and re-run the node.

    ```typescript
    // Update the state to pass the dynamic breakpoint
    await graph.updateState({ input: "foo" }, threadConfig);

    for await (const event of await graph.stream(null, threadConfig)) {
        console.log(event);
    }
    ```

    Alternatively, what if we want to keep our current input and skip the node (`myNode`) that performs the check? To do this, we can simply perform the graph update with `"myNode"` (the node name) as the third positional argument, and pass in `null` for the values. This will make no update to the graph state, but run the update as `myNode`, effectively skipping the node and bypassing the dynamic breakpoint.

    ```typescript
    // This update will skip the node `myNode` altogether
    await graph.updateState(null, threadConfig, "myNode");

    for await (const event of await graph.stream(null, threadConfig)) {
        console.log(event);
    }
    ```

## Additional Resources 📚

- [**Conceptual Guide: Persistence**](persistence.md): Read the persistence guide for more context about persistence.

- [**Conceptual Guide: Human-in-the-loop**](human_in_the_loop.md): Read the human-in-the-loop guide for more context on integrating human feedback into LangGraph applications using breakpoints.

- [**How to View and Update Past Graph State**](/langgraphjs/how-tos/time-travel): Step-by-step instructions for working with graph state that demonstrate the **replay** and **fork** actions.

---

### Docs Concepts Bring Your Own Cloud (`docs/docs/concepts/bring_your_own_cloud.md`)

# Bring Your Own Cloud (BYOC)

!!! note Prerequisites

    - [LangGraph Platform](./langgraph_platform.md)
    - [Deployment Options](./deployment_options.md)

## Architecture

Split control plane (hosted by us) and data plane (hosted by you, managed by us).

|                             | Control Plane                   | Data Plane                                    |
|-----------------------------|---------------------------------|-----------------------------------------------|
| What it does                | Manages deployments, revisions. | Runs your LangGraph graphs, stores your data. |
| Where it is hosted          | LangChain Cloud account         | Your cloud account                            |
| Who provisions and monitors | LangChain                       | LangChain                                     |

LangChain has no direct access to the resources created in your cloud account, and can only interact with them via AWS APIs. Your data never leaves your cloud account / VPC at rest or in transit.



## Requirements

- You’re using AWS already.
- You use `langgraph-cli` and/or [LangGraph Studio](./langgraph_studio.md) app to test graph locally.
- You use `langgraph build` command to build image and then push it to your AWS ECR repository (`docker push`).

## How it works

- We provide you a [Terraform module](https://github.com/langchain-ai/terraform/tree/main/modules/langgraph_cloud_setup) which you run to set up our requirements
    1. Creates an AWS role (which our control plane will later assume to provision and monitor resources)
        - https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonVPCReadOnlyAccess.html
            - Read VPCS to find subnets
        - https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonECS_FullAccess.html
            - Used to create/delete ECS resources for your LangGraph Cloud instances
        - https://docs.aws.amazon.com/aws-managed-policy/latest/reference/SecretsManagerReadWrite.html
            - Create secrets for your ECS resources
        - https://docs.aws.amazon.com/aws-managed-policy/latest/reference/CloudWatchReadOnlyAccess.html
            - Read CloudWatch metrics/logs to monitor your instances/push deployment logs
        - https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonRDSFullAccess.html
            - Provision `RDS` instances for your LangGraph Cloud instances
    2. Either
        - Tags an existing vpc / subnets as `langgraph-cloud-enabled`
        - Creates a new vpc and subnets and tags them as `langgraph-cloud-enabled`
- You create a LangGraph Cloud Project in `smith.langchain.com` providing
    - the ID of the AWS role created in the step above
    - the AWS ECR repo to pull the service image from
- We provision the resources in your cloud account using the role above
- We monitor those resources to ensure uptime and recovery from errors

Notes for customers using [self-hosted LangSmith](https://docs.smith.langchain.com/self_hosting):

- Creation of new LangGraph Cloud projects and revisions currently needs to be done on smith.langchain.com.
- You can however set up the project to trace to your self-hosted LangSmith instance if desired

---

### Docs Concepts Deployment Options (`docs/docs/concepts/deployment_options.md`)

# Deployment Options

!!! info "Prerequisites"

    - [LangGraph Platform](./langgraph_platform.md)
    - [LangGraph Server](./langgraph_server.md)
    - [LangGraph Platform Plans](./plans.md)

## Overview

There are 4 main options for deploying with the LangGraph Platform:

1. **[Self-Hosted Lite](#self-hosted-lite)**: Available for all plans.

2. **[Self-Hosted Enterprise](#self-hosted-enterprise)**: Available for the **Enterprise** plan.

3. **[Cloud SaaS](#cloud-saas)**: Available for **Plus** and **Enterprise** plans.

4. **[Bring Your Own Cloud](#bring-your-own-cloud)**: Available only for **Enterprise** plans and **only on AWS**.

Please see the [LangGraph Platform Plans](./plans.md) for more information on the different plans.

The guide below will explain the differences between the deployment options.

## Self-Hosted Enterprise

!!! important

    The Self-Hosted Enterprise version is only available for the **Enterprise** plan.

With a Self-Hosted Enterprise deployment, you are responsible for managing the infrastructure, including setting up and maintaining required databases and Redis instances.

You’ll build a Docker image using the [LangGraph CLI](./langgraph_cli.md), which can then be deployed on your own infrastructure.

For more information, please see:

* [Self-Hosted conceptual guide](./self_hosted.md)
* [Self-Hosted Deployment how-to guide](../how-tos/deploy-self-hosted.md)

## Self-Hosted Lite

!!! important

    The Self-Hosted Lite version is available for all plans.

The Self-Hosted Lite deployment option is a free (up to 1 million nodes executed), limited version of LangGraph Platform that you can run locally or in a self-hosted manner.

With a Self-Hosted Lite deployment, you are responsible for managing the infrastructure, including setting up and maintaining required databases and Redis instances.

You’ll build a Docker image using the [LangGraph CLI](./langgraph_cli.md), which can then be deployed on your own infrastructure.


For more information, please see:

* [Self-Hosted conceptual guide](./self_hosted.md)
* [Self-Hosted Deployment how-to guide](https://langchain-ai.github.io/langgraphjs/how-tos/deploy-self-hosted/)

## Cloud SaaS

!!! important

    The Cloud SaaS version of LangGraph Platform is only available for **Plus** and **Enterprise** plans.

The [Cloud SaaS](./langgraph_cloud.md) version of LangGraph Platform is hosted as part of [LangSmith](https://smith.langchain.com/).

The Cloud SaaS version of LangGraph Platform provides a simple way to deploy and manage your LangGraph applications.

This deployment option provides an integration with GitHub, allowing you to deploy code from any of your repositories on GitHub.

For more information, please see:

* [Cloud SaaS Conceptual Guide](./langgraph_cloud.md)
* [How to deploy to Cloud SaaS](/langgraphjs/cloud/deployment/cloud.md)

## Bring Your Own Cloud

!!! important

    The Bring Your Own Cloud version of LangGraph Platform is only available for **Enterprise** plans.

This combines the best of both worlds for Cloud and Self-Hosted. We manage the infrastructure, so you don't have to, but the infrastructure all runs within your cloud. This is currently only available on AWS.

For more information please see:

* [Bring Your Own Cloud Conceptual Guide](./bring_your_own_cloud.md)

## Related

For more information please see:

* [LangGraph Platform Plans](./plans.md)
* [LangGraph Platform Pricing](https://www.langchain.com/langgraph-platform-pricing)
* [Deployment how-to guides](../how-tos/index.md#deployment)

---

### Docs Concepts Double Texting (`docs/docs/concepts/double_texting.md`)

# Double Texting

!!! info "Prerequisites"
    - [LangGraph Server](./langgraph_server.md)

Many times users might interact with your graph in unintended ways.
For instance, a user may send one message and before the graph has finished running send a second message.
More generally, users may invoke the graph a second time before the first run has finished.
We call this "double texting".

Currently, LangGraph only addresses this as part of [LangGraph Platform](langgraph_platform.md), not in the open source.
The reason for this is that in order to handle this we need to know how the graph is deployed, and since LangGraph Platform deals with deployment the logic needs to live there.
If you do not want to use LangGraph Platform, we describe the options we have implemented in detail below.



## Reject

This is the simplest option, this just rejects any follow up runs and does not allow double texting.
See the [how-to guide](/langgraphjs/cloud/how-tos/reject_concurrent) for configuring the reject double text option.

## Enqueue

This is a relatively simple option which continues the first run until it completes the whole run, then sends the new input as a separate run.
See the [how-to guide](/langgraphjs/cloud/how-tos/enqueue_concurrent) for configuring the enqueue double text option.

## Interrupt

This option interrupts the current execution but saves all the work done up until that point.
It then inserts the user input and continues from there.

If you enable this option, your graph should be able to handle weird edge cases that may arise.
For example, you could have called a tool but not yet gotten back a result from running that tool.
You may need to remove that tool call in order to not have a dangling tool call.

See the [how-to guide](/langgraphjs/cloud/how-tos/interrupt_concurrent) for configuring the interrupt double text option.

## Rollback

This option rolls back all work done up until that point.
It then sends the user input in, basically as if it just followed the original run input.

This may create some weird states - for example, you may have two `User` messages in a row, with no `Assistant` message in between them.

You will need to make sure the LLM you are calling can handle that, or combine those into a single `User` message.

See the [how-to guide](/langgraphjs/cloud/how-tos/rollback_concurrent) for configuring the rollback double text option.

---

### Docs Concepts Faq (`docs/docs/concepts/faq.md`)

# FAQ

Common questions and their answers!

## Do I need to use LangChain in order to use LangGraph?

No! LangGraph is a general-purpose framework - the nodes and edges are nothing more than JavaScript/TypeScript functions. You can use LangChain, raw HTTP requests, or even other frameworks inside these nodes and edges.

## Does LangGraph work with LLMs that don't support tool calling?

Yes! You can use LangGraph with any LLMs. The main reason we use LLMs that support tool calling is that this is often the most convenient way to have the LLM make its decision about what to do. If your LLM does not support tool calling, you can still use it - you just need to write a bit of logic to convert the raw LLM string response to a decision about what to do.

## Does LangGraph work with OSS LLMs?

Yes! LangGraph is totally ambivalent to what LLMs are used under the hood. The main reason we use closed LLMs in most of the tutorials is that they seamlessly support tool calling, while OSS LLMs often don't. But tool calling is not necessary (see [this section](#does-langgraph-work-with-llms-that-dont-support-tool-calling)) so you can totally use LangGraph with OSS LLMs.

---

### Docs Concepts Functional Api (`docs/docs/concepts/functional_api.md`)

# Functional API

!!! note Compatibility

    The Functional API requires `@langchain/langgraph>=0.2.42`.

## Overview

The **Functional API** allows you to add LangGraph's key features -- [persistence](./persistence.md), [memory](./memory.md), [human-in-the-loop](./human_in_the_loop.md), and [streaming](./streaming.md) — to your applications with minimal changes to your existing code.

It is designed to integrate these features into existing code that may use standard language primitives for branching and control flow, such as `if` statements, `for` loops, and function calls. Unlike many data orchestration frameworks that require restructuring code into an explicit pipeline or DAG, the Functional API allows you to incorporate these capabilities without enforcing a rigid execution model.  

The **Functional API** uses two key building blocks:  

- **`entrypoint`** – An **entrypoint** is a wrapper that takes a function as the starting point of a workflow. It encapsulates workflow logic and manages execution flow, including handling _long-running tasks_ and [interrupts](human_in_the_loop.md).
- **`task`** – Represents a discrete unit of work, such as an API call or data processing step, that can be executed asynchronously within an entrypoint. Tasks return a future-like object that can be awaited or resolved synchronously.

This provides a minimal abstraction for building workflows with state management and streaming.

!!! tip 

    For users who prefer a more declarative approach, LangGraph's [Graph API](./low_level.md) allows you to define workflows using a Graph paradigm. Both APIs share the same underlying runtime, so you can use them together in the same application.
    Please see the [Functional API vs. Graph API](#functional-api-vs-graph-api) section for a comparison of the two paradigms.

## Example

Below we demonstrate a simple application that writes an essay and [interrupts](human_in_the_loop.md) to request human review.

```typescript
import { task, entrypoint, interrupt, MemorySaver } from "@langchain/langgraph";

const writeEssay = task("write_essay", (topic: string): string => {
  // A placeholder for a long-running task.
  return `An essay about topic: ${topic}`;
});

const workflow = entrypoint(
  { checkpointer: new MemorySaver(), name: "workflow" },
  async (topic: string) => {
    const essay = await writeEssay(topic);
    const isApproved = interrupt({
      // Any json-serializable payload provided to interrupt as argument.
      // It will be surfaced on the client side as an Interrupt when streaming data
      // from the workflow.
      essay, // The essay we want reviewed.
      // We can add any additional information that we need.
      // For example, introduce a key called "action" with some instructions.
      action: "Please approve/reject the essay",
    });

    return {
      essay, // The essay that was generated
      isApproved, // Response from HIL
    };
  }
);
```

??? example "Detailed Explanation"

    This workflow will write an essay about the topic "cat" and then pause to get a review from a human. The workflow can be interrupted for an indefinite amount of time until a review is provided.

    When the workflow is resumed, it executes from the very start, but because the result of the `writeEssay` task was already saved, the task result will be loaded from the checkpoint instead of being recomputed.

    ```typescript
    import { task, entrypoint, interrupt, MemorySaver, Command } from "@langchain/langgraph";

    const writeEssay = task("write_essay", (topic: string): string => {
      return `An essay about topic: ${topic}`;
    });

    const workflow = entrypoint(
      { checkpointer: new MemorySaver(), name: "workflow" },
      async (topic: string) => {
        const essay = await writeEssay(topic);
        const isApproved = interrupt({
          essay, // The essay we want reviewed.
          action: "Please approve/reject the essay",
        });

        return {
          essay,
          isApproved,
        };
      }
    );

    const threadId = crypto.randomUUID();

    const config = {
      configurable: {
        thread_id: threadId,
      },
    };

    for await (const item of await workflow.stream("cat", config)) {
      console.log(item);
    }
    ```

    ```typescript
    { write_essay: 'An essay about topic: cat' }
    { __interrupt__: [{
      value: { essay: 'An essay about topic: cat', action: 'Please approve/reject the essay' },
      resumable: true,
      ns: ['workflow:f7b8508b-21c0-8b4c-5958-4e8de74d2684'],
      when: 'during'
    }] }
    ```

    An essay has been written and is ready for review. Once the review is provided, we can resume the workflow:

    ```typescript
    // Get review from a user (e.g., via a UI)
    // In this case, we're using a bool, but this can be any json-serializable value.
    const humanReview = true;

    for await (const item of await workflow.stream(new Command({ resume: humanReview }), config)) {
      console.log(item);
    }
    ```

    ```typescript
    { workflow: { essay: 'An essay about topic: cat', isApproved: true } }
    ```

    The workflow has been completed and the review has been added to the essay.

## Entrypoint

The [`entrypoint`](/langgraphjs/reference/functions/langgraph.entrypoint-1.html) function can be used to create a workflow from a function. It encapsulates workflow logic and manages execution flow, including handling _long-running tasks_ and [interrupts](./low_level.md#interrupt).

### Definition

An **entrypoint** is defined by passing a function to the `entrypoint` function.

The function **must accept a single positional argument**, which serves as the workflow input. If you need to pass multiple pieces of data, use an object as the input type for the first argument.

You will often want to pass a **checkpointer** to the `entrypoint` function to enable persistence and use features like **human-in-the-loop**.

```typescript
import { entrypoint, MemorySaver } from "@langchain/langgraph";

const checkpointer = new MemorySaver();

const myWorkflow = entrypoint(
  { checkpointer, name: "myWorkflow" },
  async (someInput: Record<string, any>): Promise<number> => {
    // some logic that may involve long-running tasks like API calls,
    // and may be interrupted for human-in-the-loop.
    return result;
  }
);
```

!!! important "Serialization"

    The **inputs** and **outputs** of entrypoints must be JSON-serializable to support checkpointing. Please see the [serialization](#serialization) section for more details.

### Injectable Parameters

When declaring an `entrypoint`, you can access additional parameters that will be injected automatically at run time by using the [`getPreviousState`](/langgraphjs/reference/functions/langgraph.getPreviousState.html) function and other utilities. These parameters include:

| Parameter              | Description                                                                                                                                                                                                                                                                                     |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **config**             | For accessing runtime configuration. Automatically populated as the second argument to the `entrypoint` function (but not `task`, since tasks can have a variable number of arguments). See [RunnableConfig](https://js.langchain.com/docs/concepts/runnables/#runnableconfig) for information. |
| **config.store**       | An instance of [BaseStore](/langgraphjs/reference/classes/checkpoint.BaseStore.html). Useful for [long-term memory](#long-term-memory).                                                                                                                                                         |
| **config.writer**      | A `writer` used for streaming back custom data. See the [guide on streaming custom data](../how-tos/streaming-content.ipynb)                                                                                                                                                                    |
| **getPreviousState()** | Access the state associated with the previous `checkpoint` for the given thread using [`getPreviousState`](/langgraphjs/reference/functions/langgraph.getPreviousState.html). See [state management](#state-management).                                                                        |

??? example "Requesting Injectable Parameters"

    ```typescript
    import {
      entrypoint,
      getPreviousState,
      BaseStore,
      InMemoryStore,
    } from "@langchain/langgraph";
    import { RunnableConfig } from "@langchain/core/runnables";

    const inMemoryStore = new InMemoryStore(...);  // An instance of InMemoryStore for long-term memory

    const myWorkflow = entrypoint(
      {
        checkpointer,  // Specify the checkpointer
        store: inMemoryStore,  // Specify the store
        name: "myWorkflow",
      },
      async (someInput: Record<string, any>) => {
        const previous = getPreviousState<any>(); // For short-term memory
        // Rest of workflow logic...
      }
    );
    ```

### Executing

Using the [`entrypoint`](#entrypoint) function will return an object that can be executed using the `invoke` and `stream` methods.

=== "Invoke"

    ```typescript
    const config = {
      configurable: {
        thread_id: "some_thread_id",
      },
    };
    await myWorkflow.invoke(someInput, config);  // Wait for the result
    ```

=== "Stream"

    ```typescript
    const config = {
      configurable: {
        thread_id: "some_thread_id",
      },
    };

    for await (const chunk of await myWorkflow.stream(someInput, config)) {
      console.log(chunk);
    }
    ```

### Resuming

Resuming an execution after an [interrupt](/langgraphjs/reference/functions/langgraph.interrupt-1.html) can be done by passing a **resume** value to the [Command](/langgraphjs/reference/classes/langgraph.Command.html) primitive.

=== "Invoke"

    ```typescript
    import { Command } from "@langchain/langgraph";

    const config = {
      configurable: {
        thread_id: "some_thread_id",
      },
    };

    await myWorkflow.invoke(new Command({ resume: someResumeValue }), config);
    ```

=== "Stream"

    ```typescript
    import { Command } from "@langchain/langgraph";

    const config = {
      configurable: {
        thread_id: "some_thread_id",
      },
    };

    const stream = await myWorkflow.stream(
      new Command({ resume: someResumeValue }),
      config,
    );

    for await (const chunk of stream) {
      console.log(chunk);
    }
    ```

**Resuming after transient error**

To resume after a transient error (such as a model provider outage), run the `entrypoint` with a `null` and the same **thread id** (config).

This assumes that the underlying **error** has been resolved and execution can proceed successfully.

=== "Invoke"

    ```typescript
    const config = {
      configurable: {
        thread_id: "some_thread_id",
      },
    };

    await myWorkflow.invoke(null, config);
    ```

=== "Stream"

    ```typescript
    const config = {
      configurable: {
        thread_id: "some_thread_id",
      },
    };

    for await (const chunk of await myWorkflow.stream(null, config)) {
      console.log(chunk);
    }
    ```

### State Management

When an `entrypoint` is defined with a `checkpointer`, it stores information between successive invocations on the same **thread id** in [checkpoints](persistence.md#checkpoints).

This allows accessing the state from the previous invocation using the [`getPreviousState`](/langgraphjs/reference/functions/langgraph.getPreviousState.html) function.

By default, the previous state is the return value of the previous invocation.

```typescript
const myWorkflow = entrypoint(
  { checkpointer, name: "myWorkflow" },
  async (number: number) => {
    const previous = getPreviousState<number>();
    return number + (previous ?? 0);
  }
);

const config = {
  configurable: {
    thread_id: "some_thread_id",
  },
};

await myWorkflow.invoke(1, config); // 1 (previous was undefined)
await myWorkflow.invoke(2, config); // 3 (previous was 1 from the previous invocation)
```

#### `entrypoint.final`

[entrypoint.final](/langgraphjs/reference/functions/langgraph.entrypoint.final.html) is a special primitive that can be returned from an entrypoint and allows **decoupling** the value that is **saved in the checkpoint** from the **return value of the entrypoint**.

The first value is the return value of the entrypoint, and the second value is the value that will be saved in the checkpoint.

```typescript
const myWorkflow = entrypoint(
  { checkpointer, name: "myWorkflow" },
  async (number: number) => {
    const previous = getPreviousState<number>();
    // This will return the previous value to the caller, saving
    // 2 * number to the checkpoint, which will be used in the next invocation
    // for the previous state
    return entrypoint.final({
      value: previous ?? 0,
      save: 2 * number,
    });
  }
);

const config = {
  configurable: {
    thread_id: "1",
  },
};

await myWorkflow.invoke(3, config); // 0 (previous was undefined)
await myWorkflow.invoke(1, config); // 6 (previous was 3 * 2 from the previous invocation)
```

## Task

A **task** represents a discrete unit of work, such as an API call or data processing step. It has three key characteristics:

- **Asynchronous Execution**: Tasks are designed to be executed asynchronously, allowing multiple operations to run concurrently without blocking.
- **Checkpointing**: Task results are saved to a checkpoint, enabling resumption of the workflow from the last saved state. (See [persistence](persistence.md) for more details).
- **Retries**: Tasks can be configured with a [retry policy](./low_level.md#retry-policies) to handle transient errors.

### Definition

Tasks are defined using the `task` function, which wraps a regular function.

```typescript
import { task } from "@langchain/langgraph";

const slowComputation = task({"slowComputation", async (inputValue: any) => {
  // Simulate a long-running operation
  ...
  return result;
});
```

!!! important "Serialization"

    The **outputs** of tasks **must** be JSON-serializable to support checkpointing.

### Execution

**Tasks** can only be called from within an **entrypoint**, another **task**, or a [state graph node](./low_level.md#nodes).

Tasks _cannot_ be called directly from the main application code.

```typescript
const myWorkflow = entrypoint(
  { checkpointer, name: "myWorkflow" },
  async (someInput: number) => {
    return await slowComputation(someInput);
  }
);
```

### Retry Policy

You can specify a [retry policy](./low_level.md#retry-policies) for a **task** by passing a `retry` parameter to the `task` function.

```typescript
const slowComputation = task(
  {
    name: "slowComputation",
    // only attempt to run this task once before giving up
    retry: { maxAttempts: 1 },
  },
  async (inputValue: any) => {
    // A long-running operation that may fail
    return result;
  }
);
```

## When to use a task

**Tasks** are useful in the following scenarios:

- **Checkpointing**: When you need to save the result of a long-running operation to a checkpoint, so you don't need to recompute it when resuming the workflow.
- **Human-in-the-loop**: If you're building a workflow that requires human intervention, you MUST use **tasks** to encapsulate any randomness (e.g., API calls) to ensure that the workflow can be resumed correctly. See the [determinism](#determinism) section for more details.
- **Parallel Execution**: For I/O-bound tasks, **tasks** enable parallel execution, allowing multiple operations to run concurrently without blocking (e.g., calling multiple APIs).
- **Observability**: Wrapping operations in **tasks** provides a way to track the progress of the workflow and monitor the execution of individual operations using [LangSmith](https://docs.smith.langchain.com/).
- **Retryable Work**: When work needs to be retried to handle failures or inconsistencies, **tasks** provide a way to encapsulate and manage the retry logic.

## Serialization

There are two key aspects to serialization in LangGraph:

1. `entrypoint` inputs and outputs must be JSON-serializable.
2. `task` outputs must be JSON-serializable.

These requirements are necessary for enabling checkpointing and workflow resumption. Use JavaScript primitives
like objects, arrays, strings, numbers, and booleans to ensure that your inputs and outputs are serializable.

Serialization ensures that workflow state, such as task results and intermediate values, can be reliably saved and restored. This is critical for enabling human-in-the-loop interactions, fault tolerance, and parallel execution.

Providing non-serializable inputs or outputs will result in a runtime error when a workflow is configured with a checkpointer.

## Determinism

To utilize features like **human-in-the-loop**, any randomness should be encapsulated inside of **tasks**. This guarantees that when execution is halted (e.g., for human in the loop) and then resumed, it will follow the same _sequence of steps_, even if **task** results are non-deterministic.

LangGraph achieves this behavior by persisting **task** and [**subgraph**](./low_level.md#subgraphs) results as they execute. A well-designed workflow ensures that resuming execution follows the _same sequence of steps_, allowing previously computed results to be retrieved correctly without having to re-execute them. This is particularly useful for long-running **tasks** or **tasks** with non-deterministic results, as it avoids repeating previously done work and allows resuming from essentially the same

While different runs of a workflow can produce different results, resuming a **specific** run should always follow the same sequence of recorded steps. This allows LangGraph to efficiently look up **task** and **subgraph** results that were executed prior to the graph being interrupted and avoid recomputing them.

## Idempotency

Idempotency ensures that running the same operation multiple times produces the same result. This helps prevent duplicate API calls and redundant processing if a step is rerun due to a failure. Always place API calls inside **tasks** functions for checkpointing, and design them to be idempotent in case of re-execution. Re-execution can occur if a **task** starts, but does not complete successfully. Then, if the workflow is resumed, the **task** will run again. Use idempotency keys or verify existing results to avoid duplication.

## Functional API vs. Graph API

The **Functional API** and the [Graph APIs (StateGraph)](./low_level.md#stategraph) provide two different paradigms to create in LangGraph. Here are some key differences:

- **Control flow**: The Functional API does not require thinking about graph structure. You can use standard Python constructs to define workflows. This will usually trim the amount of code you need to write.
- **State management**: The **GraphAPI** requires declaring a [**State**](./low_level.md#state) and may require defining [**reducers**](./low_level.md#reducers) to manage updates to the graph state. `@entrypoint` and `@tasks` do not require explicit state management as their state is scoped to the function and is not shared across functions.
- **Checkpointing**: Both APIs generate and use checkpoints. In the **Graph API** a new checkpoint is generated after every [superstep](./low_level.md). In the **Functional API**, when tasks are executed, their results are saved to an existing checkpoint associated with the given entrypoint instead of creating a new checkpoint.
- **Visualization**: The Graph API makes it easy to visualize the workflow as a graph which can be useful for debugging, understanding the workflow, and sharing with others. The Functional API does not support visualization as the graph is dynamically generated during runtime.

## Common Pitfalls

### Handling side effects

Encapsulate side effects (e.g., writing to a file, sending an email) in tasks to ensure they are not executed multiple times when resuming a workflow.

=== "Incorrect"

    In this example, a side effect (writing to a file) is directly included in the workflow, so it will be executed a second time when resuming the workflow.

    ```typescript
    const myWorkflow = entrypoint(
      { checkpointer, name: "myWorkflow" },
      async (inputs: Record<string, any>) => {
        // This code will be executed a second time when resuming the workflow.
        // Which is likely not what you want.
        // highlight-next-line
        await fs.writeFile("output.txt", "Side effect executed");
        const value = interrupt("question");
        return value;
      }
    );
    ```

=== "Correct"

    In this example, the side effect is encapsulated in a task, ensuring consistent execution upon resumption.

    ```typescript
    import { task } from "@langchain/langgraph";

    // highlight-next-line
    const writeToFile = task("writeToFile", async () => {
      await fs.writeFile("output.txt", "Side effect executed");
    });

    const myWorkflow = entrypoint(
      { checkpointer, name: "myWorkflow" },
      async (inputs: Record<string, any>) => {
        // The side effect is now encapsulated in a task.
        await writeToFile();
        const value = interrupt("question");
        return value;
      }
    );
    ```

### Non-deterministic control flow

Operations that might give different results each time (like getting current time or random numbers) should be encapsulated in tasks to ensure that on resume, the same result is returned.

- In a task: Get random number (5) → interrupt → resume → (returns 5 again) → ...
- Not in a task: Get random number (5) → interrupt → resume → get new random number (7) → ...

This is especially important when using **human-in-the-loop** workflows with multiple interrupts calls. LangGraph keeps a list
of resume values for each task/entrypoint. When an interrupt is encountered, it's matched with the corresponding resume value.
This matching is strictly **index-based**, so the order of the resume values should match the order of the interrupts.

If order of execution is not maintained when resuming, one `interrupt` call may be matched with the wrong `resume` value, leading to incorrect results.

Please read the section on [determinism](#determinism) for more details.

=== "Incorrect"

    In this example, the workflow uses the current time to determine which task to execute. This is non-deterministic because the result of the workflow depends on the time at which it is executed.

    ```typescript
    const myWorkflow = entrypoint(
      { checkpointer, name: "myWorkflow" },
      async (inputs: { t0: number }) => {
        // highlight-next-line
        const t1 = Date.now();

        const deltaT = t1 - inputs.t0;

        if (deltaT > 1000) {
          const result = await slowTask(1);
          const value = interrupt("question");
          return { result, value };
        } else {
          const result = await slowTask(2);
          const value = interrupt("question");
          return { result, value };
        }
      }
    );
    ```

=== "Correct"

    In this example, the workflow uses the input `t0` to determine which task to execute. This is deterministic because the result of the workflow depends only on the input.

    ```typescript
    import { task } from "@langchain/langgraph";

    // highlight-next-line
    const getTime = task("getTime", () => Date.now());

    const myWorkflow = entrypoint(
      { checkpointer, name: "myWorkflow" },
      async (inputs: { t0: number }) => {
        // highlight-next-line
        const t1 = await getTime();

        const deltaT = t1 - inputs.t0;

        if (deltaT > 1000) {
          const result = await slowTask(1);
          const value = interrupt("question");
          return { result, value };
        } else {
          const result = await slowTask(2);
          const value = interrupt("question");
          return { result, value };
        }
      }
    );
    ```

## Patterns

Below are a few simple patterns that show examples of **how to** use the **Functional API**.

When defining an `entrypoint`, input is restricted to the first argument of the function. To pass multiple inputs, you can use an object.

```typescript
const myWorkflow = entrypoint(
  { checkpointer, name: "myWorkflow" },
  async (inputs: { value: number; anotherValue: number }) => {
    const value = inputs.value;
    const anotherValue = inputs.anotherValue;
    ...
  }
);

await myWorkflow.invoke([{ value: 1, anotherValue: 2 }]);
```

### Parallel execution

Tasks can be executed in parallel by invoking them concurrently and waiting for the results. This is useful for improving performance in IO bound tasks (e.g., calling APIs for LLMs).

```typescript
const addOne = task("addOne", (number: number) => number + 1);

const graph = entrypoint(
  { checkpointer, name: "graph" },
  async (numbers: number[]) => {
    return await Promise.all(numbers.map(addOne));
  }
);
```

### Calling subgraphs

The **Functional API** and the [**Graph API**](./low_level.md) can be used together in the same application as they share the same underlying runtime.

```typescript
import { entrypoint, StateGraph } from "@langchain/langgraph";

const builder = new StateGraph();
...
const someGraph = builder.compile();

const someWorkflow = entrypoint(
  { name: "someWorkflow" },
  async (someInput: Record<string, any>) => {
    // Call a graph defined using the graph API
    const result1 = await someGraph.invoke(...);
    // Call another graph defined using the graph API
    const result2 = await anotherGraph.invoke(...);
    return {
      result1,
      result2,
    };
  }
);
```

### Calling other entrypoints

You can call other **entrypoints** from within an **entrypoint** or a **task**.

```typescript
const someOtherWorkflow = entrypoint(
  { name: "someOtherWorkflow" }, // Will automatically use the checkpointer from the parent entrypoint
  async (inputs: { value: number }) => {
    return inputs.value;
  }
);

const myWorkflow = entrypoint(
  { checkpointer, name: "myWorkflow" },
  async (inputs: Record<string, any>) => {
    const value = await someOtherWorkflow.invoke([{ value: 1 }]);
    return value;
  }
);
```

### Streaming custom data

You can stream custom data from an **entrypoint** by using the `write` method on `config`. This allows you to write custom data to the `custom` stream.

```typescript
import {
  entrypoint,
  task,
  MemorySaver,
  LangGraphRunnableConfig,
} from "@langchain/langgraph";

const addOne = task("addOne", (x: number) => x + 1);

const addTwo = task("addTwo", (x: number) => x + 2);

const checkpointer = new MemorySaver();

const main = entrypoint(
  { checkpointer, name: "main" },
  async (inputs: { number: number }, config: LangGraphRunnableConfig) => {
    config.writer?.("hello"); // Write some data to the `custom` stream
    await addOne(inputs.number); // Will write data to the `updates` stream
    config.writer?.("world"); // Write some more data to the `custom` stream
    await addTwo(inputs.number); // Will write data to the `updates` stream
    return 5;
  }
);

const config = {
  configurable: {
    thread_id: "1",
  },
};

const stream = await main.stream(
  { number: 1 },
  { streamMode: ["custom", "updates"], ...config }
);

for await (const chunk of stream) {
  console.log(chunk);
}
```

```typescript
["updates", { addOne: 2 }][("updates", { addTwo: 3 })][("custom", "hello")][
  ("custom", "world")
][("updates", { main: 5 })];
```

### Resuming after an error

```
/* Detailed source-code truncated for AI context efficiency. */
```

When we resume execution, we won't need to re-run the `slowTask` as its result is already saved in the checkpoint.

```typescript
await main.invoke(null, config);
```

```typescript
"Ran slow task.";
```

### Human-in-the-loop

The functional API supports [human-in-the-loop](human_in_the_loop.md) workflows using the `interrupt` function and the `Command` primitive.

Please see the following examples for more details:

- [How to wait for user input (Functional API)](../how-tos/wait-user-input-functional.ipynb): Shows how to implement a simple human-in-the-loop workflow using the functional API.
- [How to review tool calls (Functional API)](../how-tos/review-tool-calls-functional.ipynb): Guide demonstrates how to implement human-in-the-loop workflows in a ReAct agent using the LangGraph Functional API.

### Short-term memory

[State management](#state-management) using the [`getPreviousState`](/langgraphjs/reference/functions/langgraph.getPreviousState.html) function and optionally using the `entrypoint.final` primitive can be used to implement [short term memory](memory.md).

Please see the following how-to guides for more details:

- [How to add thread-level persistence (functional API)](../how-tos/persistence-functional.ipynb): Shows how to add thread-level persistence to a functional API workflow and implements a simple chatbot.

### Long-term memory

[long-term memory](memory.md#long-term-memory) allows storing information across different **thread ids**. This could be useful for learning information
about a given user in one conversation and using it in another.

Please see the following how-to guides for more details:

- [How to add cross-thread persistence (functional API)](../how-tos/cross-thread-persistence-functional.ipynb): Shows how to add cross-thread persistence to a functional API workflow and implements a simple chatbot.

### Workflows

- [Workflows and agent](../tutorials/workflows/index.md) guide for more examples of how to build workflows using the Functional API.

### Agents

- [How to create a React agent from scratch (Functional API)](../how-tos/react-agent-from-scratch-functional.ipynb): Shows how to create a simple React agent from scratch using the functional API.
- [How to build a multi-agent network](../how-tos/multi-agent-network-functional.ipynb): Shows how to build a multi-agent network using the functional API.
- [How to add multi-turn conversation in a multi-agent application (functional API)](../how-tos/multi-agent-multi-turn-convo-functional.ipynb): allow an end-user to engage in a multi-turn conversation with one or more agents.

---

### Docs Concepts High Level (`docs/docs/concepts/high_level.md`)

# Why LangGraph?

LLMs are extremely powerful, particularly when connected to other systems such as a retriever or APIs. This is why many LLM applications use a control flow of steps before and / or after LLM calls. As an example [RAG](https://github.com/langchain-ai/rag-from-scratch) performs retrieval of relevant documents to a question, and passes those documents to an LLM in order to ground the response. Often a control flow of steps before and / or after an LLM is called a "chain." Chains are a popular paradigm for programming with LLMs and offer a high degree of reliability; the same set of steps runs with each chain invocation.

However, we often want LLM systems that can pick their own control flow! This is one definition of an [agent](https://blog.langchain.dev/what-is-an-agent/): an agent is a system that uses an LLM to decide the control flow of an application. Unlike a chain, an agent given an LLM some degree of control over the sequence of steps in the application. Examples of using an LLM to decide the control of an application:

- Using an LLM to route between two potential paths
- Using an LLM to decide which of many tools to call
- Using an LLM to decide whether the generated answer is sufficient or more work is needed

There are many different types of [agent architectures](https://blog.langchain.dev/what-is-a-cognitive-architecture/) to consider, which given an LLM varying levels of control. On one extreme, a router allows an LLM to select a single step from a specified set of options and, on the other extreme, a fully autonomous long-running agent may have complete freedom to select any sequence of steps that it wants for a given problem. 



Several concepts are utilized in many agent architectures:

- [Tool calling](agentic_concepts.md#tool-calling): this is often how LLMs make decisions
- Action taking: oftentimes, the LLMs' outputs are used as the input to an action
- [Memory](agentic_concepts.md#memory): reliable systems need to have knowledge of things that occurred
- [Planning](agentic_concepts.md#planning): planning steps (either explicit or implicit) are useful for ensuring that the LLM, when making decisions, makes them in the highest fidelity way.

## Challenges

In practice, there is often a trade-off between control and reliability. As we give LLMs more control, the application often becomes less reliable. This can be due to factors such as LLM non-determinism and / or errors in selecting tools (or steps) that the agent uses (takes).



## Core Principles

The motivation of LangGraph is to help bend the curve, preserving higher reliability as we give the agent more control over the application. We'll outline a few specific pillars of LangGraph that make it well suited for building reliable agents. 



**Controllability**

LangGraph gives the developer a high degree of [control](/langgraphjs/how-tos#controllability) by expressing the flow of the application as a set of nodes and edges. All nodes can access and modify a common state (memory). The control flow of the application can set using edges that connect nodes, either deterministically or via conditional logic. 

**Persistence**

LangGraph gives the developer many options for [persisting](/langgraphjs/how-tos#persistence) graph state using short-term or long-term (e.g., via a database) memory. 

**Human-in-the-Loop**

The persistence layer enables several different [human-in-the-loop](/langgraphjs/how-tos#human-in-the-loop) interaction patterns with agents; for example, it's possible to pause an agent, review its state, edit it state, and approve a follow-up step. 

**Streaming**

LangGraph comes with first class support for [streaming](/langgraphjs/how-tos#streaming), which can expose state to the user (or developer) over the course of agent execution. LangGraph supports streaming of both events ([like a tool call being taken](/langgraphjs/how-tos/stream-updates.ipynb)) as well as of [tokens that an LLM may emit](/langgraphjs/how-tos/streaming-tokens).

## Debugging

Once you've built a graph, you often want to test and debug it. [LangGraph Studio](https://github.com/langchain-ai/langgraph-studio?tab=readme-ov-file) is a specialized IDE for visualization and debugging of LangGraph applications.



## Deployment

Once you have confidence in your LangGraph application, many developers want an easy path to deployment. [LangGraph Cloud](/langgraphjs/cloud) is an opinionated, simple way to deploy LangGraph objects from the LangChain team. Of course, you can also use services like [Express.js](https://expressjs.com/) and call your graph from inside the Express.js server as you see fit.

---

### Docs Concepts Human In The Loop (`docs/docs/concepts/human_in_the_loop.md`)

# Human-in-the-loop

!!! tip "This guide uses the new `interrupt` function."

    As of LangGraph 0.2.31, the recommended way to set breakpoints is using the [`interrupt` function](/langgraphjs/reference/functions/langgraph.interrupt-1.html) as it simplifies **human-in-the-loop** patterns.

    If you're looking for the previous version of this conceptual guide, which relied on static breakpoints and `NodeInterrupt` exception, it is available [here](v0-human-in-the-loop.md).

A **human-in-the-loop** (or "on-the-loop") workflow integrates human input into automated processes, allowing for decisions, validation, or corrections at key stages. This is especially useful in **LLM-based applications**, where the underlying model may generate occasional inaccuracies. In low-error-tolerance scenarios like compliance, decision-making, or content generation, human involvement ensures reliability by enabling review, correction, or override of model outputs.

## Use cases

Key use cases for **human-in-the-loop** workflows in LLM-based applications include:

1. [**🛠️ Reviewing tool calls**](#review-tool-calls): Humans can review, edit, or approve tool calls requested by the LLM before tool execution.

2. **✅ Validating LLM outputs**: Humans can review, edit, or approve content generated by the LLM.

3. **💡 Providing context**: Enable the LLM to explicitly request human input for clarification or additional details or to support multi-turn conversations.

## `interrupt`

The [`interrupt` function](/langgraphjs/reference/functions/langgraph.interrupt-1.html) in LangGraph enables human-in-the-loop workflows by pausing the graph at a specific node, presenting information to a human, and resuming the graph with their input. This function is useful for tasks like approvals, edits, or collecting additional input. The [`interrupt` function](/langgraphjs/reference/functions/langgraph.interrupt-1.html) is used in conjunction with the [`Command`](/langgraphjs/reference/classes/langgraph.Command.html) object to resume the graph with a value provided by the human.

```typescript
import { interrupt } from "@langchain/langgraph";

function humanNode(state: typeof GraphAnnotation.State) {
  const value = interrupt(
    // Any JSON serializable value to surface to the human.
    // For example, a question or a piece of text or a set of keys in the state
    {
      text_to_revise: state.some_text,
    }
  );
  // Update the state with the human's input or route the graph based on the input
  return {
    some_text: value,
  };
}

const graph = workflow.compile({
  checkpointer, // Required for `interrupt` to work
});

// Run the graph until the interrupt
const threadConfig = { configurable: { thread_id: "some_id" } };
await graph.invoke(someInput, threadConfig);

// Below code can run some amount of time later and/or in a different process

// Human input
const valueFromHuman = "...";

// Resume the graph with the human's input
await graph.invoke(new Command({ resume: valueFromHuman }), threadConfig);
```

```typescript
{
  some_text: "Edited text";
}
```

??? "Full Code"

      Here's a full example of how to use `interrupt` in a graph, if you'd like
      to see the code in action.

      ```
/* Detailed source-code truncated for AI context efficiency. */
```

      ```typescript
      {
         __interrupt__: [
            {
               value: { question: 'Please revise the text', some_text: 'Original text' },
               resumable: true,
               ns: ['human_node:10fe492f-3688-c8c6-0d0a-ec61a43fecd6'],
               when: 'during'
            }
         ]
      }
      { human_node: { some_text: 'Edited text' } }
      ```

## Requirements

To use `interrupt` in your graph, you need to:

1. [**Specify a checkpointer**](persistence.md#checkpoints) to save the graph state after each step.

2. **Call `interrupt()`** in the appropriate place. See the [Design Patterns](#design-patterns) section for examples.

3. **Run the graph** with a [**thread ID**](./persistence.md#threads) until the `interrupt` is hit.

4. **Resume execution** using `invoke`/`stream` (see [**The `Command` primitive**](#the-command-primitive)).

## Design Patterns

There are typically three different **actions** that you can do with a human-in-the-loop workflow:

1. **Approve or Reject**: Pause the graph before a critical step, such as an API call, to review and approve the action. If the action is rejected, you can prevent the graph from executing the step, and potentially take an alternative action. This pattern often involves **routing** the graph based on the human's input.

2. **Edit Graph State**: Pause the graph to review and edit the graph state. This is useful for correcting mistakes or updating the state with additional information. This pattern often involves **updating** the state with the human's input.

3. **Get Input**: Explicitly request human input at a particular step in the graph. This is useful for collecting additional information or context to inform the agent's decision-making process or for supporting **multi-turn conversations**.

Below we show different design patterns that can be implemented using these **actions**.

**Note:** The `interrupt` function propagates by throwing a special `GraphInterrupt` error. Therefore, you should avoid using `try/catch` blocks around the `interrupt` function - or if you do, ensure that the `GraphInterrupt` error is thrown again within your `catch` block.

### Approve or Reject

<figure markdown="1">

{: style="max-height:400px"}

<figcaption>Depending on the human's approval or rejection, the graph can proceed with the action or take an alternative path.</figcaption>

</figure>

Pause the graph before a critical step, such as an API call, to review and approve the action. If the action is rejected, you can prevent the graph from executing the step, and potentially take an alternative action.

```typescript
import { interrupt, Command } from "@langchain/langgraph";

function humanApproval(state: typeof GraphAnnotation.State): Command {
  const isApproved = interrupt({
    question: "Is this correct?",
    // Surface the output that should be
    // reviewed and approved by the human.
    llm_output: state.llm_output,
  });

  if (isApproved) {
    return new Command({ goto: "some_node" });
  } else {
    return new Command({ goto: "another_node" });
  }
}

// Add the node to the graph in an appropriate location
// and connect it to the relevant nodes.
const graph = graphBuilder
  .addNode("human_approval", humanApproval)
  .compile({ checkpointer });

// After running the graph and hitting the interrupt, the graph will pause.
// Resume it with either an approval or rejection.
const threadConfig = { configurable: { thread_id: "some_id" } };
await graph.invoke(new Command({ resume: true }), threadConfig);
```

See [how to review tool calls](/langgraphjs/how-tos/review-tool-calls) for a more detailed example.

### Review & Edit State

<figure markdown="1">

{: style="max-height:400px"}

<figcaption>A human can review and edit the state of the graph. This is useful for correcting mistakes or updating the state with additional information.

</figcaption>

</figure>

```typescript
import { interrupt } from "@langchain/langgraph";

function humanEditing(state: typeof GraphAnnotation.State): Command {
  const result = interrupt({
    // Interrupt information to surface to the client.
    // Can be any JSON serializable value.
    task: "Review the output from the LLM and make any necessary edits.",
    llm_generated_summary: state.llm_generated_summary,
  });

  // Update the state with the edited text
  return {
    llm_generated_summary: result.edited_text,
  };
}

// Add the node to the graph in an appropriate location
// and connect it to the relevant nodes.
const graph = graphBuilder
  .addNode("human_editing", humanEditing)
  .compile({ checkpointer });

// After running the graph and hitting the interrupt, the graph will pause.
// Resume it with the edited text.
const threadConfig = { configurable: { thread_id: "some_id" } };
await graph.invoke(
  new Command({ resume: { edited_text: "The edited text" } }),
  threadConfig
);
```

See [How to wait for user input using interrupt](/langgraphjs/how-tos/wait-user-input) for a more detailed example.

### Review Tool Calls

<figure markdown="1">

{: style="max-height:400px"}

<figcaption>A human can review and edit the output from the LLM before proceeding. This is particularly
critical in applications where the tool calls requested by the LLM may be sensitive or require human oversight.

</figcaption>

</figure>

```typescript
import { interrupt, Command } from "@langchain/langgraph";

function humanReviewNode(state: typeof GraphAnnotation.State): Command {
  // This is the value we'll be providing via Command.resume(<human_review>)
  const humanReview = interrupt({
    question: "Is this correct?",
    // Surface tool calls for review
    tool_call: toolCall,
  });

  const [reviewAction, reviewData] = humanReview;

  // Approve the tool call and continue
  if (reviewAction === "continue") {
    return new Command({ goto: "run_tool" });
  }
  // Modify the tool call manually and then continue
  else if (reviewAction === "update") {
    const updatedMsg = getUpdatedMsg(reviewData);
    // Remember that to modify an existing message you will need
    // to pass the message with a matching ID.
    return new Command({
      goto: "run_tool",
      update: { messages: [updatedMsg] },
    });
  }
  // Give natural language feedback, and then pass that back to the agent
  else if (reviewAction === "feedback") {
    const feedbackMsg = getFeedbackMsg(reviewData);
    return new Command({
      goto: "call_llm",
      update: { messages: [feedbackMsg] },
    });
  }
}
```

See [how to review tool calls](/langgraphjs/how-tos/review-tool-calls) for a more detailed example.

### Multi-turn conversation

<figure markdown="1">

{: style="max-height:400px"}

<figcaption>A <strong>multi-turn conversation</strong> architecture where an <strong>agent</strong> and <strong>human node</strong> cycle back and forth until the agent decides to hand off the conversation to another agent or another part of the system.

</figcaption>

</figure>

A **multi-turn conversation** involves multiple back-and-forth interactions between an agent and a human, which can allow the agent to gather additional information from the human in a conversational manner.

This design pattern is useful in an LLM application consisting of [multiple agents](./multi_agent.md). One or more agents may need to carry out multi-turn conversations with a human, where the human provides input or feedback at different stages of the conversation. For simplicity, the agent implementation below is illustrated as a single node, but in reality it may be part of a larger graph consisting of multiple nodes and include a conditional edge.

=== "Using a human node per agent"

    In this pattern, each agent has its own human node for collecting user input.

    This can be achieved by either naming the human nodes with unique names (e.g., "human for agent 1", "human for agent 2") or by
    using subgraphs where a subgraph contains a human node and an agent node.

    ```typescript
    import { interrupt } from "@langchain/langgraph";

    function humanInput(state: typeof GraphAnnotation.State) {
      const humanMessage = interrupt("human_input");

      return {
        messages: [
          {
            role: "human",
            content: humanMessage
          }
        ]
      };
    }

    function agent(state: typeof GraphAnnotation.State) {
      // Agent logic
      // ...
    }

    const graph = graphBuilder
      .addNode("human_input", humanInput)
      .addEdge("human_input", "agent")
      .compile({ checkpointer });

    // After running the graph and hitting the interrupt, the graph will pause.
    // Resume it with the human's input.
    await graph.invoke(
      new Command({ resume: "hello!" }),
      threadConfig
    );
    ```

=== "Sharing human node across multiple agents"

    In this pattern, a single human node is used to collect user input for multiple agents. The active agent is determined from the state, so after human input is collected, the graph can route to the correct agent.

    ```typescript
    import { interrupt, Command, MessagesAnnotation } from "@langchain/langgraph";

    function humanNode(state: typeof MessagesAnnotation.State): Command {
      /**
       * A node for collecting user input.
       */
      const userInput = interrupt("Ready for user input.");

      // Determine the **active agent** from the state, so
      // we can route to the correct agent after collecting input.
      // For example, add a field to the state or use the last active agent.
      // or fill in `name` attribute of AI messages generated by the agents.
      const activeAgent = ...;

      return new Command({
        goto: activeAgent,
        update: {
          messages: [{
            role: "human",
            content: userInput,
          }]
        }
      });
    }
    ```

See [how to implement multi-turn conversations](/langgraphjs/how-tos/multi-agent-multi-turn-convo) for a more detailed example.

### Validating human input

If you need to validate the input provided by the human within the graph itself (rather than on the client side), you can achieve this by using multiple interrupt calls within a single node.

```typescript
import { interrupt } from "@langchain/langgraph";

function humanNode(state: typeof GraphAnnotation.State) {
  /**
   * Human node with validation.
   */
  let question = "What is your age?";

  while (true) {
    const answer = interrupt(question);

    // Validate answer, if the answer isn't valid ask for input again.
    if (typeof answer !== "number" || answer < 0) {
      question = `'${answer}' is not a valid age. What is your age?`;
      continue;
    } else {
      // If the answer is valid, we can proceed.
      break;
    }
  }

  console.log(`The human in the loop is ${answer} years old.`);

  return {
    age: answer,
  };
}
```

## The `Command` primitive

When using the `interrupt` function, the graph will pause at the interrupt and wait for user input.

Graph execution can be resumed using the [Command](/langgraphjs/reference/classes/langgraph.Command.html) primitive which can be passed through the `invoke` or `stream` methods.

The `Command` primitive provides several options to control and modify the graph's state during resumption:

1. **Pass a value to the `interrupt`**: Provide data, such as a user's response, to the graph using `new Command({ resume: value })`. Execution resumes from the beginning of the node where the `interrupt` was used, however, this time the `interrupt(...)` call will return the value passed in the `new Command({ resume: value })` instead of pausing the graph.

   ```typescript
   // Resume graph execution with the user's input.
   await graph.invoke(new Command({ resume: { age: "25" } }), threadConfig);
   ```

2. **Update the graph state**: Modify the graph state using `Command({ goto: ..., update: ... })`. Note that resumption starts from the beginning of the node where the `interrupt` was used. Execution resumes from the beginning of the node where the `interrupt` was used, but with the updated state.

   ```typescript
   // Update the graph state and resume.
   // You must provide a `resume` value if using an `interrupt`.
   await graph.invoke(
     new Command({ resume: "Let's go!!!", update: { foo: "bar" } }),
     threadConfig
   );
   ```

By leveraging `Command`, you can resume graph execution, handle user inputs, and dynamically adjust the graph's state.

## Using with `invoke`

When you use `stream` to run the graph, you will receive an `Interrupt` event that lets you know the `interrupt` was triggered.

`invoke` does not return the interrupt information. To access this information, you must use the [getState](/langgraphjs/reference/classes/langgraph.CompiledStateGraph.html#getState) method to retrieve the graph state after calling `invoke`.

```typescript
// Run the graph up to the interrupt
const result = await graph.invoke(inputs, threadConfig);

// Get the graph state to get interrupt information.
const state = await graph.getState(threadConfig);

// Print the state values
console.log(state.values);

// Print the pending tasks
console.log(state.tasks);

// Resume the graph with the user's input.
await graph.invoke(new Command({ resume: { age: "25" } }), threadConfig);
```

```typescript
{
  foo: "bar";
} // State values

[
  {
    id: "5d8ffc92-8011-0c9b-8b59-9d3545b7e553",
    name: "node_foo",
    path: ["__pregel_pull", "node_foo"],
    error: null,
    interrupts: [
      {
        value: "value_in_interrupt",
        resumable: true,
        ns: ["node_foo:5d8ffc92-8011-0c9b-8b59-9d3545b7e553"],
        when: "during",
      },
    ],
    state: null,
    result: null,
  },
]; // Pending tasks. interrupts
```

## How does resuming from an interrupt work?

A critical aspect of using `interrupt` is understanding how resuming works. When you resume execution after an `interrupt`, graph execution starts from the **beginning** of the **graph node** where the last `interrupt` was triggered.

**All** code from the beginning of the node to the `interrupt` will be re-executed.

```typescript
let counter = 0;

function node(state: State) {
  // All the code from the beginning of the node to the interrupt will be re-executed
  // when the graph resumes.
  counter += 1;

  console.log(`> Entered the node: ${counter} # of times`);

  // Pause the graph and wait for user input.
  const answer = interrupt();

  console.log("The value of counter is:", counter);
  // ...
}
```

Upon **resuming** the graph, the counter will be incremented a second time, resulting in the following output:

```typescript
> Entered the node: 2 # of times
The value of counter is: 2
```

## Common Pitfalls

### Side-effects

Place code with side effects, such as API calls, **after** the `interrupt` to avoid duplication, as these are re-triggered every time the node is resumed.

=== "Side effects before interrupt (BAD)"

    This code will re-execute the API call another time when the node is resumed from
    the `interrupt`.
    This can be problematic if the API call is not idempotent or is just expensive.

    ```typescript
    import { interrupt } from "@langchain/langgraph";

    function humanNode(state: typeof GraphAnnotation.State) {
      /**
       * Human node with validation.
       */
      apiCall(); // This code will be re-executed when the node is resumed.

      const answer = interrupt(question);
    }
    ```

=== "Side effects after interrupt (OK)"

    ```typescript
    import { interrupt } from "@langchain/langgraph";

    function humanNode(state: typeof GraphAnnotation.State) {
      /**
       * Human node with validation.
       */

      const answer = interrupt(question);

      apiCall(answer); // OK as it's after the interrupt
    }
    ```

=== "Side effects in a separate node (OK)"

    ```typescript
    import { interrupt } from "@langchain/langgraph";

    function humanNode(state: typeof GraphAnnotation.State) {
      /**
       * Human node with validation.
       */

      const answer = interrupt(question);

      return {
        answer
      };
    }

    function apiCallNode(state: typeof GraphAnnotation.State) {
      apiCall(); // OK as it's in a separate node
    }
    ```

### Subgraphs called as functions

When invoking a subgraph [as a function](low_level.md#as-a-function), the **parent graph** will resume execution from the **beginning of the node** where the subgraph was invoked (and where an `interrupt` was triggered). Similarly, the **subgraph**, will resume from the **beginning of the node** where the `interrupt()` function was called.

For example,

```typescript
async function nodeInParentGraph(state: typeof GraphAnnotation.State) {
    someCode();  // <-- This will re-execute when the subgraph is resumed.
    // Invoke a subgraph as a function.
    // The subgraph contains an `interrupt` call.
    const subgraphResult = await subgraph.invoke(someInput);
    ...
}
```

??? "**Example: Parent and Subgraph Execution Flow**"

      Say we have a parent graph with 3 nodes:

      **Parent Graph**: `node_1` → `node_2` (subgraph call) → `node_3`

      And the subgraph has 3 nodes, where the second node contains an `interrupt`:

      **Subgraph**: `sub_node_1` → `sub_node_2` (`interrupt`) → `sub_node_3`

      When resuming the graph, the execution will proceed as follows:

      1. **Skip `node_1`** in the parent graph (already executed, graph state was saved in snapshot).
      2. **Re-execute `node_2`** in the parent graph from the start.
      3. **Skip `sub_node_1`** in the subgraph (already executed, graph state was saved in snapshot).
      4. **Re-execute `sub_node_2`** in the subgraph from the beginning.
      5. Continue with `sub_node_3` and subsequent nodes.

      Here is abbreviated example code that you can use to understand how subgraphs work with interrupts.
      It counts the number of times each node is entered and prints the count.

      ```
/* Detailed source-code truncated for AI context efficiency. */
```

      This will print out

      ```typescript
      --- First invocation ---
      In parent node: { foo: 'bar' }
      Entered 'parentNode' a total of 1 times
      Entered 'nodeInSubgraph' a total of 1 times
      Entered humanNode in sub-graph a total of 1 times
      { __interrupt__: [{ value: 'what is your name?', resumable: true, ns: ['parent_node:0b23d72f-aaba-0329-1a59-ca4f3c8bad3b', 'human_node:25df717c-cb80-57b0-7410-44e20aac8f3c'], when: 'during' }] }

      --- Resuming ---
      In parent node: { foo: 'bar' }
      Entered 'parentNode' a total of 2 times
      Entered humanNode in sub-graph a total of 2 times
      Got an answer of 35
      { parent_node: null }
      ```

### Using multiple interrupts

Using multiple interrupts within a **single** node can be helpful for patterns like [validating human input](#validating-human-input). However, using multiple interrupts in the same node can lead to unexpected behavior if not handled carefully.

When a node contains multiple interrupt calls, LangGraph keeps a list of resume values specific to the task executing the node. Whenever execution resumes, it starts at the beginning of the node. For each interrupt encountered, LangGraph checks if a matching value exists in the task's resume list. Matching is **strictly index-based**, so the order of interrupt calls within the node is critical.

To avoid issues, refrain from dynamically changing the node's structure between executions. This includes adding, removing, or reordering interrupt calls, as such changes can result in mismatched indices. These problems often arise from unconventional patterns, such as mutating state via `Command.resume(...).update(SOME_STATE_MUTATION)` or relying on global variables to modify the node's structure dynamically.

??? "Example of incorrect code"

    ```typescript
    import { v4 as uuidv4 } from "uuid";
    import {
      StateGraph,
      MemorySaver,
      START,
      interrupt,
      Command,
      Annotation
    } from "@langchain/langgraph";

    const GraphAnnotation = Annotation.Root({
      name: Annotation<string>(),
      age: Annotation<string>()
    });

    function humanNode(state: typeof GraphAnnotation.State) {
      let name;
      if (!state.name) {
        name = interrupt("what is your name?");
      } else {
        name = "N/A";
      }

      let age;
      if (!state.age) {
        age = interrupt("what is your age?");
      } else {
        age = "N/A";
      }

      console.log(`Name: ${name}. Age: ${age}`);

      return {
        age,
        name,
      };
    }

    const builder = new StateGraph(GraphAnnotation)
      .addNode("human_node", humanNode);
      .addEdge(START, "human_node");

    // A checkpointer must be enabled for interrupts to work!
    const checkpointer = new MemorySaver();

    const graph = builder.compile({ checkpointer });

    const config = {
      configurable: {
        thread_id: uuidv4(),
      }
    };

    for await (const chunk of await graph.stream({ age: undefined, name: undefined }, config)) {
      console.log(chunk);
    }

    for await (const chunk of await graph.stream(
      new Command({ resume: "John", update: { name: "foo" } }),
      config
    )) {
      console.log(chunk);
    }
    ```

    ```typescript
    { __interrupt__: [{
      value: 'what is your name?',
      resumable: true,
      ns: ['human_node:3a007ef9-c30d-c357-1ec1-86a1a70d8fba'],
      when: 'during'
    }]}
    Name: N/A. Age: John
    { human_node: { age: 'John', name: 'N/A' } }
    ```

## Additional Resources 📚

- [**Conceptual Guide: Persistence**](persistence.md#replay): Read the persistence guide for more context on replaying.

- [**How to Guides: Human-in-the-loop**](/langgraphjs/how-tos/#human-in-the-loop): Learn how to implement human-in-the-loop workflows in LangGraph.

- [**How to implement multi-turn conversations**](/langgraphjs/how-tos/multi-agent-multi-turn-convo): Learn how to implement multi-turn conversations in LangGraph.

---

### Docs Concepts Langgraph Cli (`docs/docs/concepts/langgraph_cli.md`)

# LangGraph.js CLI

!!! info "Prerequisites"
    - [LangGraph Platform](./langgraph_platform.md)
    - [LangGraph Server](./langgraph_server.md)

The LangGraph.js CLI is a multi-platform command-line tool for building and running the [LangGraph.js API server](./langgraph_server.md) locally. This offers an alternative to the [LangGraph Studio desktop app](./langgraph_studio.md) for developing and testing agents across all major operating systems (Linux, Windows, MacOS). The resulting server includes all API endpoints for your graph's runs, threads, assistants, etc. as well as the other services required to run your agent, including a managed database for checkpointing and storage.

## Installation

The LangGraph.js CLI can be installed from the NPM registry:

=== "npx"
    ```bash
    npx @langchain/langgraph-cli
    ```

=== "npm"
    ```bash
    npm install @langchain/langgraph-cli
    ```

=== "yarn"
    ```bash
    yarn add @langchain/langgraph-cli
    ```

=== "pnpm"
    ```bash
    pnpm add @langchain/langgraph-cli
    ```

=== "bun"
    ```bash
    bun add @langchain/langgraph-cli
    ```

## Commands

The CLI provides the following core functionality:

### `build`

The `langgraph build` command builds a Docker image for the [LangGraph API server](./langgraph_server.md) that can be directly deployed.

### `dev`

The `langgraph dev` command starts a lightweight development server that requires no Docker installation. This server is ideal for rapid development and testing, with features like:

- Hot reloading: Changes to your code are automatically detected and reloaded
- In-memory state with local persistence: Server state is stored in memory for speed but persisted locally between restarts

**Note**: This command is intended for local development and testing only. It is not recommended for production use.

### `up`

The `langgraph up` command starts an instance of the [LangGraph API server](./langgraph_server.md) locally in a docker container. This requires the docker server to be running locally. It also requires a LangSmith API key for local development or a license key for production use.

The server includes all API endpoints for your graph's runs, threads, assistants, etc. as well as the other services required to run your agent, including a managed database for checkpointing and storage.

### `dockerfile`

The `langgraph dockerfile` command generates a [Dockerfile](https://docs.docker.com/reference/dockerfile/) that can be used to build images for and deploy instances of the [LangGraph API server](./langgraph_server.md). This is useful if you want to further customize the dockerfile or deploy in a more custom way.


??? note "Updating your langgraph.json file"
    The `langgraph dockerfile` command translates all the configuration in your `langgraph.json` file into Dockerfile commands. When using this command, you will have to re-run it whenever you update your `langgraph.json` file. Otherwise, your changes will not be reflected when you build or run the dockerfile.

## Related

- [LangGraph CLI API Reference](/langgraphjs/cloud/reference/cli/)

---

### Docs Concepts Langgraph Cloud (`docs/docs/concepts/langgraph_cloud.md`)

# Cloud SaaS

!!! info "Prerequisites"
    - [LangGraph Platform](./langgraph_platform.md)
    - [LangGraph Server](./langgraph_server.md)

## Overview

LangGraph's Cloud SaaS is a managed service that provides a scalable and secure environment for deploying LangGraph APIs. It is designed to work seamlessly with your LangGraph API regardless of how it is defined, what tools it uses, or any dependencies. Cloud SaaS provides a simple way to deploy and manage your LangGraph API in the cloud.

## Deployment

A **deployment** is an instance of a LangGraph API. A single deployment can have many [revisions](#revision). When a deployment is created, all the necessary infrastructure (e.g. database, containers, secrets store) are automatically provisioned. See the [architecture diagram](#architecture) below for more details.

See the [how-to guide](/langgraphjs/cloud/deployment/cloud.md#create-new-deployment) for creating a new deployment.

## Revision

A revision is an iteration of a [deployment](#deployment). When a new deployment is created, an initial revision is automatically created. To deploy new code changes or update environment variable configurations for a deployment, a new revision must be created. When a revision is created, a new container image is built automatically.

See the [how-to guide](/langgraphjs/cloud/deployment/cloud.md#create-new-revision) for creating a new revision.

## Asynchronous Deployment

Infrastructure for [deployments](#deployment) and [revisions](#revision) are provisioned and deployed asynchronously. They are not deployed immediately after submission. Currently, deployment can take up to several minutes.

## Architecture

!!! warning "Subject to Change"
The Cloud SaaS deployment architecture may change in the future.

A high-level diagram of a Cloud SaaS deployment.



## Related

- [Deployment Options](./deployment_options.md)

---

### Docs Concepts Langgraph Platform (`docs/docs/concepts/langgraph_platform.md`)

# LangGraph Platform

## Overview

LangGraph Platform is a commercial solution for deploying agentic applications to production, built on the open-source [LangGraph framework](./high_level.md).

The LangGraph Platform consists of several components that work together to support the development, deployment, debugging, and monitoring of LangGraph applications:

- [LangGraph Server](./langgraph_server.md): The server defines an opinionated API and architecture that incorporates best practices for deploying agentic applications, allowing you to focus on building your agent logic rather than developing server infrastructure.
- [LangGraph Studio](./langgraph_studio.md): LangGraph Studio is a specialized IDE that can connect to a LangGraph Server to enable visualization, interaction, and debugging of the application locally.
- [LangGraph CLI](./langgraph_cli.md): LangGraph CLI is a command-line interface that helps to interact with a local LangGraph
- [Python/JS SDK](./sdk.md): The Python/JS SDK provides a programmatic way to interact with deployed LangGraph Applications.
- [Remote Graph](../how-tos/use-remote-graph.md): A RemoteGraph allows you to interact with any deployed LangGraph application as though it were running locally.



The LangGraph Platform offers a few different deployment options described in the [deployment options guide](./deployment_options.md).

## Why Use LangGraph Platform?

LangGraph Platform is designed to make deploying agentic applications seamless and production-ready. 

For simpler applications, deploying a LangGraph agent can be as straightforward as using your own server logic—for example, setting up a FastAPI endpoint and invoking LangGraph directly.

### Option 1: Deploying with Custom Server Logic

For basic LangGraph applications, you may choose to handle deployment using your custom server infrastructure. Setting up endpoints with frameworks like [Hono](https://hono.dev/) allows you to quickly deploy and run LangGraph as you would any other JavaScript application:

```ts
// index.ts

import { Hono } from "hono";
import { StateGraph } from "@langchain/langgraph";

const graph = new StateGraph(...)

const app = new Hono();

app.get("/foo", (c) => {
  const res = await graph.invoke(...);
  return c.json(res);
});
```

This approach works well for simple applications with straightforward needs and provides you with full control over the deployment setup. For example, you might use this for a single-assistant application that doesn’t require long-running sessions or persistent memory.

### Option 2: Leveraging LangGraph Platform for Complex Deployments

As your applications scale or add complex features, the deployment requirements often evolve. Running an application with more nodes, longer processing times, or a need for persistent memory can introduce challenges that quickly become time-consuming and difficult to manage manually. [LangGraph Platform](./langgraph_platform.md) is built to handle these challenges seamlessly, allowing you to focus on agent logic rather than server infrastructure.

Here are some common issues that arise in complex deployments, which LangGraph Platform addresses:

- **[Streaming Support](streaming.md)**: As agents grow more sophisticated, they often benefit from streaming both token outputs and intermediate states back to the user. Without this, users are left waiting for potentially long operations with no feedback. LangGraph Server provides [multiple streaming modes](streaming.md) optimized for various application needs.

- **Background Runs**: For agents that take longer to process (e.g., hours), maintaining an open connection can be impractical. The LangGraph Server supports launching agent runs in the background and provides both polling endpoints and webhooks to monitor run status effectively.

- **Support for long runs**: Vanilla server setups often encounter timeouts or disruptions when handling requests that take a long time to complete. LangGraph Server’s API provides robust support for these tasks by sending regular heartbeat signals, preventing unexpected connection closures during prolonged processes.

- **Handling Burstiness**: Certain applications, especially those with real-time user interaction, may experience "bursty" request loads where numerous requests hit the server simultaneously. LangGraph Server includes a task queue, ensuring requests are handled consistently without loss, even under heavy loads.

- **[Double Texting](double_texting.md)**: In user-driven applications, it’s common for users to send multiple messages rapidly. This “double texting” can disrupt agent flows if not handled properly. LangGraph Server offers built-in strategies to address and manage such interactions.

- **[Checkpointers and Memory Management](persistence.md#checkpoints)**: For agents needing persistence (e.g., conversation memory), deploying a robust storage solution can be complex. LangGraph Platform includes optimized [checkpointers](persistence.md#checkpoints) and a [memory store](persistence.md#memory-store), managing state across sessions without the need for custom solutions.

- **[Human-in-the-loop Support](human_in_the_loop.md)**: In many applications, users require a way to intervene in agent processes. LangGraph Server provides specialized endpoints for human-in-the-loop scenarios, simplifying the integration of manual oversight into agent workflows.

By using LangGraph Platform, you gain access to a robust, scalable deployment solution that mitigates these challenges, saving you the effort of implementing and maintaining them manually. This allows you to focus more on building effective agent behavior and less on solving deployment infrastructure issues.

---

### Docs Concepts Langgraph Server (`docs/docs/concepts/langgraph_server.md`)

# LangGraph Server

!!! info "Prerequisites"
    - [LangGraph Platform](./langgraph_platform.md)
    - [LangGraph Glossary](low_level.md)

## Overview

LangGraph Server offers an API for creating and managing agent-based applications. It is built on the concept of [assistants](assistants.md), which are agents configured for specific tasks, and includes built-in [persistence](persistence.md#memory-store) and a **task queue**. This versatile API supports a wide range of agentic application use cases, from background processing to real-time interactions.

## Key Features

The LangGraph Platform incorporates best practices for agent deployment, so you can focus on building your agent logic.

* **Streaming endpoints**: Endpoints that expose [multiple different streaming modes](streaming.md). We've made these work even for long-running agents that may go minutes between consecutive stream events.
* **Background runs**: The LangGraph Server supports launching assistants in the background with endpoints for polling the status of the assistant's run and webhooks to monitor run status effectively.
- **Support for long runs**: Our blocking endpoints for running assistants send regular heartbeat signals, preventing unexpected connection closures when handling requests that take a long time to complete.
* **Task queue**: We've added a task queue to make sure we don't drop any requests if they arrive in a bursty nature.
* **Horizontally scalable infrastructure**: LangGraph Server is designed to be horizontally scalable, allowing you to scale up and down your usage as needed.
* **Double texting support**: Many times users might interact with your graph in unintended ways. For instance, a user may send one message and before the graph has finished running send a second message. We call this ["double texting"](double_texting.md) and have added four different ways to handle this.
* **Optimized checkpointer**: LangGraph Platform comes with a built-in [checkpointer](./persistence.md#checkpoints) optimized for LangGraph applications.
* **Human-in-the-loop endpoints**: We've exposed all endpoints needed to support [human-in-the-loop](human_in_the_loop.md) features.
* **Memory**: In addition to thread-level persistence (covered above by [checkpointers]l(./persistence.md#checkpoints)), LangGraph Platform also comes with a built-in [memory store](persistence.md#memory-store).
* **Cron jobs**: Built-in support for scheduling tasks, enabling you to automate regular actions like data clean-up or batch processing within your applications.
* **Webhooks**: Allows your application to send real-time notifications and data updates to external systems, making it easy to integrate with third-party services and trigger actions based on specific events.
* **Monitoring**: LangGraph Server integrates seamlessly with the [LangSmith](https://docs.smith.langchain.com/) monitoring platform, providing real-time insights into your application's performance and health.

## What are you deploying?

When you deploy a LangGraph Server, you are deploying one or more [graphs](#graphs), a database for [persistence](persistence.md), and a task queue.

### Graphs

When you deploy a graph with LangGraph Server, you are deploying a "blueprint" for an [Assistant](assistants.md). 

An [Assistant](assistants.md) is a graph paired with specific configuration settings. You can create multiple assistants per graph, each with unique settings to accommodate different use cases
that can be served by the same graph.

Upon deployment, LangGraph Server will automatically create a default assistant for each graph using the graph's default configuration settings.

You can interact with assistants through the [LangGraph Server API](#langgraph-server-api).

!!! note

    We often think of a graph as implementing an [agent](agentic_concepts.md), but a graph does not necessarily need to implement an agent. For example, a graph could implement a simple
    chatbot that only supports back-and-forth conversation, without the ability to influence any application control flow. In reality, as applications get more complex, a graph will often implement a more complex flow that may use [multiple agents](./multi_agent.md) working in tandem.

### Persistence and Task Queue

The LangGraph Server leverages a database for [persistence](persistence.md) and a task queue.

Currently, only [Postgres](https://www.postgresql.org/) is supported as a database for LangGraph Server and [Redis](https://redis.io/) as the task queue.

If you're deploying using [LangGraph Cloud](./langgraph_cloud.md), these components are managed for you. If you're deploying LangGraph Server on your own infrastructure, you'll need to set up and manage these components yourself.

Please review the [deployment options](./deployment_options.md) guide for more information on how these components are set up and managed.

## Application Structure

To deploy a LangGraph Server application, you need to specify the graph(s) you want to deploy, as well as any relevant configuration settings, such as dependencies and environment variables.

Read the [application structure](./application_structure.md) guide to learn how to structure your LangGraph application for deployment.

## LangGraph Server API

The LangGraph Server API allows you to create and manage [assistants](assistants.md), [threads](#threads), [runs](#runs), [cron jobs](#cron-jobs), and more.

The [LangGraph Cloud API Reference](/langgraphjs/cloud/reference/api/api_ref.html) provides detailed information on the API endpoints and data models.

### Assistants

An [Assistant](assistants.md) refers to a [graph](#graphs) plus specific [configuration](low_level.md#configuration) settings for that graph.

You can think of an assistant as a saved configuration of an [agent](agentic_concepts.md).

When building agents, it is fairly common to make rapid changes that *do not* alter the graph logic. For example, simply changing prompts or the LLM selection can have significant impacts on the behavior of the agents. Assistants offer an easy way to make and save these types of changes to agent configuration.

### Threads

A thread contains the accumulated state of a sequence of [runs](#runs). If a run is executed on a thread, then the [state](low_level.md#state) of the underlying graph of the assistant will be persisted to the thread.

A thread's current and historical state can be retrieved. To persist state, a thread must be created prior to executing a run.

The state of a thread at a particular point in time is called a [checkpoint](persistence.md#checkpoints). Checkpoints can be used to restore the state of a thread at a later time.

For more on threads and checkpoints, see this section of the [LangGraph conceptual guide](low_level.md#persistence).

The LangGraph Cloud API provides several endpoints for creating and managing threads and thread state. See the [API reference](/langgraphjs/cloud/reference/api/api_ref.html#tag/threadscreate) for more details.

### Runs

A run is an invocation of an [assistant](#assistants). Each run may have its own input, configuration, and metadata, which may affect execution and output of the underlying graph. A run can optionally be executed on a [thread](#threads).

The LangGraph Cloud API provides several endpoints for creating and managing runs. See the [API reference](/langgraphjs/cloud/reference/api/api_ref.html#tag/runsmanage) for more details.

### Store

Store is an API for managing persistent [key-value store](./persistence.md#memory-store) that is available from any [thread](#threads).

Stores are useful for implementing [memory](./memory.md) in your LangGraph application.

### Cron Jobs

There are many situations in which it is useful to run an assistant on a schedule. 

For example, say that you're building an assistant that runs daily and sends an email summary
of the day's news. You could use a cron job to run the assistant every day at 8:00 PM.

LangGraph Cloud supports cron jobs, which run on a user-defined schedule. The user specifies a schedule, an assistant, and some input. After that, on the specified schedule, the server will:

- Create a new thread with the specified assistant
- Send the specified input to that thread

Note that this sends the same input to the thread every time. See the [how-to guide](/langgraphjs/cloud/how-tos/cron_jobs.md) for creating cron jobs.

The LangGraph Cloud API provides several endpoints for creating and managing cron jobs. See the [API reference](/langgraphjs/cloud/reference/api/api_ref.html#tag/crons-enterprise-only) for more details.

### Webhooks

Webhooks enable event-driven communication from your LangGraph Cloud application to external services. For example, you may want to issue an update to a separate service once an API call to LangGraph Cloud has finished running.

Many LangGraph Cloud endpoints accept a `webhook` parameter. If this parameter is specified by an endpoint that can accept POST requests, LangGraph Cloud will send a request at the completion of a run.

See the corresponding [how-to guide](/langgraphjs/cloud/how-tos/webhooks.md) for more details.

## Related

* LangGraph [Application Structure](./application_structure.md) guide explains how to structure your LangGraph application for deployment.
* [How-to guides for the LangGraph Platform](../how-tos/index.md).
* The [LangGraph Cloud API Reference](/langgraphjs/cloud/reference/api/api_ref.html) provides detailed information on the API endpoints and data models.

---

### Docs Concepts Langgraph Studio (`docs/docs/concepts/langgraph_studio.md`)

# LangGraph Studio

!!! info "Prerequisites"

    - [LangGraph Platform](./langgraph_platform.md)
    - [LangGraph Server](./langgraph_server.md)

LangGraph Studio offers a new way to develop LLM applications by providing a specialized agent IDE that enables visualization, interaction, and debugging of complex agentic applications.

With visual graphs and the ability to edit state, you can better understand agent workflows and iterate faster. LangGraph Studio integrates with LangSmith allowing you to  collaborate with teammates to debug failure modes.



## Features

The key features of LangGraph Studio are:

- Visualizes your graph
- Test your graph by running it from the UI
- Debug your agent by [modifying its state and rerunning](human_in_the_loop.md)
- Create and manage [assistants](assistants.md)
- View and manage [threads](persistence.md#threads)
- View and manage [long term memory](memory.md)
- Add node input/outputs to [LangSmith](https://smith.langchain.com/) datasets for testing

## Types

### Desktop app

LangGraph Studio is available as a [desktop app](https://studio.langchain.com/) for MacOS users.

While in Beta, LangGraph Studio is available for free to all [LangSmith](https://smith.langchain.com/) users on any plan tier.

### Cloud studio

If you have deployed your LangGraph application on LangGraph Platform (Cloud), you can access the studio as part of that

## Studio FAQs

### Why is my project failing to start?

There are a few reasons that your project might fail to start, here are some of the most common ones.

#### Docker issues (desktop only)

LangGraph Studio (desktop) requires Docker Desktop version 4.24 or higher. Please make sure you have a version of Docker installed that satisfies that requirement and also make sure you have the Docker Desktop app up and running before trying to use LangGraph Studio. In addition, make sure you have docker-compose updated to version 2.22.0 or higher.

#### Configuration or environment issues

Another reason your project might fail to start is because your configuration file is defined incorrectly, or you are missing required environment variables. 

### How does interrupt work?

When you select the `Interrupts` dropdown and select a node to interrupt the graph will pause execution before and after (unless the node goes straight to `END`) that node has run. This means that you will be able to both edit the state before the node is ran and the state after the node has ran. This is intended to allow developers more fine-grained control over the behavior of a node and make it easier to observe how the node is behaving. You will not be able to edit the state after the node has ran if the node is the final node in the graph.

### How do I reload the app?  (desktop only)

If you would like to reload the app, don't use Command+R as you might normally do. Instead, close and reopen the app for a full refresh.

### How does automatic rebuilding work?  (desktop only)

One of the key features of LangGraph Studio is that it automatically rebuilds your image when you change the source code. This allows for a super fast development and testing cycle which makes it easy to iterate on your graph. There are two different ways that LangGraph rebuilds your image: either by editing the image or completely rebuilding it.

#### Rebuilds from source code changes

If you modified the source code only (no configuration or dependency changes!) then the image does not require a full rebuild, and LangGraph Studio will only update the relevant parts. The UI status in the bottom left will switch from `Online` to `Stopping` temporarily while the image gets edited. The logs will be shown as this process is happening, and after the image has been edited the status will change back to `Online` and you will be able to run your graph with the modified code!


#### Rebuilds from configuration or dependency changes

If you edit your graph configuration file (`langgraph.json`) or the dependencies (either `pyproject.toml` or `requirements.txt`) then the entire image will be rebuilt. This will cause the UI to switch away from the graph view and start showing the logs of the new image building process. This can take a minute or two, and once it is done your updated image will be ready to use!

### Why is my graph taking so long to startup?  (desktop only)

The LangGraph Studio interacts with a local LangGraph API server. To stay aligned with ongoing updates, the LangGraph API requires regular rebuilding. As a result, you may occasionally experience slight delays when starting up your project.

## Why are extra edges showing up in my graph?

If you don't define your conditional edges carefully, you might notice extra edges appearing in your graph. This is because without proper definition, LangGraph Studio assumes the conditional edge could access all other nodes. In order for this to not be the case, you need to be explicit about how you define the nodes the conditional edge routes to. There are two ways you can do this:

### Solution 1: Include a path map

The first way to solve this is to add path maps to your conditional edges. A path map is just a dictionary or array that maps the possible outputs of your router function with the names of the nodes that each output corresponds to. The path map is passed as the third argument to the `add_conditional_edges` function like so:

=== "Python"

    ```python
    graph.add_conditional_edges("node_a", routing_function, {True: "node_b", False: "node_c"})
    ```

=== "Javascript"

    ```ts
    graph.addConditionalEdges("node_a", routingFunction, { foo: "node_b", bar: "node_c" });
    ```

In this case, the routing function returns either True or False, which map to `node_b` and `node_c` respectively.

### Solution 2: Update the typing of the router (Python only)

Instead of passing a path map, you can also be explicit about the typing of your routing function by specifying the nodes it can map to using the `Literal` python definition. Here is an example of how to define a routing function in that way:

```python
def routing_function(state: GraphState) -> Literal["node_b","node_c"]:
    if state['some_condition'] == True:
        return "node_b"
    else:
        return "node_c"
```


## Related

For more information please see the following:

*  [LangGraph Studio how-to guides](../how-tos/index.md#langgraph-studio)

---

### Docs Concepts Low Level (`docs/docs/concepts/low_level.md`)

# LangGraph Glossary

## Graphs

At its core, LangGraph models agent workflows as graphs. You define the behavior of your agents using three key components:

1. [`State`](#state): A shared data structure that represents the current snapshot of your application. It is represented by an [`Annotation`](/langgraphjs/reference/modules/langgraph.Annotation.html) object.

2. [`Nodes`](#nodes): JavaScript/TypeScript functions that encode the logic of your agents. They receive the current `State` as input, perform some computation or side-effect, and return an updated `State`.

3. [`Edges`](#edges): JavaScript/TypeScript functions that determine which `Node` to execute next based on the current `State`. They can be conditional branches or fixed transitions.

By composing `Nodes` and `Edges`, you can create complex, looping workflows that evolve the `State` over time. The real power, though, comes from how LangGraph manages that `State`. To emphasize: `Nodes` and `Edges` are nothing more than JavaScript/TypeScript functions - they can contain an LLM or just good ol' JavaScript/TypeScript code.

In short: _nodes do the work. edges tell what to do next_.

LangGraph's underlying graph algorithm uses [message passing](https://en.wikipedia.org/wiki/Message_passing) to define a general program. When a Node completes its operation, it sends messages along one or more edges to other node(s). These recipient nodes then execute their functions, pass the resulting messages to the next set of nodes, and the process continues. Inspired by Google's [Pregel](https://research.google/pubs/pregel-a-system-for-large-scale-graph-processing/) system, the program proceeds in discrete "super-steps."

A super-step can be considered a single iteration over the graph nodes. Nodes that run in parallel are part of the same super-step, while nodes that run sequentially belong to separate super-steps. At the start of graph execution, all nodes begin in an `inactive` state. A node becomes `active` when it receives a new message (state) on any of its incoming edges (or "channels"). The active node then runs its function and responds with updates. At the end of each super-step, nodes with no incoming messages vote to `halt` by marking themselves as `inactive`. The graph execution terminates when all nodes are `inactive` and no messages are in transit.

### StateGraph

The `StateGraph` class is the main graph class to use. This is parameterized by a user defined `State` object. (defined using the `Annotation` object and passed as the first argument)

### MessageGraph (legacy) {#messagegraph}

The `MessageGraph` class is a special type of graph. The `State` of a `MessageGraph` is ONLY an array of messages. This class is rarely used except for chatbots, as most applications require the `State` to be more complex than an array of messages.

### Compiling your graph

To build your graph, you first define the [state](#state), you then add [nodes](#nodes) and [edges](#edges), and then you compile it. What exactly is compiling your graph and why is it needed?

Compiling is a pretty simple step. It provides a few basic checks on the structure of your graph (no orphaned nodes, etc). It is also where you can specify runtime args like checkpointers and [breakpoints](#breakpoints). You compile your graph by just calling the `.compile` method:

```typescript
const graph = graphBuilder.compile(...);
```

You **MUST** compile your graph before you can use it.

## State

The first thing you do when you define a graph is define the `State` of the graph. The `State` includes information on the structure of the graph, as well as [`reducer` functions](#reducers) which specify how to apply updates to the state. The schema of the `State` will be the input schema to all `Nodes` and `Edges` in the graph, and should be defined using an [`Annotation`](/langgraphjs/reference/modules/langgraph.Annotation.html) object. All `Nodes` will emit updates to the `State` which are then applied using the specified `reducer` function.

### Annotation

The way to specify the schema of a graph is by defining a root [`Annotation`](/langgraphjs/reference/modules/langgraph.Annotation.html) object, where each key is an item in the state.

#### Multiple schemas

Typically, all graph nodes communicate with a single state annotation. This means that they will read and write to the same state channels. But, there are cases where we want more control over this:

- Internal nodes can pass information that is not required in the graph's input / output.
- We may also want to use different input / output schemas for the graph. The output might, for example, only contain a single relevant output key.

It is possible to have nodes write to private state channels inside the graph for internal node communication. We can simply define a private annotation, `PrivateState`. See [this notebook](../how-tos/pass_private_state.ipynb) for more detail.

It is also possible to define explicit input and output schemas for a graph. In these cases, we define an "internal" schema that contains _all_ keys relevant to graph operations. But, we also define `input` and `output` schemas that are sub-sets of the "internal" schema to constrain the input and output of the graph. See [this guide](../how-tos/input_output_schema.ipynb) for more detail.

Let's look at an example:

```
/* Detailed source-code truncated for AI context efficiency. */
```

```
{ graph_output: "My name is Lance" }
```

Note that we pass `state: typeof InputStateAnnotation.State` as the input schema to `node1`. But, we write out to `foo`, a channel in `OverallStateAnnotation`. How can we write out to a state channel that is not included in the input schema? This is because a node _can write to any state channel in the graph state._ The graph state is the union of of the state channels defined at initialization, which includes `OverallStateAnnotation` and the filters `InputStateAnnotation` and `OutputStateAnnotation`.

### Reducers

Reducers are key to understanding how updates from nodes are applied to the `State`. Each key in the `State` has its own independent reducer function. If no reducer function is explicitly specified then it is assumed that all updates to that key should override it. Let's take a look at a few examples to understand them better.

**Example A:**

```typescript
import { StateGraph, Annotation } from "@langchain/langgraph";

const State = Annotation.Root({
  foo: Annotation<number>,
  bar: Annotation<string[]>,
});

const graphBuilder = new StateGraph(State);
```

In this example, no reducer functions are specified for any key. Let's assume the input to the graph is `{ foo: 1, bar: ["hi"] }`. Let's then assume the first `Node` returns `{ foo: 2 }`. This is treated as an update to the state. Notice that the `Node` does not need to return the whole `State` schema - just an update. After applying this update, the `State` would then be `{ foo: 2, bar: ["hi"] }`. If the second node returns `{ bar: ["bye"] }` then the `State` would then be `{ foo: 2, bar: ["bye"] }`

**Example B:**

```typescript
import { StateGraph, Annotation } from "@langchain/langgraph";

const State = Annotation.Root({
  foo: Annotation<number>,
  bar: Annotation<string[]>({
    reducer: (state: string[], update: string[]) => state.concat(update),
    default: () => [],
  }),
});

const graphBuilder = new StateGraph(State);
```

In this example, we've updated our `bar` field to be an object containing a `reducer` function. This function will always accept two positional arguments: `state` and `update`, with `state` representing the current state value, and `update` representing the update returned from a `Node`. Note that the first key remains unchanged. Let's assume the input to the graph is `{ foo: 1, bar: ["hi"] }`. Let's then assume the first `Node` returns `{ foo: 2 }`. This is treated as an update to the state. Notice that the `Node` does not need to return the whole `State` schema - just an update. After applying this update, the `State` would then be `{ foo: 2, bar: ["hi"] }`. If the second node returns`{ bar: ["bye"] }` then the `State` would then be `{ foo: 2, bar: ["hi", "bye"] }`. Notice here that the `bar` key is updated by concatenating the two arrays together.

### Working with Messages in Graph State

#### Why use messages?

Most modern LLM providers have a chat model interface that accepts a list of messages as input. LangChain's [`ChatModel`](https://js.langchain.com/docs/concepts/#chat-models) in particular accepts a list of `Message` objects as inputs. These messages come in a variety of forms such as `HumanMessage` (user input) or `AIMessage` (LLM response). To read more about what message objects are, please refer to [this](https://js.langchain.com/docs/concepts/#message-types) conceptual guide.

#### Using Messages in your Graph

In many cases, it is helpful to store prior conversation history as a list of messages in your graph state. To do so, we can add a key (channel) to the graph state that stores a list of `Message` objects and annotate it with a reducer function (see `messages` key in the example below). The reducer function is vital to telling the graph how to update the list of `Message` objects in the state with each state update (for example, when a node sends an update). If you don't specify a reducer, every state update will overwrite the list of messages with the most recently provided value.

However, you might also want to manually update messages in your graph state (e.g. human-in-the-loop). If you were to use something like `(a, b) => a.concat(b)` as a reducer, the manual state updates you send to the graph would be appended to the existing list of messages, instead of updating existing messages. To avoid that, you need a reducer that can keep track of message IDs and overwrite existing messages, if updated. To achieve this, you can use the prebuilt `messagesStateReducer` function. For brand new messages, it will simply append to existing list, but it will also handle the updates for existing messages correctly.

#### Serialization

In addition to keeping track of message IDs, the `messagesStateReducer` function will also try to deserialize messages into LangChain `Message` objects whenever a state update is received on the `messages` channel. This allows sending graph inputs / state updates in the following format:

```ts
// this is supported
{
  messages: [new HumanMessage({ content: "message" })];
}

// and this is also supported
{
  messages: [{ role: "user", content: "message" }];
}
```

Below is an example of a graph state annotation that uses `messagesStateReducer` as its reducer function.

```ts
import type { BaseMessage } from "@langchain/core/messages";
import { Annotation, messagesStateReducer, type Messages } from "@langchain/langgraph";

const StateAnnotation = Annotation.Root({
  messages: Annotation<BaseMessage[], Messages>({
    reducer: messagesStateReducer,
  }),
});
```

#### MessagesAnnotation

Since having a list of messages in your state is so common, there exists a prebuilt annotation called `MessagesAnnotation` which makes it easy to use messages as graph state. `MessagesAnnotation` is defined with a single `messages` key which is a list of `BaseMessage` objects and uses the `messagesStateReducer` reducer.

```typescript
import { MessagesAnnotation, StateGraph } from "@langchain/langgraph";

const graph = new StateGraph(MessagesAnnotation)
  .addNode(...)
  ...
```

Is equivalent to initializing your state manually like this:

```typescript
import { BaseMessage } from "@langchain/core/messages";
import { Annotation, StateGraph, messagesStateReducer } from "@langchain/langgraph";

export const StateAnnotation = Annotation.Root({
  messages: Annotation<BaseMessage[]>({
    reducer: messagesStateReducer,
    default: () => [],
  }),
});

const graph = new StateGraph(StateAnnotation)
  .addNode(...)
  ...
```

The state of a `MessagesAnnotation` has a single key called `messages`. This is an array of `BaseMessage`s, with [`messagesStateReducer`](/langgraphjs/reference/functions/langgraph.messagesStateReducer.html) as a reducer. `messagesStateReducer` basically adds messages to the existing list (it also does some nice extra things, like convert from OpenAI message format to the standard LangChain message format, handle updates based on message IDs, etc).

We often see an array of messages being a key component of state, so this prebuilt state is intended to make it easy to use messages. Typically, there is more state to track than just messages, so we see people extend this state and add more fields, like:

```typescript
import { Annotation, MessagesAnnotation } from "@langchain/langgraph";

const StateWithDocuments = Annotation.Root({
  ...MessagesAnnotation.spec, // Spread in the messages state
  documents: Annotation<string[]>,
});
```

#### Messages in Zod

If you're using Zod for defining your graph state, you can use the `MessagesZodMeta` schema together with `registry` from `@langchain/langgraph/zod` to define the messages state.

```typescript
import type { BaseMessage } from "@langchain/core/messages";
import { MessagesZodMeta, StateGraph } from "@langchain/langgraph";
import { registry } from "@langchain/langgraph/zod";
import { z } from "zod/v4";

const MessagesZodState = z.object({
  messages: z.custom<BaseMessage[]>().register(registry, MessagesZodMeta),
});

const graph = new StateGraph(MessagesZodState)
  .addNode(...)
  ...
```

??? note "Using Zod 3?"

    If you're using Zod 3, you can use prebuilt `MessagesZodState` instead.

    ```typescript
    import { MessagesZodState, StateGraph } from "@langchain/langgraph";

    import { z } from "zod";

    const graph = new StateGraph(MessagesZodState)
      .addNode(...)
      ...
    ```

For more on defining graph state using Zod, see the [defining graph state how-to](/langgraphjs/how-tos/define-state/#using-zod).

## Nodes

In LangGraph, nodes are typically JavaScript/TypeScript functions (sync or `async`) where the **first** positional argument is the [state](#state), and (optionally), the **second** positional argument is a "config", containing optional [configurable parameters](#configuration) (such as a `thread_id`).

Similar to `NetworkX`, you add these nodes to a graph using the [addNode](/langgraphjs/reference/classes/langgraph.StateGraph.html#addNode) method:

```typescript
import { RunnableConfig } from "@langchain/core/runnables";
import { StateGraph, Annotation } from "@langchain/langgraph";

const GraphAnnotation = Annotation.Root({
  input: Annotation<string>,
  results: Annotation<string>,
});

// The state type can be extracted using `typeof <annotation variable name>.State`
const myNode = (state: typeof GraphAnnotation.State, config?: RunnableConfig) => {
  console.log("In node: ", config.configurable?.user_id);
  return {
    results: `Hello, ${state.input}!`
  };
};

// The second argument is optional
const myOtherNode = (state: typeof GraphAnnotation.State) => {
  return state;
};

const builder = new StateGraph(GraphAnnotation)
  .addNode("myNode", myNode)
  .addNode("myOtherNode", myOtherNode)
  ...
```

Behind the scenes, functions are converted to [RunnableLambda's](https://v02.api.js.langchain.com/classes/langchain_core_runnables.RunnableLambda.html), which adds batch and streaming support to your function, along with native tracing and debugging.

### `START` Node

The `START` Node is a special node that represents the node sends user input to the graph. The main purpose for referencing this node is to determine which nodes should be called first.

```typescript
import { START } from "@langchain/langgraph";

graph.addEdge(START, "nodeA");
```

### `END` Node

The `END` Node is a special node that represents a terminal node. This node is referenced when you want to denote which edges have no actions after they are done.

```typescript
import { END } from "@langchain/langgraph";

graph.addEdge("nodeA", END);
```

## Edges

Edges define how the logic is routed and how the graph decides to stop. This is a big part of how your agents work and how different nodes communicate with each other. There are a few key types of edges:

- Normal Edges: Go directly from one node to the next.
- Conditional Edges: Call a function to determine which node(s) to go to next.
- Entry Point: Which node to call first when user input arrives.
- Conditional Entry Point: Call a function to determine which node(s) to call first when user input arrives.

A node can have MULTIPLE outgoing edges. If a node has multiple out-going edges, **all** of those destination nodes will be executed in parallel as a part of the next superstep.

### Normal Edges

If you **always** want to go from node A to node B, you can use the [addEdge](/langgraphjs/reference/classes/langgraph.StateGraph.html#addEdge) method directly.

```typescript
graph.addEdge("nodeA", "nodeB");
```

### Conditional Edges

If you want to **optionally** route to 1 or more edges (or optionally terminate), you can use the [addConditionalEdges](/langgraphjs/reference/classes/langgraph.StateGraph.html#addConditionalEdges) method. This method accepts the name of a node and a "routing function" to call after that node is executed:

```typescript
graph.addConditionalEdges("nodeA", routingFunction);
```

Similar to nodes, the `routingFunction` accepts the current `state` of the graph and return a value.

By default, the return value `routingFunction` is used as the name of the node (or an array of nodes) to send the state to next. All those nodes will be run in parallel as a part of the next superstep.

You can optionally provide an object that maps the `routingFunction`'s output to the name of the next node.

```typescript
graph.addConditionalEdges("nodeA", routingFunction, {
  true: "nodeB",
  false: "nodeC",
});
```

!!! tip
Use [`Command`](#command) instead of conditional edges if you want to combine state updates and routing in a single function.

### Entry Point

The entry point is the first node(s) that are run when the graph starts. You can use the [`addEdge`](/langgraphjs/reference/classes/langgraph.StateGraph.html#addEdge) method from the virtual [`START`](/langgraphjs/reference/variables/langgraph.START.html) node to the first node to execute to specify where to enter the graph.

```typescript hl_lines="4"
import { START } from "@langchain/langgraph";

const graph = new StateGraph(...)
  .addEdge(START, "nodeA")
  .compile();
```

### Conditional Entry Point

A conditional entry point lets you start at different nodes depending on custom logic. You can use [`addConditionalEdges`](/langgraphjs/reference/classes/langgraph.StateGraph.html#addConditionalEdges) from the virtual [`START`](/langgraphjs/reference/variables/langgraph.START.html) node to accomplish this.

```typescript hl_lines="4"
import { START } from "@langchain/langgraph";

const graph = new StateGraph(...)
  .addConditionalEdges(START, routingFunction)
  .compile();
```

You can optionally provide an object that maps the `routingFunction`'s output to the name of the next node.

```typescript hl_lines="2-5"
const graph = new StateGraph(...)
  .addConditionalEdges(START, routingFunction, {
    true: "nodeB",
    false: "nodeC",
  })
  .compile();
```

## `Send`

By default, `Nodes` and `Edges` are defined ahead of time and operate on the same shared state. However, there can be cases where the exact edges are not known ahead of time and/or you may want different versions of `State` to exist at the same time. A common example of this is with `map-reduce` design patterns. In this design pattern, a first node may generate an array of objects, and you may want to apply some other node to all those objects. The number of objects may be unknown ahead of time (meaning the number of edges may not be known) and the input `State` to the downstream `Node` should be different (one for each generated object).

To support this design pattern, LangGraph supports returning [`Send`](/langgraphjs/reference/classes/langgraph.Send.html) objects from conditional edges. `Send` takes two arguments: first is the name of the node, and second is the state to pass to that node.

```typescript hl_lines="8"
const continueToJokes = (state: { subjects: string[] }) => {
  return state.subjects.map(
    (subject) => new Send("generate_joke", { subject })
  );
};

const graph = new StateGraph(...)
  .addConditionalEdges("nodeA", continueToJokes)
  .compile();
```

## `Command`

!!! tip Compatibility
This functionality requires `@langchain/langgraph>=0.2.31`.

It can be convenient to combine control flow (edges) and state updates (nodes). For example, you might want to BOTH perform state updates AND decide which node to go to next in the SAME node rather than use a conditional edge. LangGraph provides a way to do so by returning a [`Command`](https://langchain-ai.github.io/langgraphjs/reference/classes/langgraph.Command.html) object from node functions:

```ts
import { StateGraph, Annotation, Command } from "@langchain/langgraph";

const StateAnnotation = Annotation.Root({
  foo: Annotation<string>,
});

const myNode = (state: typeof StateAnnotation.State) => {
  return new Command({
    // state update
    update: {
      foo: "bar",
    },
    // control flow
    goto: "myOtherNode",
  });
};
```

With `Command` you can also achieve dynamic control flow behavior (identical to [conditional edges](#conditional-edges)):

```ts
const myNode = async (state: typeof StateAnnotation.State) => {
  if (state.foo === "bar") {
    return new Command({
      update: {
        foo: "baz",
      },
      goto: "myOtherNode",
    });
  }
  // ...
};
```

!!! important

    When returning `Command` in your node functions, you must also add an `ends` parameter with the list of node names the node is routing to, e.g. `.addNode("myNode", myNode, { ends: ["myOtherNode"] })`. This is necessary for graph compilation and validation, and indicates that `myNode` can navigate to `myOtherNode`.

Check out this [how-to guide](../how-tos/command.ipynb) for an end-to-end example of how to use `Command`.

### When should I use Command instead of conditional edges?

Use `Command` when you need to **both** update the graph state **and** route to a different node. For example, when implementing [multi-agent handoffs](./multi_agent.md#handoffs) where it's important to route to a different agent and pass some information to that agent.

Use [conditional edges](#conditional-edges) to route between nodes conditionally without updating the state.

### Navigating to a node in a parent graph

If you are using [subgraphs](#subgraphs), you might want to navigate from a node a subgraph to a different subgraph (i.e. a different node in the parent graph). To do so, you can specify `graph: Command.PARENT` in `Command`:

```ts
const myNode = (state: typeof StateAnnotation.State) => {
  return new Command({
    update: { foo: "bar" },
    goto: "other_subgraph", // where `other_subgraph` is a node in the parent graph
    graph: Command.PARENT,
  });
};
```

!!! note

    Setting `graph` to `Command.PARENT` will navigate to the closest parent graph.

This is particularly useful when implementing [multi-agent handoffs](./multi_agent.md#handoffs).

### Using inside tools

A common use case is updating graph state from inside a tool. For example, in a customer support application you might want to look up customer information based on their account number or ID in the beginning of the conversation. To update the graph state from the tool, you can return `Command({ update: { my_custom_key: "foo", messages: [...] } })` from the tool:

```ts
import { tool } from "@langchain/core/tools";

const lookupUserInfo = tool(async (input, config) => {
  const userInfo = getUserInfo(config);
  return new Command({
    // update state keys
    update: {
      user_info: userInfo,
      messages: [
        new ToolMessage({
          content: "Successfully looked up user information",
          tool_call_id: config.toolCall.id,
        }),
      ],
    },
  });
}, {
  name: "lookup_user_info",
  description: "Use this to look up user information to better assist them with their questions.",
  schema: z.object(...)
});
```

!!! important
You MUST include `messages` (or any state key used for the message history) in `Command.update` when returning `Command` from a tool and the list of messages in `messages` MUST contain a `ToolMessage`. This is necessary for the resulting message history to be valid (LLM providers require AI messages with tool calls to be followed by the tool result messages).

If you are using tools that update state via `Command`, we recommend using prebuilt [`ToolNode`](/langgraphjs/reference/classes/langgraph_prebuilt.ToolNode.html) which automatically handles tools returning `Command` objects and propagates them to the graph state. If you're writing a custom node that calls tools, you would need to manually propagate `Command` objects returned by the tools as the update from node.

### Human-in-the-loop

`Command` is an important part of human-in-the-loop workflows: when using `interrupt()` to collect user input, `Command` is then used to supply the input and resume execution via `new Command({ resume: "User input" })`. Check out [this conceptual guide](/langgraphjs/concepts/human_in_the_loop) for more information.

## Persistence

LangGraph provides built-in persistence for your agent's state using [checkpointers](/langgraphjs/reference/classes/checkpoint.BaseCheckpointSaver.html). Checkpointers save snapshots of the graph state at every superstep, allowing resumption at any time. This enables features like human-in-the-loop interactions, memory management, and fault-tolerance. You can even directly manipulate a graph's state after its execution using the appropriate `get` and `update` methods. For more details, see the [conceptual guide](/langgraphjs/concepts/persistence) for more information.

## Threads

Threads in LangGraph represent individual sessions or conversations between your graph and a user. When using checkpointing, turns in a single conversation (and even steps within a single graph execution) are organized by a unique thread ID.

## Storage

LangGraph provides built-in document storage through the [BaseStore](/langgraphjs/reference/classes/store.BaseStore.html) interface. Unlike checkpointers, which save state by thread ID, stores use custom namespaces for organizing data. This enables cross-thread persistence, allowing agents to maintain long-term memories, learn from past interactions, and accumulate knowledge over time. Common use cases include storing user profiles, building knowledge bases, and managing global preferences across all threads.

## Graph Migrations

LangGraph can easily handle migrations of graph definitions (nodes, edges, and state) even when using a checkpointer to track state.

- For threads at the end of the graph (i.e. not interrupted) you can change the entire topology of the graph (i.e. all nodes and edges, remove, add, rename, etc)
- For threads currently interrupted, we support all topology changes other than renaming / removing nodes (as that thread could now be about to enter a node that no longer exists) -- if this is a blocker please reach out and we can prioritize a solution.
- For modifying state, we have full backwards and forwards compatibility for adding and removing keys
- State keys that are renamed lose their saved state in existing threads
- State keys whose types change in incompatible ways could currently cause issues in threads with state from before the change -- if this is a blocker please reach out and we can prioritize a solution.

## Configuration

When creating a graph, you can also mark that certain parts of the graph are configurable. This is commonly done to enable easy switching between models or system prompts. This allows you to create a single "cognitive architecture" (the graph) but have multiple different instances of it.

You can then pass this configuration into the graph using the `configurable` config field.

```typescript
const config = { configurable: { llm: "anthropic" } };

await graph.invoke(inputs, config);
```

You can then access and use this configuration inside a node:

```typescript
const nodeA = (state, config) => {
  const llmType = config?.configurable?.llm;
  let llm: BaseChatModel;
  if (llmType) {
    const llm = getLlm(llmType);
  }
  ...
};

```

See [this guide](../how-tos/configuration.ipynb) for a full breakdown on configuration

### Recursion Limit

The recursion limit sets the maximum number of [super-steps](#graphs) the graph can execute during a single execution. Once the limit is reached, LangGraph will raise `GraphRecursionError`. By default this value is set to 25 steps. The recursion limit can be set on any graph at runtime, and is passed to `.invoke`/`.stream` via the config dictionary. Importantly, `recursionLimit` is a standalone `config` key and should not be passed inside the `configurable` key as all other user-defined configuration. See the example below:

```ts
await graph.invoke(inputs, { recursionLimit: 50 });
```

Read [this how-to](/langgraphjs/how-tos/recursion-limit/) to learn more about how the recursion limit works.

## `interrupt`

Use the [interrupt](/langgraphjs/reference/functions/langgraph.interrupt-1.html) function to **pause** the graph at specific points to collect user input. The `interrupt` function surfaces interrupt information to the client, allowing the developer to collect user input, validate the graph state, or make decisions before resuming execution.

```ts
import { interrupt } from "@langchain/langgraph";

const humanApprovalNode = (state: typeof StateAnnotation.State) => {
  ...
  const answer = interrupt(
      // This value will be sent to the client.
      // It can be any JSON serializable value.
      { question: "is it ok to continue?"},
  );
  ...
```

Resuming the graph is done by passing a [`Command`](#command) object to the graph with the `resume` key set to the value returned by the `interrupt` function.

Read more about how the `interrupt` is used for **human-in-the-loop** workflows in the [Human-in-the-loop conceptual guide](./human_in_the_loop.md).

**Note:** The `interrupt` function is not currently available in [web environments](/langgraphjs/how-tos/use-in-web-environments/).

## Breakpoints

Breakpoints pause graph execution at specific points and enable stepping through execution step by step. Breakpoints are powered by LangGraph's [**persistence layer**](./persistence.md), which saves the state after each graph step. Breakpoints can also be used to enable [**human-in-the-loop**](./human_in_the_loop.md) workflows, though we recommend using the [`interrupt` function](#interrupt) for this purpose.

Read more about breakpoints in the [Breakpoints conceptual guide](./breakpoints.md).

## Subgraphs

A subgraph is a [graph](#graphs) that is used as a [node](#nodes) in another graph. This is nothing more than the age-old concept of encapsulation, applied to LangGraph. Some reasons for using subgraphs are:

- building [multi-agent systems](./multi_agent.md)
- when you want to reuse a set of nodes in multiple graphs, which maybe share some state, you can define them once in a subgraph and then use them in multiple parent graphs
- when you want different teams to work on different parts of the graph independently, you can define each part as a subgraph, and as long as the subgraph interface (the input and output schemas) is respected, the parent graph can be built without knowing any details of the subgraph

There are two ways to add subgraphs to a parent graph:

- add a node with the compiled subgraph: this is useful when the parent graph and the subgraph share state keys and you don't need to transform state on the way in or out

```ts
.addNode("subgraph", subgraphBuilder.compile());
```

- add a node with a function that invokes the subgraph: this is useful when the parent graph and the subgraph have different state schemas and you need to transform state before or after calling the subgraph

```ts hl_lines="8"
const subgraph = subgraphBuilder.compile();

const callSubgraph = async (state: typeof StateAnnotation.State) => {
  return subgraph.invoke({ subgraph_key: state.parent_key });
};

const builder = new StateGraph(...)
  .addNode("subgraph", callSubgraph)
  .compile();
```

Let's take a look at examples for each.

### As a compiled graph

The simplest way to create subgraph nodes is by using a [compiled subgraph](#compiling-your-graph) directly. When doing so, it is **important** that the parent graph and the subgraph [state schemas](#state) share at least one key which they can use to communicate. If your graph and subgraph do not share any keys, you should use write a function [invoking the subgraph](#as-a-function) instead.

<div class="admonition note">
    <p class="admonition-title">Note</p>
    <p>
      If you pass extra keys to the subgraph node (i.e., in addition to the shared keys), they will be ignored by the subgraph node. Similarly, if you return extra keys from the subgraph, they will be ignored by the parent graph.
    </p>
</div>

```ts
import { StateGraph, Annotation } from "@langchain/langgraph";

const StateAnnotation = Annotation.Root({
  foo: Annotation<string>,
});

const SubgraphStateAnnotation = Annotation.Root({
  foo: Annotation<string>, // note that this key is shared with the parent graph state
  bar: Annotation<string>,
});

// Define subgraph
const subgraphNode = async (state: typeof SubgraphStateAnnotation.State) => {
  // note that this subgraph node can communicate with
  // the parent graph via the shared "foo" key
  return { foo: state.foo + "bar" };
};

const subgraph = new StateGraph(SubgraphStateAnnotation)
  .addNode("subgraph", subgraphNode);
  ...
  .compile();

// Define parent graph
const parentGraph = new StateGraph(StateAnnotation)
  .addNode("subgraph", subgraph)
  ...
  .compile();
```

### As a function

You might want to define a subgraph with a completely different schema. In this case, you can create a node function that invokes the subgraph. This function will need to [transform](../how-tos/subgraph-transform-state.ipynb) the input (parent) state to the subgraph state before invoking the subgraph, and transform the results back to the parent state before returning the state update from the node.

```ts
import { StateGraph, Annotation } from "@langchain/langgraph";

const StateAnnotation = Annotation.Root({
  foo: Annotation<string>,
});

const SubgraphStateAnnotation = Annotation.Root({
  // note that none of these keys are shared with the parent graph state
  bar: Annotation<string>,
  baz: Annotation<string>,
});

// Define subgraph
const subgraphNode = async (state: typeof SubgraphStateAnnotation.State) => {
  return { bar: state.bar + "baz" };
};

const subgraph = new StateGraph(SubgraphStateAnnotation)
  .addNode("subgraph", subgraphNode);
  ...
  .compile();

// Define parent graph
const subgraphWrapperNode = async (state: typeof StateAnnotation.State) => {
  // transform the state to the subgraph state
  const response = await subgraph.invoke({
    bar: state.foo,
  });
  // transform response back to the parent state
  return {
    foo: response.bar,
  };
}

const parentGraph = new StateGraph(StateAnnotation)
  .addNode("subgraph", subgraphWrapperNode)
  ...
  .compile();
```

## Visualization

It's often nice to be able to visualize graphs, especially as they get more complex. LangGraph comes with a nice built-in way to render a graph as a Mermaid diagram. You can use the `getGraph()` method like this:

```ts
const representation = graph.getGraph();
const image = await representation.drawMermaidPng();
const arrayBuffer = await image.arrayBuffer();
const buffer = new Uint8Array(arrayBuffer);
```

You can also check out [LangGraph Studio](https://github.com/langchain-ai/langgraph-studio) for a bespoke IDE that includes powerful visualization and debugging features.

## Streaming

LangGraph is built with first class support for streaming. There are several different streaming modes that LangGraph supports:

- [`"values"`](../how-tos/stream-values.ipynb): This streams the full value of the state after each step of the graph.
- [`"updates`](../how-tos/stream-updates.ipynb): This streams the updates to the state after each step of the graph. If multiple updates are made in the same step (e.g. multiple nodes are run) then those updates are streamed separately.

In addition, you can use the [`streamEvents`](https://api.js.langchain.com/classes/langchain_core_runnables.Runnable.html#streamEvents) method to stream back events that happen _inside_ nodes. This is useful for [streaming tokens of LLM calls](../how-tos/streaming-tokens-without-langchain.ipynb).

LangGraph is built with first class support for streaming, including streaming updates from graph nodes during execution, streaming tokens from LLM calls and more. See this [conceptual guide](./streaming.md) for more information.

---

### Docs Concepts Memory (`docs/docs/concepts/memory.md`)

# Memory

## What is Memory?

Memory in AI applications refers to the ability to process, store, and effectively recall information from past interactions. With memory, your agents can learn from feedback and adapt to users' preferences. This guide is divided into two sections based on the scope of memory recall: short-term memory and long-term memory.

**Short-term memory**, or [thread](persistence.md#threads)-scoped memory, can be recalled at any time **from within** a single conversational thread with a user. LangGraph manages short-term memory as a part of your agent's [state](low_level.md#state). State is persisted to a database using a [checkpointer](persistence.md#checkpoints) so the thread can be resumed at any time. Short-term memory updates when the graph is invoked or a step is completed, and the State is read at the start of each step.

**Long-term memory** is shared **across** conversational threads. It can be recalled _at any time_ and **in any thread**. Memories are scoped to any custom namespace, not just within a single thread ID. LangGraph provides [stores](persistence.md#memory-store) ([reference doc](https://langchain-ai.github.io/langgraphjs/reference/classes/checkpoint.BaseStore.html)) to let you save and recall long-term memories.

Both are important to understand and implement for your application.



## Short-term memory

Short-term memory lets your application remember previous interactions within a single [thread](persistence.md#threads) or conversation. A [thread](persistence.md#threads) organizes multiple interactions in a session, similar to the way email groups messages in a single conversation.

LangGraph manages short-term memory as part of the agent's state, persisted via thread-scoped checkpoints. This state can normally include the conversation history along with other stateful data, such as uploaded files, retrieved documents, or generated artifacts. By storing these in the graph's state, the bot can access the full context for a given conversation while maintaining separation between different threads.

Since conversation history is the most common form of representing short-term memory, in the next section, we will cover techniques for managing conversation history when the list of messages becomes **long**. If you want to stick to the high-level concepts, continue on to the [long-term memory](#long-term-memory) section.

### Managing long conversation history

Long conversations pose a challenge to today's LLMs. The full history may not even fit inside an LLM's context window, resulting in an irrecoverable error. Even _if_ your LLM technically supports the full context length, most LLMs still perform poorly over long contexts. They get "distracted" by stale or off-topic content, all while suffering from slower response times and higher costs.

Managing short-term memory is an exercise of balancing [precision & recall](https://en.wikipedia.org/wiki/Precision_and_recall#:~:text=Precision%20can%20be%20seen%20as,irrelevant%20ones%20are%20also%20returned) with your application's other performance requirements (latency & cost). As always, it's important to think critically about how you represent information for your LLM and to look at your data. We cover a few common techniques for managing message lists below and hope to provide sufficient context for you to pick the best tradeoffs for your application:

- [Editing message lists](#editing-message-lists): How to think about trimming and filtering a list of messages before passing to language model.
- [Summarizing past conversations](#summarizing-past-conversations): A common technique to use when you don't just want to filter the list of messages.

### Editing message lists

Chat models accept context using [messages](https://js.langchain.com/docs/concepts/#messages), which include developer provided instructions (a system message) and user inputs (human messages). In chat applications, messages alternate between human inputs and model responses, resulting in a list of messages that grows longer over time. Because context windows are limited and token-rich message lists can be costly, many applications can benefit from using techniques to manually remove or forget stale information.



The most direct approach is to remove old messages from a list (similar to a [least-recently used cache](https://en.wikipedia.org/wiki/Page_replacement_algorithm#Least_recently_used)).

The typical technique for deleting content from a list in LangGraph is to return an update from a node telling the system to delete some portion of the list. You get to define what this update looks like, but a common approach would be to let you return an object or dictionary specifying which values to retain.

```typescript
import { Annotation } from "@langchain/langgraph";

const StateAnnotation = Annotation.Root({
  myList: Annotation<any[]>({
    reducer: (
      existing: string[],
      updates: string[] | { type: string; from: number; to?: number }
    ) => {
      if (Array.isArray(updates)) {
        // Normal case, add to the history
        return [...existing, ...updates];
      } else if (typeof updates === "object" && updates.type === "keep") {
        // You get to decide what this looks like.
        // For example, you could simplify and just accept a string "DELETE"
        // and clear the entire list.
        return existing.slice(updates.from, updates.to);
      }
      // etc. We define how to interpret updates
      return existing;
    },
    default: () => [],
  }),
});

type State = typeof StateAnnotation.State;

function myNode(state: State) {
  return {
    // We return an update for the field "myList" saying to
    // keep only values from index -5 to the end (deleting the rest)
    myList: { type: "keep", from: -5, to: undefined },
  };
}
```

LangGraph will call the "[reducer](low_level.md#reducers)" function any time an update is returned under the key "myList". Within that function, we define what types of updates to accept. Typically, messages will be added to the existing list (the conversation will grow); however, we've also added support to accept a dictionary that lets you "keep" certain parts of the state. This lets you programmatically drop old message context.

Another common approach is to let you return a list of "remove" objects that specify the IDs of all messages to delete. If you're using the LangChain messages and the [`messagesStateReducer`](https://langchain-ai.github.io/langgraphjs/reference/functions/langgraph.messagesStateReducer.html) reducer (or [`MessagesAnnotation`](https://langchain-ai.github.io/langgraphjs/reference/variables/langgraph.MessagesAnnotation.html), which uses the same underlying functionality) in LangGraph, you can do this using a `RemoveMessage`.

```typescript
import { RemoveMessage, AIMessage } from "@langchain/core/messages";
import { MessagesAnnotation } from "@langchain/langgraph";

type State = typeof MessagesAnnotation.State;

function myNode1(state: State) {
  // Add an AI message to the `messages` list in the state
  return { messages: [new AIMessage({ content: "Hi" })] };
}

function myNode2(state: State) {
  // Delete all but the last 2 messages from the `messages` list in the state
  const deleteMessages = state.messages
    .slice(0, -2)
    .map((m) => new RemoveMessage({ id: m.id }));
  return { messages: deleteMessages };
}
```

In the example above, the `MessagesAnnotation` allows us to append new messages to the `messages` state key as shown in `myNode1`. When it sees a `RemoveMessage`, it will delete the message with that ID from the list (and the RemoveMessage will then be discarded). For more information on LangChain-specific message handling, check out [this how-to on using `RemoveMessage`](https://langchain-ai.github.io/langgraphjs/how-tos/memory/delete-messages/).

See this how-to [guide](https://langchain-ai.github.io/langgraphjs/how-tos/manage-conversation-history/)for example usage.

### Summarizing past conversations

The problem with trimming or removing messages, as shown above, is that we may lose information from culling of the message queue. Because of this, some applications benefit from a more sophisticated approach of summarizing the message history using a chat model.



Simple prompting and orchestration logic can be used to achieve this. As an example, in LangGraph we can extend the [`MessagesAnnotation`](https://langchain-ai.github.io/langgraphjs/reference/variables/langgraph.MessagesAnnotation.html) to include a `summary` key.

```typescript
import { MessagesAnnotation, Annotation } from "@langchain/langgraph";

const MyGraphAnnotation = Annotation.Root({
  ...MessagesAnnotation.spec,
  summary: Annotation<string>,
});
```

Then, we can generate a summary of the chat history, using any existing summary as context for the next summary. This `summarizeConversation` node can be called after some number of messages have accumulated in the `messages` state key.

```typescript
import { ChatOpenAI } from "@langchain/openai";
import { HumanMessage, RemoveMessage } from "@langchain/core/messages";

type State = typeof MyGraphAnnotation.State;

async function summarizeConversation(state: State) {
  // First, we get any existing summary
  const summary = state.summary || "";

  // Create our summarization prompt
  let summaryMessage: string;
  if (summary) {
    // A summary already exists
    summaryMessage =
      `This is a summary of the conversation to date: ${summary}\n\n` +
      "Extend the summary by taking into account the new messages above:";
  } else {
    summaryMessage = "Create a summary of the conversation above:";
  }

  // Add prompt to our history
  const messages = [
    ...state.messages,
    new HumanMessage({ content: summaryMessage }),
  ];

  // Assuming you have a ChatOpenAI model instance
  const model = new ChatOpenAI();
  const response = await model.invoke(messages);

  // Delete all but the 2 most recent messages
  const deleteMessages = state.messages
    .slice(0, -2)
    .map((m) => new RemoveMessage({ id: m.id }));

  return {
    summary: response.content,
    messages: deleteMessages,
  };
}
```

See this how-to [here](https://langchain-ai.github.io/langgraphjs/how-tos/memory/add-summary-conversation-history/) for example usage.

### Knowing **when** to remove messages

Most LLMs have a maximum supported context window (denominated in tokens). A simple way to decide when to truncate messages is to count the tokens in the message history and truncate whenever it approaches that limit. Naive truncation is straightforward to implement on your own, though there are a few "gotchas". Some model APIs further restrict the sequence of message types (must start with human message, cannot have consecutive messages of the same type, etc.). If you're using LangChain, you can use the [`trimMessages`](https://js.langchain.com/docs/how_to/trim_messages/#trimming-based-on-token-count) utility and specify the number of tokens to keep from the list, as well as the `strategy` (e.g., keep the last `maxTokens`) to use for handling the boundary.

Below is an example.

```typescript
import { trimMessages } from "@langchain/core/messages";
import { ChatOpenAI } from "@langchain/openai";

trimMessages(messages, {
  // Keep the last <= n_count tokens of the messages.
  strategy: "last",
  // Remember to adjust based on your model
  // or else pass a custom token_encoder
  tokenCounter: new ChatOpenAI({ modelName: "gpt-4" }),
  // Remember to adjust based on the desired conversation
  // length
  maxTokens: 45,
  // Most chat models expect that chat history starts with either:
  // (1) a HumanMessage or
  // (2) a SystemMessage followed by a HumanMessage
  startOn: "human",
  // Most chat models expect that chat history ends with either:
  // (1) a HumanMessage or
  // (2) a ToolMessage
  endOn: ["human", "tool"],
  // Usually, we want to keep the SystemMessage
  // if it's present in the original history.
  // The SystemMessage has special instructions for the model.
  includeSystem: true,
});
```

## Long-term memory

Long-term memory in LangGraph allows systems to retain information across different conversations or sessions. Unlike short-term memory, which is thread-scoped, long-term memory is saved within custom "namespaces."

LangGraph stores long-term memories as JSON documents in a [store](persistence.md#memory-store) ([reference doc](https://langchain-ai.github.io/langgraphjs/reference/classes/checkpoint.BaseStore.html)). Each memory is organized under a custom `namespace` (similar to a folder) and a distinct `key` (like a filename). Namespaces often include user or org IDs or other labels that make it easier to organize information. This structure enables hierarchical organization of memories. Cross-namespace searching is then supported through content filters. See the example below for an example.

```typescript
import { InMemoryStore } from "@langchain/langgraph";

// InMemoryStore saves data to an in-memory dictionary. Use a DB-backed store in production use.
const store = new InMemoryStore();
const userId = "my-user";
const applicationContext = "chitchat";
const namespace = [userId, applicationContext];
await store.put(namespace, "a-memory", {
  rules: [
    "User likes short, direct language",
    "User only speaks English & TypeScript",
  ],
  "my-key": "my-value",
});
// get the "memory" by ID
const item = await store.get(namespace, "a-memory");
// list "memories" within this namespace, filtering on content equivalence
const items = await store.search(namespace, {
  filter: { "my-key": "my-value" },
});
```

When adding long-term memory to your agent, it's important to think about how to **write memories**, how to **store and manage memory updates**, and how to **recall & represent memories** for the LLM in your application. These questions are all interdependent: how you want to recall & format memories for the LLM dictates what you should store and how to manage it. Furthermore, each technique has tradeoffs. The right approach for you largely depends on your application's needs.
LangGraph aims to give you the low-level primitives to directly control the long-term memory of your application, based on memory [Store](persistence.md#memory-store)'s.

Long-term memory is far from a solved problem. While it is hard to provide generic advice, we have provided a few reliable patterns below for your consideration as you implement long-term memory.

**Do you want to write memories "on the hot path" or "in the background"**

Memory can be updated either as part of your primary application logic (e.g. "on the hot path" of the application) or as a background task (as a separate function that generates memories based on the primary application's state). We document some tradeoffs for each approach in [the writing memories section below](#writing-memories).

**Do you want to manage memories as a single profile or as a collection of documents?**

We provide two main approaches to managing long-term memory: a single, continuously updated document (referred to as a "profile" or "schema") or a collection of documents. Each method offers its own benefits, depending on the type of information you need to store and how you intend to access it.

Managing memories as a single, continuously updated "profile" or "schema" is useful when there is well-scoped, specific information you want to remember about a user, organization, or other entity (including the agent itself). You can define the schema of the profile ahead of time, and then use an LLM to update this based on interactions. Querying the "memory" is easy since it's a simple GET operation on a JSON document. We explain this in more detail in [remember a profile](#manage-individual-profiles). This technique can provide higher precision (on known information use cases) at the expense of lower recall (since you have to anticipate and model your domain, and updates to the doc tend to delete or rewrite away old information at a greater frequency).

Managing long-term memory as a collection of documents, on the other hand, lets you store an unbounded amount of information. This technique is useful when you want to repeatedly extract & remember items over a long time horizon but can be more complicated to query and manage over time. Similar to the "profile" memory, you still define schema(s) for each memory. Rather than overwriting a single document, you instead will insert new ones (and potentially update or re-contextualize existing ones in the process). We explain this approach in more detail in ["managing a collection of memories"](#manage-a-collection-of-memories).

**Do you want to present memories to your agent as updated instructions or as few-shot examples?**

Memories are typically provided to the LLM as a part of the system prompt. Some common ways to "frame" memories for the LLM include providing raw information as "memories from previous interactions with user A", as system instructions or rules, or as few-shot examples.

Framing memories as "learning rules or instructions" typically means dedicating a portion of the system prompt to instructions the LLM can manage itself. After each conversation, you can prompt the LLM to evaluate its performance and update the instructions to better handle this type of task in the future. We explain this approach in more detail in [this section](#update-own-instructions).

Storing memories as few-shot examples lets you store and manage instructions as cause and effect. Each memory stores an input or context and expected response. Including a reasoning trajectory (a chain-of-thought) can also help provide sufficient context so that the memory is less likely to be mis-used in the future. We elaborate on this concept more in [this section](#few-shot-examples).

We will expand on techniques for writing, managing, and recalling & formatting memories in the following section.

### Writing memories

Humans form long-term memories when we sleep, but when and how should our agents create new memories? The two most common ways we see agents write memories are "on the hot path" and "in the background".

#### Writing memories in the hot path

This involves creating memories while the application is running. To provide a popular production example, ChatGPT manages memories using a "save_memories" tool to upsert memories as content strings. It decides whether (and how) to use this tool every time it receives a user message and multi-tasks memory management with the rest of the user instructions.

This has a few benefits. First of all, it happens "in real time". If the user starts a new thread right away that memory will be present. The user also transparently sees when memories are stored, since the bot has to explicitly decide to store information and can relate that to the user.

This also has several downsides. It complicates the decisions the agent must make (what to commit to memory). This complication can degrade its tool-calling performance and reduce task completion rates. It will slow down the final response since it needs to decide what to commit to memory. It also typically leads to fewer things being saved to memory (since the assistant is multi-tasking), which will cause **lower recall** in later conversations.

#### Writing memories in the background

This involves updating memory as a conceptually separate task, typically as a completely separate graph or function. Since it happens in the background, it incurs no latency. It also splits up the application logic from the memory logic, making it more modular and easy to manage. It also lets you separate the timing of memory creation, letting you avoid redundant work. Your agent can focus on accomplishing its immediate task without having to consciously think about what it needs to remember.

This approach is not without its downsides, however. You have to think about how often to write memories. If it doesn't run in realtime, the user's interactions on other threads won't benefit from the new context. You also have to think about when to trigger this job. We typically recommend scheduling memories after some point of time, cancelling and re-scheduling for the future if new events occur on a given thread. Other popular choices are to form memories on some cron schedule or to let the user or application logic manually trigger memory formation.

### Managing memories

Once you've sorted out memory scheduling, it's important to think about **how to update memory with new information**.

There are two main approaches: you can either continuously update a single document (memory profile) or insert new documents each time you receive new information.

We will outline some tradeoffs between these two approaches below, understanding that most people will find it most appropriate to combine approaches and to settle somewhere in the middle.

#### Manage individual profiles

A profile is generally just a JSON document with various key-value pairs you've selected to represent your domain. When remembering a profile, you will want to make sure that you are **updating** the profile each time. As a result, you will want to pass in the previous profile and ask the LLM to generate a new profile (or some JSON patch to apply to the old profile).

The larger the document, the more error-prone this can become. If your document becomes **too** large, you may want to consider splitting up the profiles into separate sections. You will likely need to use generation with retries and/or **strict** decoding when generating documents to ensure the memory schemas remains valid.

#### Manage a collection of memories

Saving memories as a collection of documents simplifies some things. Each individual memory can be more narrowly scoped and easier to generate. It also means you're less likely to **lose** information over time, since it's easier for an LLM to generate _new_ objects for new information than it is for it to reconcile that new information with information in a dense profile. This tends to lead to higher recall downstream.

This approach shifts some complexity to how you prompt the LLM to apply memory updates. You now have to enable the LLM to _delete_ or _update_ existing items in the list. This can be tricky to prompt the LLM to do. Some LLMs may default to over-inserting; others may default to over-updating. Tuning the behavior here is best done through evals, something you can do with a tool like [LangSmith](https://docs.smith.langchain.com/tutorials/Developers/evaluation).

This also shifts complexity to memory **search** (recall). You have to think about what relevant items to use. Right now we support filtering by metadata. We will be adding semantic search shortly.

Finally, this shifts some complexity to how you represent the memories for the LLM (and by extension, the schemas you use to save each memories). It's very easy to write memories that can easily be mistaken out-of-context. It's important to prompt the LLM to include all necessary contextual information in the given memory so that when you use it in later conversations it doesn't mistakenly mis-apply that information.

### Representing memories

Once you have saved memories, the way you then retrieve and present the memory content for the LLM can play a large role in how well your LLM incorporates that information in its responses.
The following sections present a couple of common approaches. Note that these sections also will largely inform how you write and manage memories. Everything in memory is connected!

#### Update own instructions

While instructions are often static text written by the developer, many AI applications benefit from letting the users personalize the rules and instructions the agent should follow whenever it interacts with that user. This ideally can be inferred by its interactions with the user (so the user doesn't have to explicitly change settings in your app). In this sense, instructions are a form of long-form memory!

One way to apply this is using "reflection" or "Meta-prompting" steps. Prompt the LLM with the current instruction set (from the system prompt) and a conversation with the user, and instruct the LLM to refine its instructions. This approach allows the system to dynamically update and improve its own behavior, potentially leading to better performance on various tasks. This is particularly useful for tasks where the instructions are challenging to specify a priori.

Meta-prompting uses past information to refine prompts. For instance, a [Tweet generator](https://www.youtube.com/watch?v=Vn8A3BxfplE) employs meta-prompting to enhance its paper summarization prompt for Twitter. You could implement this using LangGraph's memory store to save updated instructions in a shared namespace. In this case, we will namespace the memories as "agent_instructions" and key the memory based on the agent.

```typescript
import { BaseStore } from "@langchain/langgraph/store";
import { State } from "@langchain/langgraph";
import { ChatOpenAI } from "@langchain/openai";

// Node that *uses* the instructions
const callModel = async (state: State, store: BaseStore) => {
  const namespace = ["agent_instructions"];
  const instructions = await store.get(namespace, "agent_a");
  // Application logic
  const prompt = promptTemplate.format({
    instructions: instructions[0].value.instructions,
  });
  // ... rest of the logic
};

// Node that updates instructions
const updateInstructions = async (state: State, store: BaseStore) => {
  const namespace = ["instructions"];
  const currentInstructions = await store.search(namespace);
  // Memory logic
  const prompt = promptTemplate.format({
    instructions: currentInstructions[0].value.instructions,
    conversation: state.messages,
  });
  const llm = new ChatOpenAI();
  const output = await llm.invoke(prompt);
  const newInstructions = output.content; // Assuming the LLM returns the new instructions
  await store.put(["agent_instructions"], "agent_a", {
    instructions: newInstructions,
  });
  // ... rest of the logic
};
```

#### Few-shot examples

Sometimes it's easier to "show" than "tell." LLMs learn well from examples. Few-shot learning lets you ["program"](https://x.com/karpathy/status/1627366413840322562) your LLM by updating the prompt with input-output examples to illustrate the intended behavior. While various [best-practices](https://js.langchain.com/docs/concepts/#1-generating-examples) can be used to generate few-shot examples, often the challenge lies in selecting the most relevant examples based on user input.

Note that the memory store is just one way to store data as few-shot examples. If you want to have more developer involvement, or tie few-shots more closely to your evaluation harness, you can also use a [LangSmith Dataset](https://docs.smith.langchain.com/how_to_guides/datasets) to store your data. Then dynamic few-shot example selectors can be used out-of-the box to achieve this same goal. LangSmith will index the dataset for you and enable retrieval of few shot examples that are most relevant to the user input based upon keyword similarity ([using a BM25-like algorithm](https://docs.smith.langchain.com/how_to_guides/datasets/index_datasets_for_dynamic_few_shot_example_selection) for keyword based similarity).

See this how-to [video](https://www.youtube.com/watch?v=37VaU7e7t5o) for example usage of dynamic few-shot example selection in LangSmith. Also, see this [blog post](https://blog.langchain.dev/few-shot-prompting-to-improve-tool-calling-performance/) showcasing few-shot prompting to improve tool calling performance and this [blog post](https://blog.langchain.dev/aligning-llm-as-a-judge-with-human-preferences/) using few-shot example to align an LLMs to human preferences.

---

--- METRICS ---
- Files Extracted: 83
- Estimated Token Budget: ~126707 tokens
- Canonical Reference: https://codewiki.google/github.com/langchain-ai/langgraphjs
