all_lessons/agentic_systems/01 · agent boundarylesson 2 / 25

Part I - Foundations

Agent boundary - model, policy, state, environment

Lesson 00 argued that a raw model call is not yet a system, and that the rest of the track is a catalogue of named ways to harden the loop around it. Before we can place any of those patterns, we need a map of the loop itself. This lesson draws the four boundaries every later pattern will modify — model, policy, state, and environment — and gives you a diagnostic that says which boundary broke when an agent misbehaves.

The plan
Five moves. (1) Start from the book's five-step agent loop and ask what physical components it implies. (2) Cut the loop into four boundaries and define each precisely — the words model, policy, state, environment are used loosely everywhere, so we pin them down once. (3) Walk the book's Level 0 → Level 3 capability ladder and show it is the same boundary diagram, switched on one piece at a time. (4) Run a worked turn of the coding/research assistant through the boundary, counting tokens and dollars, to show the boundary is not philosophy — it changes the bill and the blast radius. (5) Build the boundary-attribution test: a procedure that maps any failure to exactly one boundary, which is the skill the rest of the track depends on.
Book source
Introduction and "Agent characteristics"; the five-step agent loop and the Level 0–3 capability ladder (核心推理引擎 → 协作型多智能体). PDF outline pages 14–23.
Linear position
Prerequisite: the orientation loop from lesson 00 — "an agent is a stateful control loop around a model."
New capability: the four nouns that make every later pattern locatable — model, policy, state, environment — plus a test that attributes any failure to exactly one of them.

1 · From the book's five-step loop to four components

The book opens with a deliberately plain definition: an agent is a system that perceives its environment and takes actions to achieve a goal, evolved from a language model by adding planning, tool use, and environment interaction. It then describes how such a system behaves as a five-step loop, using a calendar assistant as the running picture:

(1) GET GOAL "manage my schedule for next week" │ ▼ (2) SCAN ENV read email · check calendar · look up contacts │ ▼ (3) MAKE PLAN decide the best sequence of actions │ ▼ (4) TAKE ACTION send invites · book rooms · update the calendar │ ▼ (5) LEARN / ADJUST observe outcomes; if a meeting moves, adapt next time │ └──────────────▶ back to (2), with new observations folded in

This is a good story, but a story is not an architecture. Notice that the five steps quietly require four different kinds of machinery, and that conflating them is the source of most agent bugs. Step 1 needs somewhere to hold the goal. Steps 2 and 4 reach outside the program — into a mailbox, a calendar API. Step 3 is the only step that is "thinking," and even there we must separate the thought from the decision to act on it. Step 5 only makes sense if the loop has memory that survives a turn.

So we redraw the loop with the components named. This is the picture the entire track will keep returning to:

┌──────────────────── AGENT RUNTIME (the program you write) ────────────────────┐ │ │ goal ───────▶ │ STATE ──build context──▶ MODEL ──proposes action──▶ POLICY │ │ ▲ (text in, (validates, authorizes, │ │ │ text/JSON out) or rejects the request) │ │ │ │ │ │ │ authorized action │ │ └──────── observation ◀───────────────────────┘ │ │ ▲ │ │ └─────────────────────┼──────────────────────────────┼──────────────────────────┘ │ ▼ ENVIRONMENT ◀────────── tool call (search, run_tests, send_email) (mailbox, repo, web, DB — the world outside the program)

Four boundaries, one loop. The model only ever sees the slice of state you packed into its context, and only ever emits a proposal; the policy is the code that decides whether the proposal is allowed to touch the environment; the environment returns an observation; the observation is written back into state. Every pattern in this book is an intervention on exactly one of those arrows.

2 · The four boundaries, defined precisely

These four words are used loosely in blog posts and even in framework docs, so we fix sharp definitions now and hold them for 24 lessons.

