Phase 14 · Lesson 37 of 54

Runtime Feedback Loops

Agents that do not see real command output guess. A feedback runner captures stdout, stderr, exit code, and timing into a structured record the next turn can read. Then the agent reacts to facts instead of to its own prediction of facts.

Lesson 37 of 54Build~50 minutesPython (stdlib)

Before this: Lesson 32 of Phase 14 (Minimal Workbench), lesson 35 of Phase 14 (Init Script)

On this page

Learning Objectives

  • Distinguish runtime feedback from observability telemetry.
  • Build a feedback runner that wraps shell commands and persists structured records.
  • Truncate large outputs deterministically so the loop stays within token budget.
  • Refuse to advance the loop when feedback is missing.

The Problem

The agent says "running tests now." The next message says "all tests pass." The reality is that no test ran. The agent imagined the output, or it ran the command and never read the result, or it read the result and silently truncated the failure line.

A feedback runner removes that gap. Every command goes through the runner. Every record carries the command, the captured stdout and stderr, the exit code, the wall-clock duration, and a one-line agent note. The agent reads the record at the next turn. The verification gate reads the records at the end of the task.

The Concept

Diagram (opens full size)

What goes in a feedback record

Field Why it matters
command Exact argv, no shell expansion surprises
stdout_tail Last N lines, deterministic truncation
stderr_tail Last N lines, separate from stdout
exit_code The unambiguous success signal
duration_ms Surfaces slow probes and runaway processes
started_at Timestamp for replay
agent_note One line the agent writes about what it expected

Truncation is deterministic

A 50 MB log destroys the loop. The runner truncates head and tail with a ...truncated N lines... marker, deterministic so the same output always produces the same record. No sampling; the parts the agent needs to see (final error, final summary) live at the tail.

Feedback versus telemetry

Telemetry (Phase 14 · 23, OTel GenAI conventions) is for human operators reviewing runs across time. Feedback is for the next turn of this run. They share fields but they live in different files with different retention.

Refuse to advance without feedback

If the runner errors before capturing exit, the record carries exit_code: null and error: <reason>. The agent loop must refuse to claim success on a null exit. No exit, no progress.

wb-feedback-loop

Build It

code/main.py implements:

  • run_with_feedback(command, agent_note) that wraps subprocess.run, captures stdout/stderr/exit/duration, truncates deterministically, appends to feedback_record.jsonl.
  • A small loader that streams the JSONL into a Python list.
  • A demo that runs three commands (success, failure, slow) and prints the last record per command.

Run it:

python3 code/main.py

Output: three feedback records appended to feedback_record.jsonl, the last one of each printed inline. Tail the file across re-runs to see the loop accumulate.

Production patterns in the wild

Three patterns harden the runner enough to ship.

Redact at write, not at read. Any record that touches stdout or stderr can leak secrets. The runner ships a redaction pass before the JSONL append: strip lines matching ^Bearer , password=, api[_-]?key=, AKIA[0-9A-Z]{16} (AWS), xox[baprs]- (Slack). Redaction at read time is a foot-gun; the file on disk is what an attacker reaches. Audit the redaction patterns quarterly against the production runtime's observed secret formats.

Rotation policy, not a single file. Cap feedback_record.jsonl at 1 MB per file; on overflow rotate to .1, .2, drop .5. The agent's loop only reads the current file, so the runtime cost is bounded. CI artifact storage gets the full rotated set. Without rotation the file becomes the bottleneck on every loader call.

Parent-command id for retry chains. Every record gets command_id; retries carry parent_command_id pointing at the previous attempt. The reviewer's "failed attempts" list (Phase 14 · 40) and the verification gate's audit both follow the chain. Without this link, retries look like independent successes and the audit hides the failure history.

Use It

Production patterns:

  • Claude Code Bash tool. The tool already captures stdout, stderr, exit, and duration. The runner in this lesson is the framework-agnostic equivalent for any agent product.
  • LangGraph nodes. Wrap any shell node in the runner so the record persists outside graph state.
  • CI logs. Pipe the JSONL into your CI artifact store; reviewers can replay any command without rerunning the session.

The runner is a thin wrapper that survives every framework migration because it owns the shape of the record.

Ship It

outputs/skill-feedback-runner.md generates a project-specific run_with_feedback.py with the right truncation budget, a JSONL writer wired to the workbench, and a loader the agent reads at every turn.

