new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

LangChain · LangGraph · all subjects

nodes and edges

31 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Node return type must be dict (Python) or object (JavaScript)

In LangGraph, nodes in a StateGraph must return a dictionary (Python) or object (JavaScript) containing one or more keys defined in the state schema. Returning any other type, such as a list, will cause an InvalidUpdateError.

Python node returning non-dict example

A node in a StateGraph that returns a list instead of a dict will trigger the error. Example: a node returning `['whoops']` when it should return a dict with the state key 'some_key'. The fix is to ensure all code paths in the node return an appropriate dict matching the defined state schema.

JavaScript node returning non-object example

A node in a StateGraph that returns an array instead of an object will trigger the error. Example: a node returning `['whoops']` when it should return an object with the state key 'someKey'. The fix is to ensure all code paths in the node return an appropriate object matching the defined state schema.

Ensure all code paths return correct type

When troubleshooting INVALID_GRAPH_NODE_RETURN_VALUE errors, check that all code paths in complex node logic return an appropriate dict (Python) or object (JavaScript) for the defined state. Some branches may inadvertently return a different type.

Model node calls LLM and returns response

The model node invokes model_with_tools() with system message and current messages, then returns the response in a dict with 'messages' key and optionally other state fields.

Tool node processes tool calls from last message

The tool node extracts tool_calls from the last message in state, looks up each tool by name, invokes it with the tool arguments, and returns ToolMessage objects with the results.

ToolNode state access limitation

Tools can only access the state values passed to the ToolNode. When ToolNode is added directly as a StateGraph node, the input is the current graph state. If you invoke a ToolNode manually from another node, you must pass the full state when tools need custom state fields. For example, tool_node.invoke(state) or toolNode.invoke(state, config) exposes the full state, while passing only {"messages": state["messages"]} only exposes messages.

Access graph state and context from tools - JavaScript

In JavaScript, read graph state and run-scoped context from tools using the tool's second argument, typed as @ToolRuntime.

ToolNode for tool execution

ToolNode is a prebuilt node that executes tools in LangGraph workflows. It handles parallel tool execution, error handling, and state injection automatically. Use ToolNode when you need fine-grained control over how your graph executes tools. It is the building block that powers tool execution in many LangGraph agent patterns.

ToolNode in JavaScript - creating with array of tools

In JavaScript, create a ToolNode by importing it from @langchain/langgraph/prebuilt and passing an array of tool instances to its constructor. Example: const toolNode = new ToolNode([search, calculator]).

Defining tools with @langchain/core/tools in JavaScript

Use the tool function from @langchain/core/tools to define tools. Provide a function as the first argument and an object with name, description, and schema (using zod) as the second argument. Example: const search = tool(({ query }) => `Results for: ${query}`, { name: 'search', description: 'Search for information.', schema: z.object({ query: z.string() }) }).

ToolNode receives model-generated arguments as first argument

Tools executed by ToolNode receive the arguments generated by the model as their first argument.

Access graph state and context from tools - Python

In Python, read graph state and run-scoped context from tools by using the injected @ToolRuntime argument.

END node represents terminal state

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.

Nodes and Edges are functions

Nodes and Edges in LangGraph are nothing more than functions. Nodes can contain an LLM or just regular code. Edges determine which node to execute next.

START node represents user input entry

The START node is a special node that represents the node that sends user input to the graph. The main purpose for referencing this node is to determine which nodes should be called first when user input arrives.

Nodes as functions in LangGraph

A node in LangGraph is a Python function (or TypeScript function) that reads the graph's state and makes updates to it. The first argument to this function is always the state. Nodes should return updates to the state directly, instead of mutating the state.

Creating sequential node flows

Use add_node and add_edge methods to create sequences. Example: builder.add_node(step_1); builder.add_node(step_2); builder.add_edge(START, 'step_1'); builder.add_edge('step_1', 'step_2'). Alternatively, use the add_sequence shorthand: builder = StateGraph(State).add_sequence([step_1, step_2, step_3]).

Parallel node execution with fan-out/fan-in

Use state reducers (operator.add for lists) to enable append-only updates that accumulate values from parallel nodes. Define edges from one node to multiple nodes (fan-out), then from those nodes back to a single node (fan-in). Parallel nodes execute concurrently in the same superstep.

Set maximum concurrency for parallel execution

Control the maximum number of concurrent tasks by setting max_concurrency in the configuration when invoking the graph. Example Python: graph.invoke({'value_1': 'c'}, {'configurable': {'max_concurrency': 10}}). Example TypeScript: await graph.invoke({value1: 'c'}, {configurable: {max_concurrency: 10}});

Defer node execution until all pending tasks complete

Set defer=True when adding a node to delay its execution until all other pending tasks are completed. This is useful for branches of different lengths. Example: builder.add_node('d', defer=True). Deferred nodes wait for all preceding branches to finish before executing.

Map-Reduce with Send API

Use the Send API to implement map-reduce patterns. Return a list of Send objects from a conditional edge, where each Send specifies a node and state update. Example: def continue_to_jokes(state): return [Send('generate_joke', {'subject': s}) for s in state['subjects']].

Creating loops with termination conditions

Implement loops by adding conditional edges that specify a termination condition and route to END when satisfied. Example: def route(state): if termination_condition(state): return END; else: return 'b'.

Async nodes with await

Convert sync nodes to async by using async def instead of def and await for async operations. Example: async def node(state: MessagesState): new_message = await llm.ainvoke(state['messages']); return {'messages': [new_message]}. Invoke with .ainvoke or .astream.

Command object for combined control flow and state updates

Return a Command object from node functions to both update state and specify the next node in a single operation. Example: Command(update={'foo': 'bar'}, goto='my_other_node'). This replaces conditional edges for routing logic.

Command return type annotation

Use Command[Literal['node_b', 'node_c']] as the return type annotation for nodes returning Command objects. This is necessary for graph rendering and tells LangGraph which nodes can be navigated to.

Update graph state from tools using Command

Return Command(update={'state_key': value, 'messages': [...]}) from tools to update graph state. Must include messages with ToolMessage when returning Command from tools. Example: Command(update={'user_info': info, 'messages': [ToolMessage('...', tool_call_id=...)]}).

ToolMessage required in Command returns from tools

When returning Command from a tool, the messages list must contain a ToolMessage. This ensures the resulting message history is valid for LLM providers which require AI messages with tool calls to be followed by tool result messages.

ToolNode for handling Command returns from tools

Use the prebuilt ToolNode which automatically handles tools returning Command objects and propagates them to the graph state. For custom nodes calling tools, manually propagate Command objects returned by tools as the node's update.

Node naming with add_node

Specify custom names for nodes using add_node. When no name is provided, the default is the function's __name__ (Python) or .name (JavaScript). Example Python: builder.add_node('my_node', step_1). Example TypeScript: graph.addNode('myNode', step1).

START and END special nodes

START marks the entry point of a graph. END marks termination points. Import from langgraph.graph (Python) or @langchain/langgraph (TypeScript). Use START in edges to define where execution begins, and return END from conditional edges to terminate.

Give your agent this brain