jvinhit//lab

Search posts

Type to search across journal entries.

navigate open esc close

Agent Patterns: ReAct, Reflection & Planning — From One LLM Call to a Production Loop

ReAct, Reflection, and Planning for LLM agents — when to use each, guardrails against runaway loops, and links to tool use and orchestration.

Mười bài trước ta đếm token. Đến Phần 9 ta đã nối tool và parse tool_calls. Bài cuối khép vòng: cách biến một LLM call thành agent — runtime lặp inference, thực thi side effect, và quyết định khi nào dừng.

Agent không phải prompt thông minh hơn. Nó là pattern orchestration: vòng lặp qua model, tool, và memory với quy tắc kết thúc rõ ràng. Ba pattern dưới — ReAct, Reflection, Planning — cover hầu hết kiến trúc agent production bạn sẽ ship hoặc debug.


Demo tương tác: bước qua ba vòng agent

Demo đi một task canned — “Tìm chuyến bay rẻ nhất SFO → NYC và đặt khách sạn Midtown” — qua ReAct, Reflection, và Planning. Bấm Run next step để animate từng phase; không API key, không network.

Mở demo đầy đủ:


Từ một LLM call đến agent

Completion single-turn là request → response. Agent thêm control loop bọc call đó:

┌─────────────────────────────────────────────────────────────────┐
│                        AGENT RUNTIME                            │
│  ┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐  │
│  │  Prompt  │ →  │   LLM    │ →  │  Parse   │ →  │  Tools   │  │
│  │  builder │    │  infer   │    │  output  │    │  / env   │  │
│  └──────────┘    └──────────┘    └──────────┘    └────┬─────┘  │
│       ↑                                                │         │
│       └──────── append observations / memory ─────────┘         │
│                                                                 │
│  Terminate when: answer │ max_steps │ budget │ eval pass        │
└─────────────────────────────────────────────────────────────────┘

Mọi vòng agent chia sẻ bốn thành phần:

IngredientRoleSeries reference
ContextWhat the model sees this turnContext Engineering & Memory
ToolsSide effects — search, write, executeFunction Calling & Tool Use
StoppingWhen generation ends per stepStopping Criteria & Output Control
EvaluationDid the run succeed?Evaluating LLMs & Agents

Mental model: LLM là CPU; runtime của bạn là OS — scheduling, I/O, memory, và kill signal.

Không có vòng lặp, tool schema và thiết kế memory là vô dụng. Pattern bạn chọn quyết định gọi model bao lâu một lần, mỗi call làm gì, và lỗi cộng dồn ở đâu.


ReAct: reasoning và acting xen kẽ

ReAct (Reason + Act) xen kẽ trace reasoning rõ ràng với lời gọi tool.

Thought: I need current flight prices before recommending.
Action: search_flights(origin="SFO", dest="JFK", depart="2026-06-12")
Observation: [{"airline":"Alaska","price":318}, ...]
Thought: Alaska is cheapest. Search hotels next.
Action: search_hotels(location="Midtown NYC", ...)
Observation: [{"name":"Yotel","rate":142}, ...]
...
Answer: Booked Alaska AS418 + Yotel. Total ~$744.

Runtime contract

Orchestrator phải enforce ba quy tắc:

  1. Dừng trước Observation: — inject output tool thật; không để model bịa observation.
  2. Parse Action: — map tới tool đã đăng ký hoặc reject.
  3. Append toàn bộ trace vào context cho turn tiếp.

Phần 4 đã cover stop sequence cho handoff này:

response = client.chat.completions.create(
    model="gpt-4o",
    messages=messages,
    stop=["\nObservation:"],  # runtime injects Observation after tool runs
    max_tokens=512,
)

Với function calling native (Phần 9), cùng vòng lặp dùng tool_calls thay vì parse text — nhưng nhịp Thought → Action → Observation vẫn giữ.

Khi ReAct thắng

ScenarioWhy ReAct
Unknown tool sequenceNext action depends on prior observation
Live data (APIs, DB, web)Cannot plan all calls upfront
DebuggingText trace is human-readable
Mixed reasoning + I/OModel decides when it has enough evidence

Failure mode ReAct

  • Loop thrashing — search lặp giống nhau; fix bằng dedup hash hoặc step memory.
  • Answer sớm — model trả lời trước khi gọi tool bắt buộc; fix bằng schema validation hoặc eval gate.
  • Context phình — mỗi trace làm window lớn; summarize hoặc trim theo Phần 5.

Reflection: draft, critique, revise

Reflection (và Reflexion) thêm pass thứ hai model đánh giá output của chính nó trước khi trả. Không cần tool — vòng generation thuần.

