Day 2

The Agent Loop

Master the Reason-Act-Observe cycle that powers every AI agent.

The agent loop is the core runtime that drives all agentic behavior. An LLM generates a thought and an action, the system executes the action and records the observation, and the loop continues until the agent decides it has enough information to produce a final answer.

45m
1 problem

Today’s Lesson

3

Review

Test yourself with these interview-style questions.

1Walk through the lifecycle of a single iteration in a ReAct agent loop. Describe what happens from the moment the LLM receives the prompt to the point where the next iteration begins. Cover the key data structures involved and the termination conditions.+

Each iteration starts with the LLM receiving the system prompt (tool definitions) plus accumulated history of (thought, action, observation) tuples. The LLM generates a thought and either a tool action (with name and arguments) or a Final Answer. If tool action, the runtime dispatches to the correct tool, catches exceptions, formats the result as an observation string, and appends it to history. If Final Answer, the loop terminates. If max_steps is hit without a Final Answer, the loop returns a timeout error. The history accumulates on every iteration and is included in full on the next LLM call.

Read full answer

Each ReAct iteration has five phases. First, prompt assembly: the runtime concatenates the system prompt (tool list with schemas) with the full history of prior turns serialised as structured text. This grows linearly with each step. Second, LLM generation: the model produces a thought (reasoning about what to do next) followed by either a tool call specification or a Final Answer. Third, parsing: the runtime extracts the structured action from the LLM's text output using regex or JSON parsing. Fourth, execution: if it is a tool action, the runtime looks up the tool in the registry, validates arguments against the schema, calls the tool function, wraps the result or exception into a formatted observation. Fifth, history update: the (thought, action, observation) triple is appended to the history list. If the action was a Final Answer, return it. If step count equals max_steps, return a timeout error. Otherwise, loop back to phase one. The key data structures are the registry (maps tool names to schemas and implementations), the history list (accumulates serialised turns), and the step counter. The system prompt is static but grows implicitly because history keeps expanding.

2An agent produces this trace: Step 1: Thought "I need to find the user email." Action: search_user(name="Alice"). Observation: "User found: alice@example.com". Step 2: Thought "Now I will send the email." Action: send_email(to="alice@example.com", body="Hello"). Observation: "Email sent". Step 3: Thought "I should check delivery." Action: check_delivery(email_id=None). Observation: "Error: email_id is required". Identify the bug and explain how to fix it.+

The bug is state loss: the agent failed to preserve the email_id returned by send_email for use by check_delivery. The send_email tool returned an ID, but the observation text "Email sent" lost the structured data. The fix is to return structured observations that include all relevant fields, or have the LLM explicitly capture intermediate results in its scratchpad. Without state preservation across steps, the agent cannot chain dependent tool calls.

Read full answer

This is a classic state management failure. The root cause is that send_email likely returned `{"status": "sent", "email_id": "msg_123"}`, but the agent only recorded the observation text "Email sent" — discarding the structured email_id. The LLM then had no email_id to pass to check_delivery. Fixes include: enforcing structured observations where every tool returns consistent JSON, having the LLM scratchpad capture key fields, or storing tool outputs in a session state dict. The most robust solution combines structured returns with a session state dict the LLM can reference. The broader lesson is that agents cannot reliably chain tool calls without explicit state management.

3Design a strategy to handle three types of partial LLM failures in the agent loop: (1) malformed JSON for the action, (2) repeated identical actions, and (3) thought without any action. Propose detection mechanisms and recovery strategies for each.+

For malformed JSON, wrap parsing in try-catch and inject the parser error as an observation telling the LLM to fix the format. For repeated actions, maintain a sliding window of recent action signatures — if the same tool and normalised args appear 3+ times, inject an observation warning about the loop. For thought without action, validate that output contains either a tool action or Final Answer, and if missing, re-prompt with a format example.

Read full answer

I design a layered error handler. For malformed JSON, I wrap parsing in try-catch and inject an observation: "Your response could not be parsed. Expected format: {'type': 'tool', ...} Your raw output was: [raw]. Please fix." This gives the LLM a self-correction path. For repeated actions, I maintain a window of last N action signatures. If the same (tool_name, normalised_args) appears 3+ times consecutively, I inject: "You have called the same tool 3 times. This appears to be a loop. Consider a different approach or produce a Final Answer." For missing actions, I validate post-parse that action_type exists. If missing, I re-prompt with stricter format instruction and an example. The key principle: every failure mode gets a deterministic, LLM-readable recovery path that guides the LLM back to productive behaviour without crashing the loop.


Back to 30-Day Agentic AI Interview Prep Path
Agent Loop Explained: Reason-Act-Observe Cycle | AgenticPrep