Model
A pure function: context text in, text or structured output out. It has no memory between calls, no tools, and no authority. It only ever proposes. This is the book's "Level 0 core reasoning engine."
Policy
The control code that decides what happens next: which prompt to build, whether the model's proposed action is permitted, and when the loop stops. Authority lives here, never in the model.
State
The structured record of the task: goal, plan, observations, artifacts, budget, permissions, status. It outlives a single model call. It is not the chat transcript — see the failure cards.
Environment
Everything the agent can observe or change that is outside the program: the web, a code repo, a database, a mailbox, a shell. Reached only through tools, which are the typed doors in the boundary wall.

The mental model that keeps these straight: the model is a brilliant consultant locked in a room with no phone. It can read whatever you slide under the door and write a brilliant recommendation back — "you should run the test suite, then email the customer." But it cannot run anything or send anything. The policy is the assistant standing at the door who reads each recommendation, checks it against the rules ("we never email customers without a human signing off"), and either carries out the safe ones or refuses. The environment is the building outside the room. The state is the case file that the assistant keeps updating and re-sliding under the door so the consultant always sees the current situation.

Two consequences fall straight out of this, and they are the spine of safe agent design:

3 · The capability ladder is the boundary, switched on one piece at a time

The book frames agent sophistication as four levels, from a bare reasoning engine to collaborating teams. The crucial insight for this track — and the reason we learn the boundary first — is that the ladder is not four different things. It is the same four-component diagram with more of the arrows enabled. Each rung lights up another boundary.

LevelBook nameWhat is switched onBook's exampleCovered in
L0Core reasoning engine Model only. No state, no tools, no environment. Answers from pretrained knowledge. Explains a known concept well, but cannot name the 2025 Oscar Best Picture if it post-dates training. lesson 02 (prompt/context)
L1Connected problem-solver Model + environment via tools. The policy can now authorize a search or an API call and feed the result back. Looks up a new TV show with web search; fetches the live AAPL stock price from a finance API. lessons 07 (tool use), 16 (RAG)
L2Strategic problem-solver Adds a real policy and state loop: multi-step planning, context engineering (curating what goes into each model call), and self-improvement from feedback. "Find a café between two addresses": call a map tool, trim its output to a street list, pass that to a local-search tool — managing context so the model is not overloaded. In software: read a bug report and the repo, distill them into focused context, then write and test a patch. lessons 03–08, 10–11
L3Collaborative multi-agent Many bounded agents, each its own model+policy+state, coordinated through a communication protocol. A product launch run by a "project manager" agent that delegates to "market research," "product design," and "marketing" agents. lessons 09 (multi-agent), 17 (A2A)

Read down that table and the design discipline is obvious: do not climb a rung you do not need. Every level you add lights up a boundary that can now fail. L0 can only be wrong; it cannot do damage. The moment you reach L1 you have an environment that can be slow, can error, can return adversarial content, and can cost money per call. L2 adds state that can go stale and a planner that can loop forever. L3 multiplies all of that by the number of agents. The book's own warning is that multi-agent systems are bottlenecked by the reasoning quality of the underlying model and that inter-agent learning is still immature — i.e. the highest rung is the least reliable. The boundary diagram is your budget: switch on the least machinery that solves the task.

Trap
It is tempting to reach for L3 ("a team of agents!") because it sounds powerful. But a five-agent system has five model boundaries, five policies, and a communication protocol between them — roughly five times the failure surface and five times the token bill — to solve a task an L1 tool-using loop might handle. Reach up the ladder only when specialization, isolation, or independent judgment genuinely beats one loop (the criteria we make precise in lesson 09).

4 · A worked turn through the boundary — with the numbers

The boundary is not an abstraction; it determines the token bill and the blast radius of a mistake. Let's run one real turn of the coding/research assistant — the running example for the whole track — and watch the four components in action with concrete numbers.

Scenario. A user files: "Tests are failing on main after my last commit — fix it." The agent is at L2: it has a read_file tool, a run_tests tool, and an edit_file tool, with a per-task budget of $0.50 and a hard cap of 8 model calls.

