Practical Coding Agent Walkthrough (ReAct + Self-Reflection + memory.md)¶
What this agent is¶
examples/real/coding_agent.py is a “realistic minimal” coding agent:
- ReAct-style tool execution (
ReActTextParser) - persistent local memory (
MarkdownFileMemorywritesmemory.md) - Engine-level critic (
ReActSelfReflectionCritic) that can request retries
It is designed to be a tutorial for building a “shippable” agent:
- bounded state
- explicit verification
- reproducible traces
Core design choices¶
- State contains trajectory, not hidden global variables.
- Verification is a first-class tool call, not narrative text.
- Self-reflection is a Critic, not extra prompt tokens sprinkled randomly.
- Memory is owned by the AgentModule (
self.memory), and consumed explicitly inprepare.
Method-by-method design¶
CodingState: store only what you need to drive actions¶
Fields:
scratchpad: trajectory breadcrumbstarget_file: makes tool calls deterministictest_command: enforces a “proof of fix”expected_snippet: a minimal acceptance check
__init__: tools and parser define the executable surface¶
What it wires:
EditorToolSet(view/replace_lines/insert/etc.)RunCommand(verification)ReActTextParserfor text-protocol decisions
history_policy: control model-facing history in Engine¶
This example sets:
Design principle:
- keep LLM history bounded and reproducible at engine level.
prepare: publish task + constraints, and optionally inject memory context¶
What it can expose:
- file/test constraints
- bounded scratchpad
- selected memory snippets from
self.memory(if needed)
build_system_prompt: enforce one-action-per-step and verification discipline¶
This prompt is intentionally strict:
- one tool call per step
- inspect before editing
- run verification frequently
- stop only with “what changed + proof”
prepare: inject just enough context for consistent steps¶
It composes:
- task + file + expected snippet + verification command
- step counters
- optional memory summary (if present)
- recent trajectory
Design principle:
- keep it short but decision-sufficient.
reduce: treat tool outputs as evidence¶
The reducer:
- logs thought/action/observation into scratchpad
- sets
final_resultonly after verification succeeded (returncode == 0)
Design principle:
- “done” should be a function of tool evidence, not model confidence.
Engine wiring (why it matters)¶
This example passes into Engine(...):
super().__init__(..., memory=MarkdownFileMemory(path=".../memory.md"))critics=[ReActSelfReflectionCritic(max_retries=2)]env=HostEnv(workspace_root=...)history_policy=HistoryPolicy(max_messages=12)trace_writer=...(optional)
That’s the core “builder stack” in QitOS:
- Env provides execution backend
- Memory provides context persistence
- Critic adds controlled retries
- Trace makes it debuggable and comparable