Exercises

  1. Add a cwd field per record so the same command run from different directories is distinguishable.
  2. Add a redaction step that strips lines matching ^Bearer or password=. Test on a fixture record.
  3. Cap total feedback_record.jsonl size at 1 MB by rotating to .1, .2 files. Defend the rotation policy.
  4. Add a parent_command_id so retry chains are visible: which command produced the input that the next command consumed.
  5. Pipe the JSONL into a tiny TUI that highlights the latest non-zero exit. List eight key features the TUI must show to be useful in a review.

Key Terms

Term What people say What it actually means
Feedback record "Run log" Structured JSONL entry with command, output, exit, duration
Tail truncation "Trim the log" Deterministic head+tail capture so records fit in token budget
Refuse-on-null "Block on missing data" The loop must not advance when exit_code is null
Agent note "Expectation tag" The one-line prediction the agent writes before reading the result
Telemetry split "Two log files" Feedback for the next turn, telemetry for the operator

Further Reading

Check yourself

Quick quiz

  1. What does the feedback runner force the agent to do?

    1. React to imagined output
    2. React to facts: structured stdout/stderr/exit/duration records captured into the loop on every command
    3. Skip verification
    4. Use a different model
    Show the answer

    B. React to facts: structured stdout/stderr/exit/duration records captured into the loop on every command The runner closes the gap between 'tests passed' (imagined) and 'tests actually ran and exited zero' (recorded).

  2. How does feedback differ from telemetry?

    1. Feedback is for the next turn of this run; telemetry is for operators reviewing runs across time (different files, different retention)
    2. They are the same thing
    3. Telemetry is paid
    4. Telemetry uses OTel; feedback uses GraphQL
    Show the answer

    A. Feedback is for the next turn of this run; telemetry is for operators reviewing runs across time (different files, different retention) Both share fields but live in different files with different retention; feedback is intra-run, telemetry is cross-run.

  3. Which field MUST appear in every feedback record?

    1. exit_code (and a null exit must refuse to advance the loop)
    2. embedding_vector
    3. model_id
    4. prompt_cache_token
    Show the answer

    A. exit_code (and a null exit must refuse to advance the loop) exit_code is the unambiguous success signal; null exit means no progress.

  4. How does the runner truncate large outputs?

    1. Compresses with gzip
    2. Random sampling
    3. First 10 lines only
    4. Deterministic head + tail with a 'truncated N lines' marker so the same output always produces the same record
    Show the answer

    D. Deterministic head + tail with a 'truncated N lines' marker so the same output always produces the same record Deterministic truncation keeps records replayable while bounding token cost; tails carry the failure summary.

  5. Why redact at write time rather than read time?

    1. Read-time redaction breaks JSON
    2. The file on disk is what an attacker reaches; redacting only on read leaves secrets in JSONL files
    3. It is faster
    4. Compression
    Show the answer

    B. The file on disk is what an attacker reaches; redacting only on read leaves secrets in JSONL files Redact lines matching Bearer, password=, api_key=, AKIA..., xox[baprs]- before append; auditing the patterns quarterly.

  6. What does parent_command_id give the workbench?

    1. Faster file I/O
    2. Lower memory
    3. Retries link to their parent attempt so the reviewer and audit see the failure chain; without it retries look like independent successes
    4. Cheaper inference
    Show the answer

    C. Retries link to their parent attempt so the reviewer and audit see the failure chain; without it retries look like independent successes Parent linkage makes retry chains visible to the reviewer (Lesson 39) and the verification gate.

  7. Why cap feedback_record.jsonl at 1 MB with rotation?

    1. Disks are too slow
    2. The agent only reads the current file; rotation keeps runtime cost bounded while CI artifacts capture the full set
    3. JSON does not handle larger files
    4. The provider charges per byte
    Show the answer

    B. The agent only reads the current file; rotation keeps runtime cost bounded while CI artifacts capture the full set Bounded current file + rotated history is the same pattern logrotate uses; predictable cost in the hot loop.

Questions people ask

Why do AI agents claim something worked when it did not?

Often they predict the outcome instead of checking it, or they miss an error buried in long output. Recording each command's output, error messages and exit status in a structured log forces decisions to rest on what happened.

What is a feedback loop for an AI agent?

It is the cycle of acting, seeing the real result, and adjusting. For agents, that means running a command or tool, reading the true output and errors, and using them to decide the next step.

Next lessonVerification GatesPrevious: Scope Contracts and Task Boundaries

Lessons from AI Engineering from Scratch by Rohit Ghumare and contributors, MIT license. Notes for owners by Lozo. License

Next step

Rather have it built for you?

Reading is optional. Tell me what's stuck and I'll build it into the business you already run.

  • A real conversation, not a pitch
  • You keep your accounts
  • Nothing sends without your yes