6.2.1 · D3AI Agents & Tool Use

Worked examples — Agent architectures and reasoning loops

3,650 words17 min readBack to topic

The parent note gave you the machinery — the reasoning loop, ReAct, memory. This page does one thing: it drags that machinery through every kind of situation it can meet, one worked example per situation, so you never hit a case you haven't seen.

Before any example, we agree on what "the loop" means concretely, in plain words.

That is the whole engine. Every example below is just this line, run until a stop condition fires.


The scenario matrix

Every reasoning-loop problem lands in one of these cells. The rest of the page fills each cell with a fully worked example.

# Cell class What makes it special Example
A Happy path, multi-tool Goal met before budget; each step chains cleanly Ex 1
B Zero-tool degenerate Agent should answer directly, no tool call at all Ex 2
C Failure + recovery A tool errors; self-correction via Reflexion Ex 3
D Budget exhausted Goal not met, fires; graceful stop Ex 4
E Context overflow / limiting too big; must summarize (limiting behaviour of memory) Ex 5
F Infinite loop trap Same action repeats forever without the budget guard Ex 6
G Real-world word problem Compound question needs decomposition + comparison Ex 7
H Exam-style twist Tool returns ambiguous / conflicting data; agent must reconcile Ex 8

The pattern that solves every cell is the flowchart below. Read it as one turn of the loop, top to bottom:

goal met

budget hit

context full

none

Observe: build context

Reason: thought plus action

Which stop check

Emit final answer

Stop with best effort

Summarize then continue

Act: run tool

Update context

Walking the boxes, one by one:

  • Observe: build context — the agent gathers the user message, memory, and any prior observations into . This is where a turn begins.
  • Reason: thought plus action — the model reads and produces a thought (its plain-words plan) and a proposed action .
  • Which stop check — the diamond is a decision: before doing anything, ask which of the stop conditions applies.
    • goal met → Emit final answer — the action is a final answer; the loop ends happily (cells A, B, C, G, H).
    • budget hit → Stop with best effort; exit and return the best partial result (cell D).
    • context full → Summarize then continue; shrink memory, then loop again (cell E).
    • none → Act: run tool — no stop condition fired, so actually run the tool.
  • Act: run tool — execute , producing an observation .
  • Update context — glue onto to make , then arrow back up to Observe: the cycle repeats.

Every example below is just a specific walk through these boxes.


Cell A — Happy path, multi-tool

Steps.

  1. = the user question. Thought: "Two unknowns: author, then their death century. Get author first." Action . Why this step? A compound question is split into atomic sub-goals; you cannot search "century of death" until you know whose death.
  2. "William Shakespeare". Update: . Why this step? The observation is glued on so step 2's reasoning can see the name.
  3. Thought: "Now find Shakespeare's death year." Action . "1616". Why this step? Chaining: the answer of step 1 becomes the subject of step 2.
  4. Thought: "1616 is in the 1600s → the 17th century." Action . Goal met at . Why this step? Converting a year to a century is arithmetic the model does internally — no tool needed, so it answers.

Verify (century formula, done once, cleanly): The century of a year is , where means "round down to the nearest whole number". Here , so and , which rounds down to . Then . So 1616 falls in the 17th century ✓. Steps used ✓. (Forecast answer: 3 steps.)


Cell B — Zero-tool degenerate input

Steps.

  1. = the question. Thought: "This is simple arithmetic I can do directly; a tool call wastes a step." Action . Goal met at . Why this step? The degenerate case of the loop is a single pass: observe → reason → answer. Calling a tool here is a real failure mode (over-tooling) — every tool call costs latency and tokens.

Verify: ✓. Steps used ; the loop degenerated to a straight line with no observation ever produced ✓.


Cell C — Failure and recovery (Reflexion)

First, the syntax point that this example turns on, stated plainly:

