Unified Harness Protocol — specification 2026-10-19
An open standard for running complete agent harnesses as shared infrastructure.
This is the normative specification. For an introduction to what UHP is and why it exists, start at the protocol README.
Chapters
| # | Chapter | Defines |
|---|---|---|
| 1 | Architecture | Roles, conformance classes, object model, transport, authentication, design principles |
| 2 | Lifecycle | Version negotiation, capability discovery, task and session states, concurrency |
| 3 | Harnesses | Discovering, selecting, configuring and managing harnesses; models and availability |
| 4 | Plugins | Packages of tools and skills, in the Agent Plugins format, installed into a harness; composition; export |
| 5 | Environments | A project's files and installed dependencies, built once, read-only in every session that names it; builds, versions, attachment |
| 6 | Memories | Memory that outlasts a session: a tree of memories with access granted per node, records, recall, providers, and when a harness reaches them |
| 7 | Tasks | Running work, the response object, model substitution, idempotency |
| 8 | Streaming | The event vocabulary, ordering guarantees, reconnection |
| 9 | Sessions | Continuing, inspecting, cancelling, sharing, deleting |
| 10 | Files | File input, artifacts, download, retention and scope |
| 11 | Errors | The error envelope, codes, retry rules, timeouts |
| 12 | Security | Credentials, object scope, artifacts, injection, exhaustion, plugins, environments, memories, error hygiene |
| 13 | Schema | Machine-readable definitions and how to generate from them |
Endpoint summary
| Method | Path | Class | Chapter |
|---|---|---|---|
GET |
/v1/uhp |
Core | Lifecycle |
GET |
/v1/harnesses |
Core | Harnesses |
GET |
/v1/harnesses/{id} |
Core | Harnesses |
GET |
/v1/models |
Core | Harnesses |
GET |
/v1/harnesses/{id}/models |
Core | Harnesses |
POST |
/v1/responses |
Core | Tasks |
GET |
/v1/responses/{id} |
Core | Tasks |
GET |
/v1/responses/{id}/input_items |
Core | Tasks |
POST |
/v1/responses/{id}/cancel |
Core | Sessions |
DELETE |
/v1/responses/{id} |
Core | Tasks |
POST |
/v1/sessions/{id}/cancel |
Core | Sessions |
GET |
/v1/sessions |
Extended | Sessions |
GET |
/v1/sessions/{id} |
Extended | Sessions |
GET |
/v1/sessions/{id}/turns |
Extended | Sessions |
POST |
/v1/files |
Extended | Files |
GET |
/v1/sessions/{id}/files |
Extended | Files |
GET |
/v1/sessions/{id}/files/archive |
Extended | Files |
GET |
/v1/containers/{cid}/files/{fid}/content |
Extended | Files |
GET |
/v1/containers/{cid}/files/{fid}/pdf |
Extended | Files |
POST |
/v1/harnesses |
Full | Harnesses |
PUT |
/v1/harnesses/{id} |
Full | Harnesses |
DELETE |
/v1/harnesses/{id} |
Full | Harnesses |
GET |
/v1/harnesses/{id}/skills/{name}/files |
Full | Harnesses |
GET |
/v1/harnesses/{id}/plugins/{name}/files |
Full, plugins |
Plugins |
GET |
/v1/harnesses/{id}/plugin |
Full, plugins |
Plugins |
POST |
/v1/sessions/{id}/share |
Full | Sessions |
GET |
/v1/sessions/{id}/share |
Full | Sessions |
DELETE |
/v1/sessions/{id} |
Full | Sessions |
DELETE |
/v1/traces/{id} |
Full | Sessions (older path, same operation) |
GET |
/v1/environments |
Full, capability environments |
Environments |
POST |
/v1/environments |
Full, capability environments |
Environments |
GET PUT DELETE |
/v1/environments/{id} |
Full, capability environments |
Environments |
GET |
/v1/environments/{id}/files |
Full, capability environments |
Environments |
GET PUT DELETE |
/v1/environments/{id}/files/{path} |
Full, capability environments |
Environments |
POST |
/v1/environments/{id}/directories |
Full, capability environments |
Environments |
POST |
/v1/environments/{id}/import |
Full, capability environments |
Environments |
GET |
/v1/environments/runtimes |
Full, capability environments |
Environments |
POST |
/v1/environments/{id}/build |
Full, capability environments |
Environments |
GET |
/v1/environments/{id}/builds/{version} |
Full, capability environments |
Environments |
GET |
/v1/environments/{id}/versions |
Full, capability environments |
Environments |
POST |
/v1/environments/{id}/versions/{version}/activate |
Full, capability environments |
Environments |
GET |
/v1/environments/{id}/harnesses |
Full, capability environments |
Environments |
GET POST |
/v1/memories |
Full, capability memories |
Memories |
GET PUT DELETE |
/v1/memories/{id} |
Full, capability memories |
Memories |
GET POST |
/v1/memories/{id}/grants |
Full, capability memories |
Memories |
DELETE |
/v1/memories/{id}/grants/{grant_id} |
Full, capability memories |
Memories |
POST |
/v1/memories/{id}/observe |
Full, capability memories |
Memories |
GET |
/v1/memories/{id}/jobs/{job} |
Full, capability memories |
Memories |
GET POST |
/v1/memories/{id}/records |
Full, capability memories |
Memories |
GET PATCH DELETE |
/v1/memories/{id}/records/{rid} |
Full, capability memories |
Memories |
GET |
/v1/memories/{id}/records/{rid}/history |
Full, capability memories |
Memories |
GET |
/v1/memories/{id}/records/{rid}/content/{index} |
Full, capability memories |
Memories |
POST |
/v1/memories/{id}/records/{rid}/operations/{name} |
Full, capability memories |
Memories |
POST |
/v1/memories/{id}/recall |
Full, capability memories |
Memories |
POST |
/v1/memories/{id}/graph |
Full, capability memories |
Memories |
POST |
/v1/memories/{id}/erase |
Full, capability memories |
Memories |
GET |
/v1/memories/{id}/queries |
Full, capability memories |
Memories |
PUT POST |
/v1/memories/{id}/queries/{name} |
Full, capability memories |
Memories |
POST |
/v1/memories/{id}/query |
Full, capability memories |
Memories |
GET POST |
/v1/memories/{id}/snapshots |
Full, capability memories |
Memories |
GET POST |
/v1/memories/{id}/consolidations |
Full, capability memories |
Memories |
GET |
/v1/memories/{id}/consolidations/{run} |
Full, capability memories |
Memories |
GET |
/v1/memories/{id}/consolidations/{run}/changes |
Full, capability memories |
Memories |
POST |
/v1/memories/{id}/consolidations/{run}/revert |
Full, capability memories |
Memories |
GET |
/v1/memories/providers |
Full, capability memories |
Memories |
GET |
/v1/memories/types |
Full, capability memories |
Memories |
GET PUT |
/v1/harnesses/{id}/memories |
Full, capability memories |
Memories |
The plugins column entries are served only by a server whose discovery document reports the
plugins capability; the capability is optional at every class.
The memories entries are served only by a server that reports the memories capability, which is
optional at every class as well; within it, named and free queries, types, the media a record may carry, snapshots,
consolidation runs and erase are declared per provider (Memories §10.2).
What changed in this version
Against 2026-10-04, one rule changes and the rest is additive.
- Retiring a harness may retire its sessions with it, under a stated restore window
(Harnesses §5.3). A server that reports the new
harness_retirementcapability may remove a harness's sessions and responses with it once a restore window it stated when the harness was retired has passed; within the window a restore brings them back. It never retires a harness mid-task (harness_busy), and only a person's own erasure request removes their sessions sooner. A server that reports itfalse, or says nothing, keeps them, as every earlier version required. The delete response gainssessionsandrestorableUntil. This is the one change that is not additive: a client that relies on a retired harness's sessions staying readable checks the capability. - Harness writes refuse what they cannot store (Harnesses §5.1): a field
the harness does not have, and a
default_modelits base does not run, are422. Both maintained servers have done this since 2026-10-10, inside2026-10-04; this version states it.
The changelog has the details.
Conformance
A server is conformant at a class when it passes the conformance suite at that class. Nothing else is a conformance claim — not a self-assessment, not an implementation of the endpoints, not passing "most" tests.
pip install -e protocol/conformance
uhp-conformance --base-url https://your-server --api-key "$KEY" --class extended
The suite is part of this specification. If the suite and this prose disagree, that is a bug in one of them and MUST be resolved by changing whichever is wrong — never by leaving them inconsistent.
Conventions
- MUST / SHOULD / MAY are used as defined in RFC 2119 and RFC 8174.
- JSON examples are illustrative; the schema is authoritative for structure.
- Field names are
snake_caseon the task surface (inherited from the Responses-compatible shape) andcamelCaseon the harness object. This inconsistency is real, is called out here rather than hidden, and is retained because changing either would break existing clients for cosmetic gain. A future major version SHOULD unify them.