You switched the model with /model, ran the same task again, and got a different answer. But the agent read CLAUDE.md the same way, asked for permission before running a command the same way, and the hook fired just like before. so all of that lives somewhere other than the model.

Let's work out where the model ends and the program around it begins. That helps you figure out what to check when the agent gets something wrong.

The model and the harness

The model processes the context it's given and produces either an answer or a request to a tool. It picks which file to read, for example, or which command to run. Actually carrying out those actions takes a program around the model: it accesses the files, runs the commands and hands the results back to the model.

That program is called a harness. Outside software, it's the gear you put on a horse (yes, that kind), and in the docs you'll also come across the longer form, agentic harness. Anthropic's documentation puts it plainly: Claude Code is the harness, Claude is the model inside it. The word also shows up in writing about agents in general, so it's worth remembering.

A request on the left enters the harness. The model sits in the middle of the harness, surrounded by three groups: what the model sees, what the model acts with, where the model gets stopped. The harness carries out the tool request and returns its result to the model so it can choose the next step. On the right is the result of the work in the projectHarnessloopYour requestModelpicks the stepWhat the model seesinstructions, CLAUDE.mdWhat the model acts withtools, MCP, subagentsWhere the model gets stoppedpermissions, hooksResultin the project
The working loop: tool request, result, next step

In the diagram, the harness gathers the context, checks permissions and carries out the model's tool requests. The arrow under the model is the loop: the tool's result goes back into the context, and the model picks the next step or finishes its answer. A finished answer doesn't prove the task is solved, though. Someone still has to check the result.

What you've already set up

Here's how the parts of the harness show up in Claude Code. The files and commands in the right-hand column help you find each mechanism in a project or a session.

Part of the harnessWhat it doesWhere to find it
System instructionsClaude Code adds them to the context before your first message: how to work, which tools exist, which folder the session runs inthe System prompt line in the output of /context
CLAUDE.mdproject rules the agent reads at the start of a sessiona file in the project root
Toolsreading and editing files, search, terminal commandslines like Read(...) and Bash(...) as the agent works
Skillsinstructions the model can pick for a task, or you can invoke explicitly.claude/skills/, /skills
MCPa bridge to external services and live data/mcp
Subagentsa separate worker with its own context.claude/agents/
Permission promptsthe harness checks whether an action is allowed and asks for your approval when neededa question in the terminal before a command or an edit
Hooksyour own commands tied to session events; they run without the model deciding anything/hooks
Context and sessionwhat the model sees right now, and which point you can go back to/context, /clear, /rewind
Agentic loopreturns tool results to the model so it can pick the next stepseveral actions in a row in response to one request

CLAUDE.md and skills give the model instructions. The model can misread a rule. Or skip it altogether. Permission checks and the commands in your configured hooks run programmatically. What they produce depends on the conditions you set and on the commands themselves.

Plugins didn't make it into the table because they aren't a separate part, they're a package: several skills, commands or hooks that you install in one go.

Same model, different behavior

Take a web chat that isn't connected to your project or your terminal. It has a harness of its own: the conversation history, the interface, sometimes web search or file uploads. In that chat the model can explain an edit and show you the code, while Claude Code, with access to the project, can actually make the edit in the file. Same model, different capabilities, because the program around it is different.

With /model it's the other way round. The model changes, the harness stays the same, so the rules, tools and permission prompts don't go anywhere.

The model determines how the task is understood, which tools get chosen and how their results are judged. The harness gathers the context, provides the tools and checks permissions. Say the model is missing a file. It asks for it, and the harness does the reading and hands back the contents.

What this looks like in Claude Code

The agent is confidently reasoning about a function that was removed from the project ages ago? First check whether the current code actually made it into the context. It can get there through @ with a file path, by being pasted into your message, or through the read tool. In the first two cases there may be no separate read call at all. If the tool was called, look at what it returned: the file's contents, or an access or path error. If the code isn't in the context, pass it in or ask the agent to read the file. If the code is already there but the conclusion is wrong, check the reasoning against specific lines. A different model can help here too, by the way.

What to fix when the agent gets it wrong

A one-off mistake is easiest to fix with a quick reply: "wrong file, look in src/utils.js". If the same mistake keeps coming back from one session to the next, though, check the instructions and the data the agent has access to. Maybe you're having to explain the same rule from scratch every time.

In practice it looks roughly like this:

  • the agent forgets a project rule in every session, e.g. that tests run with npm test - write the rule down in CLAUDE.md. An important rule is safer saved explicitly in that file than left to reminders in the chat;
  • you're explaining the same procedure for the third time - it's time to move it into a skill. The agent can then load the instructions when the task calls for them. Check as you go that the skill was actually invoked; if it wasn't, invoke it yourself with /skill-name, using its real name;
  • the agent is guessing about data it doesn't have - give it the data: add the file to the context with @ or connect the external service through MCP. No amount of persuading cures guesswork;
  • the agent says "done" without running any checks - a hook on the Stop event can run the tests on its own, without the model deciding anything. you're still the one who accepts the work, going by the command's output, not the report;
  • the data is available and has been read, but the agent gets tangled in a complex line of reasoning - try a different model with /model and compare the results on the same task.
Check the cause

First check whether the data and tools the agent needs are available. If the trouble is in the reasoning, you can try a different model right away. Compare the quality of the result and the spend shown in /usage: repeated failed attempts eat into your limit and your time as well.