> ## Documentation Index
> Fetch the complete documentation index at: https://docs.verifiedx.me/llms.txt
> Use this file to discover all available pages before exploring further.

# LangGraph

> Protect LangGraph graphs, state updates, stores, and tools without changing your graph design.

**Best for:** teams using LangGraph directly with `StateGraph`, `ToolNode`, stores, checkpointers, or direct state updates.

<Note>
  Run doctor in the repo before you wire anything:

  * TypeScript: `npx @verifiedx-core/sdk doctor`
  * Python: `verifiedx doctor`

  Protect one action free: [verifiedx.me](https://verifiedx.me/?vx_source=docs.langgraph)

  If doctor shows a different native adapter already owns the tool loop, switch to that page before integrating.
</Note>

## Install

<CodeGroup>
  ```bash Python theme={null}
  pip install verifiedx
  ```

  ```bash TypeScript theme={null}
  npm install @verifiedx-core/sdk
  ```
</CodeGroup>

## Net-new VerifiedX code

This is usually the only VerifiedX delta in an existing pure LangGraph setup.

<CodeGroup>
  ```python Python theme={null}
  from verifiedx import init_verifiedx, install_langgraph

  vx = init_verifiedx()
  install_langgraph(verifiedx=vx)

  graph = builder.compile(
      checkpointer=InMemorySaver(),
      store=InMemoryStore(),
  )
  ```

  ```typescript TypeScript theme={null}
  import { initVerifiedX } from "@verifiedx-core/sdk";
  import { install as installLanggraph } from "@verifiedx-core/sdk/langgraph";

  const verifiedx = await initVerifiedX();
  await installLanggraph({ verifiedx });

  const graph = builder.compile({
    checkpointer: new MemorySaver(),
    store: new InMemoryStore(),
  });
  ```
</CodeGroup>

<Note>
  That one install call is the few-LOC path. Your existing graph nodes, `Command.update`, `ToolNode`, tools, stores, and checkpointer stay the same.
</Note>

<Tip>
  Start with the graph that owns the highest-impact tool call, store write, or state update. LangGraph protection is broad once installed, but rollout can still be incremental.
</Tip>

<Note>
  In Python, `install_langgraph(...)` patches `StateGraph.compile` and LangChain `BaseTool.invoke`. In TypeScript, `installLanggraph(...)` patches `StateGraph.compile`, `StructuredTool.call`, and `ToolNode.runTool`.
</Note>

<Note>
  Your LangGraph surface is the config. VerifiedX uses your existing node names, tool names, descriptions, schemas, store namespaces, and state-update surfaces as the source of truth for what to preflight.
</Note>

## If you want explicit wrapping instead of `install`

Most builders do not need this, but it is available.

<CodeGroup>
  ```python Python theme={null}
  from verifiedx import compile as compile_langgraph, init_verifiedx

  vx = init_verifiedx()

  graph = compile_langgraph(
      builder,
      verifiedx=vx,
      checkpointer=InMemorySaver(),
      store=InMemoryStore(),
  )
  ```

  ```typescript TypeScript theme={null}
  import { initVerifiedX } from "@verifiedx-core/sdk";
  import {
    compile as compileLanggraph,
    wrapStore as wrapLanggraphStore,
    wrapTools as wrapLanggraphTools,
  } from "@verifiedx-core/sdk/langgraph";

  const verifiedx = await initVerifiedX();
  const store = await wrapLanggraphStore(new InMemoryStore(), { verifiedx });
  const tools = await wrapLanggraphTools(rawTools, { verifiedx });

  const graph = await compileLanggraph(builder, {
    verifiedx,
    store,
    checkpointer: new MemorySaver(),
  });
  ```
</CodeGroup>

<Note>
  You normally do not need to instantiate `VerifiedXCheckpointer` manually. `install` and `compile` handle LangGraph checkpointers for you.
</Note>

## Composed systems

If this LangGraph run is part of a larger multi-agent or agent+human workflow, pass upstream context into VerifiedX so the current graph run has better system and situational awareness before it takes a high-impact action.

This is useful when a supervisor agent, parent workflow, or human reviewer already has context that the current graph run should use before taking action.

VerifiedX does not require a fixed schema for this. Pass the upstream context you already have in any JSON-serializable shape.

<CodeGroup>
  ```python Python theme={null}
  upstream = {
      "source": "workflow_supervisor",
      "workflow_id": "WF-2203",
      "approval_status": "approved_with_follow_up",
      "human_review": {
          "reviewer": "ops_lead",
          "result": "approved",
      },
      "prior_agent_output": {
          "summary": "Billing verification is complete.",
      },
  }

  with vx.with_upstream_context(upstream):
      result = graph.invoke(
          {
              "messages": [
                  {
                      "role": "user",
                      "content": "Inspect workflow WF-2203 and then update it to awaiting_human.",
                  }
              ]
          }
      )
  ```

  ```typescript TypeScript theme={null}
  const upstream = {
    source: "workflow_supervisor",
    workflow_id: "WF-2203",
    approval_status: "approved_with_follow_up",
    human_review: {
      reviewer: "ops_lead",
      result: "approved",
    },
    prior_agent_output: {
      summary: "Billing verification is complete.",
    },
  };

  const result = await verifiedx.withUpstreamContext(upstream, async () => {
    return await graph.invoke({
      messages: [
        {
          role: "user",
          content: "Inspect workflow WF-2203 and then update it to awaiting_human.",
        },
      ],
    });
  });
  ```
</CodeGroup>

<Note>
  Upstream context is supporting workflow context from outside the current run. It is not proof that this run already executed any local action.
</Note>

## What the adapter already captures

Once attached, VerifiedX captures native LangGraph surfaces across both SDKs, including:

* `StateGraph.compile`
* Node registration through `add_node` or `addNode`
* Graph execution through `invoke`, `ainvoke`, `stream`, and `astream` where available
* Selected tool history from `AIMessage.tool_calls` and `ToolMessage.tool_call_id`
* Tool execution through LangChain tool surfaces
* Direct state mutations through `Command.update`
* Direct compiled state mutations through `graph.update_state` or `graph.updateState`
* Store reads through `store.get` and `store.search`
* Store writes through `store.put` and `store.delete`
* Checkpoint events through `checkpointer.put` and `put_writes` or `putWrites`

## What gets preflighted

VerifiedX preflights the high-impact LangGraph boundaries directly.

That includes:

* Wrapped tool executions
* `store.put`
* `store.delete`
* `Command.update`
* Compiled `graph.update_state` or `graph.updateState`

The following surfaces are still captured, but as support history rather than direct guarded boundaries:

* `store.get`
* `store.search`
* `graph.get_state` or `graph.getState`

Checkpoint writes are also captured as native checkpoint events for runtime truth and ingest compatibility, but in the current pure LangGraph path they are not treated as a standalone clean-run guarded boundary.

## Framework and provider attribution

The framework stays `langgraph` on this adapter path, even when your underlying model or tool-call shape comes from another provider.

When LangGraph carries provider hints, VerifiedX still records them truthfully. For example:

* OpenAI-shaped tool call IDs can infer `provider: "openai"`
* Anthropic-shaped tool call IDs can infer `provider: "anthropic"`

That means the framework remains `langgraph`, while provider attribution stays accurate when LangGraph exposes it.

## What to expect at runtime

Protected LangGraph boundaries can return:

* `allow`
* `allow_with_warning`
* `replan_required`
* `goal_fail_terminal`

Every outcome includes a structured decision receipt.

If a tool, store write, or state update is replanned, the side effect does not execute. VerifiedX returns the blocked result or loopback guidance so the graph can keep moving toward the same goal safely.

If LangGraph already surfaced the selected tool through `AIMessage.tool_calls`, VerifiedX reuses that preflight at execution time instead of sending a duplicate boundary request.

## Pricing note

One protected action check equals one real boundary preflight. Taint, event ingest, execution reports, and decision reads are all included at that price. The Free Sandbox includes every language, provider, framework, and adapter.

VerifiedX does not replace your orchestrator or workflow. It returns receipts your system can keep local, route downstream, or pass upstream.

***

If your graph is specifically built around provider-native model loops, see the LangGraph OpenAI and LangGraph Anthropic pages for provider-specific examples on top of this same LangGraph boundary layer.
