When the Harness Becomes a Platform
Part 6 of 6 Harness Engineering: How Coding Agents Turn Decisions into Work
In brief
In brief
Skills carry instructions, hooks run at named events, and plugins bundle components. MCP connects an app to outside tools and data, ACP connects an editor to an agent, and an SDK exposes agent operations to your program. Choose the interface for the work you need to reuse.
- Skills teach a procedure, hooks run at named events, and plugins package components. The host still decides permissions.
- MCP connects outside tools and data to a host, while ACP carries sessions and updates between a client and an agent.
- Test cancellation, denied writes, final status and result retrieval against the actual code and workspace. A shared API alone cannot prove them.
The preview cache has been repaired. Its key includes the locale the renderer actually uses, and a regression requests English then German through the same cache. Now a second repository needs the same investigation. An editor team wants to run it from a panel. A document service offers a remote preview inspector. Someone wants to compare two coding agents on the task.
Each request reuses something different. The second repository needs a procedure. The editor needs to start and follow agent sessions. The remote inspector needs a tool interface. The comparison needs rules for running each agent and judging its results.
Skills, hooks, plugins, protocols and software development kits (SDKs) offer different ways to extend the harness, the code around the model. This chapter explains what each interface carries, what the application still has to handle, and how to choose the smallest one the task needs.
Section 14 of Barbaste et al.'s Harness Engineering calls this opening of harnesses to plugins, protocols and SDKs a platform turn.
What each extension reuses
A repair can leave behind a patch, a test, a search procedure, a remote tool, or an application integration. The patch belongs to one codebase. A procedure can travel between repositories. A service interface can outlast its implementation.
Model Context Protocol (MCP) connects an application with outside tools and data. Agent Client Protocol (ACP), created by Zed, connects clients such as editors with coding agents. An SDK lets application code call agent operations. A meta-harness sends tasks to several existing harnesses, for example to compare two coding agents, instead of running its own edit loop. The table separates what each interface carries from the decisions left to the application running it.
| Interface | What it carries | What the application still decides |
|---|---|---|
| Skill | Instructions and supporting material | When it loads, what runs, and with which permissions |
| Hook | A named event and the handler's result | What the event means and how the result is enforced |
| Plugin | An installable bundle of components | Which plugins to install and how each part behaves |
| MCP | Requests to server tools and data, and their results | Which context to share, user consent, and coordination |
| ACP | Sessions, prompts, and updates between a client and an agent | Whether the task is correct and which workspace is used |
| SDK | Program access to agent operations | How the program starts, stops, and resumes work |
| Meta-harness | Work assigned to existing harnesses | Coordination across harnesses and which results to accept |
Product terminology varies. A plugin can contain a skill and an MCP server. An SDK can expose an ACP agent. One package can therefore use several interfaces.
When a component fails, look at the job it does. If the cache procedure never loads, check discovery and activation. If the agent calls the wrong remote preview endpoint, check the tool and its arguments. If the editor reports success while tests still run, check how it handles sessions and completion. Bundling them into one package still leaves three separate places to debug.
A skill carries instructions
The Agent Skills specification defines a directory containing SKILL.md, with metadata and Markdown instructions. Optional files can include scripts and references. The format packages a procedure. Whether it fits the current repository still needs checking.
For our example, a skill could teach how to investigate a cache. Find which inputs affect rendering, trace the lookup and store keys, check invalidation, and test repeated requests. Explain why a fresh cache for every assertion can miss reuse bugs. The procedure can then apply beyond document previews.
Keep the assumptions clear. A document ID might refer to immutable content in one service and changing content in another. Middleware might resolve locale, or the caller might pass it directly to the renderer. The procedure should ask the agent to inspect those rules. Hard-coding “append locale to the key” would turn one example into a fix that may not apply elsewhere.
Review a bundled script as carefully as any installed tool. Reading source and clearing a production cache need different permissions. Loading a skill should grant neither automatically. The host still decides which commands may run, under its permission rules and sandbox limits.
Keep a skill's references clear about the project behavior they expect. Its checks should fail visibly when those assumptions stop holding. Otherwise the skill keeps teaching yesterday's architecture against today's code.
A hook runs at a named event
A skill asks the agent to follow a procedure. A hook runs a handler at a named event. The Claude Code hooks reference documents PreToolUse, PostToolUse, and Stop, each with its own inputs and decisions. Check another harness's behavior separately, even if its event names match.
In our workflow, one hook could record which workspace and command produced a test result. Another might prevent completion until a test result covers the current patch. Both need a record of the test run, rather than the model's phrase “tests passed.”
Timing matters. A handler that runs after a write can observe it or block further work, but the write has already happened. A pre-execution check can block a command only if every relevant way to run it passes through that check. A hook on one tool does not, by itself, check other tools with equivalent access.
Hooks can add hidden work: logs, subprocesses, or extra checks. Account for their latency and failures. A timed-out test hook leaves the result unknown, rather than proving the patch failed. A hidden retry that changes the source revision makes the result hard to interpret.
For this repair, I prefer a small test-result recorder to a complex policy engine. Accept a result only if it identifies the test run on the final workspace. Whether a hook fits that job depends on when its event fires and how the host stores results.
A plugin ships several parts together
The Claude Code plugin documentation describes installable collections of skills, agents, hooks, MCP servers, and other components. A plugin ships these parts together. Each part still runs in its own way.
A proposed preview-engineering plugin could bundle the cache skill, a test-result hook, and preview-inspector configuration. Installing it makes those parts available together. Check separately when the skill activates, which events trigger the hook, and what the inspector can read.
Updates need the same care. A revised instruction changes what the model reads. A revised executable can change file or network behavior. A changed server endpoint can send documents to a different operator. One package version labels the bundle, but review what each changed part does.
Test portability part by part too. A Markdown skill may carry much of its procedure to a compatible host. A hook needs compatible events and outputs. Server configuration needs compatible connections and authorization. A package can travel whole while some parts work differently in the receiving harness.
MCP connects an application to outside tools
In the MCP architecture for revision 2025-11-25, the host manages clients, each connected to a server. Servers offer resources, tools, and prompts. The host chooses context and manages authorization, while the server handles its own requests.
Suppose a remote service offers a preview-inspection tool. It could accept a document ID and the locale the renderer uses, then return a preview key, renderer version, and diagnostic result. This application defines those fields. MCP itself defines no document fields. The host must check whether the call serves the task and whether sending the document ID is allowed.
The local regression might use a renderer stub, while the inspector checks a deployed service. The two results come from different runs. An old deployed version can still show a cache collision after the local patch fixes it. A clean remote inspection also says nothing about whether the local regression tests the right behavior.
Keep each result with its task, source revision, and target environment. The server reports its own run. The host decides what that report supports. Part 5 needed the same care when a research worker returned a test result for an older patch.
MCP fits when the inspector runs as a separate service or serves several hosts. For a helper that runs one local unit test, a normal command may be easier to inspect and maintain. Add the protocol when the workload needs the extra interface.
ACP connects an editor to an agent
The ACP v1 overview describes sessions, prompt turns, updates, and operations such as permission requests between client and agent. Its initialization specification negotiates protocol version and the features each side supports, called capabilities.
An editor launching the repair needs to create a session, send the task, display updates, present decisions, and identify when the turn ends. ACP handles that client/agent interaction. The inspector offers a tool to the agent. The editor lets a person work with the agent.
The client must also know where the agent runs. Is it using saved files or another workspace? Can it see the latest unsaved buffer? Who handles the terminal it started? Declaring a supported operation still leaves the application to connect it to the right files and processes.
The editor can otherwise show a green completion indicator while a child process still runs. Or it can place a diff from one workspace beside test output from another. A session interface organizes the messages. The application must keep them tied to the same work.
The repair's requirements stay the same in an editor. Lookup and store must use the same key, built from the locale the renderer uses. The regression must catch the old collision, and the checks must cover the delivered patch. ACP changes how the editor talks to the agent. It does not do those checks for you.
An SDK exposes the agent to your program
An SDK gives application code access to agent operations. Start the review with what your application needs: start a task, receive events, answer permission requests, interrupt work, resume state, and retrieve the result. A method that sends a prompt covers only part of that list. The agent loop still needs clear stop and cancellation rules.
Imagine a build service using an SDK to run the repair in an isolated workspace. The service decides which jobs start, supplies credentials, creates workspaces, and handles deadlines. The harness runs its loop and tools there. If the service restarts during a test, the application must find the old process and decide whether the resumed task can trust its result.
Keep a provider timeout, denied tool call, failed test, and application cancellation separate when reporting errors. The service needs those details to decide whether to retry. Repeating a read differs from repeating a partly completed write, especially if a tool can reach outside the workspace.
Check whether the SDK fits how the application starts, stops, and resumes work. The application must find unfinished work and tie results to a code revision. A subprocess interface may be enough if it offers the records and control the workload needs.
A meta-harness inherits every difference it wraps
A controller can choose among existing agent harnesses. This is the meta-harness from the table: it assigns work to those harnesses rather than implementing the editing loop itself. The paper's platform thesis makes this boundary interesting.
To compare two harnesses on our repair, start each from the same source snapshot and task in its own workspace. Record each run's model, configuration, budget, acceptance test, and denied or unavailable operations. Giving one harness a stronger tool or larger budget must be explicit.
The same API call can still do different things. One adapter may interrupt running work while another only stops future turns. One may let the controller answer a permission request while another applies local rules first. The controller should only promise behavior that every adapter supports.
When a harness cannot support an operation, its adapter should say so, or run that harness under stricter limits. Test what the controller depends on: cancellation, denied writes, final-state reporting, and result retrieval. A tidy common API can otherwise hide incompatible behavior.
For one cache repair, this layer would probably cost more to run than it saves. Consider it when the application already needs to send work to several harnesses, then measure whether the added coordination helps.
Pick the smallest interface the task needs
The six chapters followed one defect from the model's request to a tested change. As components are added, keep that work traceable. Installing every available component is unnecessary.
Before choosing an interface, I would answer these questions:
- Repeated procedure: What should travel between tasks, and which repository assumptions need rechecking? Use a skill when the procedure recurs.
- Execution trigger: Which event should start work automatically? Can the host enforce it on every relevant path? A hook needs exact timing and rules for what its handler can change.
- Distribution: Which parts should be installed and updated together? A plugin should make those parts easy to inspect.
- Remote tool: What data and credentials cross a process or service boundary? Define the tool's inputs and outputs for the MCP integration.
- Client or embedding: Who creates sessions, manages the workspace, and handles interruption? Match ACP or the SDK to those jobs.
- Multiple harnesses: Why must the application send work to different harnesses, and which adapter differences must stay visible? Specify the behaviors to test.
Then try a few failures. Change source after a test. Cancel an active process. Deny a write or return an unknown locale. Make the remote inspector report a different renderer version. Each should reveal whether the application knows what happened and who must act next.
The result we need stays small: a preview reuses only cache entries that match its rendering inputs, and a regression checks that behavior. Extending the harness should keep the work repeatable, reviewable, and controllable while someone else supplies part of the system.
Series index · Previous: More Agents, More State to Own
Updated
