Skip to content

Enhance LangGraph guides: v1.2.11 update + richer code examples - #344

Open
CodeHalwell wants to merge 16 commits into
mainfrom
claude/loving-goodall-wlutr4
Open

CodeHalwell wants to merge 16 commits into
mainfrom
claude/loving-goodall-wlutr4

Conversation

@CodeHalwell

Copy link
Copy Markdown
Owner

Summary

All LangGraph reference docs were verified against source code at v1.2.11 and updated accordingly. Four new detailed recipes were added to the recipes guide, and two reference pages received substantive new sections covering APIs that were previously undocumented in the guides.

Version bumps

  • All six reference docs updated from langgraph==1.2.2 / 1.2.4 → 1.2.11
  • langgraph_recipes.md updated from 1.2.10 → 1.2.11

New content in reference docs

reference-state-graph.md

  • Added trace_policy= row to the add_node options table (was missing despite being available since v1.2)

reference-prebuilt-nodes.md

  • Added a full create_react_agent reference section covering: signature table, pre_model_hook / post_model_hook patterns, dynamic model selection via a callable, and structured output with response_format=

reference-channels.md

  • Added Overwrite + BinaryOperatorAggregate section showing how to bypass a reducer for a single write, including all three recognised Overwrite forms (typed dataclass, sentinel-key dict {"__overwrite__": v}, JSON-serialized {"value": v, "type": "__overwrite__"})

New recipes (18–21)

# Title Key APIs
18 TracePolicy — Hiding Sensitive Payloads in LangSmith TracePolicy, omit_payload, add_node(trace_policy=...)
19 ToolCallTransformer — Structured Per-Tool Streaming ToolCallTransformer, ToolCallStream, compile(transformers=[...]), stream_mode="tools"
20 entrypoint.final — Decoupled Return and Checkpoint Value entrypoint.final[R, S], @entrypoint, previous
21 GraphOutput and Durability — v2 Invoke API GraphOutput, Durability, version="v2", interrupt()

All code examples were written from direct inspection of the v1.2.11 source at /usr/local/lib/python3.11/dist-packages/langgraph/.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Kn4Hvrh7QDiJ6HoggwDWgR


Generated by Claude Code

- Bump all reference docs from langgraph==1.2.2/1.2.4 to langgraph==1.2.11
- reference-state-graph: add trace_policy= row to add_node options table
- reference-prebuilt-nodes: add create_react_agent reference section with
  pre/post model hooks, dynamic model selection, and structured output examples
- reference-channels: add Overwrite + BinaryOperatorAggregate section with
  all three recognised Overwrite forms (typed, sentinel-key dict, JSON form)
- langgraph_recipes: update to v1.2.11, add four new recipes:
  - Recipe 18: TracePolicy + omit_payload for PII-safe tracing
  - Recipe 19: ToolCallTransformer + ToolCallStream structured per-tool streaming
  - Recipe 20: entrypoint.final for decoupled return and checkpoint values
  - Recipe 21: GraphOutput + Durability modes with v2 invoke API

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kn4Hvrh7QDiJ6HoggwDWgR
Copilot AI lite review requested due to automatic review settings September 21, 2026 06:39
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-21T07:48:12.467478Z 50b3285 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4c1de01965

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/content/docs/langgraph-guide/python/langgraph_recipes.md Outdated
Comment thread src/content/docs/langgraph-guide/python/langgraph_recipes.md Outdated
Comment thread src/content/docs/langgraph-guide/python/langgraph_recipes.md Outdated
Comment thread src/content/docs/langgraph-guide/python/reference-prebuilt-nodes.md Outdated
Comment thread src/content/docs/langgraph-guide/python/reference-prebuilt-nodes.md Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Several new examples contain API mismatches, broken imports, incorrect hook behavior, and an ineffective PII-redaction guarantee.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 Medium severity · 2 Low severity

Open (3)
What changed in this PR

Updates LangGraph documentation to v1.2.11 and adds new API reference material and recipes.

Changes:

  • Bumps version verification metadata.
  • Documents trace_policy, create_react_agent, and Overwrite.
  • Adds recipes for tracing, tool streaming, functional checkpoints, and v2 invocation.