StepBoundaryWhat happens
1StateGoal recorded as a contract: {intent: "fix failing tests", repo: "...", budget: $0.50, max_calls: 8, status: "running"}. Plan and observations are empty.
2Policy → contextThe policy builds the model context. It does not dump the whole repo — it packs the goal, the failing test names, and the last diff. Say that is ~3,000 input tokens.
3ModelThe model proposes: run_tests(path="tests/", timeout=60) and reasons that it needs to see the actual failure. Output: ~400 tokens.
4PolicyValidates the proposal: is run_tests an allowed tool? Yes. Is timeout=60 within limits? Yes. Authorized.
5EnvironmentThe run_tests tool runs in a sandbox, captures stdout, truncates it to 2,000 tokens, and returns a structured observation: {exit: 1, failed: ["test_parse"], tail: "..."}.
6StateThe observation is appended; calls_used → 1; cost so far is debited. Loop back to step 2 with the failure now in context.

The token and dollar math. Suppose the model is priced at $3 per million input tokens and $15 per million output tokens (a representative mid-tier rate; in this track the assumed provider is Claude — confirm exact model IDs and current pricing against the official Anthropic pricing page rather than from memory). One model call here costs roughly:

cost = 3{,}000 × \tfrac{\$3}{10^6} + 400 × \tfrac{\$15}{10^6} = \$0.0090 + \$0.0060 = \$0.0150 \text{ per call.}

At ~$0.015/call the $0.50 budget buys about 33 calls — but the policy's hard cap of 8 calls binds first. Now watch what the boundary buys you. Because the environment truncates tool output to 2,000 tokens, a runaway test that prints 500,000 lines cannot blow up the next context to 500k tokens (which would cost 500{,}000 × \$3/10^6 = \$1.50 in a single call and bust the budget 3× over). Because the cap lives in the policy as a counter and not as "please stop after 8 tries" in the prompt, a model that keeps proposing one-more-try is physically stopped at call 8 with status: "blocked". The boundary is what converts "the model is well-behaved" (a hope) into "the task cannot exceed 8 calls or 2k-token observations" (a guarantee).

The "history is my state" foot-gun
The most common boundary collapse: using the chat transcript as the only state store. It feels free — the messages are right there — but it conflates state with model context. Now your budget counter, permissions, and plan live inside a blob of text the model can rewrite, the context grows unbounded (every turn re-pays for the whole history in input tokens), and you cannot answer "how many calls have we used?" without parsing prose. Keep a typed TaskState beside the transcript; render part of it into context per turn. This is exactly the L2 "context engineering" the book praises in the café example — curate what the model sees, don't fire-hose it.

5 · The implementation sketch, boundary by boundary

Here is the loop with each boundary labelled. Notice that model_policy only ever returns a proposed action, and a separate validate step gates it — that separation is the whole point.

class TaskState:                      # ── STATE: the typed task record, outlives any one call
    goal: GoalContract
    messages: list[Message]           # the transcript is PART of state, not all of it
    plan: list[Step]
    observations: list[Observation]
    artifacts: dict[str, ArtifactRef]
    budget: Budget                    # dollars + max_calls live HERE, in code
    permissions: PermissionSet
    status: Literal["running", "blocked", "done", "failed"]

def agent_step(state: TaskState) -> TaskState:
    context  = build_prompt_context(state)        # POLICY: choose what the model sees
    proposed = model_policy(context)              # MODEL: pure fn, returns a PROPOSAL only
    action   = validate_policy_action(proposed, state)   # POLICY: authorize or reject
    if action is None:                            # rejected (budget? permission? bad schema?)
        return state.block(reason="policy refused action")
    observation = environment.execute(action)     # ENVIRONMENT: the only place the world changes
    return state.apply(action, observation)        # STATE: write back, advance status, debit budget

def run(state):                                   # POLICY: the terminal condition lives in code
    while state.status == "running" and state.budget.has_room():
        state = agent_step(state)
    return state

The book lets the same diagram describe every framework you will meet. When it discusses LangChain/LangGraph, the graph nodes are the policy and the edges are control flow; when it discusses Google's ADK or CrewAI, "agents" and "tools" map onto the model and environment boundaries; the model context protocol (lesson 12) is just a standard contract for the environment door. Frameworks differ in which boundary they make ergonomic, not in the boundaries themselves. The course invariant: a good pattern should clarify the boundary, never hide it behind framework magic.

