06 Memory and State 3 min read 535 words
State Management Patterns (Dec 2025)
State management in AI systems has moved from simple "sessions" to Stateful Agent Graphs. In late 2025, managing the flow and persistence of an agent's "mind" is as critical as the LLM itself.
The State Object
The "State" is the Single Source of Truth for an agent session.
class AgentState(TypedDict):
messages: Annotated[list[AnyMessage], add_messages]
plan: list[str]
current_task: str
tool_results: dict[str, Any]
user_context: dict[str, Any]
iteration_count: int
2025 Best Practice: State should be Strictly Typed and Append-Only whenever possible to prevent data loss during long execution loops.
State Machines (LangGraph)
Industry has converged on Cyclic Graphs (State Machines).
- Nodes: Functions that take the state and return an update.
- Edges: Conditional logic that determines the next node based on state values (e.g.,
if state['error'] -> goto 'recovery_node').
Checkpointing and Resume
In production, agents can run for minutes or hours.
- Persistence Layer: Every state update is saved to a DB (Postgres/Redis).
- Resiliancy: If the server crashes, the orchestrator retrieves the last
checkpoint_idand resumes exactly where it left off. - UX: This allows for Asynchronous Agents where the user gets an "I'm working on it" message and a notification 10 minutes later when the state is "Complete."
Parallel State (Fork/Join)
For complex tasks, we Fork the state.
- Fan-out: Send the state to 3 sub-agents (e.g., Researcher A, B, and C).
- Fan-in (Join): A "Manager" agent receives the outputs of all three and merges them back into the main state object.
Time-Travel (State Rewriting)
As covered in the HITL chapter, state management allows for Human Intervention.
- A developer can browse the session history, find a "bad turn," edit the state object at that specific timestamp, and Re-run the graph from that point.
Interview Questions
Q: Why use a "Graph-based" State Machine (LangGraph) instead of a simple "While loop" for agents?
Strong answer: A While loop is Opaque and Brittle. You can't easily visualize the logic, and error handling becomes a mess of nested if-statements. A Graph-based approach is Observable and Modular. You can visualize the Entire Flow (as a Mermaid diagram), unit-test individual nodes, and implement complex features like "Backtracking" or "Parallel execution" simply by adding new edges. It also makes State Persistence trivial because the framework handles the saving/loading between nodes.
Q: How do you prevent "State Bloat" in long-running agent sessions?
Strong answer:
We use State Pruning and Message Summarization. Instead of carrying the entire tool_results dictionary through the whole graph, we trim it once a sub-task is complete. For the messages list, we use a specialized "Summarizer Node" that runs every 10 turns to compress history into a concise context block, ensuring we don't hit the token limit while keeping the state object responsive.
References
- LangChain. "LangGraph: Multi-Agent Workflows" (2024/2025)
- Temporal.io. "Stateful AI Agents at Scale" (2025)
- AWS Bedrock. "Managing Long-Running Agent Sessions" (2025)
Key takeaways
01
State is one typed object
State carries messages, plan, current task, tool results, user context and iteration count; keeping it strictly typed and append-only is what prevents loss in long loops.
02
Graphs beat while loops for agents
A cyclic graph makes the flow diagrammable, individual nodes unit-testable and persistence automatic, where a while loop buries the same logic in nested conditionals.
03
Checkpoints make long agents restartable
Persisting every state update to Postgres or Redis lets a crashed orchestrator resume from the last checkpoint, which is also what enables asynchronous notify-me-later agents.
04
Stored history enables time travel
Because state is saved per turn, a developer can locate a bad turn, edit the state object at that timestamp, and re-run the graph forward from there.
05
Prune state or hit token limits
Tool results are trimmed once a subtask completes, and a summariser node compresses message history roughly every ten turns to keep the state object responsive.