File Description
reference-streaming-modes.md Version metadata update
reference-store.md Version metadata update
reference-state-graph.md Adds trace_policy documentation
reference-prebuilt-nodes.md Adds create_react_agent reference
reference-functional-api.md Version metadata update
reference-channels.md Adds Overwrite guidance
langgraph_recipes.md Adds recipes 18–21

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/content/docs/langgraph-guide/python/reference-prebuilt-nodes.md Outdated
Comment thread src/content/docs/langgraph-guide/python/langgraph_recipes.md Outdated
Comment thread src/content/docs/langgraph-guide/python/reference-prebuilt-nodes.md Outdated
- Recipe 18: import omit_payload from langgraph.types (not langgraph.tracing);
  use TracePolicy(process_inputs=omit_payload, process_outputs=omit_payload)
  instead of omit_payload(); add scope-limitation note (node span only, not
  root graph run)
- Recipe 19: sync ToolCallStream API requires context manager (with graph.stream()
  as run); plain for-loop over (mode, data) pairs does not expose run.tool_calls
- reference-prebuilt-nodes create_react_agent: state_schema must include both
  messages (add_messages) AND remaining_steps: int; document this requirement
- reference-prebuilt-nodes trim_history hook: fix — returning a slice does not
  remove older messages via add_messages (merges by ID); use
  RemoveMessage(id=REMOVE_ALL_MESSAGES) + to_keep slice instead

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kn4Hvrh7QDiJ6HoggwDWgR
Copilot AI review requested due to automatic review settings September 21, 2026 06:46
… signature

- langgraph_recipes.md: fix remaining v1.2.10 reference in features list body
- reference-prebuilt-nodes.md: state_schema default is None (not MessagesState);
  None resolves to built-in AgentState (messages + remaining_steps); update
  both the signature comment and the parameter table row to reflect this

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kn4Hvrh7QDiJ6HoggwDWgR

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Several new API descriptions and recipes contain inaccurate signatures or examples that do not actually provide the documented behavior.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 High severity · 1 Medium severity · 1 Low severity

Open (3)
Resolved since last review (3)
Previously missed (5)

In code that hasn't changed since last review

Medium severity Wrap anonymize in a traced Runnable for payload redaction

src/​content/​docs/​langgraph-guide/​python/​langgraph_recipes.md:3153

anonymize is a plain Python callable. The TracePolicy reference says plain function nodes are registered with trace=False and have no span, so these processors never run and this recipe does not demonstrate node-level payload redaction. Wrap the callable in a traced Runnable before attaching the policy.

Low severity Correct terminology to personally identifiable information

src/​content/​docs/​langgraph-guide/​python/​langgraph_recipes.md:3111

“Personal-identifiable information” is grammatically incorrect; the standard term is “personally identifiable information.”

Low severity Qualify the two-node description for response_format

src/​content/​docs/​langgraph-guide/​python/​reference-prebuilt-nodes.md:1062

This unconditional two-node description is false for the response_format option documented below: v1.2.11 adds a generate_structured_response node and makes a separate final model call. Qualify the two-node description as the default case.

Low severity Document the complete v1.2.11 create_react_agent signature

src/​content/​docs/​langgraph-guide/​python/​reference-prebuilt-nodes.md:1084

This is not the v1.2.11 create_react_agent signature documented in langgraph_comprehensive_guide.md:4760-4767: state_schema defaults to None, name defaults to None, and the debug and version parameters are missing. Users cannot discover the v2/v1 selection or debug option from this reference.

Low severity Document hook return variants and ephemeral model messages

src/​content/​docs/​langgraph-guide/​python/​reference-prebuilt-nodes.md:1102

The hook contract is narrower/different than this description: pre_model_hook can return llm_input_messages for an ephemeral model-only view without mutating persisted messages, and post_model_hook can return a Command or None as well as a dict. Document these cases so callers do not assume every hook result is merged state.

Comment thread src/content/docs/langgraph-guide/python/langgraph_recipes.md Outdated
Comment thread src/content/docs/langgraph-guide/python/langgraph_recipes.md Outdated
Comment thread src/content/docs/langgraph-guide/python/reference-prebuilt-nodes.md Outdated
Copilot AI review requested due to automatic review settings September 21, 2026 06:51

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 75be7e7a25

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/content/docs/langgraph-guide/python/langgraph_recipes.md Outdated
Comment thread src/content/docs/langgraph-guide/python/langgraph_recipes.md
Comment thread src/content/docs/langgraph-guide/python/reference-prebuilt-nodes.md Outdated
- scrub_ssn processor matched keys containing "ssn" but the example
  state stores PII under raw_pii; rename to scrub_pii and check a
  set of known PII field names including raw_pii

