h3-harness-sdk 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. h3_harness_sdk-0.1.1/.gitignore +33 -0
  2. h3_harness_sdk-0.1.1/AGENTS.md +83 -0
  3. h3_harness_sdk-0.1.1/CHANGELOG.md +17 -0
  4. h3_harness_sdk-0.1.1/CODEOWNERS +3 -0
  5. h3_harness_sdk-0.1.1/CODE_OF_CONDUCT.md +33 -0
  6. h3_harness_sdk-0.1.1/CONTRIBUTING.md +136 -0
  7. h3_harness_sdk-0.1.1/GOVERNANCE.md +31 -0
  8. h3_harness_sdk-0.1.1/LICENSE +21 -0
  9. h3_harness_sdk-0.1.1/Makefile +39 -0
  10. h3_harness_sdk-0.1.1/PKG-INFO +160 -0
  11. h3_harness_sdk-0.1.1/README.md +132 -0
  12. h3_harness_sdk-0.1.1/SECURITY.md +13 -0
  13. h3_harness_sdk-0.1.1/SUPPORT.md +20 -0
  14. h3_harness_sdk-0.1.1/docs/api/examples.md +56 -0
  15. h3_harness_sdk-0.1.1/docs/api/harness.md +150 -0
  16. h3_harness_sdk-0.1.1/docs/api/index.md +92 -0
  17. h3_harness_sdk-0.1.1/docs/api/middleware.md +63 -0
  18. h3_harness_sdk-0.1.1/docs/api/protocol.md +425 -0
  19. h3_harness_sdk-0.1.1/docs/api/testbed.md +89 -0
  20. h3_harness_sdk-0.1.1/docs/audit-2026-08.md +33 -0
  21. h3_harness_sdk-0.1.1/docs/dogfood/2026-08-03-integration.md +190 -0
  22. h3_harness_sdk-0.1.1/docs/dogfood/diagnostics.md +108 -0
  23. h3_harness_sdk-0.1.1/pyproject.toml +70 -0
  24. h3_harness_sdk-0.1.1/scripts/generate-protocol.py +342 -0
  25. h3_harness_sdk-0.1.1/scripts/serve_echo.py +24 -0
  26. h3_harness_sdk-0.1.1/src/h3_harness/__init__.py +56 -0
  27. h3_harness_sdk-0.1.1/src/h3_harness/examples/__init__.py +2 -0
  28. h3_harness_sdk-0.1.1/src/h3_harness/examples/echo.py +90 -0
  29. h3_harness_sdk-0.1.1/src/h3_harness/examples/langchain_agent.py +101 -0
  30. h3_harness_sdk-0.1.1/src/h3_harness/examples/minimal.py +45 -0
  31. h3_harness_sdk-0.1.1/src/h3_harness/harness.py +227 -0
  32. h3_harness_sdk-0.1.1/src/h3_harness/middleware.py +71 -0
  33. h3_harness_sdk-0.1.1/src/h3_harness/protocol.py +308 -0
  34. h3_harness_sdk-0.1.1/src/h3_harness/testbed.py +115 -0
  35. h3_harness_sdk-0.1.1/tests/__init__.py +1 -0
  36. h3_harness_sdk-0.1.1/tests/test_benchmarks.py +260 -0
  37. h3_harness_sdk-0.1.1/tests/test_example_langchain.py +61 -0
  38. h3_harness_sdk-0.1.1/tests/test_harness.py +308 -0
  39. h3_harness_sdk-0.1.1/tests/test_middleware.py +190 -0
  40. h3_harness_sdk-0.1.1/tests/test_protocol.py +256 -0
  41. h3_harness_sdk-0.1.1/tests/test_quickstart.py +144 -0
  42. h3_harness_sdk-0.1.1/tests/test_schema_validation.py +496 -0
  43. h3_harness_sdk-0.1.1/tests/test_testbed.py +205 -0
  44. h3_harness_sdk-0.1.1/uv.lock +1369 -0
