LangGraph Multi-Agent Architecture: Building a Self-Critiquing AI Debate System
Last Updated on May 4, 2026 by Editorial Team Author(s): Rishav Saigal Originally published on Towards AI. A technical deep-dive into the LangGraph state machine, Pydantic-driven routing, and Critique Agent design powering the LLM Drift Experiment. In the opening piece of this series, we explored the conceptual “why” behind LLM Drift — how AI agents lose their persona, reasoning quality, and behavioral consistency under sustained adversarial pressure. But for the engineers and architects in the room, the “how” is where the real story lives. Building a system designed to intentionally stress-test agent stability requires more than a sequential script. It requires a stateful, resilient, and adversarial architecture — one where failure modes are first-class citizens, not edge cases to be patched later. To build the LLM Drift Experiment, we chose LangGraph. Here is a deep dive into the architectural decisions that power our multi-agent debate engine. Why LangGraph? Stateful Graphs vs. Naive Loops When building complex agentic workflows, the biggest engineering challenge isn’t the LLM call itself — it’s the logic between the calls. We needed a system capable of: Maintaining stateful context across dozens of debate rounds Implementing conditional loops that re-enter specific nodes upon rejection Supporting node-level retries without restarting the entire workflow Plain Python loops or simple LangChain chains don’t handle this gracefully. A for loop over LLM calls gives you no way to selectively re-run a single node, inspect intermediate state, or branch on structured output without building your own routing infrastructure from scratch. LangGraph’s directed graph model solves all three problems natively. It lets you define an explicit typed state object, create conditional edges that read from that state, and implement node-level retries with full visibility into what happened at each step. For a system where agents must iterate until they satisfy a hostile internal critic, this isn’t just convenient — it’s architecturally necessary. “LangGraph enables conditional re-entry — a naive loop cannot.” The Full Debate Graph: How Every Turn Is Orchestrated The heart of the project is the orchestration graph. Every turn of the debate follows a rigorous, deterministic path: The Pros Agent generates an argument The argument passes through the internal refinement loop (more on this below) Only upon approval is it committed to shared memory The Cons Agent reads from shared memory and generates a counter-argument The same internal loop applies before the Cons argument is published The cycle repeats for N configured rounds We rely on LangGraph’s auto-generated graph visualization to monitor this flow in real time. Two conditional edges — should_continue_pros and should_continue_cons — act as gatekeepers, reading the is_approved boolean from the agent's structured output and deciding whether to advance to the next team or loop back for refinement. START → pros_agent → critique_pros → [conditional] → cons_agent → critique_cons → [conditional] → END or loop. The Refinement Loop: An Agent Designed to Reject Its Own Team The most architecturally novel component of this system is the internal Persona → Thinking → Critique loop. In most agentic systems, critic agents are designed to be helpful — nudging outputs toward better quality. In our experiment, the Critique Agent is deliberately adversarial. Every argument generated by the Pros or Cons team must pass through three internal stages before it reaches shared memory: Persona Agent Architects or actively redesigns the team’s adversarial identity each round. It reads persona.json to assess the current persona, then decides whether to reuse the existing identity or design a new strategic persona based on the opponent's latest moves. This dynamic decision — maintain or evolve — is precisely what makes the Persona Agent the most sensitive node for drift detection. The persona it settles on becomes the identity anchor we measure all subsequent outputs against. Thinking Agent Stress-tests the argument internally. It identifies logical gaps, weak evidence chains, and rhetorical inconsistencies before the Critique Agent ever sees the output. Critique Agent Acts as a hostile internal auditor. Its sole function is to find grounds for rejection. If the argument is logically circular, emotionally inconsistent with the persona, or reasoning from the same evidence as the previous round, it issues a rejection with structured feedback — and the loop restarts at the Persona Agent. Arguments only exit to shared_memory.json after surviving this audit. This enforces a high baseline of argument quality — but it also creates a fascinating failure mode we are actively monitoring: loop-lock, where the Critique Agent becomes so strict that neither agent can produce an argument that passes. Loop-lock is, in itself, a measurable form of cognitive drift. “Loop-lock monitored as a drift signal.” Memory Architecture: Isolation by Design Memory management is treated as a first-class architectural concern, not an afterthought. We implemented a two-tier isolation system to preserve experimental integrity. Shared Memory (shared_memory.json) The public transcript of the debate. Both teams can read from this file — it contains only finalized, approved arguments. This represents the “official record” of what each agent has argued. Team-Private Memory Each team maintains three private files that are invisible to the opposing agent: persona.json — the identity anchor and behavioral constraints for this team thinking.json — internal reasoning scratchpad (not part of the public argument) critique.json — the Critique Agent's rejection logs and feedback history This isolation is architecturally critical. If the Cons team could read the Pros team’s internal thinking.json, they would have access to reasoning that was explicitly not published — effectively cheating. More importantly for drift measurement, cross-team memory contamination would corrupt the persona consistency scores by introducing external framing before the argument is finalized. Two additional design rules enforce experimental integrity: Append-Only Writes. The write_json_direct() function only ever appends entries to memory files — it never overwrites. Every version of every persona, every thinking draft, and every critique rejection is preserved. This enables full forensic reconstruction of how any argument evolved across all its internal iterations. Automatic Run Archiving. When a simulation completes, the entire memory state is automatically archived to Research Runs/ using a structured naming convention: memory-v{VERSION}-temp-{TEMPERATURE}-max-tokens-{MAX_TOKENS}# e.g. memory-v6-temp-1-max-tokens-4096 If a […]