Steps.

  1. Thought: "Sum then divide." Action — note the wrong square brackets on len. Why this step? The mean needs two quantities from the same list — a total and a count — combined in one arithmetic expression. Running it as one code snippet is cleaner than two separate tool calls (which would return two numbers the agent must still divide by hand), and code is exact where the model's own mental arithmetic on longer lists could slip. So "compute in code" beats both "respond directly" and "call two separate tools".
  2. TypeError: 'builtin_function_or_method' object is not subscriptable — triggered by the len[...] square-bracket mistake explained above. Why this observation matters? The error text is the learning signal — it is glued into .
  3. Reflexion thought: "len[...] uses square brackets — that's indexing, not a call. I must call it as len([...]) with round brackets." Action . Why this step? Self-critique reads from context and edits the plan — this is exactly the trial-and-error idea, but the "reward" is the presence/absence of an error string, not a number.
  4. 9.0. Thought: "Success." Action . Goal met at .

Verify: ✓. Steps (one wasted on the error, then recovery) ✓.


Cell D — Budget exhausted (goal NOT met)

Steps.

  1. Action . "Estimated ; no exact figure exists." Why this step? The agent can't know in advance that the question is unanswerable; the rational first move is to try the most direct search and see what comes back — you diagnose impossibility from evidence, not by assuming it.
  2. Thought: "That's an estimate, not exact. Try again." . "No exact count is possible." Why this step? One "estimate only" result is not proof no exact figure exists — maybe a better query finds one. Re-searching with a sharper phrase ("exact ... count") is a reasonable second attempt before concluding the goal is impossible.
  3. Thought: "Still no exact number." . same. Now . Why this step forces a stop? The budget check fires before step 4. The loop must exit even though the goal is unmet.
  4. Forced exit: Why this phrasing? On a forced exit you owe the user the most useful partial result, not silence. The response states honestly that no exact answer exists and hands over the best estimate gathered in step 1 — turning a failed goal into a helpful reply.

Verify: Loop terminated by budget, not goal. Steps taken ✓. The graceful failure returns the best estimate instead of hanging — this is the correct behaviour of cell D.


Cell E — Context overflow (limiting behaviour of memory)

Steps (with a figure).

Figure — Agent architectures and reasoning loops

Figure caption (read this even if the image fails to load): Horizontal axis = step (equivalently, how many messages have arrived). Vertical axis = context length . The dashed plum line is the ceiling ; anything above it does not fit. The burnt-orange line is raw concatenation (): it rises one unit per step and at pierces the ceiling (orange dot + arrow) — that is the overflow moment. The teal line is the compacted strategy: each time it would cross the ceiling it summarizes 11 messages into 1 and drops back down (teal arrow: "summarize → drop to 20"), then climbs again, staying under the dashed line forever. Takeaway: raw growth is unbounded and breaks the window; compaction keeps for all .

  1. Growing : length = number of messages . As climbs, rises linearly (the orange line). Why watch ? The window imposes a hard ceiling . The limiting behaviour is: as , raw concatenation eventually exceeds .
  2. At , check . Overflow branch fires. Why this branch? Look at the figure: the burnt-orange raw line pierces the ceiling at the orange dot. We cannot append blindly.
  3. Summarize: replace messages 1–11 with one summary message. New length ... continue accumulating so that by message 40 the count is . The teal line shows this drop-and-climb. Why summarize instead of discard? Discarding loses retrievable facts; a summary keeps the gist (long-term memory) while freeing token budget — the teal "compacted" line in the figure stays under the ceiling forever.

Verify: After summarizing 11 messages into 1, the 40-message chat holds length ✓. The compacted length is bounded (never exceeds ), so the loop can run indefinitely ✓.


Cell F — Infinite-loop trap