Pass 1 (Draft):     "United $342 + Hampton $189/n ≈ $909."
Pass 2 (Critique):  "Missed Alaska $318. Hotel over budget. No booking confirmation."
Pass 3 (Revised):   "Alaska $318 + Yotel $142/n = ~$744. PNR ABC123, HT-8842."

Implementation sketch

draft = llm("Answer the user query.", user_query)
critique = llm(
    "Review this draft. List factual errors, missing constraints, and quality gaps.",
    draft,
)
if needs_revision(critique):  # heuristic or classifier
    final = llm(
        "Revise using the critique. Return only the corrected answer.",
        draft= draft,
        critique=critique,
    )
else:
    final = draft

Reflexion mở rộng qua episode: lưu critique vào long-term memory để run sau tránh lặp lỗi.

Khi Reflection thắng

ScenarioWhy Reflection
Writing, summarization, code reviewQuality > latency; no live I/O
Constraint-heavy answersSelf-critique catches missed requirements
Cheap model + one retryTwo small calls beat one huge ReAct trace
Post-tool synthesisReAct gathers data; Reflection polishes the answer

Trade-off chi phí: Reflection thêm 1–2 LLM call nhưng thường giảm tổng bước so với ReAct lang thang.


Planning: phân rã trước, thực thi sau

Plan-and-execute tách planning khỏi execution. Planner phát subtask đánh số; worker (cùng hoặc khác model) thực thi; synthesizer gộp kết quả.

Plan:
  1. Search flights SFO→JFK Jun 12–15
  2. Select lowest fare
  3. Search Midtown hotels ≤ $200/n
  4. Book flight + hotel
  5. Return summary with confirmations

Execute 1 → Execute 2 → Execute 3 → Synthesize

Biến thể

PatternPlanner outputExecutor behavior
Plan-and-executeNatural-language subtasksLLM + tools per subtask
ReWOOTool call plan upfrontWorkers run tools without intermediate LLM
HierarchicalTree of goalsSub-planners for deep tasks
LATS / tree searchBranching plansExplore multiple paths, prune by eval

ReWOO front-load mọi tool call — ít round-trip LLM hơn, nhưng dễ gãy khi bước n+1 phụ thuộc output bước n.

Khi Planning thắng

  • Workflow đã biết — checklist onboarding, pipeline ETL, bước CI.
  • Subtask song song — search độc lập nhiều nguồn.
  • Gate phê duyệt — plan review được trước khi chạy.
  • Kiểm soát chi phí — planner rẻ + worker call có mục tiêu.

Failure mode Planning

  • Plan cũ — executor thấy bước 2 không khả thi; cần vòng re-planning.
  • Phân rã quá — 20 micro-step đốt token; gộp khi an toàn.
  • Plan bịa tool — validate với registry (Phần 9).

Reasoning model và khi CoT explicit thừa

Reasoning model (o-series, DeepSeek-R1, QwQ, v.v.) internalize chain-of-thought khi training. Chúng phát extended thinking token trước câu trả lời hiển thị.

ApproachExplicit Thought: scaffoldingReasoning model
ReAct text formatRequired for interpretabilityOften redundant; use tools + final answer
Reflection critiqueStill valuable — external pass catches blind spotsDraft may already be strong; critique remains useful
PlanningPlanner can be a reasoning modelStrong at decomposition; watch cost per plan token
DebuggingHarder — thinking may be hiddenLog reasoning_content if API exposes it

Quy tắc ngón tay cái: Nếu model đã “nghĩ” nội bộ, đừng trả double cho prefix Thought: dài trừ khi cần audit log hoặc stop-sequence handoff.

Về trade-off chọn model, xem Choosing a Model. Về ổn định sampling trong vòng multi-step, xem Phần 2.


Kết hợp pattern trong production

Agent thực tế hiếm khi chỉ dùng một pattern.

Planning → ReAct (per subtask) → Reflection (final polish)
         ↘ ReWOO (parallel I/O) ↗
LayerPatternExample
Top-level orchestratorPlanning”Research competitor → draft report → send email”
Subtask executorReActLive web search + scrape within one subtask
Output gateReflectionCritique draft before user sees it
Quality assuranceEval (Part 7)Regression suite on golden tasks

Tool use (Phần 9) cắm vào bất kỳ pattern nào ở tầng execution. Memory (Phần 5) quyết định plan, critique, observation trước nào sống sót turn sau.


Multi-agent orchestration

Khi một vòng lặp không đủ, kiến trúc multi-agent gán role:

  • Orchestrator + worker — planner delegate cho agent chuyên biệt (Orchestrator Pattern).
  • Pipeline — handoff tuần tự với output có kiểu.
  • Debate / verifier — một agent đề xuất, agent khác critique (Reflection như kiến trúc).

Về topology cấp hệ thống — state machine, message bus, scratchpad dùng chung — xem Agent Architecture Deep Dive.

