Metadata-Version: 2.4
Name: uhp
Version: 0.1.0
Summary: The Unified Harness Protocol in one import: connect to a harness server, run agent tasks, stream them, and collect what they produce.
Author: HarnessRouter
License: Apache-2.0
Project-URL: Homepage, https://github.com/HarnessRouter/harnessrouter/tree/main/protocol
Project-URL: Source, https://github.com/HarnessRouter/harnessrouter
Project-URL: Issues, https://github.com/HarnessRouter/harnessrouter/issues
Keywords: uhp,unified-harness-protocol,agent,harness,ai-agents,sdk,client,streaming
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: harnessrouter>=0.1.0
Requires-Dist: harnessclientprotocol>=0.1.0
Requires-Dist: unifiedharnessprotocol>=0.1.0
Dynamic: license-file

# uhp

**The Unified Harness Protocol in one import.**

```
   your product ──▶ UHP ──▶ ┌── Codex
                            ├── Claude Code
                            ├── Hermes
                            └── the harness that ships next year
```

A *harness* is a complete agent runtime — a loop that plans, calls tools, edits files and reports
back. Each one already knows how to do the work; what none of them agree on is how a product should
*drive* one. UHP answers that once: how to start a task, follow its progress, continue the
conversation, cancel it, get the files it produced, and understand why it failed.

UHP is not a model API and does not replace one. A model API gives you a *turn*: messages in, tokens
out, tools you have to run yourself. UHP gives you a *task*: work in, and a running agent that uses
its own tools, keeps its own session, and hands back results and files.

```bash
pip install uhp
```

## Use it

```python
import os
from uhp import connect

client = connect("http://localhost:3000", os.environ["UHP_API_KEY"])

harness = client.harnesses()[0]
for event in client.stream("Summarise README.md", harness_id=harness["id"]):
    if event["type"] == "response.output_text.delta":
        print(event["delta"], end="", flush=True)
```

Ask a server what it is before handing it a credential — discovery is unauthenticated by design:

```python
from uhp import probe

probe("http://localhost:3000")
# {'protocol': 'uhp', 'versions': ['2026-08-11'], 'conformance_class': 'full', 'capabilities': {...}}
```

## What's in the box

This package is the front door. It re-exports three focused ones so a caller needs a single
dependency:

| Package | What it is |
|---|---|
| [`unifiedharnessprotocol`](https://pypi.org/project/unifiedharnessprotocol/) | The specification as data — versions, classes, statuses, events, error codes, endpoints |
| [`harnessclientprotocol`](https://pypi.org/project/harnessclientprotocol/) | SSE decoding, dropped-event detection, output assembly, idempotency, retry policy |
| [`harnessrouter`](https://pypi.org/project/harnessrouter/) | The HTTP client and CLI |

`connect()` returns that client; `UhpClient` is the same class under the protocol's name.

## CLI

```bash
export UHP_BASE_URL=http://localhost:3000
export UHP_API_KEY=…

uhp discover
uhp harnesses
uhp stream "Summarise README.md" --harness chrn_…
```

## It does not require anyone's cloud

UHP is an HTTP contract. A conformant server is any server that answers the requests in the
specification with the responses in the specification — in containers, in subprocesses, on a queue,
or on someone else's infrastructure. Nothing in the wire format requires a hosted service, an
account, a licence key, or a call home. A client written against the specification works with any
implementation that passes the conformance suite.

## Specification

<https://github.com/HarnessRouter/harnessrouter/tree/main/protocol>

Apache-2.0.