- fetch_price tool emitted no output deltas so the ToolCallStream
  delta loop yielded nothing; add ToolRuntime parameter and call
  emit_output_delta to demonstrate actual incremental streaming

- add a concrete custom-state code example after the state_schema
  parameter table showing that MessagesState must be extended with
  remaining_steps: int for create_react_agent to accept it

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kn4Hvrh7QDiJ6HoggwDWgR
add_messages cannot reorder existing messages by ID, so returning
[SystemMessage] + state["messages"] appends the system message at
the end rather than prepending it. Use llm_input_messages instead,
which controls model input directly without going through the reducer.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kn4Hvrh7QDiJ6HoggwDWgR

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Several new examples misrepresent or fail to exercise the v1.2.11 APIs, including ineffective tracing and broken tool-stream iteration.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 High severity

Open (1)
Resolved since last review (3)
Previously missed (7)

In code that hasn't changed since last review

Medium severity Iterate the output_deltas streaming channel

src/​content/​docs/​langgraph-guide/​python/​langgraph_recipes.md:3263

ToolCallStream is not the delta iterator; the documented streaming channel is output_deltas. Iterating tc_stream will not consume the emitted chunks, so use the channel explicitly.

This issue also appears on line 3288 of the same file.

Medium severity Correct v1.2.11 signature options and name default

src/​content/​docs/​langgraph-guide/​python/​reference-prebuilt-nodes.md:1083

This is not the v1.2.11 signature: debug=False and version="v2" are omitted, while name defaults to None, not "LangGraph". Since this block is presented as a source-verified signature, please include the supported options and correct the default.

Medium severity Use llm_input_messages to avoid persisting system prompts

src/​content/​docs/​langgraph-guide/​python/​reference-prebuilt-nodes.md:1123

Returning messages here writes the new SystemMessage through the add_messages reducer; it does not prepend it, and each loop can append another system message. Return llm_input_messages so the prompt is supplied only to this model call and is not persisted.

Low severity Correct terminology to personally identifiable information

src/​content/​docs/​langgraph-guide/​python/​langgraph_recipes.md:3111

The term is “personally identifiable information,” not “personal-identifiable information.”

Low severity Document supported hook return types and ephemeral messages

src/​content/​docs/​langgraph-guide/​python/​reference-prebuilt-nodes.md:1096

The hook contract is broader than “return a dict”: pre_model_hook may return None, and post_model_hook may return a Command or None. The pre-hook also commonly returns llm_input_messages for an ephemeral model-only view, so the reference should document these supported forms.

Low severity Describe remaining_steps as managed RemainingSteps

src/​content/​docs/​langgraph-guide/​python/​reference-prebuilt-nodes.md:1097

remaining_steps is a managed RemainingSteps field in the built-in AgentState, not an ordinary int. Describing it as int can lead readers to model it as a normal writable state field instead of using the managed field required by create_react_agent.

Low severity Update API labels to reflect eight StreamMode values

src/​content/​docs/​langgraph-guide/​python/​reference-streaming-modes.md:13

The verification stamp is now 1.2.11, but this page still labels the API as “seven” in its front matter and section heading even though its StreamMode union contains eight values (tools is the eighth). Please update those labels as part of this refresh; otherwise the page contradicts its own API table.

Comment thread src/content/docs/langgraph-guide/python/langgraph_recipes.md
Copilot AI review requested due to automatic review settings September 21, 2026 06:58

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 56c18b98b1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

from langgraph.graph.message import MessagesState, add_messages

class MyAgentState(MessagesState):
remaining_steps: int # required — omitting this raises ValueError

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Declare the counter as the managed RemainingSteps type

The new follow-up example satisfies the key-name validation but declares an ordinary int channel, so LangGraph will not inject or decrement the recursion budget; when callers invoke the shown agent without supplying this field, the agent loses the built-in graceful remaining-step handling and may instead run until GraphRecursionError. Import RemainingSteps and declare this as NotRequired[RemainingSteps], matching the actual built-in AgentState.

