---
title: "Design principles"
description: "Twelve laws every conforming pack, runtime and host follows, the failure each one prevents, and what HCP/1.x leaves out on purpose."
canonical: https://harnesscontextprotocol.io/docs/introduction/design-principles
---

# Design principles

> Twelve laws every conforming pack, runtime and host follows, the failure each one prevents, and what HCP/1.x leaves out on purpose.

HCP is small on purpose: twelve laws, each mapped to a lint check or a runtime
behaviour and each there because the alternative was tried and broke. The
[non-goals](#non-goals) list what HCP/1.x leaves out, and only an RFC changes
either list.

## L1: The CLI is the harness

A capability enters HCP as a CLI, or as an in-process SDK that projects to one,
and every command has a CLI face with structured output (`--json`, or JSON by
default). That is the interface people and CI already script, so agents share
it. MCP is an optional export from a pack and never the install path.

## L2: The twin face is identity

`transit plan A B --json` and `{ "pack_id": "transit", "verb_key": "plan", … }`
are the same command under the same Policy, Binding and Adapter, and `verb_key`
is the command name with no second ontology behind it. No Invoker gets a code
path of its own, which is where separate auth and audit would grow.

## L3: Named commands, 5 to 12, never a PATH wrap

A pack declares a closed set of commands, never a whole binary behind an
`allowedSubcommands` allow-list or a catch-all `run` or `exec -- <argv>`,
because Policy and Skill can only be written for things with names. A
pass-through wrap is a bootstrap step, and the pack conforms only once it is
promoted to named commands.

## L4: Binding mints; packs never hold secrets

A pack names a Binding mode (`public`, `user`, `local`, `mothership`, `mock`)
and the runtime's hub mints the credential. Exec fails closed when the mint
fails, with no silent fallback to environment tokens, and mock mode is explicit
in the envelope, never an environment flag. A mode is portable, while a secret
in a manifest, Skill or host config leaks, drifts and escapes audit.

## L5: Three lands; entity arguments are not tenants

`privacy.land` is `personal` (private to the actor), `brain` (a shared project)
or `local` (a workspace directory). Tenant and project come from the
authenticated Principal's session, so an argument such as `--entity` picks an
account inside the Binding's scope but never the tenant, and one user cannot
reach another user's data through a pack argument.

## L6: Writes are gated

A write that must not fire from a hallucinated turn declares `confirm: true`,
passed as `--confirm` or `--apply` on the CLI face and `confirm: true` on the
JSON face, and the runtime checks it before any Adapter runs, whoever invokes.
A dry run is still `operation: write` and must not persist. Health commands
(`doctor`, `status`) report and never mint, and exit `0` for ok, `2` for warn
and `1` for fail.

## L7: Execute and Sense are two loops on one pack

Inbound commands and outbound triggers share Policy, Binding and Principal but
never merge into one tool, because an event that could execute could also spend
money. A trigger cannot run a command, and an Invoker that reacts to one still
goes through Execute.

## L8: Sense must not mint, and polling is not Sense

A trigger cannot mint credentials or bypass Binding. Calling `status` or
`follow` repeatedly is Execute, and uptime monitors, UI refresh timers and
control-plane ticks are not pack triggers, otherwise every pack would claim to
sense by burning tokens in a loop.

## L9: Control and runtime are two packs

Admin, fleet and operator CLIs run in a second pack with `plane: control` and
Binding `mothership`, never silently available to an end-user Principal. That
closes the classic privilege-escalation bug in agent tooling, an end-user agent
inheriting operator credentials because a binary happened to be on `PATH`.

## L10: The Skill is one screen; Policy covers everything

`HARNESS.md` teaches the declared commands on one screen (a lead, a hot-path
table, copy-paste examples, anti-patterns, pointers), because a Skill that grows
into a manual stops being read. Every command and every trigger has a Policy
row or lint fails, since a runtime cannot reason about a command without one.

## L11: Invokers never redefine Policy or Binding

Agents, APIs, UIs and people run the same command, each carrying a Principal
whose grants the runtime evaluates, and none adds its own auth or policy for
it, because when one command has two policies the weaker one decides.

## L12: One living repo per pack; proof is a script

A pack id maps to one maintained repository, and the pack proves conformance
with a script CI can run: lint, one read, one gated write in mock or paper mode,
one live deny without confirm and, if it declares Sense, one announce with the
grant on and one deny with it off. A claim in Markdown does not count, because a
pack that cannot prove itself drifts away from its Skill.

## How the laws become checks

| Law | Enforced by |
|-----|-------------|
| L3 | Lint: `wrap requires named commands or pass_through` |
| L4 | Runtime: fail-closed mint; the sandbox denies env-flag mocks |
| L5 | Runtime: `brain` requires `project_id`; the Policy schema rejects unknown lands |
| L6 | Runtime: `confirm required` before the Adapter |
| L9 | Lint: `control plane packs default Binding mothership` |
| L10 | Lint: `missing HARNESS.md`, `verb … missing from policy.json`, `stimulus … missing from policy.json` |
| L12 | [Testing](/docs/packs/check#testing) and [Conformance](/docs/specification/conformance) |

## Non-goals

HCP/1.x leaves these out on purpose.

| HCP does not | Why |
|--------------|-----|
| Make MCP the install unit | MCP is a transport HCP can export to, and a transport carries no Policy, Binding, Sense or Skill |
| Define a verb ontology | Ontologies rot, so packs name commands after the CLI they wrap, and `read`/`write` is the only class a runtime needs |
| Put tenant, user or role identifiers in packs | A pack is shared across tenants, so anything tenant-specific in it is a leak or a lie; tenant comes from the session and grants from the runtime |
| Carry credentials | Packs are copied, published and read by agents, so they hold no tokens, key files or `.env` files ([L4](#l4-binding-mints-packs-never-hold-secrets)) |
| Mandate a network client/server split | A runtime may be in-process, a CLI or a hosted service, and the smallest useful one is a function call |
| Require UI or A2UI | Agents and CLIs invoke most capabilities first, so `transports` and host rendering stay optional |
| Wrap `PATH` | The sandbox does not resolve bare names on the host `PATH`, or an agent could run a binary nobody allow-listed |
| Merge teaching packs with capability packs | A Skill that only teaches is an Agent Skill, and Policy needs commands to govern |
| Bake product schemas into core types | Ledger, CRM and database record types belong to the packs that wrap those products |
| Name vendors in the specification | An open standard names roles, so hosts and runtimes appear as examples only in the Hosts section |
| Define a signed registry or pack versions (yet) | Packs are directories identified by `pack_id` while the pack model and the two loops come first. Signed fetch by `pack_id@version` is on the [roadmap](/docs/community/roadmap) for HCP/2.0, and the [community catalog](/docs/packs/share#catalog) indexes directories and CLI scaffolds without being a registry |
| Poll on behalf of packs | Sense is push, and polling for a pack would turn every read into a silent background write to the runtime's own store |

A pack author who needs one of these is probably building a runtime feature
([Build runtimes](/docs/runtimes)). A runtime builder may add any of them inside
the runtime but may not require packs to change for it, and moving the boundary
takes an [RFC](/docs/community/governance#rfc-process) that names the item and
the cost of keeping it out.

## Sitemap

- [Documentation](https://harnesscontextprotocol.io/docs)
- [Packs](https://harnesscontextprotocol.io/packs)
- [Glossary](https://harnesscontextprotocol.io/docs/reference/glossary)
- [llms.txt](https://harnesscontextprotocol.io/llms.txt)
- [llms-full.txt](https://harnesscontextprotocol.io/llms-full.txt)
- [OpenAPI](https://harnesscontextprotocol.io/openapi.json)
- [MCP](https://harnesscontextprotocol.io/mcp)
