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.
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 harness | What it does | Where to find it |
|---|---|---|
| System instructions | Claude Code adds them to the context before your first message: how to work, which tools exist, which folder the session runs in | the System prompt line in the output of /context |
CLAUDE.md | project rules the agent reads at the start of a session | a file in the project root |
| Tools | reading and editing files, search, terminal commands | lines like Read(...) and Bash(...) as the agent works |
| Skills | instructions the model can pick for a task, or you can invoke explicitly | .claude/skills/, /skills |
| MCP | a bridge to external services and live data | /mcp |
| Subagents | a separate worker with its own context | .claude/agents/ |
| Permission prompts | the harness checks whether an action is allowed and asks for your approval when needed | a question in the terminal before a command or an edit |
| Hooks | your own commands tied to session events; they run without the model deciding anything | /hooks |
| Context and session | what the model sees right now, and which point you can go back to | /context, /clear, /rewind |
| Agentic loop | returns tool results to the model so it can pick the next step | several 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.
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 inCLAUDE.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
Stopevent 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
/modeland compare the results on the same task.
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.
GO TO FULL VERSION