Useful? React with 👍 / 👎.

Comment on lines +3416 to +3418
# The checkpoint stores ThreadState (no context_used field):
snap = qa_agent.get_state(cfg)
print(type(snap.values)) # ThreadState — compact form

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Do not claim save is the only checkpointed value

For a Functional API entrypoint, save= controls the hidden previous channel used by the next invocation, but the returned value is also written to the output channel and get_state(cfg).values exposes that latest output. Consequently this line reports TurnResult, not ThreadState, and the context_used data still occupies checkpoint state; demonstrate persistence by observing previous on the next call rather than claiming this removes the rich result from storage.

Useful? React with 👍 / 👎.

Comment thread src/content/docs/langgraph-guide/python/reference-prebuilt-nodes.md

### Pre/post model hooks

`pre_model_hook` and `post_model_hook` run inside the `agent` node, before and after the LLM call respectively. Both receive the current state and must return a dict that is merged back into state.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Describe model hooks as separate graph nodes

When either hook is configured, create_react_agent adds dedicated pre_model_hook and post_model_hook nodes around the agent node rather than running both inside it. This distinction is observable in streamed updates, traces, state history, and interrupt_before/interrupt_after; documenting them as internal callbacks leads users to target the wrong node when configuring interrupts or interpreting execution.

Useful? React with 👍 / 👎.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The TracePolicy recipe is ineffective for plain function nodes, and the expanded agent reference omits or misstates supported API behavior.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 High severity

Open (1)
Resolved since last review (1)
Previously missed (5)

In code that hasn't changed since last review

Medium severity Document the extra structured-response model call

src/​content/​docs/​langgraph-guide/​python/​reference-prebuilt-nodes.md:1062

This description is false when response_format is used: the API adds a generate_structured_response node and makes a separate structured-output model call. Since response_format is documented below, qualify the two-node statement or mention the extra node and its latency/cost.

Medium severity Document complete pre- and post-model hook return types

src/​content/​docs/​langgraph-guide/​python/​reference-prebuilt-nodes.md:1076

