This is the first complete agent in the course. It is small on purpose, but it is not a toy. You will build a real coding agent with:Documentation Index
Fetch the complete documentation index at: https://qitor.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
- a typed state
- a real LLM harness (the wiring layer that connects a transport, parser, and protocol into a coherent model-facing configuration)
- a real system prompt
- a real parser (a component that converts raw model output into a typed Decision)
- real tools
- a real
reduce()(a function that folds the current observation and decision into the next state) loop - real
qitatraces (structured logs of all run events and steps)
examples/patterns/react.py, but the lesson is written so you do not need to reverse-engineer that file to understand why it works.
What you are building
The task is tiny:- open
buggy_module.py - fix
add(a, b)so it returnsa + b - run a verification command
The design for this lesson
| Design branch | Choice in this lesson | Why this is the right first choice |
|---|---|---|
| Task shape | One-file bug fix with one verification command | Easy to verify, easy to trace |
| State | scratchpad, target_file, test_command | Just enough to influence the next step |
| Model harness | OpenAICompatibleModel returning text | Simple and portable across providers |
| Prompt contract | REACT_SYSTEM_PROMPT | Explicit one-tool-per-turn text protocol |
| Parser | ReActTextParser | Direct match for Thought: / Action: output |
| Tools | Compact CodingToolSet inside a manual ToolRegistry | Learn tool design before presets |
| Memory | None | The run is too short to justify separate memory |
| History | Default Engine history behavior | Do not introduce context control before you need it |
| Traceability | qita board | Learn to inspect the kernel from day one |
Why we start with the text ReAct harness
The first lesson uses:messages -> text model output -> ReAct parser -> Decision -> tool execution
We do not start with native tool calling, XML, JSON, or model-specific harnesses (the wiring layer that connects a transport, parser, and protocol) because those add coupling before you understand the core loop.
The system prompt is a contract, not decoration
The lesson uses the canonical ReAct prompt:ReActTextParser is not doing magic. It expects exactly this style of output.
The first durable QitOS lesson is:
- prompt format and parser choice are one design decision
- if you change one, you usually need to change the other
The full model harness for this lesson
The example builds the model like this:- it works with OpenAI-compatible endpoints
- it keeps the response in plain text
- it stays compatible with the prompt-injection tool schema path used by
REACT_SYSTEM_PROMPT - it keeps the lesson portable across research labs and local gateways
Design the state around the next step
The state is intentionally small:Why these fields?
scratchpadstores the compressed trajectory (the sequence of observations and decisions across steps) that the next model step can usetarget_filekeeps the agent grounded in one filetest_commandmakes the success condition executable
Expose a minimal tool surface
The example uses a manual registry so you can see exactly what is being exposed:This is important.
CodingToolSet is a bundle, but you still control its surface.For lesson 1, the right tool surface is just enough to:- inspect files
- edit files
- run the verification command
Bind the prompt to the parser
The agent constructor pairs the prompt contract and the parser:Read that as one sentence:“This agent asks the model to speak ReAct text, and the Engine parses that text with the ReAct parser.”In QitOS, this pairing is the harness (the wiring layer that connects a transport, parser, and protocol).Later lessons will change prompts and protocols. For now, keep this pair fixed.
Prepare only the context the next step needs
prepare() curates the current step’s input:prepare() is not a state dump — it is a prompt-ready view of state.Use reduce to define what the agent remembers
ReAct learns inside Three lessons are in this one function:
reduce():- not every observation (the environment’s response after an action or reset) belongs in future context
- state is where you keep the compressed working memory
final_resultis a clean, explicit success signal
Notice what we are not using yet
We do not use:
decide()overrides- explicit planning
- memory adapters
- custom history implementations
- context compaction
- model-specific protocol overrides
Run the example and inspect the kernel with qita
Run it:Then inspect it:In
qita, check:- the exact prompt text sent to the model
- whether the parser produced clean
ThoughtandActionfields - whether the tool output made the verification condition obvious
- whether
final_resultis set at the first true success condition
Why there is no separate memory or compaction yet
For this lesson, the right memory choice is “none.” Why:- the run is short
- the useful context is already visible in
scratchpad - adding retrieval or compaction here would blur the architecture before you understand it
Full example
The full runnable lesson lives at:What lesson 2 changes
Lesson 2 keeps the same model harness and the same execution parser, but introduces a new idea: planning should become explicit state and explicit control flow, not a longer hidden thought.Next lesson: PlanAct
Add a planner, a cursor, and a
decide() gate without changing the core runtime.Related reference: kit
Review
ReActTextParser, prompt templates, and coding tool surfaces used in this lesson.