Skip to main content
This lesson is the first time you bend the default loop. You are still building an ordinary QitOS agent, but now you will introduce:
  • a planning artifact (a persistent output produced by a run) in state
  • a planner prompt separate from the execution prompt
  • a decide() override that only handles the planning boundary
The key idea is that you still do not introduce a second runtime.

What changes from lesson 1

That last row matters. You are adding planning, not context complexity.

The two-prompt architecture

This lesson uses two prompt contracts.

Planner prompt

In code, that is PLAN_DRAFT_PROMPT.

Executor prompt

In code, that is PLAN_EXEC_SYSTEM_PROMPT. The design lesson is:
  • planning and acting can use different prompts
  • but they still flow through the same AgentModule + Engine runtime

The parser story in this lesson

The planner path does not use ReActTextParser. Instead:
  • _plan() renders PLAN_DRAFT_PROMPT
  • NumberedPlanBuilder calls the same LLM harness
  • the builder parses a numbered list into list[str]
The execution path does use ReActTextParser. Lesson 2 already teaches a subtle but important QitOS idea: different phases of the same agent can use different parsing contracts, as long as the control boundary is explicit.

The model harness stays intentionally boring

Just like lesson 1, the example uses:
Why keep the same harness?
  • so you can isolate the effect of planning
  • so prompt and parser changes are easy to interpret
  • so the new lesson teaches one new idea instead of five
1

Extend state with a plan and a cursor

The state adds only what execution needs:
This is the first time the course makes a hidden reasoning artifact (a persistent output produced by a run) explicit.Why store the plan in state?
  • the trace can show it
  • prepare() can surface it
  • reduce() can advance it
  • your own logic can rewrite it later if needed
2

Use a dedicated plan builder

The planner is initialized once:
And called like this:
This is the right QitOS move:planning becomes a named artifact with a dedicated parser (a component that converts raw model output into a typed Decision), not an unstructured paragraph in the main scratchpad.
3

Use decide only as the planning gate

The control logic is small:
That return None is the whole point.Once a plan exists, the Engine goes back to its default LLM path:prompt -> ReActTextParser -> Decision -> tool executionLesson 2 is not about replacing the runtime. It is about adding one explicit control boundary to it.
4

Bind execution prompt and parser clearly

Execution still uses:
and:
So the planning phase and the execution phase are visibly different:
  • numbered plan builder for planning
  • ReAct text contract for execution
5

Make the plan visible in prepare

prepare() now renders both the global task and the current plan step:
This changes the agent’s working memory shape.Instead of re-reasoning over the entire task every step, the model reasons over:
  • one task
  • one explicit plan
  • one current plan item
6

Advance plan progress in reduce

Progress becomes ordinary state logic:
The important lesson is not the exact condition. It is the placement:reduce() is where you decide what counts as plan completion.
7

Keep memory and history simple on purpose

Lesson 2 still does not add:
  • a memory adapter
  • HistoryPolicy tuning
  • CompactHistory
Why not?Because the plan itself already compresses the task into a better working form. Introducing context compaction here would blur whether behavior changed because of planning or because of context management.
8

Run it and inspect the planning boundary in qita

Run:
Inspect:
In the trace, pay attention to:
  • the step where Decision.wait("plan_ready") appears
  • the moment plan_steps becomes part of state
  • the fact that later execution still uses the same ReAct parser path

Why PlanAct is still the same kernel

Researchers often think adding planning requires:
  • a separate planner service
  • a planner-executor loop outside the framework
  • a second agent runtime
This lesson is showing the opposite design:
  • a planner is just another controlled model call
  • a plan is just another state artifact
  • execution is still the normal Engine path
This is one of the deepest QitOS ideas.

Full example

The full runnable lesson lives at:

What lesson 3 adds

Lesson 3 keeps the same kernel again, but now the agent becomes operationally long-running. You will finally introduce:
  • preset (a reusable configuration bundle) toolsets instead of manual wiring
  • a workflow-oriented system prompt
  • explicit history control
  • the point where context compaction (summarizing older context to stay within token limits) and memory become real design questions

Next lesson: Claude Code-style agent

Move from pattern design to a long-running workspace agent with presets, history policy, and qita-driven debugging.

Related guide: memory and history

Review the distinction between state, history, compaction, and memory before the long-running lesson.