Steps.

  1. Thought: "Search for a prime in that range." Action . "No results." Why this step? The agent has no reason yet to suspect the question is unsatisfiable — the natural first move is to try the direct search. The trap only reveals itself after this attempt returns nothing and the agent must decide what to do next.
  2. Thought: "That found nothing; try the same search again." Action identical action, identical observation "No results." Why this is the trap? The context grew (a thought and an observation were appended), but it carried no new information: and . The reasoning input is effectively unchanged, so the next output is the same again. This is the loop's "period-2 repeat" — like repeating every , the state cycles back onto itself.
  3. Thought: "Still nothing; try the same search again." Action , "No results". Then , , and so on — the trace never terminates on its own. This is the failure: each turn adds text but the pair never changes, so no stop condition of type "goal met" can ever fire. Why does it never break by itself? "Goal met" needs a final-answer action, but the agent keeps choosing a search; and the answer it wants (a prime in that gap) does not exist, so no observation can ever satisfy it. Only an external guard can end it.
  4. Two guards break the trap:
    • Budget: once (here ), the loop is forced to exit (this is cell D's mechanism reused). It then responds honestly: "No prime exists strictly between 8 and 10."
    • Repeat detector: if and , declare "no progress" and stop immediately — cheaper than waiting for the budget.

Verify: The true fact — there is no prime strictly between 8 and 10 (9 = 3² is not prime; 10 = 2·5 is not prime; 8 = 2³ is not prime) — means the goal is unsatisfiable, so only a guard can end the loop ✓. Number of primes strictly between 8 and 10 is ✓.


Cell G — Real-world compound word problem

Steps.

  1. Thought: "First resolve which city is Japan's capital." Action . "Tokyo." Why this step? Atomic sub-goal 1 — you must resolve the referent ("the capital of Japan") before you can look up its attribute (population). You cannot search "population of the capital of Japan" directly because the tool wants a concrete place name, not a nested description.
  2. Thought: "Now get Tokyo's population." Action . "≈ 37 million." Why this step? The subject "Tokyo" only became known in step 1, so this search depends on the previous observation — classic chaining, exactly like Cell A.
  3. Thought: "I also need London's population for the comparison." Action . "≈ 9 million." Why this step? The comparison needs a second independent number. London's population has no dependence on Tokyo's, so it earns its own dedicated search rather than being folded into the previous call.
  4. Thought: "Compare: is ? Yes." Action Goal met at . Why internal, not a tool? The comparison is arithmetic the model does itself (this is Cell B's zero-tool logic embedded inside a bigger task).

Verify: ; Yes ✓. Searches used , total steps ✓. (Forecast answer: 3 searches, answer "Yes".)


Cell H — Exam twist: conflicting tool outputs

Steps.

  1. Thought: "Consult the most authoritative source first." Action . "1889 (opened for the World's Fair)." Why this source first? For a factual date you consult the most authoritative source available first — a curated encyclopedia has editorial checking, so its answer is your strong prior. Only after that do you sample weaker sources to see whether they agree.
  2. Thought: "Cross-check with a second, independent source." Action . "1887" (this page is describing when construction started). Why a second source? Cross-checking is the reconciliation strategy for the twist cell — one source alone can be wrong.
  3. Reconciliation thought: "Conflict: 1889 vs 1887. The blog's 1887 is the construction start; the opening was 1889. Two reasons favour 1889: the higher-reliability source, and the semantically-correct field (opening ≠ start)." Action Goal met at . Why 1889 and not an average? Two independent reasons agree: source reliability and the distinction between started and opened. Facts are adjudicated by provenance and meaning, never averaged.

Verify: The Eiffel Tower opened 1889; construction began 1887, a gap of years. The agent chose 1889 ✓. (Forecast answer: 1889, chosen by source reliability + start-vs-open distinction.)


Recall

Recall Every stop condition

Name the three ways any reasoning loop can terminate. Three loop stop conditions ::: Goal met (final-answer action), step budget hit (), context overflow ().

Recall The degenerate case

When should the loop make zero tool calls? Zero-tool case ::: When the model can answer directly (simple arithmetic/known facts); calling a tool wastes steps and can introduce errors.

Recall Why a budget is mandatory

What breaks if you remove ? Removing the budget ::: Unsatisfiable or looping goals never terminate — the loop is no longer total; it can hang forever (cell F).

Recall Overflow handling

What do you do when exceeds the context window ()? Context overflow fix ::: Summarize old messages into one message (keeping the gist as long-term memory) rather than blindly discarding, so the length stays bounded under and the loop can run indefinitely.

See also: Tool Use and Function Calling · Chain-of-Thought Prompting · Prompt Engineering · Multi-Agent Systems