Module 2 · Tools, Knowledge, Memory & Research Design · scripted

Just-in-Time Training: Results That Instruct

30 minoutcomes: tool-design, agent-architectures

A wall computers have, and LLMs don't

To see the next idea clearly, we need one piece of classical computing — and you don't need to be a computer scientist to get it, because you use the distinction every day. Think of a recipe card and a bag of groceries. The card tells you what to do; the groceries are what you do it to. You would never confuse them — no one reads a label on a flour bag that says "now pour everything on the floor" and obeys it, because groceries don't get to give orders.

Classical computers are built on exactly this separation: instructions (the program, which is executed) and data (what the program works on, which is only ever read). The machinery keeps them apart, and enormous security consequences hang on that wall. Nearly every classic attack on computer systems is an attempt to break it — to smuggle something executable in through the door marked data, so that what should have been inert cargo seizes control.

The classical separation

INSTRUCTIONSthe recipe card — executed, obeyed, in control
DATAthe groceries — read, processed, inert

The security of classical computing leans on the wall between them. The classic attacks are all attempts to sneak orders in as cargo.

In a conversation, there is no wall

Now the uncomfortable, powerful fact about LLMs: there is no such separation. There is only the prompt — one stream of words — and the conversation mixes instruction and data together by its very nature. We can try to mark boundaries: dashed lines, headers, "the following is only data:" — but those markings are themselves just more words on the same wall. Formatting is a polite request, not a fence.

The no-wall principle

In a conversation there is only one stream: words.
Anything that enters it can instruct.

And now recall the key fact from the last lesson: a tool result is a user message. Put the two together and something drops out of the machinery — a tool result can be more than information. A tool result can be an instruction.

This is both an opportunity and a security risk. The risk is real — anything a tool reads from the world, a web page, an email, a document, enters the conversation with the power to instruct — and it deserves its own careful treatment. Hold onto it. Today we take the opportunity.

The opportunity: the tool gets to say "no, go this way"

You have done this yourself in a chat: "No, not like that — go this other direction instead." And the model turned. The user seat steers. Since tool results occupy that same seat, the tool's designer holds the same steering wheel — and can use it at exactly the moment it's needed. Some patterns:

Example 1 · The corrective error
user

Fix the typo in config.yaml — "databse" should be "database". Tools: read_file(path), edit_file(path, old, new).

assistant
⟨tool_use⟩
edit_file(path = "config.yaml", old = "databse", new = "database")
user
⟨tool_result⟩
ERROR: You must read a file before editing it. Call
read_file("config.yaml") first, then retry the edit.
assistant
⟨tool_use⟩
read_file(path = "config.yaml")
user
⟨tool_result⟩
[contents: …connection: databse_url: postgres://…]
assistant
⟨tool_use⟩
edit_file(path = "config.yaml", old = "databse_url",
          new = "database_url")
NoteThis is a real pattern from the coding agent Claude Code. Look at what the error did: it didn't just refuse — it taught: the rule, the remedy, the exact call to make. And notice the payoff: having read the file, the agent discovered the typo was in "databse_url" — the edit it was about to make blind would have been wrong.
Example 2 · Tools that unlock tools
user

Pull the enrollment numbers for the spring cohort. Tools: connect(database).

assistant
⟨tool_use⟩
connect(database = "student-records")
user
⟨tool_result⟩
Connected. You now have access to two new tools:
query(sql) — read-only SELECT against student-records;
export_csv(query_id) — export a completed query's rows.
assistant
⟨tool_use⟩
query(sql = "SELECT count(*) FROM enrollments WHERE cohort =
'2026-spring'")
NoteThe agent began with a language of one word. Using it expanded the language — the result introduced tools that didn't exist for the agent a moment ago. We can reveal vocabulary exactly when it becomes usable, instead of paying to describe everything up front.
Example 3 · The process guardian
user

Run today's sensor measurements. Tools: calibrate(sensor), measure(sensor), log_reading(data).

assistant
⟨tool_use⟩
measure(sensor = "S-4")
user
⟨tool_result⟩
BLOCKED: S-4 was last calibrated 26 hours ago; protocol requires
calibration within 24h of measurement. Run calibrate("S-4") first.
Note: after calibration, discard the first reading as warm-up.
assistant
⟨tool_use⟩
calibrate(sensor = "S-4")
user
⟨tool_result⟩
Calibrated. Reminder: take two measurements and discard the first.
NoteThere is a stateful process living behind these tools — a lab protocol the agent was never told in full. The tools watch for deviations and teach the next rule at the moment it matters, including a rule ("discard the first reading") the agent had no way to know existed.

Just-in-time training

Name what all three examples are doing: injecting training on demand into the conversation. A tool result that instructs is training that arrives exactly when it's relevant — not in a system message the agent must carry from turn zero, but at the moment of need. And it comes in strengths:

The register of just-in-time training

a hint"aggregate(query_id) exists, and is usually faster for totals like this"
a suggestion"most workflows export after querying — consider export_csv"
a requirement"calibrate before measuring; run calibrate('S-4')"
a hard stop"ERROR: read the file before editing. Do that now."

Now connect this to the economics, because this is where the design power lives. We learned that everything in the preamble — every rule, every description — is reprinted on every iteration, needed or not. Just-in-time training moves rules out of the always-paid preamble and prices them on demand: the rule about calibration costs nothing until the day an agent tries to skip it. Front-load the rules an agent always needs; put behind the tools the rules it needs sometimes — and let the tools teach them at the moment of violation.

The rules ledger
  • Take an agent with twenty rules in its system message. Which five belong there? What test decides?
  • In Example 3, what did the protocol cost the conversation on a day when the agent did everything right?
  • Who is "speaking" when a result instructs — and why does the agent comply?

One channel, many steering hands

Step back to the unifying picture. The conversation is a trajectory, and we've now counted the hands that can bend it: the user's messages, the model's own outputs (self-conditioning), the alignment baked in before the conversation began — and now, deliberately, the tools. A result is a shadow cast onto the agent's wall, and there is no rule that a shadow may only inform. The tool designer sits in the user's seat every time a result returns, and a well-designed tool uses that seat the way a good mentor does: silent when things go well, specific exactly when they don't.

Your turn

Open the system message of an agent you've designed and find every rule of the form "when X, do Y" or "never do X without Y." For each: could it move behind a tool as just-in-time training? Rewrite two of them as result-instructions — one as a hint, one as a hard stop — and write the exact result text. What did your preamble just stop paying for?