What is HCP?
The open standard for installing a capability into any agent harness as a portable pack, and the integration problems it removes.
Harness Context Protocol (HCP) is an open standard for installing a capability into an agent harness, meaning whatever drives an agent: a coding assistant, a chat product, an automation runner or a TypeScript tool loop. Teaching and transport already had open standards while install was left to each product, so HCP gives install one portable unit, the Harness Pack, and a short list of rules for the runtime. The Quickstart gets you running.
Why HCP exists#
An agent stack has three jobs, and most integration pain comes from the one that had no standard.
| Job | What it needs | Standard |
|---|---|---|
| Teach the agent how to use a capability | Progressive disclosure, examples, anti-patterns | Agent Skills |
| Connect the model to tools over a wire | Client and server transport, a tool catalog, sessions | MCP |
| Install a capability into the harness | Identity, authorisation, credential binding, policy, a sandbox, and an outbound loop | HCP |
Without an install layer, each harness adds a capability (planning a route, reading a mailbox, sending a bank transfer) its own way: a config file, an MCP server or setup steps pasted into an instructions file. Teams with more than a handful of domain CLIs in front of agents then hit the same problems, which better prompts or a faster transport cannot fix.
| Without an install layer | With HCP |
|---|---|
| Every product invents a private connector schema, so one CLI is described three ways for three hosts | One folder that any conforming runtime activates |
| OAuth tokens and API keys sit in environment variables and Skill files, because nothing defines where a credential lives | The pack names a Binding mode and the runtime mints |
| A UI button and an agent's bash call are different APIs for one operation, with different auth and audit | Every caller, a UI included, runs one command under one Policy and one Binding |
A CLI that already prints --json gets an MCP server wrapped around it, one more process and schema to keep in sync | The CLI is the harness and MCP an optional export |
Each new host copies a 40-line setup table into AGENTS.md, and the copies drift | hcpx adopt cursor or hcpx adopt opencode writes one Skill and one bash tool, hcp, for every activated pack, so a pack added later adds no tools to the host |
| A write fires from a hallucinated turn because nothing forces a confirmation | A transfer without an explicit confirm is refused before any adapter runs, whoever asked |
| Changing transport or UI means rewriting the capability, because its identity is tied to the transport | Identity is the pack_id and command names, so packs survive a change of MCP or UI message format |
Wrapping a domain CLI this way takes an afternoon: describe the commands you already ship and add a Policy row for each, and the same binary reaches a terminal, an agent and a product UI. Landscape shows how HCP composes with Agent Skills, MCP, Agent Plugins, A2UI and A2A.
The Harness Pack#
A pack is a directory of three files, and that is all an author writes.
| File | Role | What you write |
|---|---|---|
surface.json | Manifest | Pack id, adapter kind, Binding mode, and 5 to 12 named commands |
policy.json | Policy | One row per command and per trigger: read or write, which land it touches, and whether it needs confirmation |
HARNESS.md | Skill | One screen that teaches the hot path and the anti-patterns |
A pack holds no secrets, allow-lists, tenant ids or server code. It describes an
existing CLI or API and what it may do, so an agent learns the pack without a
hand-built tool catalog, and a public pack with find, plan, show, status
and follow needs no login. Policy stays at two axes and a confirm flag,
because scale lives in the runtime's grants.
{
"id": "transit",
"kind": "wrap",
"cliBin": "transit",
"binding": { "mode": "public" },
"verbs": {
"plan": {
"description": "Time-first options between two places.",
"cli": ["transit", "plan", "{{from}}", "{{to}}"]
}
}
}Two loops on one pack#
Execute is inbound. Someone runs one of the pack's named commands in a CLI form
(transit plan A B --json) or a JSON form
({ "pack_id": "transit", "verb_key": "plan", "args": {…} }), and both are the
same command under the same Policy.
Sense is outbound and kept apart from Execute. A pack may announce a change in
the world by raising a trigger such as new_item or binding.degraded,
declared in the same Policy file and delivered to a runtime sink only under its
own grant. A trigger can never mint credentials or spend money, and an Invoker
that acts on one still goes through Execute and its gates.
Concepts covers both loops and the objects they share.
What a runtime does with a pack#
When a runtime installs a pack, it:
- Finds the three files and validates them (lint).
- Resolves the Binding the pack asks for and mints the credential.
- Runs named commands through either face, under one Policy and one set of capability grants.
- Receives Sense if the pack declares triggers, under a separate grant that can neither mint nor act.
- Reports availability as four flags (
installed,activated,connected,executable), with a reason for every denial, so an agent knows what it may run before it plans.
The protocol stops there. Catalog storage, the credential hub, RBAC tables, inbox UI and trigger delivery belong to the runtime, which may keep them private, and Design principles gives the reasoning behind each rule.
Status#
HCP/1.1 is a draft that includes the accepted wrap-hardening and exec-plane RFCs. The reference TypeScript SDK, runtime and CLI implement it plus the draft RFCs on the Roadmap, as a private preview on GitHub Packages whose versions Implementations lists. The Specification section is generated from the normative text in the protocol repository, and Versioning explains how versions move.