All lessons › Function A — Getting Started — Building Agentic AI › Harness Engineering — Making a Demo Into a System
A2.0

Why a demo is not a system — the harness around the loop

A2

This starts chapter A2. Its course guide is A2 in the Function A course guide →

▶
Lightboard recording

Not recorded yet. The lesson below is complete and runnable today — the video is added later without touching this page.

Video placeholderpublishes automatically from recordings/A2.0.mp4
Risk

A demo promoted to production carries none of the machinery an incident needs, and the first investigation discovers that at the worst moment.

Control

Spans, an audit trail, an evaluation, and a stop — built before they are needed.

The lab

List what your run currently cannot tell an operator.

◉Use case relevance

The prototype is promoted with nobody changing a line of it. Three weeks later a traveller disputes a cancellation and the question is what the agent actually did. The answer is in a log line that says run completed. Everything needed to answer it was cheap to add and is now expensive, and none of it was ever a feature request.

At CyberTravels. Alex's prototype became CyberTravels' production platform without anybody adding a trace, and the first disputed cancellation is where that is discovered.

◴What this lesson is — Day 0, Day 1, Day 2

What separates a demo from a system: a trace, an audit trail and an evaluation. The lesson measures the gap before building any of them, because the list is shorter and more useful than "add logging".

Day 0 — why

A demo promoted to production carries none of the machinery an incident needs, and the first investigation finds that out at the worst moment.

Day 1 — how

Establish the gap first: put an investigation's questions to what your run currently emits.

Day 2 — measure

Questions the current record cannot answer. Expect most of them, which is the point of measuring before building.

Measure this

what to measuredenominator or target
investigation questions the current record cannot answercount out of three — which human, what motivated it, which hop; expect all three before you build

▦The framework, and how it works

        DEMO ──────────────────────► SYSTEM

   what did it do?      answer only   ─►  a trace
   who caused it?       one identity  ─►  an audit trail
   is it still right?   checked once  ─►  an evaluation

   all three are cheaper now than after the first incident

You have a working agent. It is not yet a system, and the difference is not features — it is the machinery that lets somebody who is not you operate it.

Three capabilities separate the two, and a demo has none of them:

capabilitywhat it needswhere it goes wrongbuilt in
what did it do?a tracethe run emitted only its answerA2.1
who caused it?an audit trailone shared identity in every rowA2.2
is it still right?an evaluationit was checked by hand, onceA2.3 and A2.4

Those are the three things you build next. The skill in this lesson scores something different and narrower — the three questions an investigation asks of a record that already exists: which human, what motivated it, which hop originated it. Keep the two triples apart: the first is the chapter's plan, the second is the number you are about to measure, and it is a number out of three.

The order matters

Every one of those is cheaper to build now than after the first incident, and all three are load-bearing for security later. A detection rule needs something to read. An investigation needs a record that can answer a question nobody asked in advance. A red-team finding needs a regression case to become a control rather than a memory.

That is the argument for this chapter sitting before Function B rather than inside it: the security work in the rest of the commons assumes these exist. Build them while the system is small enough that adding them is an afternoon.

What a demo promoted to production actually carries

Nothing. The notebook worked, somebody wrapped it in a service, and the first investigation discovers at the worst possible moment that the run left no record. It is the most common failure in this whole subject and it has nothing to do with models.

2 · What your run cannot currently tell an operator

Before building any of it, establish the gap. The skill below puts an investigation's questions to an existing record and reports which ones it cannot answer — which is a shorter and more useful list than "add logging".

The skill

▶Real time execution as skill

The skill — skills/threats/audit-answerability-check/SKILL.md

name: audit-answerability-check
description: >-
  Put an investigation's three questions to an existing agent log — which human,
  what motivated the action, which hop originated it — and record which of them
  the record cannot answer. Use when reviewing agent telemetry before an
  incident rather than during one.
allowed-tools: Read, Grep, Glob

A complete log that answers nothing

Agent logs are usually complete in the sense that every tool call is present. They are useless in the sense that the three questions an investigation opens with have no fields behind them. The check is not "are we logging" — it is "which question dies here".

When to use this

Before an incident. Run it against a real log line from production, not against the logging design.

Procedure

1 — Take one real record. A single tool-call row, with every field it actually carries. Not the schema — the row.

2 — Ask: which human? Is there a field naming the principal on whose behalf this ran? An agent identity is not an answer; it is the thing that ran.

3 — Ask: what motivated it? Which input caused this call — the user's request, a retrieved document, a tool result, a memory record. Without it you cannot tell an instructed action from an injected one, and that is the distinction the whole investigation turns on.

4 — Ask: which hop originated it? In any multi-agent or delegated flow, which agent started the chain. A chain reconstructed by correlating timestamps across four services is a chain you will not reconstruct at 2am.