Mỗi sub-agent bên trong vẫn là một trong ba pattern. Việc orchestrator là routing, không thay ReAct/Reflection/Planning.


Chọn pattern theo task

Task shapeStart hereAvoid
Open-ended research, unknown stepsReActRigid upfront plan
Single-shot quality (email, summary, review)ReflectionUnnecessary tool loops
Repeatable workflow, SOPPlanningReAct wandering
High parallelism, stable tool graphReWOO / PlanningStep-by-step ReAct
Long horizon, branching decisionsHierarchical planning + evalFlat ReAct without budgets
Coding agent in IDEReAct + Reflection on diffPlan-only without file I/O

Hỏi ba câu trước khi ship:

  1. Bước tiếp phụ thuộc observation live? → ReAct.
  2. Output chấm theo chất lượng, không phải số tool? → Reflection.
  3. Viết được bước trước khi chạy? → Planning.

Failure mode và guardrail

Agent fail khác LLM single-turn.

FailureSymptomGuardrail
Infinite loopSame Action repeatedmax_steps, action dedup, diminishing returns detector
Hallucinated toolsAction calls unknown functionTool registry whitelist; reject + retry prompt
Runaway costToken budget blown in one runPer-run $ cap, cumulative token counter, step pricing alerts
Context overflowTruncated mid-traceRolling summary, observation compression (Part 5)
Silent wrong answerConfident but incorrectEval harness (Part 7), Reflection gate, human-in-the-loop
Unsafe tool callDestructive write/deletePermission tiers, confirmation UI, sandboxed execution
MAX_STEPS = 12
MAX_TOKENS_PER_RUN = 80_000
seen_actions: set[str] = set()

for step in range(MAX_STEPS):
    response = llm(messages, tools=registry)
    total_tokens += response.usage.total_tokens
    if total_tokens > MAX_TOKENS_PER_RUN:
        raise BudgetExceeded()

    if response.tool_calls:
        action_key = canonicalize(response.tool_calls)
        if action_key in seen_actions:
            messages.append({"role": "user", "content": "Duplicate action. Try a different approach or answer."})
            continue
        seen_actions.add(action_key)
        # execute tools, append observations ...
    else:
        return response.content  # final answer

raise MaxStepsExceeded()

Tiêu chí ship: Agent không có max_steps, budget tracking, và eval regression test là demo — không phải production.


Tham chiếu prompt scaffolding

System prompt tối thiểu cho mỗi pattern (adapt stack của bạn):

# ReAct
You have tools: {tool_list}. After each Action, stop. The user will provide Observation.
Format: Thought: ... / Action: tool_name(args) / (wait for Observation) / ... / Answer: ...

# Reflection
Pass 1: Produce a complete draft.
Pass 2: Critique the draft — list errors, omissions, constraint violations.
Pass 3: Produce a revised answer addressing every critique point.

# Planning
Pass 1: Output a numbered plan of subtasks. Do not execute yet.
Pass 2+: Execute subtask N. Return structured result.
Final: Synthesize all subtask results into one answer.

Phần 3 (Prompt Engineering for Agents) cover role prompt, few-shot exemplar, và output format giúp scaffold này tin cậy.


Tổng kết loạt bài: full stack

Giờ bạn có bức tranh đầy đủ để build LLM agent:

Tokens & window (1) → Sampling (2) → Prompts (3) → Stopping (4)

Context & memory (5) → RAG vs fine-tune (6) → Eval (7) → Model choice (8)

Tools (9) → Agent patterns: ReAct · Reflection · Planning (10)

Multi-agent orchestration · production guardrails · continuous eval

Xuyên suốt: mỗi tầng là một contract. Token budget cái gì vừa. Sampling kiểm soát phương sai. Stopping định nghĩa ranh giới bước. Context quyết định gì persist. Tool định nghĩa side effect. Pattern định nghĩa control flow. Eval chứng minh nó hoạt động khi thay đổi.

Bắt đầu với pattern đơn giản nhất phù hợp — thường Reflection cho task text-only, ReAct khi cần tool, Planning khi SOP đã biết. Chỉ thêm phức tạp khi eval chứng minh vòng đơn giản hơn fail.

Ghi chú cuối: Kiến trúc agent tốt nhất là cái team bạn quan sát, test, và rollback được — không phải cái có nhiều tên pattern nhất trong README.


Loạt bài Building AI Agents

  1. Tokens & Context Windows
  2. Sampling: temperature, top_p, top_k
  3. Prompt Engineering for Agents
  4. Stopping Criteria & Output Control
  5. Context Engineering & Memory
  6. Fine-tuning vs Prompting vs RAG
  7. Evaluating LLMs & Agents
  8. Choosing a Model
  9. Function Calling & Tool Use
  10. Agent Patterns: ReAct, Reflection, Planning (current)