Python client for the ai-heeczer ingestion service.
Project description
cognizhi-heeczer (Python)
Async Python client for the ai-heeczer ingestion service.
⚠️ Pre-1.0 surface. The HTTP envelope contract (envelope_version
1) is stable; the typed wrapper API may evolve until we ship1.0.0.
Install
Pre-release.
cognizhi-heeczeris not on PyPI yet (see plan 0012). Until then, install from source:uv sync --project bindings/heeczer-py.
uv add cognizhi-heeczer
Requires Python ≥ 3.11.
Usage
import asyncio
from heeczer import HeeczerClient
async def main() -> None:
async with HeeczerClient(
base_url="https://ingest.example.com",
api_key="…",
) as client:
result = await client.ingest_event(
workspace_id="ws_default",
event=canonical_event, # see core/schema/event.v1.json
)
print(result["score"]["final_estimated_minutes"])
asyncio.run(main())
Error handling
Every client method raises :class:heeczer.HeeczerApiError on a non-2xx
response. The error carries the closed kind enum from the ingestion
service's envelope:
from heeczer import HeeczerApiError
try:
await client.ingest_event(workspace_id="ws", event=bad_event)
except HeeczerApiError as err:
if err.kind == "schema":
...
Configuration
| Argument | Type | Default | Description |
|---|---|---|---|
base_url |
str |
required | Base URL of the ingestion service. Trailing slash is stripped. |
api_key |
str | None |
None |
Sent as x-heeczer-api-key. |
timeout |
float |
10.0 |
Per-request timeout in seconds. |
transport |
httpx.AsyncBaseTransport | None |
None |
Inject a custom transport (e.g. httpx.MockTransport in tests). |
Methods
| Method | HTTP | Returns |
|---|---|---|
healthz() |
GET /healthz |
bool |
version() |
GET /v1/version |
VersionResponse |
ingest_event(workspace_id, event) |
POST /v1/events |
IngestEventResponse |
test_score_pipeline(event, profile=…, tier_set=…, tier_override=…) |
POST /v1/test/score-pipeline |
TestPipelineResponse (gated by the test-orchestration feature flag) |
Error kinds
HeeczerApiError.kind is a closed Literal mirroring the ingestion
service envelope:
| Kind | When |
|---|---|
schema |
Event failed canonical schema validation. |
bad_request |
Malformed JSON or missing top-level fields. |
scoring |
Engine rejected a normalized event (e.g. unknown tier id). |
storage |
Persistence layer error. |
not_found |
Read endpoint did not find the resource. |
forbidden |
Auth or RBAC denied the request. |
feature_disabled |
Endpoint exists but the feature flag is off. |
unknown |
Non-JSON 5xx body; the raw text is in api_message. |
Runnable example
See examples/python/quickstart.py
and the cross-language index in examples/README.md.
Common patterns
Validate locally before sending (avoids a network round-trip on bad
events). The schema is JSON Schema Draft 2020-12; use
jsonschema or
fastjsonschema:
import json, jsonschema
with open("core/schema/event.v1.json") as f:
schema = json.load(f)
jsonschema.validate(event, schema) # raises jsonschema.ValidationError if invalid
Surface schema field errors from the service:
try:
await client.ingest_event(workspace_id="ws", event=event)
except HeeczerApiError as err:
if err.kind == "schema":
# err.api_message contains the field-level detail from the server envelope.
print("schema rejection:", err.api_message)
Batching note. POST /v1/events:batch (single-transaction,
partial-success semantics) is planned but not yet shipped — see
plan 0004. Until then,
use asyncio.gather for concurrent sends.
Contract
The SDK speaks envelope_version: "1" to the ingestion service per
ADR-0011. Additive fields land
without breaking the typed surface (ScoreResult is a TypedDict
with total=False).
Synchronous client
For scripts and notebooks where no event loop is running, use the
SyncHeeczerClient wrapper:
from heeczer import SyncHeeczerClient
with SyncHeeczerClient(base_url="https://ingest.example.com", api_key="…") as client:
result = client.ingest_event(workspace_id="ws_default", event=my_event)
print(result["score"]["final_estimated_minutes"])
SyncHeeczerClient exposes the same methods as HeeczerClient
(healthz, version, ingest_event, test_score_pipeline),
all blocking. Internally it calls asyncio.get_event_loop().run_until_complete().
Do not mix it with an already-running asyncio loop (e.g. inside
async def); use HeeczerClient directly there instead.
Framework adapters
LangGraph
Wrap SyncHeeczerClient inside a custom LangGraph node to record each
agent step's cost before passing control downstream:
from langgraph.graph import StateGraph
from heeczer import SyncHeeczerClient
from typing import TypedDict
class AgentState(TypedDict):
event: dict
score: dict | None
def heeczer_node(state: AgentState) -> AgentState:
with SyncHeeczerClient(base_url="http://localhost:3000") as client:
resp = client.ingest_event(
workspace_id="ws_default",
event=state["event"],
)
return {**state, "score": resp["score"]}
builder = StateGraph(AgentState)
builder.add_node("heeczer", heeczer_node)
In async LangGraph graphs call the async client instead:
async def heeczer_node(state: AgentState) -> AgentState:
async with HeeczerClient(base_url="http://localhost:3000") as client:
resp = await client.ingest_event(
workspace_id="ws_default",
event=state["event"],
)
return {**state, "score": resp["score"]}
Google ADK
Google's Agent Development Kit (ADK) uses an async event-loop internally.
Use HeeczerClient directly in ADK tool callbacks:
from google.adk.tools import FunctionTool
from heeczer import HeeczerClient
async def record_step(workspace_id: str, event: dict) -> dict:
"""Record an agent step with heeczer and return the score."""
async with HeeczerClient(base_url="http://localhost:3000") as client:
return await client.ingest_event(workspace_id=workspace_id, event=event)
heeczer_tool = FunctionTool(record_step)
Attach heeczer_tool to your ADK Agent via tools=[heeczer_tool].
The return value of record_step is serialised by ADK and forwarded as
the tool response to the model.
Development
uv sync --extra dev
uv run pytest
uv run ruff check
uv run mypy
License
MIT.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cognizhi_heeczer-0.5.1.tar.gz.
File metadata
- Download URL: cognizhi_heeczer-0.5.1.tar.gz
- Upload date:
- Size: 30.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7958a297afdc029ad6118669f91667c88671c435c16479784a05c48f01b09c03
|
|
| MD5 |
491057f0776c5ac4f24db9bfa41f43b1
|
|
| BLAKE2b-256 |
76e15d8ea58bf4df3c1cd291aba1450fa6b65ba0d4ede7da8358d1c44b9a4b25
|
Provenance
The following attestation bundles were made for cognizhi_heeczer-0.5.1.tar.gz:
Publisher:
release.yml on cognizhi/ai-heeczer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cognizhi_heeczer-0.5.1.tar.gz -
Subject digest:
7958a297afdc029ad6118669f91667c88671c435c16479784a05c48f01b09c03 - Sigstore transparency entry: 1378462573
- Sigstore integration time:
-
Permalink:
cognizhi/ai-heeczer@c42dfc78c8e4a741eb6a3e12697a8bd283b85c3b -
Branch / Tag:
refs/tags/heeczer-py-v0.5.1 - Owner: https://github.com/cognizhi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@c42dfc78c8e4a741eb6a3e12697a8bd283b85c3b -
Trigger Event:
push
-
Statement type:
File details
Details for the file cognizhi_heeczer-0.5.1-py3-none-any.whl.
File metadata
- Download URL: cognizhi_heeczer-0.5.1-py3-none-any.whl
- Upload date:
- Size: 12.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9bf6757093f21278bdb814881fd6cabd038cfca6a557c07693660874e89983c9
|
|
| MD5 |
4d9f8859db0a888db76e3345c867b78b
|
|
| BLAKE2b-256 |
26640c86f3302dc702c2f6cb900716e2722d7245fc78ca4deb09c4678760a420
|
Provenance
The following attestation bundles were made for cognizhi_heeczer-0.5.1-py3-none-any.whl:
Publisher:
release.yml on cognizhi/ai-heeczer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cognizhi_heeczer-0.5.1-py3-none-any.whl -
Subject digest:
9bf6757093f21278bdb814881fd6cabd038cfca6a557c07693660874e89983c9 - Sigstore transparency entry: 1378462707
- Sigstore integration time:
-
Permalink:
cognizhi/ai-heeczer@c42dfc78c8e4a741eb6a3e12697a8bd283b85c3b -
Branch / Tag:
refs/tags/heeczer-py-v0.5.1 - Owner: https://github.com/cognizhi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@c42dfc78c8e4a741eb6a3e12697a8bd283b85c3b -
Trigger Event:
push
-
Statement type: