Harness Engineering
The model is the engine. The harness is the car, the pit crew, and the rulebook. Here is how to build one around Claude, one layer at a time.
Have you ever tried a brand new model and thought, “This is clearly good, but I can’t tell it apart from the last version for the things I actually use it for”?
I think a lot of people feel that right now. And I don’t think the model is the reason.
For the last few years, the race in AI was to build smarter models. Picture it as a Formula 1 team designing a new engine every six months. But F1 is more than an engine. There is the car, the pit crew, the race engineers, the track limits, and the driver. A better engine gives you an edge. An engine alone does not win the race.
The model is no longer the whole product. The model is the engine. What you build around it decides how much of that engine you can actually use.
That “everything around it” has a name: the harness.
I build agent systems for a living, so this framing matches how I think about them. In this article I will walk through a concrete example, a resume screener built on Claude Code, and show the six layers of a harness one by one. The F1 analogy and the walkthrough are adapted from a video tutorial I learned this from, and I have added my own notes on where each layer matters and where it can go wrong.
The goal is not to teach you to screen resumes. It is to show you a pattern you can copy for almost any job you keep handing to AI.
What a harness actually is
Here is the simplest definition I know.
A harness is everything you build around an AI model to make it reliably do a good job.
It decides what the model sees, what it can access, what it is allowed to do, what a good answer looks like, how its work gets checked, what it remembers, and when it runs.
The term has been spreading fast. According to one overview of the idea, Mitchell Hashimoto, the creator of Terraform, wrote that he knew of no established name for how he works with agents and called it harness engineering, and OpenAI published a report under the same name a few days later. A recent research paper defines it as a runtime layer around a foundation-model agent that manages context, tools, memory, verification, and permissions.
Two boundaries help here.
- It is not prompt engineering. Prompting is how you phrase the request.
- It is not only context engineering. Context is what the model sees. In this article, context is just layer one of six.
There is a practical reason to care. Models are getting commoditized quickly, and you and I will probably have access to similar ones. The model can be identical while the available information, tools, and limits are completely different, and that is where the results diverge. If you are comparing setups, compare the model, but also the tools, the context, and the limits around it.
The example: a resume screener
A team is hiring a salesperson. Somewhere around 15 to 20 resumes arrive every day. Someone has to read them, compare them fairly, and shortlist.
We will build a harness around Claude that does this the same way every single time. Here is the folder we will end up with:
resume-screener/
CLAUDE.md
context/
jd.md
rubric.md
ideal-candidate.md
report-template.md
memory/
process.md
.claude/
skills/
screen-resumes/SKILL.md
calibrate/SKILL.md
agents/
verifier.mdIt looks like a lot of files. But every file exists to fix one specific failure, and that is the way to read this whole article.
Let’s build it.
Layer 1: Context
Before an F1 driver gets in the car, the team gives a race briefing: what you are trying to achieve, what the track looks like, what the conditions are, what constraints apply, and what strategy to follow.
Context is that briefing for the model. It is the information, rules, constraints, and examples it needs before you ask it to do the job.
The tutorial uses the Claude desktop app with Claude Code, which can read local files you give it permission to. Make a folder called resume-screener, then a context folder inside it.
The job description (jd.md). This is the first piece of the rulebook, because it is what you are hiring against. Paste in the same description you post on hiring platforms.
The rubric (rubric.md). A job description tells you what the role is. It does not tell you how to judge a resume, and that gap is where most of the inconsistency comes from.
In the example, the rubric covers six things: sales experience, proof of results, who the person has sold to, curiosity about AI, communication, and ownership. Each one is scored exactly 1, 3, or 5, nothing in between, and each score has a written meaning. A 5 on proof of results, for instance, means the resume shows real numbers, like achieving 120% of a target.
Here is a sketch of one entry:
Criterion: Proof of results
1 = no outcomes mentioned
3 = outcomes mentioned, no numbers
5 = real numbers (for example, 120% of target)Rule: every score needs a direct quote from the resume.
No quote, no score.That last rule is the one I like most. No quote, no score. The model cannot call someone a strong candidate out of thin air. It has to point at the line in the resume that proves it.
An ideal candidate (ideal-candidate.md). Examples help, but there is a catch: show a model an example and it will start copying it. So the file opens with a section called "when not to copy from this resume." It says the company, the college, and the formal letter do not matter. The example exists only to show what strong evidence looks like.
A CLAUDE.md file. Claude Code loads this automatically whenever you work in the folder. It explains what the job is, where every file lives, and the scoring rules. It also contains what I think is the most important line in the project:
You never make hiring decisions. A human does.
Did it change anything?
The test is simple. Upload one candidate’s resume and ask Claude whether they are a good fit. Do it three times.
Without context, you get three different answers. One calls it a decent resume. Another says it lacks key qualities. Claude can’t make up its mind.
With the context layer in place, the same three runs return the same scores every time. The rubric is deciding, not the model’s mood that day.
A caution from me, though. That result shows consistency, not correctness. A flawed rubric will give you the same flawed answer three times in a row. Layer one makes the behavior repeatable. It is your job to make sure the rubric is worth repeating.
There is still a problem. You are uploading resumes by hand, and 20 a day will not work.
Layer 2: Tool access
An F1 driver can have a perfect strategy, but it is useless if the car cannot carry it out. The driver needs the steering, brakes, throttle, DRS, and radio. Each one has a purpose and limits, and the driver uses them only within the rules of the race.
Tool access does the same for AI. You give it the systems it needs, and you decide what it can and cannot do with them.
In the example, all resumes land in a Google Drive folder. So instead of uploading one by one, you connect Claude to Drive using MCP, the Model Context Protocol. The simplest way to think about MCP is as a universal plug that lets an LLM talk to different tools and apps. Rather than copying data from an app into the AI, you plug the AI into the app where the data already lives.
In the desktop app that means opening Customize, going to Connectors, adding Google Drive, and granting permission. Then test it with a harmless prompt: ask Claude to list the files in the resume inbox, without screening anything yet. If every resume shows up, the connection works.
Now the tip a lot of people skip.
Giving AI access to your apps is the easy part. Giving it limits is the hard part.
These are track limits. In CLAUDE.md, the example sets three rules: use this one folder only, never delete or move any resume, and never contact candidates. The point is a system that does what you want and, just as important, does not do what you don't want.
One honest note: instructions in a file are guidance the model follows, not a hard lock. For anything truly dangerous, I would also restrict permissions at the connector or tool level, so the system cannot do it even by mistake.
Layer 3: Output
An F1 pit stop is one of the most rehearsed processes in racing. Every person has a specific job, every movement has a sequence, and the goal is to execute it exactly the same way every time. You do not want the crew improvising when the car comes in.
With AI, the same task can produce different processes and different formats every time. If today’s output is a tidy list and tomorrow’s is three long paragraphs, you cannot compare day one with day five.
So you define both the process and the final shape.
The report template (report-template.md). At the top, a summary table so you can see the whole report at a glance. For shortlisted candidates, the full detail: a score for each criterion with the supporting quote, any red flags, and questions to ask on the call.
A skill. Instead of typing a long prompt every morning, package the whole process into a Claude skill. Inside the project you create a hidden .claude folder, then skills/screen-resumes/, then a SKILL.md file. A skill is a markdown file at .claude/skills/<name>/SKILL.md, and its name and short description tell Claude when to use it.
Below that header you write the steps in order: read the rules, pick up the resumes from Drive, score each candidate on their own, and so on. You are codifying the process.
After that, the entire morning workflow is one command. Type a forward slash, pick screen-resumes, and run it. Every score now has a quote behind it, and every verdict has a reason.
Get Adil Shamim’s stories in your inbox
Join Medium for free to get updates from this writer.
That is already more useful than doing it by hand. But one question is still open. Can we trust these answers?
Layer 4: Verification
Even the best F1 drivers do not rely only on what they can see from the cockpit. A team on the pit wall watches telemetry, lap times, tire temperatures, and fuel levels. Their job is not to drive. It is to spot what the driver might miss and say when something is wrong.
Here is the problem. If the same AI that scored the resume also checks its own work, it will mostly agree with itself.
So the fix is a separate checker, built as a separate agent. It has its own instructions, its own tools, and a fresh context. It does not see how the first Claude reasoned. It sees only the resume and the scores, and that is exactly what makes it a fair reviewer.
It helps to be precise about the difference between a skill and an agent:
- A skill is a file of instructions Claude follows.
- An agent is a separate worker Claude can hand a job to. In Claude Code, a subagent lives in
.claude/agents/<name>.mdand runs in its own context window.
Here is a sketch of the verifier:
---
name: verifier
description: Independently checks resume scorecards before any report is written.
tools: Read, Glob, Grep
---
You do not score. You verify.
For every scorecard, check:
- Is each quoted line actually in the resume?
- Does the quote support the score given?
- Is the arithmetic right?
- Were any red flags missed?
If everything holds up, say "confirmed".Three details matter here.
First, read-only tools. The verifier can inspect everything and change nothing, not even by accident.
Second, it is allowed to say “confirmed.” That sounds obvious, but a checker that is never allowed to say everything looks fine starts inventing problems just to look useful.
Third, it runs automatically. The screening skill includes a step that sends every scorecard to the verifier before the report is written, so you never have to remember to run it.
This layer is what takes you from “the AI said so” to “here is the proof.”
A caution again: an independent checker is better than self-review, but it is not infallible. It can still be wrong. Treat verification as a strong filter, not a guarantee, and spot-check it yourself now and then.
Layer 5: Memory
An F1 team never shows up to a race with a clean slate. They bring what they learned from the last one: which setups worked, which strategies failed, how the tires behaved, what they got wrong. Every race becomes data for the next.
Without memory, our harness is accurate, but if you close it today it starts from zero tomorrow. There are two kinds of memory worth building.
Memory 1: What has it already done?
Create a memory folder with a process.md file. Update the skill so every resume it screens gets logged there with the date.
Now run the skill again. It reports that there are no new resumes. It does not rescreen the same ten people. Tomorrow it will pick up only what has landed in the inbox since.
Memory 2: Learning from mistakes
This is the kind everyone talks about: a system that improves itself. And this is where I want you to be careful.
If you let an AI rewrite its own rules with nobody watching, it slowly drifts. Small changes stack up and compound, and one day it is judging people by rules nobody agreed to.
The safer design is a second skill called calibrate, which sits next to the first one. Its job is to turn your feedback into a general rule, not a one-off fix. And it is set so Claude can never run it on its own. Only you can.
Here is how it works. Say you disagree with one verdict in today’s report. You run calibrate with the date and paste your feedback on that candidate. Then:
- It works out why it got that one wrong.
- It proposes a general rule, not a patch for that single person.
- It stops and waits for your approval.
- Once you approve, the lesson is saved in a calibration file that every future run reads.
- It rechecks the earlier resumes and shows you which verdicts changed, including any you did not expect.
So yes, the system learns. But it learns only from your corrections and only with your approval. That is the safe way to do it.
Layer 6: Automation
On race day, the driver does not sit in the garage and ask the team to start the race. The lights go out and the systems you set up take over.
Right now you still have to remember to type the command every morning. So the last layer is a trigger.
In the Claude desktop app, open Schedule and create a new task. Give it a name, set the instruction to run the screen-resumes skill, choose the model, and set it for every weekday at 9:00 a.m. Point it at the project folder and allow the permissions.
One limit to know about. In the tutorial, the task runs locally, so your laptop has to be on and the Claude app open at that time. If you need it to run regardless, you will want a different hosting setup.
With that done, the report is waiting every morning. All you do is read it and decide who to call. Tomorrow’s report will look exactly like today’s: same format, same constraints, same guardrails.
What did not change
Here is the part I find most interesting.
None of this made the model smarter. We did not change the engine. We changed everything around it.
Instead of opening Claude every morning and asking it to screen 20 resumes, you now have a system that wakes up, finds the new resumes, scores them against the same criteria, has its work checked by an independent reviewer, and leaves a report. You made no changes to the model. The reliability came entirely from the harness.
The same six layers can power a sales qualification flow, a customer support workflow, a content review process, or a research assistant. If you keep handing a repetitive job to AI and getting uneven results, this is the pattern to try.
A harness for your own job: six questions
When you apply this to something else, ask one question per layer.
A few more things I would keep in mind.
- Start with context and output. They cost the least and fix the most visible problem, which is inconsistency.
- Keep a human in the decision. The most important line in this whole project is the one that says a human decides. Hiring is also a sensitive area where scoring rubrics can encode bias and where some places regulate automated screening, so audit your rubric and check your local rules.
- Treat failures as signals. When the system gets something wrong, ask which layer let it through. Usually the fix is a better rule, a missing check, or a tighter limit, not a bigger model.
The final mental model
An agent is a model plus a harness.
If the model is the engine, the harness is the team: the briefing, the controls and their limits, the rehearsed procedure, the pit wall, the lessons from last race, and the lights going out on schedule.
The future is probably not going to be decided by who has access to the smartest model. We will all have powerful models anyway. The advantage will come from knowing how to build a system around one, and the better you get at that, the more you can get out of the engine you already have.
That is harness engineering.
What is one job you keep handing to AI that gives you a different answer every time? Tell me. I would like to know which layer you would build first.
Sources and references
- Jules Robineau. What is a harness? Everything that is not the model. Overview of the term, including the Hashimoto and OpenAI references.
- AI Harness Engineering: A Runtime Substrate for Foundation-Model Software Agents. A research definition of the harness and what it manages.
- Tejas Kumar. AI Agent Harnesses: Building Reliability Around an Unreliable Model. Talk on tools, guardrails, context management, and verification.
- Anthropic. Effective context engineering for AI agents. Context as a finite resource.
- Claude Code documentation. Subagents and Memory and CLAUDE.md.
- Model Context Protocol. The open standard for connecting AI to tools and data.
- The video tutorial this walkthrough is adapted from: the F1 framing and the six-layer resume-screener build.