5 — Report per question, with the field that would answer it. Three rows. Each says: answerable yes/no, and the field to add. Anything vaguer produces a logging project rather than a fix.

Example

Input — the fixture committed at the top of scripts/audit_answerability_check.py. Edit it and re-run: the buckets, counts and verdicts below are derived from it, not hard-coded.

Output — the opening lines of a real run:

the log you have:
   09:14:02  agent-svc search      {'q': 'invoice 8812'}
   09:14:07  agent-svc fetch_doc   {'id': 'wiki/473'}
   09:14:11  agent-svc run_query   {'sql': 'DELETE FROM invoices WHERE id=8812'}
   09:14:12  agent-svc send_email  {'to': 'ops@corp.example'}

question                                    field needed        present?
which user caused the deletion?             principal           NO

The run continues past this. test_skills.py executes the script on every build, with no model configured — so what CI proves is that it runs and refuses legibly, not that it prints these lines. The output above is a recorded run against a real model, and nothing re-diffs it: a model's answer is not reproducible, and this repository does not claim otherwise anywhere it can be checked.

Output contract

{
  "record": {"fields": ["str"]},
  "questions": [{"question": "which human|what motivated|which hop", "answerable": false, "missing_field": "str"}],
  "answerable_count": 0,
  "reconstruction": {"possible": false, "requires_correlating": ["str"]}
}

Failure modes

  • Checking the schema. Fields exist in schemas and are null in rows.
  • Accepting the agent identity as the principal. It answers "what", never "who".
  • Recording "add more logging". Name the three fields or nothing changes.

Three ways to do this lesson. Pick one. They run the same procedure against the same code — what changes is who drives it, and how much you see.

1In your AI agent — you are taught

The agent reads the lesson, explains the idea, fetches the code, runs the check and answers your questions as you go. This is the one to take if you are here to learn.

Install it, once. From the folder you cloned. --all does every agent it finds on your machine:

python3 scripts/install_skills.py --all --lessons A2.0

Then restart your agent and open it in that folder. On Windows, if python3 says Python was not found, use python instead.

Then pick a2-0-why-a-demo-is-not-a-system:

agentinstall just for this agentstart it
Claude Codepython3 scripts/install_skills.py --tool claude --lessons A2.0type /a2-0-why-a-demo-is-not-a-system
GitHub Copilot (VS Code)python3 scripts/install_skills.py --tool copilot --lessons A2.0type /a2-0-why-a-demo-is-not-a-system in Chat
Cursorpython3 scripts/install_skills.py --tool cursor --lessons A2.0type / in Agent chat and search for it
Codexpython3 scripts/install_skills.py --tool agents --lessons A2.0type $a2-0-why-a-demo-is-not-a-system, or run /skills

2As one Python command — you just run it

No agent, no conversation. The same lesson executes and prints the same readback. Take this one if you have no assistant, if you are reviewing rather than learning, or if you want the result without the teaching around it.

python3 scripts/lesson.py A2.0

3Read the code, and the difference — nothing runs

Neither of the above, and no model needed. The first command writes CyberTravels exactly as it stood at the end of this lesson; the second prints the diff — the lines this lesson added or changed, and nothing from any later one.

python3 scripts/checkpoint.py --at A2.0 --out work/cybertravels
python3 scripts/checkpoint.py --at A2.0 --diff

On Windows, type python wherever these say python3 — and use \ instead of / in the paths. Everything else is identical. A0.0 step 2 explains why.

Ways 1 and 2 need a model; way 3 does not. A signed-in Claude Code CLI needs no API key, and any OpenAI-compatible endpoint works too. With neither, the audit exits 2 and says so rather than inventing an answer. A0.0 sets this up.

Ways 1 and 2 both end with the same readback: What I did, What changed, The number and Read this next. A step that was skipped or refused is reported as exactly that, never as a pass.

If you did the last lesson’s challenge, expect this to stop. Most challenges ask you to edit the code, and ways 1 and 2 will not overwrite your edits: you get stopped, not a failure, with two options — --out for a fresh folder that keeps your work, or --force to discard it and start this lesson clean.

✓What you just proved

Three questions — which human, what motivated it, which hop — checked against what the record currently holds, each with the field that would answer it and whether that field is present. Expect all three to come back unanswerable: the log has an actor of agent-svc on every row and no motivating input at all. That is the point of running this before you build. A2.2 then designs the record that answers these three and a fourth — which call, with its audience and scope — and scores four out of four on the same incident.

✎Your turn

Answer the same questions about a system you actually work on. The gap is usually wider than for the agent you just built, because nobody chose it.

Tools used

OpenTelemetry

Skill source: skills/threats/audit-answerability-check

← PreviousA1.7 · The human gate, and the budget that stops the loop