These hook type comments are too narrow: pre_model_hook accepts dict | None, while post_model_hook also accepts Command | None (and the page's own hook guidance currently says both must return a dict). This omits supported no-op and early-routing patterns from the API reference; document the actual return unions.

Medium severity Document missing parameters and correct the name default

src/​content/​docs/​langgraph-guide/​python/​reference-prebuilt-nodes.md:1083

Compared with the v1.2.11 signature documented in langgraph_comprehensive_guide.md:4760-4767, this block omits the public debug and version parameters and gives name the wrong default ("LangGraph" instead of None). Consumers using this reference cannot discover or configure those options, and the shown default is inaccurate.

Low severity Add Recipes 18–21 to the feature index

src/​content/​docs/​langgraph-guide/​python/​langgraph_recipes.md:12

Recipes 18–21 are appended below, but the guide's feature index still ends at Recipe 17. The new TracePolicy, tool-streaming, entrypoint.final, and v2 invoke topics are therefore missing from the overview; add them to the list or explicitly mark it as non-exhaustive.

Low severity Correct the phrase to personally identifiable information

src/​content/​docs/​langgraph-guide/​python/​langgraph_recipes.md:3111

The phrase "personal-identifiable information" is grammatically incorrect; use "personally identifiable information".

Comment thread src/content/docs/langgraph-guide/python/reference-prebuilt-nodes.md Outdated
- create_react_agent signature: add debug=False, version="v2", fix name
  default to None (was incorrectly shown as "LangGraph")
- Custom state schema: use NotRequired[RemainingSteps] from
  langgraph.managed instead of plain int; add managed-value explanation
- Pre/post model hooks: clarify they are separate graph nodes inserted
  before/after the agent node, not callbacks inside it
- Recipe 20 get_state(): correct snap.values comment — returns TurnResult
  (value= output), not ThreadState; note ThreadState is only accessible
  as `previous` on the next call

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kn4Hvrh7QDiJ6HoggwDWgR
Copilot AI review requested due to automatic review settings September 21, 2026 07:07
- Line 1062: clarify the graph has a minimum of two nodes; when
  response_format is set, a third generate_structured_response node
  makes a separate structured-output LLM call (extra latency/cost);
  hooks add further nodes before/after agent
- Signature and table: pre_model_hook returns dict | None (must include
  messages or llm_input_messages); post_model_hook returns
  Command | dict | None (Command overrides default conditional routing)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kn4Hvrh7QDiJ6HoggwDWgR
- "personal-identifiable information" → "personally identifiable
  information" (standard term)
- Add Recipes 18-21 to the guide's feature index at the top so
  TracePolicy, ToolRuntime delta streaming, entrypoint.final, and
  GraphOutput/Durability are discoverable from the overview

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kn4Hvrh7QDiJ6HoggwDWgR

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Several new examples expose sensitive state or document incorrect hook, model-selection, and checkpoint semantics.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 High severity · 1 Medium severity · 1 Low severity

Open (3)
Resolved since last review (1)
Previously missed (3)

In code that hasn't changed since last review

Medium severity Avoid registering the anonymize node twice

src/​content/​docs/​langgraph-guide/​python/​langgraph_recipes.md:3185

builder already contains the anonymize node from the complete example above, so executing this alternative block as written tries to register the same node a second time and raises instead of swapping the policy. Mark this block as a replacement for the earlier registration or build a fresh graph for the alternative.

Medium severity Return an unbound chat model

src/​content/​docs/​langgraph-guide/​python/​reference-prebuilt-nodes.md:1194

pick_model returns ChatOpenAI(...).bind_tools(...), but this factory's documented callable contract returns a BaseChatModel and the tools argument is bound by create_react_agent itself. Returning the bound runnable can be rebound or rejected when the agent selects the model; return the unbound ChatOpenAI and let the factory bind [search].

Low severity Use the correct PII terminology

src/​content/​docs/​langgraph-guide/​python/​langgraph_recipes.md:3111

Use “personally identifiable information”; “personal-identifiable information” is ungrammatical.

Comment thread src/content/docs/langgraph-guide/python/langgraph_recipes.md
Comment thread src/content/docs/langgraph-guide/python/langgraph_recipes.md
Comment thread src/content/docs/langgraph-guide/python/reference-prebuilt-nodes.md Outdated
Copilot AI review requested due to automatic review settings September 21, 2026 07:13

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ce309d9ece

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

When you need extra state fields, extend `MessagesState` and add `remaining_steps`:

```python
from typing import NotRequired, Annotated

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Import NotRequired from typing_extensions

On Python 3.10, which this guide explicitly supports, typing.NotRequired does not exist because it was added to the standard library in Python 3.11. Readers running this custom-state example on 3.10 therefore get an ImportError; import NotRequired from typing_extensions instead.

Useful? React with 👍 / 👎.

interrupt_before=None,
interrupt_after=None,
debug=False,
version="v2", # "v1" runs tools sequentially; "v2" (default) runs in parallel via Send

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Describe v1 tool calls as batched rather than sequential

For responses containing multiple tool calls, v1 sends all calls together through one ToolNode invocation, and ToolNode executes that batch concurrently; v2 instead fans the calls out as independent Send tasks. Fresh evidence in the updated diff is this newly added signature line, which now incorrectly labels v1 as sequential and can give readers wrong concurrency and failure-isolation expectations.

Useful? React with 👍 / 👎.

- version comment: v1 batches all tool calls into a single ToolNode
  invocation (ToolNode runs them concurrently internally); v2 fans each
  call out as an independent Send task. "sequential" was wrong.
- NotRequired: typing.NotRequired requires Python 3.11+; use
  typing_extensions.NotRequired for Python 3.10 compatibility

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kn4Hvrh7QDiJ6HoggwDWgR

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

New examples contain an invalid ToolRuntime import and fail to keep the persisted recipe state compact.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 High severity · 1 Low severity

Open (2)
Resolved since last review (3)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Checkpoint stores full retrieval context in last_answer

src/​content/​docs/​langgraph-guide/​python/​langgraph_recipes.md:3403

ans already embeds the full retrieval context because answer() interpolates ctx_str into it at lines 3373–3374, so saving last_answer=ans still persists all of the supposedly heavy intermediate snippets. This makes the “compact, no context snippets” checkpoint claim false; save a context-free answer or another compact representation instead.

Comment thread src/content/docs/langgraph-guide/python/langgraph_recipes.md
Comment thread src/content/docs/langgraph-guide/python/reference-prebuilt-nodes.md Outdated
Copilot AI review requested due to automatic review settings September 21, 2026 07:18
Clarify the full return contract for both hooks:
- pre_model_hook: dict | None; llm_input_messages is ephemeral (not
  checkpointed — only used as model input for that call)
- post_model_hook: Command | dict | None; Command overrides default
  conditional routing

The previous one-line description said "must return a dict" which
omitted None no-ops, Command routing, and the ephemeral nature of
llm_input_messages.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kn4Hvrh7QDiJ6HoggwDWgR

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dae05d945e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

**`post_model_hook`** receives the current state dict and must return `Command | dict | None`:
- Return `None` for a no-op.
- Return a dict to merge into state (e.g., record token usage).
- Return a `Command` to override the default conditional routing (e.g., short-circuit to `END` without calling tools).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Do not claim Command cancels tool routing

When the last AIMessage contains pending tool calls, returning Command(goto=END) from post_model_hook does not replace the graph's conditional routing; the existing router can still schedule the tools unless the hook also removes or replaces those tool calls. The advertised short-circuit can therefore execute side-effecting tools that a guardrail intended to block, so document the required state/message update instead.

Useful? React with 👍 / 👎.

# Use REMOVE_ALL_MESSAGES first, then re-add the messages to keep.
from langchain_core.messages import RemoveMessage
from langgraph.graph.message import REMOVE_ALL_MESSAGES
to_keep = state["messages"][-10:]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve tool-call pairs when trimming history

When a conversation contains tool calls, taking the last ten individual messages can retain a ToolMessage while deleting the preceding AIMessage that declared its tool_call_id. After a few tool-using turns, the next model request may therefore contain an orphan tool result and be rejected by OpenAI-compatible backends; trim complete tool-call groups or use llm_input_messages for prompt-only truncation.

Useful? React with 👍 / 👎.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Several new documentation sections contain inaccurate or internally inconsistent API semantics.

Review effort: Lite
Findings: None

Resolved since last review (2)
Previously missed (4)

In code that hasn't changed since last review

Medium severity Correct durability=exit persistence and interrupt behavior

src/​content/​docs/​langgraph-guide/​python/​langgraph_recipes.md:3496

durability="exit" persists when the run exits or is interrupted. Since this first invocation calls interrupt(), saying it checkpoints only when the graph exits/no mid-run persistence is inaccurate and obscures why the resume works; the durability table below repeats the same wording.

Medium severity Include tools in the complete stream modes list

src/​content/​docs/​langgraph-guide/​python/​reference-functional-api.md:13

With this page now verified against 1.2.11, the statement at line 269 that all stream modes apply is followed by a seven-item list that omits tools, even though the canonical streaming reference documents it as the eighth mode. Add tools to this list or narrow the claim.

Medium severity Update stream mode count and include tools in ALL_MODES

src/​content/​docs/​langgraph-guide/​python/​reference-streaming-modes.md:13

After this version bump, the page is internally inconsistent: its StreamMode union/table already include eight modes including tools (lines 67-79), but the title/frontmatter still says seven and the ALL_MODES example omits tools (line 965). Update all three so the v1.2.11 reference does not teach an incomplete set.

Low severity Qualify messages field as required only for non-empty updates

src/​content/​docs/​langgraph-guide/​python/​reference-prebuilt-nodes.md:1097

An empty dict is a supported no-op here (the example itself returns {} at line 1159, and chapter-08 documents {}/None as pass-through), so saying a dict "must include" messages or llm_input_messages is too strong. Please qualify this as required only for non-empty updates; the same wording is also repeated in the signature comment at line 1075.

This issue also appears on line 1098 of the same file.

post_model_hook_router is a separate conditional edge writer that runs
regardless of any Command.goto returned by the hook. Returning
Command(goto=END) alone does not prevent tools from firing when the
AIMessage has pending tool calls — the router reads fresh state and
routes to tools independently. Updated docs to reflect the correct
approach: clear tool_calls from the AIMessage to reroute to END.

Also fixed trim_history to drop leading ToolMessages whose parent
AIMessage was cut off by the naive last-N slice. OpenAI-compatible
backends reject orphaned ToolMessages (no matching AIMessage), so the
trim now advances the start of the kept window past any such orphans.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kn4Hvrh7QDiJ6HoggwDWgR
Copilot AI review requested due to automatic review settings September 21, 2026 07:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

New hook/model examples contain invalid patterns, and the streaming reference still undercounts the documented modes.

Review effort: Lite
Findings: None

Previously missed (3)

In code that hasn't changed since last review

Medium severity Return None instead of an invalid empty pre-model hook result

src/​content/​docs/​langgraph-guide/​python/​reference-prebuilt-nodes.md:1159

When the history already starts with a system message this branch returns {}, but the hook contract documented above requires a pre_model_hook result to contain messages or llm_input_messages; this can be rejected instead of acting as a no-op. Return None for the no-op branch.

Medium severity Return the unbound chat model from the callable model form

src/​content/​docs/​langgraph-guide/​python/​reference-prebuilt-nodes.md:1227

The callable model form is expected to return a BaseChatModel, and create_react_agent binds the supplied tools itself (as documented in the parameter table above). Calling bind_tools here returns a bound runnable rather than the required model and can fail dynamic-model validation or double-bind the tools; return the unbound ChatOpenAI instance.

Low severity Update StreamMode documentation to reflect eight values including tools

src/​content/​docs/​langgraph-guide/​python/​reference-streaming-modes.md:13

This version bump leaves the page internally inconsistent: StreamMode and the table enumerate eight values, including tools at lines 64–79, while the metadata and section headings still say seven. Update the description and headings to say eight and include tools in the all-modes wording so the v1.2.11 reference does not undercount the API.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fc04816ca1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +3192 to +3193
builder.add_node(
"anonymize",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Replace the existing node instead of registering it again

When this recipe is run top-to-bottom, builder already contains an anonymize node and has already been compiled, so this follow-up add_node("anonymize", ...) raises a duplicate-node ValueError rather than demonstrating the custom processor. Present this as a replacement for the earlier registration, or construct and compile a fresh builder for the custom-policy variant.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 5ef059f. The custom-processor snippet now constructs its own StateGraph (builder2) and compiles it independently, so running the recipe top-to-bottom no longer raises a duplicate-node ValueError.


Generated by Claude Code

Re-using the already-compiled builder raised a duplicate-node ValueError.
The custom-processor example now builds its own StateGraph (builder2)
so it is self-contained and safe to run top-to-bottom.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kn4Hvrh7QDiJ6HoggwDWgR
Copilot AI review requested due to automatic review settings September 21, 2026 07:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

The new reference material contains documentation inconsistencies in the TracePolicy import index and a no-op hook example.

Review effort: Lite
Findings: None

Previously missed (2)

In code that hasn't changed since last review

Low severity Return None for the documented no-op hook branch

src/​content/​docs/​langgraph-guide/​python/​reference-prebuilt-nodes.md:1159

This no-op branch returns {}, but the signature and parameter description above say a returned dict must include messages or llm_input_messages; the hook docs also identify None as the no-op form. Return None here (and reflect that in the helper annotation) so the example is consistent with the documented contract.

Low severity Add TracePolicy to the langgraph.types import table

src/​content/​docs/​langgraph-guide/​python/​reference-state-graph.md:132

This new option introduces TracePolicy as a public type, but the page's import table still omits it from the langgraph.types row at line 53 even though that table says it covers all symbols below. Add TracePolicy there so readers can discover the import path without following the separate link.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5ef059f8c2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


> **Deprecated since v1.0.** `create_react_agent` was moved to the separate `langchain` package (`langchain.agents.create_agent`). It remains in `langgraph.prebuilt` for backward compatibility and is scheduled for removal in v2.0.0. For new code, build a `StateGraph` with a `ToolNode` directly (as shown in the minimal example at the top of this page).

`create_react_agent` builds a ReAct-style agent graph in one call. It returns a compiled `StateGraph` with at minimum two nodes — `agent` (the LLM) and `tools` (a `ToolNode`) — wired with `tools_condition`. When `response_format` is set, a third `generate_structured_response` node is appended after `agent`/`tools`; it makes a **separate** structured-output LLM call and adds latency and cost. When hooks are provided, `pre_model_hook` and/or `post_model_hook` nodes are also inserted around `agent`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Account for tool-free agents in the node count

When tools=[], which create_react_agent supports, the factory omits the tools node and tools_condition entirely and can compile a graph containing only agent (plus any optional hook or structured-response nodes). Describing two nodes as the minimum misleads readers configuring node interrupts or interpreting streamed updates for tool-free agents.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 50b3285. The description now lists nodes conditionally rather than claiming a fixed minimum of two. When tools=[], tool_calling_enabled is False and the factory builds a graph with only agent (plus any optional hook/response nodes), so the docs now reflect that.


Generated by Claude Code

| `response_format` | Pydantic model or `(system_prompt, model)` tuple for structured output on the final response. |
| `pre_model_hook` | Separate node inserted **before** `agent`. Returns `dict \| None`; must include at least `messages` or `llm_input_messages`. Returning `None` is a no-op. Use for message trimming, injecting system prompts, etc. |
| `post_model_hook` | Separate node inserted **after** `agent` (v2 only). Returns `Command \| dict \| None`. Returning a `Command` overrides the default conditional routing (tools → end). Returning `None` is a no-op. Use for guardrails, human-in-the-loop, token tracking, etc. |
| `state_schema` | Custom state schema. Default `None` resolves to the built-in `AgentState` which has both `messages` (annotated with `add_messages`) and `remaining_steps: int`. Custom schemas must include both fields — `MessagesState` alone is rejected because it lacks `remaining_steps`. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require structured_response in custom structured-output state

When a caller combines a custom state_schema with response_format, validation also requires a structured_response field; documenting only messages and remaining_steps causes that supported combination to raise ValueError during create_react_agent. Add this conditional third requirement and show it in the custom-schema example or structured-output section.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 50b3285. The parameter table now documents that structured_response is also required when response_format is set (verified against chat_agent_executor.py:538-545). The custom-schema example now shows both the base pattern and the response_format variant with structured_response.


Generated by Claude Code

… requirement

create_react_agent omits the tools node entirely when tools=[] (verified
at chat_agent_executor.py:787). The "minimum two nodes" claim was wrong;
replaced with a bullet list showing which nodes are added conditionally.

Also: when state_schema + response_format are both set, structured_response
is required (chat_agent_executor.py:540-545). Updated the parameter table
and the custom-schema example to document this and show the correct pattern.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kn4Hvrh7QDiJ6HoggwDWgR
Copilot AI review requested due to automatic review settings September 21, 2026 07:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The new hook reference incorrectly states that Command overrides post-model routing even when pending tool calls remain.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 Low severity

Open (1)

Comment thread src/content/docs/langgraph-guide/python/reference-prebuilt-nodes.md Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 50b3285cb2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/content/docs/langgraph-guide/python/langgraph_recipes.md
…and table

The signature comment and parameter table both still claimed Command
overrides post_model_hook routing. Removed those claims: clarified
in both places that post_model_hook_router fires as a separate
conditional edge regardless of Command.goto, and that clearing
tool_calls on the AIMessage is the correct way to prevent tools.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kn4Hvrh7QDiJ6HoggwDWgR
Copilot AI review requested due to automatic review settings September 21, 2026 07:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

The new pre-model hook example returns an invalid empty dictionary on a valid execution path.

Review effort: Lite
Findings: None

Resolved since last review (1)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Return valid pre_model_hook output for an initial system message

src/​content/​docs/​langgraph-guide/​python/​reference-prebuilt-nodes.md:1181

When the first message is already a system message, this hook returns {}, but pre_model_hook requires a dict containing messages or llm_input_messages (or None for a no-op). The documented example therefore fails on that valid input; return the existing messages as an explicit llm_input_messages view (or change the return annotation and use None).

When the first message is already a system message, the hook should
return None (the documented idiomatic no-op) rather than an empty dict.
Update the return type annotation to reflect dict | None.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kn4Hvrh7QDiJ6HoggwDWgR
Copilot AI review requested due to automatic review settings September 21, 2026 07:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Recipe 20 incorrectly presents entrypoint.final as keeping the rich return value out of checkpoint state, making its central storage-saving example misleading.

Review effort: Lite
Findings: None

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants