Installation
gethaki (haki was already taken on PyPI by
an unrelated project) — the importable package stays haki:
from haki import HakiClient.
Inside the Haki repository itself, the SDK is instead a local editable
dependency (pyproject.toml, [tool.uv.sources]): uv sync at the repo
root installs it automatically, alongside the API. Useful when working on
the SDK’s source directly:
HakiClient — synchronous (httpx)
Sync by default: the main consumers are scripts and agent hooks.
transport is injectable for tests
(httpx.ASGITransport(app=app)).
dict
GET /health.dict
POST /v1/capture. events: list of dicts in EventIn shape.dict
POST /v1/context → {packet, token_count, trace_id}.dict
GET /v1/inspect/{trace_id} (scope required).dict
GET /v1/timeline.dict
POST /v1/consolidate → {processed}.dict
POST /v1/forget.dict
POST /v1/feedback.dict
POST /v1/conflicts/{id}/resolve.dict
POST /v1/keys — the clear key only appears here.dict
GET /v1/keys (masked).dict
DELETE /v1/keys/{key_id}.AsyncHakiClient exposes the exact same methods, await-able
(backed by httpx.AsyncClient).
Typed errors
HakiError
The API is unreachable (network, timeout, DNS…).
HakiError
The API responded with
{"error": {...}}. Carries status_code,
error_type, field, payload — see the
list of error types.The two agent hooks (haki.runtime)
What build_prompt_context() actually produces
What build_prompt_context() actually produces
A delimited
<haki_memory>...</haki_memory> block with a fixed
instruction (“apply these facts, especially the reply language, cite
the source”), one line per fact (predicate: value (valid from ...; sources: ...)), then the dated episodes, then the warnings prefixed
!. An empty packet (no facts, no episodes) → empty string.
Identical text between the Python SDK and the TypeScript SDK.capture_turn(client, subject_id, project_id, user_msg, assistant_msg, *, org_id="org_default", agent_id=None, thread_id=None, kind="conversation.turn")
writes an event with payload.messages = [{role: user, content}, {role: assistant, content}]
and a per-call unique idempotency_key (f"turn-{uuid4()}").
Gateway (haki.gateway)
httpx.Client/httpx.AsyncClient with
Authorization and the X-Haki-* headers already set — see the
Gateway reference for the full contract.
CLI haki
command
Tests
/health, writes ~/.haki/config.json.command
Full timed scenario: capture → consolidate → new thread → context
recalls the fact. Exit 0/1. Attempts a key bootstrap if none is
configured.
command
API health + latency.
command
command
command
command
Internal: invoked by Cursor itself (
.cursor/hooks.json), never by
hand.
