✎ Edit content·DAY 076 · POST 4 OF 5 · Code Example

The ReAct Pattern

AI Agents · 11 slides
DAY 076 · POST 4 OF 5
(REMINDER)
DAY 076
Build a ReAct Agent in Code
@saurav_dnj_24github.com/SauravDnj · linkedin.com/in/sauravdnj
1 / 11

Theme

Palette

Download

4K — sharpest, slowest
🎬 Video options
Preparing preview…
Live preview · loops the “none” effect
All rendering runs in your browser. No server, no cost, no upload. MP4/WebM = full motion + effects · GIF = lightweight loop · PNG/PDF = static for the Instagram & LinkedIn carousel.

Caption (tap to copy)

📖 Deep dive (full written explanation)

The slides stay clean and scannable. Here's the in-depth explanation behind each one — great for the blog version, show notes, or studying the topic properly.
Slide 1 · Build a ReAct Agent in Code

This cover sets expectations: the post is a working agent, not a lecture. You will build ReAct twice — first in the raw text format so every moving part is visible, then with native tool-calling so you have the production-shaped version — because seeing the brittle hand-rolled version first is what makes the clean API legible rather than magical.

The through-line is the loop from the previous post, now made concrete: define tools, write the prompt, parse and dispatch actions, feed observations back, and bound the whole thing with guardrails. By the end you have an agent you understand line by line.

Slide 2 · 1. Define the tools

The tools step establishes the simplest possible contract: a tool is a function that takes a string and returns a string. calc evaluates an arithmetic expression inside a stripped-down namespace; search is a stub returning canned facts you would replace with a real API. The TOOLS dictionary maps names to functions for dispatch.

Two things deserve attention. The calc function passes an empty builtins dict to eval, a nod toward sandboxing — though, as the guardrails slide warns, eval on untrusted input is dangerous and a real system needs a proper sandbox. And keeping the tool signature uniform (string in, string out) is what lets the loop dispatch to any tool without special-casing, which keeps the controller simple.

Slide 3 · 2. Write the system prompt

The system prompt is where you encode the agent's behavior. This version uses a deliberately simple delimiter — tool_name|argument — instead of function-call syntax, because a single pipe is far easier to parse reliably than balanced parentheses and quotes. It shows the exact step format, tells the model to stop and wait after each Action, and lists the two tools with their argument shapes.

The instruction to STOP and wait for an Observation is doing real work: paired with a stop sequence in the loop, it prevents the model from hallucinating the tool's result and reasoning against fiction. The prompt is the agent's specification, and every ambiguity here becomes a bug downstream, so it pays to be explicit and to match the format your parser expects exactly.

Slide 4 · 3. Parse the action line

The parser turns the model's text into a dispatchable call. It runs a regex looking for an Action line with the tool|argument shape, pulls out the name and the argument, and strips whitespace. If no action is found it returns None, None, which the loop treats as a signal that the step was reasoning or an answer rather than a tool call.

This function is the fragile seam the day keeps warning about. The regex assumes the model formats the line exactly as instructed; a stray space, a different delimiter, or a quoted argument can break it. It is perfect for learning because you can see precisely what is parsed, but the modern-version slides exist specifically to retire this brittleness in production.

Slide 5 · 4. The ReAct loop

The loop ties everything together and is worth reading slowly. It seeds the transcript with the system prompt and the question, then iterates up to max_steps. Each pass calls the LLM with a stop on 'Observation:' so control returns to your code right after the Action. If the step contains an Answer, it extracts and returns it. Otherwise it parses the action, guards against an unknown tool name, runs the tool, and appends the result as an Observation.

The unknown-tool guard is a small but important touch: instead of crashing, it feeds an error string back as an Observation, giving the model a chance to recover by choosing a valid tool. And the for-loop bound is the infinite-loop fuse. This single function is a complete, self-contained ReAct agent in roughly a dozen lines.

Slide 6 · What the agent does at runtime

The cycle diagram captures what the agent does at runtime as a repeating rhythm: the LLM emits a Thought and Action, the parser extracts the tool and argument, the controller executes the tool, and the result is observed and appended — then back to the top. It is the same think-act-observe loop, now grounded in the specific code you just wrote.

Seeing it as a cycle reinforces that the agent has no hidden state. Each lap consumes the growing transcript and produces one more step. Everything the model knows on the third lap is the text accumulated over the first two, which is exactly why managing that transcript becomes the central production concern in the mistakes post.

Slide 7 · 5. Modern version: native tool-calling

This slide makes the leap to production by replacing text parsing with the model's native tool-calling API. You declare each tool with a name, description, and JSON input schema; the model, when it decides to act, returns a structured tool_use block instead of prose. You read the tool name and the already-parsed input dict and dispatch with a clean keyword-argument call — no regex anywhere.

The payoff is robustness. The format can no longer drift because the model is constrained to emit structured data, and the arguments arrive typed according to your schema. The lesson of building the text version first is now obvious: native tool-calling is the same ReAct loop with the brittle parsing seam replaced by a contract the model is guaranteed to honor.

Slide 8 · 6. Feed the result back

This slide shows the other half of the native loop: feeding the result back. You append the assistant's turn (the tool_use block) to the message list, then append a user turn containing a tool_result that references the call by its id and carries the tool's output. Re-calling the model continues the loop, and you repeat until the stop_reason is no longer tool_use.

The tool_use_id linkage is the detail that makes multi-tool and parallel calls work — it tells the model exactly which call each result answers. This message-passing structure is the production pattern: instead of one growing text blob, the conversation is a typed sequence of turns the API manages, which is cleaner, more reliable, and what every modern agent framework uses under the hood.

Slide 9 · Text format vs native tool-calling

The comparison contrasts the two implementations trait by trait so you can choose deliberately. The text format regex-parses Action lines, is brittle when the format drifts, works on any LLM including ones with no tool API, and is excellent for learning. Native tool-calling uses structured tool_use blocks, has no parsing and no drift, requires a tool-aware model, and is the production default.

The honest takeaway is that both have a place. Build and learn with the text version because it exposes every mechanic; ship with the native version because it removes the most common source of production failures. They are the same pattern — the difference is only in how the Action crosses the boundary between the model and your code.

Slide 10 · Make it production-ready

The tips translate the agent into operational discipline. Always cap max_steps so a confused agent cannot run forever. Catch tool errors and feed them back as Observations so the model can self-correct instead of crashing. Prefer native tool-calling over regex to eliminate format drift. Log the full transcript for every run so failures are diagnosable. And never eval untrusted input — sandbox any tool that executes code or touches the system.

Each tip closes a specific hole in the naive implementation you just built. The calc tool's bare eval is the clearest example: fine for a demo, a security hole in production. Together these five points are the gap between an agent that demos well once and one you can actually deploy.

Slide 11 · Save this. Follow for Day 77.

The CTA bridges to the failure modes. You now have a working agent in two forms, which means you are now exposed to the subtler danger: an agent that runs but fails in expensive, hard-to-spot ways — looping, mis-parsing, choosing wrong tools, bloating context. The next post is the field guide to those traps.

Save this post as your implementation reference. When you sit down to build a real agent, these six steps — tools, prompt, parser, loop, native version, guardrails — are the skeleton you fill in with your own tools, model, and limits.

🎨 AI image prompt (matches this theme + palette)

Paste into Midjourney, DALL·E, Ideogram, etc. to generate an on-brand image, then upload it on the Edit content page. The prompt updates automatically with the selected theme + palette.