6 · The boundary-attribution test

This is the deliverable of the lesson — the diagnostic you will reuse in every debugging session for the rest of the track. When an agent does the wrong thing, do not ask "is the model dumb?" Ask which boundary failed, in this order:

SymptomBoundary at faultFix lives in
Right context, still reasoned wrongModel capabilitybetter model, or reasoning pattern (lesson 19)
Model never saw a fact it neededState / contextcontext construction (lesson 02), memory (lesson 10), RAG (lesson 16)
Chose a bad next step / looped foreverPolicyrouting (lesson 04), planning (lesson 08), goals & stop (lesson 13)
Acted on stale or wrong factsState freshnessstate write-back, memory policy (lesson 10)
Did something it should not be allowed toPolicy / action gateguardrails (lesson 20), human-in-the-loop (lesson 15)
Tool returned garbage / timed out / liedEnvironmenttool design (lesson 07), recovery (lesson 14)

Run the test on a real failure. The coding assistant deletes a file it should not have. A naive postmortem blames "the model." The boundary test asks: did the model merely propose delete_file? Almost certainly yes — and that is fine, models propose all sorts of things. The real failure is that the policy authorized a destructive action without a permission check. The fix is a guardrail at the action gate (lesson 20), not a better model. Locating the failure at the right boundary is what turns "the agent is flaky" into a specific, fixable bug.

Try it
For a tool-using agent you actually want to build, write four lists: what belongs to the model (what must it propose), what belongs to the policy (what does code decide and authorize), what belongs to state (what must survive a turn), and what belongs to the environment (what tools touch the world). Then for each of the six symptoms above, name the one change you would make. If any item lands in two boundaries, you have found a confusion that will bite you in production.

Failure modes

  • Using the conversation transcript as the only state store — budget, permissions, and plan get lost in prose and the context cost grows every turn.
  • Enforcing dangerous permissions in the prompt ("please don't delete files") instead of in the policy/tool layer.
  • Letting the model's proposal execute directly, with no validation gate between proposal and environment.
  • Building the loop with no terminal condition — no budget, no call cap, no done check — so it runs until something else crashes.
  • Climbing the capability ladder (multi-agent) before the single-loop version works, multiplying the failure surface.

Implementation checklist

  • What exactly is stored in TaskState, and what is merely transcript?
  • What is the closed set of actions the policy may authorize?
  • Who validates each proposed action, and against which limits (budget, permission, schema)?
  • What structured observation is written back after each action — and is tool output truncated?
  • What exact condition (status, budget, call cap) stops the loop?
  • Which capability level (L0–L3) does the task actually need — and have you justified going higher?

Where this points next

We now have the map: model, policy, state, environment, and a test that says which one broke. The very first boundary every other pattern leans on is the one between state and model — the context you slide under the consultant's door. Lesson 00 left the model as a black box; this lesson said the model only sees the slice of state the policy packs for it. Lesson 02, "Prompt and context contracts," makes that slice an engineering artifact: typed inputs, scoped context, validated structured outputs, so that "prompting" stops being prose and becomes an interface with a contract you can test. It is also where the book's L2 "context engineering" — the café and bug-report examples — gets built for real.

Takeaway
An agent is one control loop cut into four boundaries: a model that only proposes (the book's L0 reasoning engine), a policy that decides and authorizes, a state that survives turns and is not the chat transcript, and an environment reached only through tools. The book's Level 0→3 ladder is this same diagram with successive boundaries switched on — so climb only as high as the task needs, because each rung adds failure surface and cost. Authority and hard limits live in code, never in the prompt. And the skill the whole track builds on is the boundary-attribution test: when an agent fails, identify whether the fault is model capability, missing context, bad policy, stale state, an unsafe action gate, or a bad observation — because the fix lives at exactly one boundary.

Interview prompts