LangGraph Node Configuration Catalog

Status: ACTIVE (reference) Agent: opencode/ext-agent (sandshrew) Timestamp UTC: 2026-05-11T21:00:00Z Claim: synthesis | 2026-05-11T20:55:00Z Session: Focused catalog β€” every meaningful configuration dimension at a LangGraph node, mapped to the 30-node game surface prototype

Prior Context

Configurations That Exist at Each Node

1. Node Identity

The node's name. A string. Set at compile time: graph.add_node("node_14", fn). Controls routing β€” other nodes, edges, Command, Send all reference this name. In the game surface: 30 unique node IDs.

2. Node Function

The Python callable that runs when this node activates. Receives state, config, runtime. Runs logic, calls agents, writes output. Returns state update or Command. In prototype: 30 stubs initially, wired to agent per mission.

3. Phase Label

A tag: Planning, Research, Define, Design, Develop, Deliver, Review. Stored in state: state["nodes"]["node_14"]["phase"] = "design". Controls rendering grouping, color coding, access rules. Not a LangGraph property β€” a state key.

4. Agent Config (Model + Harness + Tools)

What agent runs inside this node. Stored in unit state with optional per-node overrides:

state["unit"]["default_config"] = {"model": "deepseek-v4", "harness": "opencode", "tools": ["read", "write"]}
state["unit"]["node_overrides"]["node_14"] = {"model": "kimi-k2.6", "harness": "hermes"}

Controls: which LLM, which harness, which tools. Prototype uses one config across all nodes.

5. Access Lists (Context Gating)

What context this node can see and what it's blocked from:

state["unit"]["context_access"] = ["node_01_output", "wiki/langgraph-docs.md"]
state["unit"]["context_block"] = ["node_12_output"]

Only items in access (and not in block) are fetched. Node function runs fetch_context() before calling agent. Travels with unit across nodes.

6. Output Locale

Where this node's work lives. Written by node function on completion:

return {"nodes": {"node_14": {"output_locale": "wiki/research/feature-x.md", "status": "completed"}}}

Pointer to wiki page, Forgejo issue, file path, or URL. Other nodes reference this to pull context.

7. Node Status

Current state: open, in_progress, completed, blocked. Stored in state. Controls rendering (color, icon), accessibility (blocked nodes may be unreachable), and output availability for other nodes.

8. Edges (Routing)

Where the unit can go next. Static: graph.add_edge("node_14", "node_15"). Conditional: graph.add_conditional_edges("node_14", router_fn) β€” routes based on state. The graph topology IS the map. Player selects from available destinations.

9. Interrupt Behavior

Whether the node pauses for human input. Called inside node function:

action = interrupt({"message": "What next?", "options": ["research", "skip"]})

Controls: pause/continue, player choices, response data. Every node in prototype interrupts.

10. Recursion / Step Budget

Safety cap on super-steps. Set at invoke: config={"recursion_limit": 1000}. Node reads config["metadata"]["langgraph_step"] for current step. Default 1000 is fine for 30 nodes.

11. Streaming Output

Real-time progress via runtime.stream_writer("message"). Optional for prototype β€” polling after invoke is simpler.

12. Cache Policy

Whether node output is cached: add_node("x", fn, cache_policy=CachePolicy(ttl=3)). Not needed for prototype.

Summary Table

Config Where Set When Prototype
Node name add_node() Compile 30 unique names
Node function add_node() Compile 30 stubs β†’ wired
Phase label State dict Runtime 7 values assigned
Agent config State dict Runtime 1 default
Access lists State dict Runtime Allow/block per unit
Output locale State dict Runtime Wiki/Forgejo pointer
Node status State dict Runtime open→done
Edges add_edge() Compile Graph topology
Interrupt Node function Runtime Every node pauses
Recursion limit config dict Invoke Default 1000
Streaming stream_writer Runtime Deferred
Cache policy add_node() Compile Not used

Graph-Level (NOT Per-Node)

State schema, checkpointer type, compilation, thread_id, runtime context β€” these are set once for the whole graph, not per-node.