- 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
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
1
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
2
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
3
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.
4
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.5
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
6
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
7
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.