← All writing

Technical note · 2026-09-15

Agent graphs: making state and routing explicit

Use a research workflow to understand state, nodes, edges and cycles, including budget-aware routing, parallel updates and the limits of checkpoint recovery.

Exploration · Principles and possible approaches inspired by a project context.

  • AI learning
  • Graph
  • LangGraph
  • State management

Two sources disagree. Should a research assistant search again, record the disagreement or start writing? As such decisions accumulate, a single loop can hide its branches inside string checks and exception handlers.

A graph makes execution paths explicit. Here, graph means an execution graph, not a knowledge graph of entities and relations. It does not require multiple agents.

Think of it as a task flowchart that chooses a route from the current situation. Has the source been read? Is the evidence sufficient? Are more searches allowed? A box represents a step, and an arrow shows where execution can go next.

Three concepts with different jobs

The LangGraph Graph API describes state, nodes and edges. In this example, these correspond to what is known, what a step does and where execution goes next. Execution can return to an earlier step; a graph need not be acyclic, or restricted to moving forward without returning.

Concept Research-assistant example
State Question, evidence, source references, gaps and remaining searches
Node Search, read, check references or draft a note
Edge Return to search when evidence is missing; write when requirements are met

A node can contain an ordinary function, a model call or a small agent loop. Naming a function a node does not make it intelligent.

Define state before drawing arrows

This is a custom design sketch, not a complete LangGraph configuration:

{
  "question": "Can a timed-out tool call be retried immediately?",
  "sources": [{"id": "source-1", "status": "read"}],
  "claims": [{"text": "A timeout can occur after a write", "sourceIds": ["source-1"]}],
  "openQuestions": ["Does the target API support idempotency keys?"],
  "searchesRemaining": 2,
  "draftPath": null
}

Source records distinguish what was read; claims associate statements with evidence; open questions preserve uncertainty. A single summary string makes it harder to separate confirmed findings, guesses and unexplored questions.

Keep large documents outside the state when stable references suffice. Data present in execution state need not all become model input; see context and memory.

Route on progress and budget

Start → Search → Read → Check evidence
                       ├─ Requirements met → Draft → Verify → End
                       ├─ Gaps, budget available → Search
                       └─ Gaps, budget exhausted → Gap report → End

A gap report is a legitimate partial outcome, with a distinct status from a verified complete report. It should state what was established and what remains unknown.

Decide when an attempt consumes its allowance. Counting only successful searches permits endless failures without exhausting the counter. Record an attempt before dispatch, and distinguish model calls, tool calls and monetary costs rather than pretending they are interchangeable budgets.

Parallel updates need merge rules

Two readers may add sources concurrently. Replacing the old value can lose one result; always appending can introduce duplicates. Define merge rules by field. A reducer is a function that combines an old value with an incoming update; check what the chosen framework’s reducer actually does.

For this assistant, source IDs or normalized URLs can identify duplicates while retaining retrieval times and versions. Conflicting claims should preserve both pieces of evidence for review. A last-writer-wins update would conceal the disagreement. Different URLs carrying the same syndicated text are not automatically independent evidence either.

A serial version helps validate these contracts first. Parallel scheduling does not determine what a correct merge means.

Checkpoints do not make every side effect exactly once

A checkpoint is a saved record of task progress. A side effect is an action that changes something outside the running calculation, such as saving a file or creating a record.

A process can exit after saving a file but before recording completion. Persisted graph state does not automatically make the external write transactional. The LangGraph Functional API documentation discusses idempotency for operations that may run again.

Ask two separate questions: where execution resumes, and whether its next external action is safe to repeat. The second belongs to tool retry contracts.

When a graph helps

Two fixed steps may be clearer as ordinary function calls. Explicit state transitions become useful when branching, retries, human input and recovery positions start shaping the tests.

Try routing three fixed inputs without calling a model: sufficient evidence, missing evidence with budget, and exhausted budget. Then introduce conflicting sources. The workflow should not mistake a longer evidence list for stronger support.