executing-plans
executing-plans
Use when executing an implementation plan in the current session as the implementer yourself — your human partner chose inline execution, or no subagent tool is available
prebuilt-agentsUse LangGraph prebuilt ReAct agents, ToolNode, ValidationNode, injected state/store/runtime, tool error handling, and human interrupt schemas.
Independent GitHub snapshot · Automated classification · Original documentation governs
Use this sub-skill when an agent task involves langgraph.prebuilt: ReAct-style agent graphs, ToolNode, ValidationNode, tool-call routing, injected state/store/runtime, custom tool error handling, or human-in-the-loop interrupt payloads.
StateGraph mechanics, use sibling graph-runtime.| Goal | Use | Notes |
|---|---|---|
| Build a quick tool-calling loop | create_react_agent | Deprecated in LangGraph in favor of langchain.agents.create_agent, but still present in langgraph.prebuilt. |
| Execute model tool calls in a custom graph | ToolNode | Supports dict state, message-list input, and direct tool-call input. |
| Route only when an AI message has tool calls | tools_condition | Returns "tools" or "__end__"; accepts a custom messages_key. |
| Validate tool-call args without executing tools | ValidationNode | Deprecated; useful for extraction/re-prompt patterns that must preserve tool IDs. |
| Hide state/store/runtime from model-visible tool schemas | InjectedState, InjectedStore, ToolRuntime | Values are injected by ToolNode, not supplied by the LLM. |
| Pause for human review | HumanInterrupt, HumanResponse schemas | Interrupt schemas moved toward langchain.agents.interrupt; expect deprecation warnings from old imports. |
python skills/langgraph/sub-skills/prebuilt-agents/scripts/smoke_tool_node.py --help
python skills/langgraph/sub-skills/prebuilt-agents/scripts/smoke_tool_node.py
Expected smoke output includes a JSON object with a successful add tool result and an error ToolMessage for a malformed call. The script is self-contained and does not require credentials, network access, a checkpointer, or destructive writes.
Prefer the newer LangChain create_agent when starting greenfield code. Use langgraph.prebuilt.create_react_agent when maintaining existing LangGraph code or when the task explicitly asks for this API.
from langgraph.prebuilt import create_react_agent
def get_weather(city: str) -> str:
"""Return a small weather fixture."""
return f"sunny in {city}"
agent = create_react_agent(
model="anthropic:claude-3-7-sonnet-latest",
tools=[get_weather],
prompt="You are concise.",
version="v2",
)
result = agent.invoke({"messages": [{"role": "user", "content": "weather in sf"}]})
Important create_react_agent parameters:
prompt may be str, SystemMessage, callable, async callable, or Runnable; it receives graph state and may use configured store when supported.response_format adds a final structured response under structured_response and requires model .with_structured_output support.pre_model_hook must return at least messages or llm_input_messages; use RemoveMessage(id=REMOVE_ALL_MESSAGES) when overwriting messages.post_model_hook is available only with version="v2" and is useful for validation, guardrails, or human review.state_schema must include messages and remaining_steps; add structured_response when response_format is used.context_schema is the run-scoped context schema; config_schema is deprecated.checkpointer persists per-thread conversation state; store provides cross-thread persistent data to prompts and injected tools.interrupt_before and interrupt_after support node names such as "agent" and "tools".version="v1" executes all tool calls from one message inside one tool node; version="v2" distributes tool calls through Send and is the default.from langchain_core.messages import AIMessage
from langgraph.prebuilt import ToolNode
def add(a: int, b: int) -> int:
"""Add two integers."""
return a + b
node = ToolNode([add])
state = {
"messages": [
AIMessage(content="", tool_calls=[{"name": "add", "args": {"a": 2, "b": 3}, "id": "call-1"}])
]
}
output = node.invoke(state)
Accepted inputs:
messages or a custom messages_key containing messages.tool_calls.name, args, id, and type="tool_call" for programmatic tests.Outputs:
{messages_key: [ToolMessage(...)]} for ordinary tools.[ToolMessage(...)].Command may update graph state, navigate, or send messages; current-graph Command.update must include a matching ToolMessage for the tool-call ID unless it removes all messages.ToolNode(..., handle_tool_errors=...) accepts:
True: catch errors and return an error ToolMessage.False: re-raise errors; use this in tests when failures should be visible."message": catch errors and return the fixed message.ValueError or (ValueError, ToolException): catch only matching exception types.callable: format handled exceptions as a string; type annotations can narrow which exception types are handled.GraphInterrupt and other bubble-up graph control exceptions should not be swallowed as ordinary tool errors.
Use injected arguments for data the model must not control:
from typing import Annotated
from langgraph.prebuilt import InjectedState, InjectedStore
from langgraph.prebuilt.tool_node import ToolRuntime
from langgraph.store.base import BaseStore
def lookup_user(
query: str,
user_id: Annotated[str, InjectedState("user_id")],
store: Annotated[BaseStore, InjectedStore()],
runtime: ToolRuntime,
) -> str:
"""Use hidden graph context while exposing only query to the model."""
item = store.get(("users",), user_id)
return f"{query}: {item.value if item else 'missing'} via {runtime.tool_call_id}"
Rules:
InjectedState() injects the entire state; InjectedState("field") injects one state key or attribute.InjectedStore() requires compiling or invoking the graph with a store; otherwise ToolNode raises an injection error.ToolRuntime is injected by type annotation without Annotated and includes state, config, context, store, stream_writer, tool_call_id, tools, execution info, and server info.ToolNode invocation outside a compiled graph, injection-sensitive tests may need a runnable config that includes graph runtime context; prefer compiled graph tests when possible.ValidationNode validates tool calls from the last AIMessage against Pydantic models, BaseTool arg schemas, or function signatures, and returns ToolMessage objects. It does not execute tools.
Use it when a model should be re-prompted until generated tool-call args conform to a schema and existing tool-call IDs must be preserved for chat history consistency. On validation failure, the returned ToolMessage has additional_kwargs={"is_error": True} by default.
langgraph.prebuilt.interrupt exposes typed payloads for Agent Inbox style human review:
HumanInterruptConfig: booleans allow_ignore, allow_respond, allow_edit, allow_accept.ActionRequest: action string plus args dict.HumanInterrupt: action_request, config, and optional description.HumanResponse: type of "accept", "ignore", "response", or "edit", with matching args.Treat old prebuilt interrupt imports as compatibility support and expect deprecation warnings that point to langchain.agents.interrupt.
python skills/langgraph/sub-skills/prebuilt-agents/scripts/smoke_tool_node.py for a dependency-light local check.ToolMessage.tool_call_id matches the originating AIMessage.tool_calls[*].id.Command-returning tools, assert exactly one terminating ToolMessage is present for the tool call.ValidationNode, assert malformed calls return additional_kwargs["is_error"] and preserve the original tool-call ID.