Skip to main content

H3 Harness SDK for Python

Python SDK for building H3-compliant agent harnesses.

Install

pip install h3-harness-sdk

Install fallback (source / git)

If a release isn't published to PyPI yet (or you want the latest unreleased changes), install directly from the repository:

# From git
pip install git+https://github.com/get-h3/sdk-python.git

# Editable source install (development)
git clone https://github.com/get-h3/sdk-python.git
cd sdk-python
pip install -e .

Quickstart

from datetime import datetime, timezone

from h3_harness import (
    BaseHarness,
    Decision,
    DecisionType,
    End,
    TextResponse,
    create_router,
)
from fastapi import FastAPI


class MyHarness(BaseHarness):
    def __init__(self):
        # Track sessions so cancel/session lookups 404 on unknown ids
        # (battery: test_5_9b cancel_unknown_session, test_5_10 session_not_found).
        self._sessions: dict[str, dict] = {}

    async def on_process(self, req):
        # Echo conversation history from context (battery: history preserved).
        history = list(req.context.history)
        # Streaming: "do not finish" in message -> unfinished text.
        streaming = "do not finish" in req.message.content
        finished = not streaming
        self._sessions[req.session_id] = {
            "started_at": datetime.now(timezone.utc).isoformat(),
            "turn_count": (
                self._sessions.get(req.session_id, {}).get("turn_count", 0) + 1
            ),
        }
        return Decision(
            decision=DecisionType.TEXT,
            text=TextResponse(
                content=f"Echo: {req.message.content}",
                finished=finished,
            ),
            history=history,
        )

    async def on_result(self, req):
        return Decision(decision=DecisionType.END, end=End(reason="task_complete"))

    def get_session_info(self, session_id: str) -> dict | None:
        return self._sessions.get(session_id)


app = FastAPI()
app.include_router(create_router(MyHarness()))

Testbed

from h3_harness.testbed import MockHermes
from h3_harness.examples.echo import EchoHarness

mock = MockHermes(EchoHarness())
decision = await mock.send_message("Hello!")
assert decision.text.content == "Echo: Hello!"

Examples

  • echo.py — Echo harness that mirrors user messages
  • minimal.py — Minimal harness with health endpoint, uvicorn runner
  • langchain_agent.py — LangChain integration: LLM call with text response

Passing the battery (h3-test compliance)

The gate for any H3 harness is the test battery (test_battery.py from get-h3/shim — 43 tests across 6 categories). Run it against any running harness endpoint:

# The shim is not yet published to PyPI — install from source (get-h3/shim)
pip install git+https://github.com/get-h3/shim
h3-test --endpoint http://localhost:9191   # exit 0 = compliant

The Quickstart harness above implements all four conventions and is fully battery-compliant (44/44). If you modify it, keep the conventions intact — a naive harness that drops them scores 41/44. The four conventions the battery checks (beyond "return a Decision") are:

  1. Echo context.history in every Decision. The battery sends a session with prior history and asserts it flows back through the response (test_2_8_process_preserves_history). Pass it through explicitly:
    history = list(req.context.history)
    return Decision(..., history=history)
    
  2. Never issue llm_call when context.models is empty. The battery sends context.models: [] and FAILS any harness that returns an llm_call decision (test_5_8_no_models_available — "hallucinated model"). Only return LLM_CALL when the request actually lists models.
  3. Return text.finished=false for "do not finish" prompts. The battery sends "Just start a thought, do not finish it yet." and asserts the response has text.finished == False (test_2_4_process_text_finished_false). Detect streaming/unfinished intent and set finished accordingly.
  4. 404 unknown sessions. The battery cancels a nonexistent session (test_5_9b cancel_unknown_session) and GETs one (test_5_10 session_not_found) and asserts a 404. Track sessions in the harness (get_session_info returning None for unknown ids) — the router turns that into the 404.

The canonical battery-ready template is echo.py — it implements all four conventions and scores 44/44. Use it as the starting point for your own harness.

Development

make install   # create venv + install deps
make build     # build wheel (and sdist) into dist/
make test      # run tests
make lint      # ruff check
make fmt       # ruff format

Reference

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

h3_harness_sdk-0.1.2.tar.gz (144.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

h3_harness_sdk-0.1.2-py3-none-any.whl (15.6 kB view details)

Uploaded Python 3

File details

Details for the file h3_harness_sdk-0.1.2.tar.gz.

File metadata

  • Download URL: h3_harness_sdk-0.1.2.tar.gz
  • Upload date:
  • Size: 144.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.11.15

File hashes

Hashes for h3_harness_sdk-0.1.2.tar.gz
Algorithm Hash digest
SHA256 b04dacd65b0cc325b7438c8cbf7607a8aca3af74bb565a2a84abd2ee431555c6
MD5 58dd55b29650d810a45d524d3394b9bb
BLAKE2b-256 7f161e3335d2e2c411d610abf6ab9187c1602eee1a5b30dea521c46a94022446

See more details on using hashes here.

File details

Details for the file h3_harness_sdk-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: h3_harness_sdk-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 15.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.11.15

File hashes

Hashes for h3_harness_sdk-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 579e3460f314efc288eee06856aee83344886f7a495a93a1b0391cfb3067a385
MD5 997827d7931741242458801477764f11
BLAKE2b-256 41dca09f928929d790474c3b6234ec53332b6bc554b0e8effc2baee8e94e5671

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page