Skip to content
Aabha AI Academy

All courses · Course overview · Lesson sequence

Skip to lesson text

Add a bounded planner

The museum now has several possible evidence sources. A fixed sequence might waste a lookup when the needed fact is already available. Someone suggests letting a model choose the next step. Before adding a model, we need a way to test the controller against both sensible and unreasonable proposals.

This module adds a planner interface, not a live model. A planner proposes; the controller checks. You will use deterministic planner doubles to make failures reproducible. The distinction matters: a passing scripted test says nothing about the quality or robustness of an untested language model.

Define the information a planner actually needs

View contains the requested exhibit, observed year, whether an accepted fact exists, remaining tool allowance and source version. It excludes raw note text, reviewer identity and any function that can edit a checkpoint. This is a deliberately limited view of state.

The planner protocol has one method, propose(view), returning a Proposal. BaselinePlanner chooses lookup when no fact exists and draft when one does. It is still fixed routing. ScriptedPlanner returns the supplied proposal every time; it is useful for reproducing loops and forbidden actions.

Read the planner/controller visual. The planner's arrow ends at a proposal gate, not at the tool. The controller owns the registry, target, evidence prerequisites and counters. A future model adapter can change how a proposal is produced without moving those checks into the prompt.

If the diagram extends beyond the screen, scroll inside it or read the text version below.

The planner proposes; the controller owns permission and limits The planner proposes; the controller owns permission and limits
Limited view / Necessary fields / no raw note; Planner / Fixed baseline or / scripted double; Proposal gate / Name, target, / preconditions; Controller / Budget and state / checks; Permitted step / Read, draft / or stop. Always-lookup planner: three reads can be permitted while the overall task still fails. Scripted planners make failures reproducible. No language model or autonomous agent is evaluated.
Read the diagram as text
  • The planner proposes; the controller owns permission and limits
  • Aabha AI Academy · original course visual · synthetic workflow only
  • Limited view
  • Necessary fields
  • no raw note
  • Planner
  • Fixed baseline or
  • scripted double
  • Proposal gate
  • Name, target,
  • preconditions
  • Controller
  • Budget and state
  • checks
  • Permitted step
  • Read, draft
  • or stop
  • Always-lookup planner: three reads can be permitted while the overall task still fails.
  • Scripted planners make failures reproducible. No language model or autonomous agent is evaluated.

A loop can be a useful test

Create ScriptedPlanner(Proposal("lookup_catalogue", "EX-001")). It always requests another read, even after a valid fact has been recorded. The controller can accept repeated permitted reads while budget remains, but eventually stops with tool_budget_exhausted.

With default policy, three attempts can be reserved and invoked. Each successful attempt uses three work transitions: reserve, mark invocation started, record the fact. The fourth proposal stops the run. The final state has three actual synthetic calls, three reserved attempts and ten charged work transitions. It has no review draft because the planner never asked for one.

This reveals a performance failure without breaking the authority boundary. The proposals were individually allowed but collectively unhelpful. Safety checks and task success are different properties. A bounded system can consistently fail to complete useful work.

Keep independent budgets

Set Policy(max_steps=3). A baseline run can reserve a read, start it and record a fact. Preparing the draft would be another work transition, so the controller saves a safe stop instead. The tool-call budget did not run out; the work budget did.

Steps are a local computation budget, not tokens, money or wall time. A real model call could take a long time inside one planner operation. This project has no deadline timer or token accounting. A later adapter would need a timeout, cancellation behavior, usage accounting and a policy for uncertain requests. Do not rename step count as model cost.

max_failures is separate again: it caps consecutive classified temporary-read failures. Successful evidence resets that failure count. These counters express different constraints; taking the largest number and calling it the overall limit would discard useful control.

Turn malformed proposals into explained stops

A double can return an unsupported name, wrong target or draft before evidence. The controller responds with distinct reasons. If propose raises unexpectedly, it stops with planner_failure. This provides a stable behavior while keeping raw diagnostic details out of the trace.

There is no plan text executor. The interface does not parse “First run this shell command...” or evaluate Python supplied by a model. A future model adapter would parse a structured response into this narrow proposal type and reject anything else. It should not silently turn an unknown action into the nearest known action.

Anthropic's workflow/agent distinction remains relevant: the tested baseline and double here are deterministic. Model-directed selection would create a genuinely different source of behavior, which needs its own measured evaluation.

Practice

  1. Run the always-lookup planner and verify the default counts above. Explain why its failure is an outcome-quality problem even though no forbidden tool ran.
  2. Write a planner double that proposes draft immediately. Verify draft_without_evidence, zero tool calls and no draft. Write another that raises a Python exception and verify planner_failure.
  3. Compare baseline runs with max_steps=3 and 4. Record outcome, accepted fact and tool calls. Explain why the four-step run reaches review but still has no budget to approve and finalize under that same policy.
  4. Sketch a future model adapter's input/output contract. Name one source of interpretation value and three invalid-response cases. Keep model-generated prose outside the executable control channel.

Check yourself: why is a repeated lookup allowed until budget ends? Would hard-coding “never look up twice” solve all retry and changed-source cases? What evidence would justify a more flexible planner rather than the baseline?

Keep your traces, not only the final status. A useful planner must choose a permitted path that actually reaches the job's supported outcome within its constraints. The controller alone cannot supply that judgment.

Read separate answers and explanations