base_url. Everything else — model, messages, parameters —
stays the same. Haki injects memory before the call, forwards to the
configured provider, captures the exchange afterwards, and returns the
provider’s response byte for byte.
Memory identity headers
string
Required to activate memory. Without it: plain pass-through,
X-Haki-Memory: disabled, no capture — an existing OpenAI client never
breaks by pointing at the gateway.string
Conversation thread, forwarded to the captured event.
string
Run id, forwarded to the captured event.
string
Forwarded to
build_context (see Policy Engine, rule 3).string
Default:
"gw-" + sha256(raw body). A retry with the same body never
captures the same exchange twice.string
Used only in open dev mode (
HAKI_AUTH_REQUIRED=false, no key so
no resolved project); defaults to prj_gateway_dev. With a real
hk_... key, the project is the key’s project, no exception — the
chat/completions body carries no project_id anyway.What happens on every call
1
Scope resolution
The
hk_... key (auth middleware already extended to
/gateway/v1/*) resolves project_id. The Haki key is never
forwarded upstream — only the HAKI_LLM_* credentials are.2
Context construction
If
X-Haki-Subject-Id and a last user message are both present:
build_context(...) (the same Context Assembler as /v1/context) is
called with that last message as the query.3
Injection
The packet is rendered by
build_prompt_context (the same
function as the Python SDK — one implementation, never a divergent
copy) and prepended to the system message inside a
<haki_memory>…</haki_memory> block (a system message is created
first if none existed).4
Forwarding
POST {HAKI_LLM_BASE_URL}/chat/completions, 60s timeout.5
Capture (after the response, best-effort)
If memory was active and the response is
2xx: the exchange becomes
an idempotent conversation.turn event, and a consolidation job is
queued — off the critical path.6
Response returned
The provider’s body and status, unchanged, plus three Haki
headers.
Response headers
string
required
active (memory injected and exchange captured) · disabled (no
subject, or stream: true) · degraded (context construction failed —
the request still goes through, without memory).uuid
Present when memory is active — inspectable via
GET /v1/inspect/{trace_id}.string
Duration of
build_context in milliseconds (1 decimal).Clean degradation
The agent is never blocked by Haki:Streaming: pure pass-through, a deliberate choice
Honest limit
The gateway sees calls to the model, not the tools an agent runs locally between calls — those must be captured via the SDK or the API directly (reference:research/Haki_Memory_Runtime.md).
Latency
The memory overhead is dominated bybuild_context (~15 ms locally; p95
of /v1/context < 250 ms — see the measured numbers).
Reproducible benchmark:

