Loop Engineering

A Better Way to Think, Create, and Work with AI - Companion site

← All worked examples

Worked Example - Motor + Sensory (Agent Action Log)

Companion to Chapter 9. A real agent action log for a multi-step task - file edits, shell commands, network calls, and the confirmation-gate sequence that punctuates the side-effects. Side-effect class annotations show where the materiality-gating discipline kicks in.

The task

"Update the production-DB connection pool size from 10 to 20 in the deployment manifests, run the validation tests, and open a PR." Five distinct side-effect classes: file read, file write, shell command (test run), shell command (git operations), network call (open PR via API).

The action log (abridged)

[10:42:01] read_file: deploy/values.prod.yaml side-effect class: READ scope: single file gate: none (read-only) result: 47 lines
[10:42:03] grep_search: "poolSize" in deploy/**/*.yaml side-effect class: READ scope: deploy/ subtree gate: none (read-only) result: 3 matches in deploy/values.prod.yaml, deploy/values.stg.yaml, deploy/values.dev.yaml

The agent notes that the user said "production" specifically and stops before editing all three. It surfaces the question.

Confirmation gate - disambiguation

The pool-size value appears in three manifests (prod, stg, dev). The request said "production" - should I update only values.prod.yaml, or all three for consistency? Default: prod only.

User: "Prod only."

[10:42:17] replace_string_in_file: deploy/values.prod.yaml side-effect class: WRITE (file) scope: 1 line in 1 file gate: confirmed (per harness policy: file writes under deploy/ require confirmation) diff: - poolSize: 10 + poolSize: 20
Confirmation gate - file write under deploy/

Edit shown above will modify the production deployment manifest. Apply? [Y/n]

User: "Y"

[10:42:24] run_in_terminal: npm test -- deploy-validation side-effect class: SHELL (test runner) scope: read-only at the test level; writes only to tmp gate: none (test runner; sandboxed) exit code: 0 output: 12 passed, 0 failed
[10:42:33] run_in_terminal: git diff --stat side-effect class: SHELL (git read) scope: read-only gate: none output: deploy/values.prod.yaml | 2 +-
[10:42:34] run_in_terminal: git add deploy/values.prod.yaml side-effect class: SHELL (git stage) scope: index-only; no network gate: none (no network effect) result: 1 file staged
[10:42:36] run_in_terminal: git commit -m "[behaviour] prod: bump DB connection pool 10->20" side-effect class: SHELL (git commit) scope: local repo only gate: none (no network effect; reversible via git reset --soft HEAD~1) result: committed as 8a3f12c
Confirmation gate - push to remote

About to git push origin feat/prod-pool-size-bump. This will create a remote branch and make the change visible to CI. Proceed? [Y/n]

User: "Y"

[10:42:48] run_in_terminal: git push -u origin feat/prod-pool-size-bump side-effect class: NETWORK (git push) scope: pushes 1 commit to 1 remote branch (new branch) gate: confirmed (per harness policy: network writes require confirmation) result: branch pushed; PR not yet opened
Confirmation gate - open PR (API call)

About to call the GitHub API to open a PR from feat/prod-pool-size-bump to main with the title "prod: bump DB connection pool 10->20". This is a public action visible to reviewers and CI. Proceed? [Y/n]

User: "Y"

[10:43:02] gh api: POST /repos/.../pulls side-effect class: NETWORK (API write) scope: creates 1 PR gate: confirmed result: PR #2847 opened url: https://github.com/.../pull/2847

The side-effect class annotations

Six classes appeared in this trace, with three different gate behaviors:

What the architecture's discipline buys here

The agent did not ask permission for every read or every harmless local action - that would have made the loop unusable. It asked permission at exactly the transitions that mattered: ambiguous scope (one file or three?), first write to a production-class artifact, first network call, first public-facing call. Materiality-gated; not paranoid, not reckless.

Two failure modes the discipline prevents:

What this trace does not show

This example assumes a well-behaved environment (no prompt injection, no model error, no network anomaly). The companion failure-diagnosis worked example covers what the diagnostic process looks like when one of those goes wrong.

Practitioner templates

The prompts library hosts confirmation-gate templates and action-log review prompts.