Beyond Prompt Chaining: Architecting Resilient Agentic Control Systems
Sat Jul 11 2026

Architecting Agentic Workflows: Moving from Static Prompt Chaining to Iterative Loop-Based Control Systems
You are building a system to automate complex technical documentation updates. You start with a Directed Acyclic Graph (DAG) pipeline: a prompt extracts requirements, a second prompt generates code, a third writes the documentation, and a final prompt formats the output. It works for simple tasks. Then, you encounter a subtle bug in the code generation stage. Because the pipeline is linear and stateless, the documentation prompt receives the flawed code, hallucinates an explanation for that flaw, and produces a technically incorrect document. By the time the process ends, the error has compounded, and the original intent is lost.
This is the "linear collapse" problem. In non-deterministic environments, static prompt chains are fragile because they lack a feedback mechanism. They assume that each step in the chain will succeed with high probability, which is rarely true when dealing with LLMs.
The Fragility of Linear Prompt Chains
Linear pipelines treat LLM interactions as a series of fire-and-forget events. In a DAG, the output of Node A is the input of Node B. If Node A produces a slightly off-target result, Node B has no way to request a correction or query the original context to resolve the ambiguity.
Error Propagation
In sequential chains, errors are additive. If your first prompt has an 80% success rate, a five-step chain has a mathematical success probability of roughly 32% (0.8^5). In practice, it is often worse because LLMs tend to "double down" on errors. When a model receives a faulty input from a previous step, it often attempts to rationalize the input rather than correcting it, leading to a compounding effect where the final output bears little resemblance to the initial requirements.
Context Window Limitations
Stateless pipelines force you to pass the entire conversation history forward to maintain coherence. As the chain grows, you hit context limits or incur unnecessary token costs. Because there is no state management layer to summarize or prune information, the system eventually becomes bloated, leading to degraded performance as the "needle in the haystack" problem manifests within your own prompt chain.
Architecting the Iterative Loop: Re-Plan, Execute, Reflect
To build reliable agents, we must move from linear DAGs to cyclical state machines. This is the core of the ReAct (Reasoning and Acting) framework: the agent perceives the environment, decides on an action, executes it, and—crucially—observes the result to determine the next step.
The Reflective Loop
The "Reflect" step is the differentiator. Instead of moving blindly to the next node, the agent evaluates the output of its last action against a set of success criteria. If the output fails validation (e.g., a compiler error, a missing file, or a hallucinated function signature), the agent transitions back to a "Plan" or "Re-Plan" state rather than proceeding.
Deterministic Transition Functions
We bound LLM behavior by using deterministic code to manage the state machine. The LLM acts as the "brain" that selects an action, but the "controller" (your Python code) enforces the rules of the environment. This ensures that the agent cannot enter an invalid state or perform an unauthorized action, regardless of what the model suggests.
System Architecture: State Management and Persistence
An agentic loop is only as good as its memory. If the process crashes mid-loop, you should not have to restart the entire sequence.
The Memory Layer
We treat state as a persistent object. Each iteration of the loop updates the state, which is serialized and stored in a database (e.g., Redis or PostgreSQL).
graph TD
A[Input Request] --> B[State Initialization]
B --> C{Loop Controller}
C --> D[Reasoning Step]
D --> E[Tool Execution]
E --> F{Validation/Reflection}
F -- Failure --> G[Error Handling/Re-Plan]
G --> C
F -- Success --> H[Final Output]
F -- Needs Human --> I[HITL Gateway]
I --> C
Pydantic as a Contract
Pydantic schemas act as the interface between the LLM and your code. By forcing the model to output JSON that conforms to a specific schema, you create a hard contract. If the model returns a field that doesn't match the expected type or structure, the controller catches the error before it propagates, allowing for an immediate retry or a structured error message back to the LLM.
Implementation: Building a Resilient ReAct Loop
Below is a simplified implementation of a state machine controller using Python and Pydantic.
from pydantic import BaseModel, Field
from typing import List, Optional
class AgentState(BaseModel):
task: str
history: List[str] = []
is_complete: bool = False
error: Optional[str] = None
def run_agent_loop(initial_task: str):
state = AgentState(task=initial_task)
while not state.is_complete:
# # 1. Reasoning/Action Selection
action = llm.decide_next_step(state)
# # 2. Execution with Error Handling
try:
result = execute_tool(action)
state.history.append(f"Action: {action}, Result: {result}")
except Exception as e:
state.error = str(e)
state.history.append(f"Action: {action} failed with error: {e}")
# # 3. Reflection
if "error" in state.history[-1]:
continue # Loop back to re-plan
state.is_complete = check_if_done(state)
return state
Human-in-the-Loop (HITL) as a State Gateway
Not every task should be autonomous. For high-stakes operations, we implement a "state-gating" mechanism. When the agent reaches a decision point that requires human approval, it pauses execution and persists its entire state to the database.
The system emits an event (e.g., a Slack notification or an API callback) and waits. Because the state is fully persisted, the agent effectively "sleeps" until the human provides input. This prevents context loss and avoids the costs associated with keeping a process running while waiting for human interaction.
Operational Risks and Mitigation
Preventing Infinite Loops
The most common failure mode in iterative systems is the infinite retry loop. If an agent consistently fails a task, it may try the same incorrect action repeatedly.
- Mitigation: Implement a
max_stepscounter and ahistory_depthlimit. If the agent exceeds a threshold, force a fallback to a human operator or terminate the process with a diagnostic report.
Observability
Tracing is non-negotiable. You need to see the state transitions: what the agent thought, what it did, and why it decided to loop back. Use structured logging to capture the input/output of every state transition. Without this, debugging an agent that has gone rogue is nearly impossible.
Use Cases: Where Iterative Systems Outperform Chains
- Autonomous Software Engineering: An agent that writes code, runs unit tests, reads the stderr output, and modifies the code until the tests pass. A linear chain would stop at the first test failure.
- Complex Data Analysis: An agent that queries a database, realizes the data format is unexpected, updates its query, and performs a second pass before synthesizing the final report.
- Research Synthesis: An agent that performs a search, reads the results, identifies missing information, and performs targeted follow-up searches before writing the final summary.
References
- Yao et al. (2022). ReAct: Synergizing Reasoning and Acting in Language Models.
- Pydantic Documentation. Data validation for AI agent state management.
- Architectural patterns for state machines in LLM-based systems.