@@ -0,0 +1,33 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.pyc
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .pytest_cache/
8
+ .ruff_cache/
9
+
10
+ # Hilo — local cache files (rebuildable)
11
+ .vfs/graph/graph.db
12
+ .vfs/graph/graph.db.wal
13
+ .vfs/graph/.last_warm
14
+ .gitreins/tasks.yaml
15
+ .coverage
16
+
17
+ # Temp audit / inspection scripts (generated by foreman ticks)
18
+ # Anchored to repo root: an unanchored `_*.py` also matched package
19
+ # __init__.py files, which hatchling's gitignore-based wheel file selection
20
+ # then excluded from built wheels (empty namespace package on install).
21
+ /_*.py
22
+ # GitReins verdict history (local)
23
+ .gitreins/history/
24
+
25
+ # pytest-benchmark cache (regenerated on every run)
26
+ .benchmarks/
27
+
28
+ # DuckDB board local cache (rebuildable from Parquet)
29
+ .coding-hermes/board/board.db
30
+ .coding-hermes/board/board.db.wal
31
+ .coding-hermes/board/*.parquet
32
+
33
+ .coding-hermes/board/*.duckdb
@@ -0,0 +1,83 @@
1
+ # AGENTS.md — H3 SDK for Python
2
+
3
+ Python SDK for building H3-compliant agent harnesses.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install h3-harness-sdk
9
+ ```
10
+
11
+ ### Install fallback (source / git)
12
+
13
+ If a release isn't published to PyPI yet (or you want the latest unreleased
14
+ changes), install directly from the repository:
15
+
16
+ ```bash
17
+ # From git
18
+ pip install git+https://github.com/get-h3/sdk-python.git
19
+
20
+ # Editable source install (development)
21
+ git clone https://github.com/get-h3/sdk-python.git
22
+ cd sdk-python
23
+ pip install -e .
24
+ ```
25
+
26
+ ## Quickstart
27
+
28
+ ```python
29
+ from h3_harness import (
30
+ BaseHarness,
31
+ Decision,
32
+ DecisionType,
33
+ End,
34
+ TextResponse,
35
+ create_router,
36
+ )
37
+ from fastapi import FastAPI
38
+
39
+
40
+ class MyHarness(BaseHarness):
41
+ async def on_process(self, req):
42
+ # Echo conversation history from context (battery: history preserved).
43
+ history = list(req.context.history)
44
+ # Streaming: "do not finish" in message -> unfinished text.
45
+ streaming = "do not finish" in req.message.content
46
+ finished = not streaming
47
+ return Decision(
48
+ decision=DecisionType.TEXT,
49
+ text=TextResponse(
50
+ content=f"Echo: {req.message.content}",
51
+ finished=finished,
52
+ ),
53
+ history=history,
54
+ )
55
+
56
+ async def on_result(self, req):
57
+ return Decision(decision=DecisionType.END, end=End(reason="task_complete"))
58
+
59
+
60
+ app = FastAPI()
61
+ app.include_router(create_router(MyHarness()))
62
+ ```
63
+
64
+ ## Package Structure
65
+
66
+ - `protocol.py` — Pydantic models (generated from get-h3/protocol JSON Schema)
67
+ - `harness.py` — BaseHarness ABC + FastAPI router
68
+ - `middleware.py` — Request logging middleware via BaseHTTPMiddleware
69
+ - `testbed.py` — MockHermes for pytest
70
+
71
+ ## Development
72
+
73
+ - GitReins quality gate mandatory
74
+ - Must pass `h3-test` from get-h3/shim before release
75
+ - To score 43/43 on the battery: echo `context.history` in every Decision,
76
+ never issue `llm_call` when `context.models` is empty, and return
77
+ `text.finished=false` for "do not finish" prompts. See README → *Passing the
78
+ battery (h3-test compliance)*. `src/h3_harness/examples/echo.py` is the
79
+ battery-ready template.
80
+
81
+ ## Reference
82
+
83
+ Spec: `get-h3/h3` → `specs/04-SDK-Libraries.md`
@@ -0,0 +1,17 @@
1
+ # Changelog
2
+
3
+ All notable changes to the H3 Python SDK.
4
+
5
+ ## [1.0.0] — 2026-07-19
6
+
7
+ ### Added
8
+ - `protocol.py`: Pydantic models generated from H3 JSON Schema
9
+ - `harness.py`: BaseHarness ABC + FastAPI router
10
+ - `middleware.py`: Request logging middleware
11
+ - `testbed.py`: MockHermes for pytest
12
+ - Echo example harness (examples/echo/)
13
+ - Structured access logging
14
+ - Pydantic defaults for optional fields (max_iterations, session_state)
15
+ - response_model_exclude_none=True for wire-compatible JSON
16
+ - GitReins quality gate
17
+ - Hilo code graph
@@ -0,0 +1,3 @@
1
+ # H3 SDK Python — Code Owners
2
+
3
+ * @banesullivan
@@ -0,0 +1,33 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
6
+
7
+ We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
8
+
9
+ ## Our Standards
10
+
11
+ Examples of behavior that contributes to a positive environment:
12
+
13
+ - Demonstrating empathy and kindness toward other people
14
+ - Being respectful of differing opinions, viewpoints, and experiences
15
+ - Giving and gracefully accepting constructive feedback
16
+ - Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
17
+ - Focusing on what is best not just for us as individuals, but for the overall community
18
+
19
+ Examples of unacceptable behavior:
20
+
21
+ - The use of sexualized language or imagery, and sexual attention or advances of any kind
22
+ - Trolling, insulting or derogatory comments, and personal or political attacks
23
+ - Public or private harassment
24
+ - Publishing others' private information without explicit permission
25
+ - Other conduct which could reasonably be considered inappropriate in a professional setting
26
+
27
+ ## Enforcement
28
+
29
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at the GitHub organization [get-h3](https://github.com/get-h3). All complaints will be reviewed and investigated promptly and fairly.
30
+
31
+ ## Attribution
32
+
33
+ This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 2.1.
@@ -0,0 +1,136 @@
1
+ # Contributing to H3 SDK for Python
2
+
3
+ Python SDK for building H3-compliant agent harnesses. Implements the harness side of the H3 protocol using Pydantic + FastAPI.
4
+
5
+ ## Development Setup
6
+
7
+ ```bash
8
+ cd sdk-python/
9
+ python -m venv .venv
10
+ source .venv/bin/activate
11
+ uv pip install -e ".[dev]"
12
+ ```
13
+
14
+ ## Package Structure
15
+
16
+ ```
17
+ sdk-python/
18
+ ├── src/h3_harness/
19
+ │ ├── protocol.py # Pydantic models (generated from protocol repo JSON Schema)
20
+ │ ├── harness.py # BaseHarness ABC + FastAPI router
21
+ │ ├── middleware.py # Request logging middleware
22
+ │ └── testbed.py # MockHermes for pytest
23
+ ├── tests/
24
+ │ ├── test_protocol.py
25
+ │ ├── test_harness.py
26
+ │ └── test_testbed.py
27
+ └── examples/
28
+ ├── echo/ # Echo harness (returns messages back)
29
+ ├── minimal/ # Bare-minimum example
30
+ └── langchain/ # LangChain integration demo
31
+ ```
32
+
33
+ ## Before Making Changes
34
+
35
+ ### Run Tests
36
+
37
+ ```bash
38
+ python -m pytest tests/ -v
39
+ # 34 tests
40
+ ```
41
+
42
+ ### Run Lint + Type Check
43
+
44
+ ```bash
45
+ ruff check src/ tests/
46
+ mypy src/
47
+ ```
48
+
49
+ ### Run the Test Battery
50
+
51
+ ```bash
52
+ # Start the echo example in one terminal:
53
+ python examples/echo/main.py
54
+
55
+ # In another terminal, run the compliance test battery:
56
+ h3-test --endpoint http://localhost:9191
57
+ # 43 compliance tests, exit code 0 = compliant
58
+ ```
59
+
60
+ ### Sync Protocol Types
61
+
62
+ If the upstream protocol changed:
63
+
64
+ ```bash
65
+ python scripts/sync_protocol.py
66
+ ```
67
+
68
+ This regenerates `src/h3_harness/protocol.py` from `get-h3/protocol` schemas. Never hand-edit generated Pydantic models.
69
+
70
+ ## Making Changes
71
+
72
+ ### BaseHarness Interface
73
+
74
+ - `harness.py` defines the `BaseHarness` ABC with `on_process` and `on_result`
75
+ - Changes to the ABC are MAJOR — they break all existing harnesses
76
+ - New optional hooks should use separate mixins
77
+
78
+ ### FastAPI Router
79
+
80
+ - `create_router()` builds a FastAPI APIRouter with `/v1/health`, `/v1/process`, `/v1/result`
81
+ - Must follow the H3 protocol exactly — see `get-h3/protocol/h3-protocol.yaml`
82
+ - All endpoints log METHOD /path STATUS DURATION via middleware
83
+
84
+ ### Middleware
85
+
86
+ - `middleware.py` uses FastAPI's `BaseHTTPMiddleware`
87
+ - Logs structured request info without leaking credentials
88
+
89
+ ### Pydantic Models
90
+
91
+ - Models use `Optional` types for protocol-optional fields
92
+ - Validation must match JSON Schema constraints from `get-h3/protocol/schemas/v1/`
93
+ - `model_dump(exclude_none=True)` for wire format compatibility
94
+
95
+ ## Quality Gates
96
+
97
+ ### Pre-Commit
98
+
99
+ ```bash
100
+ ruff check src/ tests/ # Lint
101
+ ruff format --check src/ tests/ # Format
102
+ mypy src/ # Type check
103
+ python -m pytest tests/ -v # Tests (34)
104
+ ```
105
+
106
+ ### CI Pipeline
107
+
108
+ GitHub Actions runs on every PR:
109
+ 1. Lint (ruff)
110
+ 2. Type check (mypy)
111
+ 3. Tests (pytest, 34 tests)
112
+ 4. `h3-test --endpoint http://localhost:9191` (against echo example)
113
+
114
+ All must pass.
115
+
116
+ ## Release
117
+
118
+ ```bash
119
+ git tag v1.0.0
120
+ git push origin v1.0.0
121
+ # CI publishes to PyPI automatically
122
+ ```
123
+
124
+ ## Review Checklist
125
+
126
+ - [ ] `pytest tests/ -v` passes (34 tests)
127
+ - [ ] `ruff check` passes
128
+ - [ ] `mypy src/` passes
129
+ - [ ] `h3-test --endpoint http://localhost:9191` passes against echo example
130
+ - [ ] New Pydantic fields use `Optional` where appropriate
131
+ - [ ] Protocol changes regenerated via `sync_protocol.py`
132
+ - [ ] No hand-edits to generated types
133
+
134
+ ## Questions?
135
+
136
+ See the umbrella project at [get-h3/h3](https://github.com/get-h3/h3) for architecture, specs, and the cross-repo task board.
@@ -0,0 +1,31 @@
1
+ # Governance
2
+
3
+ This document describes the governance model for the H3 Python SDK project.
4
+
5
+ ## Roles
6
+
7
+ - **Maintainers**: Responsible for reviewing and merging contributions, managing releases, and enforcing the code of conduct.
8
+ - **Contributors**: Anyone who submits patches, documentation, or bug reports.
9
+
10
+ ## Decision Making
11
+
12
+ Decisions are made through consensus among maintainers. For significant changes (new features, API changes, breaking changes), a design discussion should precede implementation.
13
+
14
+ ## Pull Request Process
15
+
16
+ 1. Open an issue describing the change before submitting a PR (for non-trivial changes).
17
+ 2. All PRs must pass CI (tests + lint).
18
+ 3. At least one maintainer must approve before merge.
19
+ 4. The PR author is responsible for merging after approval.
20
+
21
+ ## Release Process
22
+
23
+ Releases follow [Semantic Versioning](https://semver.org/). Maintainers publish releases to PyPI.
24
+
25
+ ## Code of Conduct
26
+
27
+ See [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md).
28
+
29
+ ## License
30
+
31
+ This project is licensed under the terms in [LICENSE](LICENSE).
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 H3 Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,39 @@
1
+ .PHONY: install build test lint fmt clean generate
2
+
3
+ VENV := .venv
4
+ PYTHON := $(VENV)/bin/python
5
+
6
+ $(VENV):
7
+ python3 -m venv $(VENV)
8
+ $(PYTHON) -m pip install --upgrade pip
9
+ $(PYTHON) -m pip install -e ".[dev]"
10
+
11
+ install: $(VENV)
12
+
13
+ build:
14
+ uv build
15
+ @echo "build: OK — dist/ now contains the wheel (and sdist)"
16
+
17
+ test:
18
+ uv run pytest -x --tb=short -q
19
+
20
+ test-full:
21
+ uv run pytest -x -v
22
+
23
+ lint:
24
+ uv run ruff check src/ tests/
25
+
26
+ fmt:
27
+ uv run ruff format src/ tests/
28
+
29
+ clean:
30
+ rm -rf $(VENV) __pycache__ src/h3_harness/__pycache__
31
+ find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
32
+ find . -type d -name "*.egg-info" -exec rm -rf {} + 2>/dev/null || true
33
+
34
+ all: install lint build test
35
+
36
+ generate:
37
+ uv run python scripts/generate-protocol.py
38
+ uv run ruff check --fix src/h3_harness/protocol.py
39
+ uv run ruff format src/h3_harness/protocol.py
@@ -0,0 +1,160 @@
1
+ Metadata-Version: 2.4
2
+ Name: h3-harness-sdk
3
+ Version: 0.1.1
4
+ Summary: Python SDK for building H3-compliant agent harnesses
5
+ Author: Total Windup Flight Systems
6
+ License: MIT
7
+ License-File: LICENSE
8
+ Keywords: agent,h3,harness,hermes
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Requires-Python: >=3.10
17
+ Requires-Dist: fastapi>=0.109.0
18
+ Requires-Dist: pydantic>=2.0
19
+ Requires-Dist: uvicorn[standard]>=0.25.0
20
+ Provides-Extra: dev
21
+ Requires-Dist: httpx>=0.26; extra == 'dev'
22
+ Requires-Dist: jsonschema>=4.20; extra == 'dev'
23
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
24
+ Requires-Dist: pytest-benchmark>=5.2.3; extra == 'dev'
25
+ Requires-Dist: pytest>=8.0; extra == 'dev'
26
+ Requires-Dist: ruff>=0.1; extra == 'dev'
27
+ Description-Content-Type: text/markdown
28
+
29
+ # H3 Harness SDK for Python
30
+
31
+ Python SDK for building H3-compliant agent harnesses.
32
+
33
+ ## Install
34
+
35
+ ```bash
36
+ pip install h3-harness-sdk
37
+ ```
38
+
39
+ ### Install fallback (source / git)
40
+
41
+ If a release isn't published to PyPI yet (or you want the latest unreleased
42
+ changes), install directly from the repository:
43
+
44
+ ```bash
45
+ # From git
46
+ pip install git+https://github.com/get-h3/sdk-python.git
47
+
48
+ # Editable source install (development)
49
+ git clone https://github.com/get-h3/sdk-python.git
50
+ cd sdk-python
51
+ pip install -e .
52
+ ```
53
+
54
+ ## Quickstart
55
+
56
+ ```python
57
+ from h3_harness import (
58
+ BaseHarness,
59
+ Decision,
60
+ DecisionType,
61
+ End,
62
+ TextResponse,
63
+ create_router,
64
+ )
65
+ from fastapi import FastAPI
66
+
67
+
68
+ class MyHarness(BaseHarness):
69
+ async def on_process(self, req):
70
+ # Echo conversation history from context (battery: history preserved).
71
+ history = list(req.context.history)
72
+ # Streaming: "do not finish" in message -> unfinished text.
73
+ streaming = "do not finish" in req.message.content
74
+ finished = not streaming
75
+ return Decision(
76
+ decision=DecisionType.TEXT,
77
+ text=TextResponse(
78
+ content=f"Echo: {req.message.content}",
79
+ finished=finished,
80
+ ),
81
+ history=history,
82
+ )
83
+
84
+ async def on_result(self, req):
85
+ return Decision(decision=DecisionType.END, end=End(reason="task_complete"))
86
+
87
+
88
+ app = FastAPI()
89
+ app.include_router(create_router(MyHarness()))
90
+ ```
91
+
92
+ ## Testbed
93
+
94
+ ```python
95
+ from h3_harness.testbed import MockHermes
96
+ from h3_harness.examples.echo import EchoHarness
97
+
98
+ mock = MockHermes(EchoHarness())
99
+ decision = await mock.send_message("Hello!")
100
+ assert decision.text.content == "Echo: Hello!"
101
+ ```
102
+
103
+ ## Examples
104
+
105
+ - **[echo.py](src/h3_harness/examples/echo.py)** — Echo harness that mirrors user messages
106
+ - **[minimal.py](src/h3_harness/examples/minimal.py)** — Minimal harness with health endpoint, uvicorn runner
107
+ - **[langchain_agent.py](src/h3_harness/examples/langchain_agent.py)** — LangChain integration: LLM call with text response
108
+
109
+ ## Passing the battery (h3-test compliance)
110
+
111
+ The gate for any H3 harness is the **test battery** (`test_battery.py` from
112
+ [get-h3/shim](https://github.com/get-h3/shim) — 43 tests across 6 categories).
113
+ Run it against any running harness endpoint:
114
+
115
+ ```bash
116
+ # The shim is not yet published to PyPI — install from source (get-h3/shim)
117
+ pip install git+https://github.com/get-h3/shim
118
+ h3-test --endpoint http://localhost:9191 # exit 0 = compliant
119
+ ```
120
+
121
+ The Quickstart harness above implements all three conventions and is fully
122
+ battery-compliant (**43/43**). If you modify it, keep the conventions intact —
123
+ a naive harness that drops them scores **41/43**. The three conventions the
124
+ battery checks (beyond "return a Decision") are:
125
+
126
+ 1. **Echo `context.history` in every Decision.** The battery sends a session
127
+ with prior history and asserts it flows back through the response
128
+ (`test_2_8_process_preserves_history`). Pass it through explicitly:
129
+ ```python
130
+ history = list(req.context.history)
131
+ return Decision(..., history=history)
132
+ ```
133
+ 2. **Never issue `llm_call` when `context.models` is empty.** The battery
134
+ sends `context.models: []` and FAILS any harness that returns an `llm_call`
135
+ decision (`test_5_8_no_models_available` — "hallucinated model"). Only
136
+ return `LLM_CALL` when the request actually lists models.
137
+ 3. **Return `text.finished=false` for "do not finish" prompts.** The battery
138
+ sends *"Just start a thought, do not finish it yet."* and asserts the
139
+ response has `text.finished == False` (`test_2_4_process_text_finished_false`).
140
+ Detect streaming/unfinished intent and set `finished` accordingly.
141
+
142
+ The canonical battery-ready template is **[echo.py](src/h3_harness/examples/echo.py)**
143
+ — it implements all three conventions and scores 43/43. Use it as the starting
144
+ point for your own harness.
145
+
146
+ ## Development
147
+
148
+ ```bash
149
+ make install # create venv + install deps
150
+ make build # build wheel (and sdist) into dist/
151
+ make test # run tests
152
+ make lint # ruff check
153
+ make fmt # ruff format
154
+ ```
155
+
156
+ ## Reference
157
+
158
+ - Spec: [get-h3/h3 — specs/04-SDK-Libraries.md](https://github.com/get-h3/h3/blob/main/specs/04-SDK-Libraries.md)
159
+ - Protocol: [get-h3/protocol](https://github.com/get-h3/protocol)
160
+ - API reference: [docs/api/index.md](docs/api/index.md)
@@ -0,0 +1,132 @@
1
+ # H3 Harness SDK for Python
2
+
3
+ Python SDK for building H3-compliant agent harnesses.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install h3-harness-sdk
9
+ ```
10
+
11
+ ### Install fallback (source / git)
12
+
13
+ If a release isn't published to PyPI yet (or you want the latest unreleased
14
+ changes), install directly from the repository:
15
+
16
+ ```bash
17
+ # From git
18
+ pip install git+https://github.com/get-h3/sdk-python.git
19
+
20
+ # Editable source install (development)
21
+ git clone https://github.com/get-h3/sdk-python.git
22
+ cd sdk-python
23
+ pip install -e .
24
+ ```
25
+
26
+ ## Quickstart
27
+
28
+ ```python
29
+ from h3_harness import (
30
+ BaseHarness,
31
+ Decision,
32
+ DecisionType,
33
+ End,
34
+ TextResponse,
35
+ create_router,
36
+ )
37
+ from fastapi import FastAPI
38
+
39
+
40
+ class MyHarness(BaseHarness):
41
+ async def on_process(self, req):
42
+ # Echo conversation history from context (battery: history preserved).
43
+ history = list(req.context.history)
44
+ # Streaming: "do not finish" in message -> unfinished text.
45
+ streaming = "do not finish" in req.message.content
46
+ finished = not streaming
47
+ return Decision(
48
+ decision=DecisionType.TEXT,
49
+ text=TextResponse(
50
+ content=f"Echo: {req.message.content}",
51
+ finished=finished,
52
+ ),
53
+ history=history,
54
+ )
55
+
56
+ async def on_result(self, req):
57
+ return Decision(decision=DecisionType.END, end=End(reason="task_complete"))
58
+
59
+
60
+ app = FastAPI()
61
+ app.include_router(create_router(MyHarness()))
62
+ ```
63
+
64
+ ## Testbed
65
+
66
+ ```python
67
+ from h3_harness.testbed import MockHermes
68
+ from h3_harness.examples.echo import EchoHarness
69
+
70
+ mock = MockHermes(EchoHarness())
71
+ decision = await mock.send_message("Hello!")
72
+ assert decision.text.content == "Echo: Hello!"
73
+ ```
74
+
75
+ ## Examples
76
+
77
+ - **[echo.py](src/h3_harness/examples/echo.py)** — Echo harness that mirrors user messages
78
+ - **[minimal.py](src/h3_harness/examples/minimal.py)** — Minimal harness with health endpoint, uvicorn runner
79
+ - **[langchain_agent.py](src/h3_harness/examples/langchain_agent.py)** — LangChain integration: LLM call with text response
80
+
81
+ ## Passing the battery (h3-test compliance)
82
+
83
+ The gate for any H3 harness is the **test battery** (`test_battery.py` from
84
+ [get-h3/shim](https://github.com/get-h3/shim) — 43 tests across 6 categories).
85
+ Run it against any running harness endpoint:
86
+
87
+ ```bash
88
+ # The shim is not yet published to PyPI — install from source (get-h3/shim)
89
+ pip install git+https://github.com/get-h3/shim
90
+ h3-test --endpoint http://localhost:9191 # exit 0 = compliant
91
+ ```
92
+
93
+ The Quickstart harness above implements all three conventions and is fully
94
+ battery-compliant (**43/43**). If you modify it, keep the conventions intact —
95
+ a naive harness that drops them scores **41/43**. The three conventions the
96
+ battery checks (beyond "return a Decision") are:
97
+
98
+ 1. **Echo `context.history` in every Decision.** The battery sends a session
99
+ with prior history and asserts it flows back through the response
100
+ (`test_2_8_process_preserves_history`). Pass it through explicitly:
101
+ ```python
102
+ history = list(req.context.history)
103
+ return Decision(..., history=history)
104
+ ```
105
+ 2. **Never issue `llm_call` when `context.models` is empty.** The battery
106
+ sends `context.models: []` and FAILS any harness that returns an `llm_call`
107
+ decision (`test_5_8_no_models_available` — "hallucinated model"). Only
108
+ return `LLM_CALL` when the request actually lists models.
109
+ 3. **Return `text.finished=false` for "do not finish" prompts.** The battery
110
+ sends *"Just start a thought, do not finish it yet."* and asserts the
111
+ response has `text.finished == False` (`test_2_4_process_text_finished_false`).
112
+ Detect streaming/unfinished intent and set `finished` accordingly.
113
+
114
+ The canonical battery-ready template is **[echo.py](src/h3_harness/examples/echo.py)**
115
+ — it implements all three conventions and scores 43/43. Use it as the starting
116
+ point for your own harness.
117
+
118
+ ## Development
119
+
120
+ ```bash
121
+ make install # create venv + install deps
122
+ make build # build wheel (and sdist) into dist/
123
+ make test # run tests
124
+ make lint # ruff check
125
+ make fmt # ruff format
126
+ ```
127
+
128
+ ## Reference
129
+
130
+ - Spec: [get-h3/h3 — specs/04-SDK-Libraries.md](https://github.com/get-h3/h3/blob/main/specs/04-SDK-Libraries.md)
131
+ - Protocol: [get-h3/protocol](https://github.com/get-h3/protocol)
132
+ - API reference: [docs/api/index.md](docs/api/index.md)