Skip to main content
Un client déjà compatible OpenAI n’a qu’une seule chose à changer : base_url. Le reste du code — modèle, messages, paramètres — ne bouge pas. Haki injecte la mémoire avant l’appel, transmet au provider configuré, capture l’échange après, et renvoie la réponse du provider octet pour octet.

En-têtes d’identité mémoire

L’identité voyage uniquement en en-têtes, jamais dans le corps de la requête — le modèle ne choisit jamais ce qu’on mémorise.
string
Requis pour activer la mémoire. Sans lui : transmission simple, X-Haki-Memory: disabled, aucune capture — un client OpenAI existant ne casse jamais en pointant vers la gateway.
string
Fil de conversation, propagé à l’événement capturé.
string
Identifiant d’exécution, propagé à l’événement capturé.
string
Transmis à build_context (voir Policy Engine, règle 3).
string
Défaut : "gw-" + sha256(corps brut). Un retry avec le même corps ne capture jamais deux fois le même échange.
string
Utilisé seulement en mode dev ouvert (HAKI_AUTH_REQUIRED=false, sans clé donc sans projet résolu) ; défaut prj_gateway_dev. Avec une vraie clé hk_..., le projet est celui de la clé, sans exception — le corps chat/completions ne porte de toute façon aucun project_id.

Ce qui se passe à chaque appel

1

Résolution du scope

La clé hk_... (middleware d’auth déjà étendu à /gateway/v1/*) résout project_id. La clé Haki n’est jamais transmise en amont — seules les credentials HAKI_LLM_* le sont.
2

Construction du contexte

Si X-Haki-Subject-Id et un dernier message user sont présents : build_context(...) (le même Context Assembler que /v1/context) est appelé avec ce dernier message comme requête.
3

Injection

Le packet est rendu par build_prompt_context (la même fonction que le SDK Python — une seule implémentation, jamais de copie divergente) et préfixé au message system dans un bloc <haki_memory>…</haki_memory> (un message system est créé en première position s’il n’existait pas).
4

Transmission

POST {HAKI_LLM_BASE_URL}/chat/completions, timeout 60 s.
5

Capture (après la réponse, best-effort)

Si la mémoire était active et la réponse 2xx : l’échange devient un événement conversation.turn idempotent, et un job de consolidation est mis en file — hors du chemin critique.
6

Réponse renvoyée

Le corps et le statut du provider, inchangés, plus trois en-têtes Haki.

En-têtes de réponse

string
requis
active (mémoire injectée et échange capturé) · disabled (pas de sujet, ou stream: true) · degraded (échec de construction du contexte — la requête part quand même, sans mémoire).
uuid
Présent quand la mémoire est active — inspectable via GET /v1/inspect/{trace_id}.
string
Durée de build_context en millisecondes (1 décimale).

Dégradation propre

L’agent n’est jamais bloqué par Haki :

Streaming : pass-through pur, choix assumé

stream: true est un pass-through SSE brut : ni injection, ni capture, X-Haki-Memory: disabled inconditionnel. Ce n’est pas une limitation à corriger : injecter la mémoire sans pouvoir capturer la réponse finale casserait la boucle mémoire (« pas de réponse finale sans passage Haki après ») ; bufferiser tout le stream annulerait l’intérêt même du streaming. Documenté dans le README et le code (app/gateway/__init__.py).

Limite honnête

La gateway voit les appels au modèle, pas les outils que l’agent exécute localement entre deux appels — ceux-ci doivent être capturés via le SDK ou l’API directement (référence : research/Haki_Memory_Runtime.md).

Latence

Le surcoût mémoire est dominé par build_context (~15 ms en local ; p95 de /v1/context < 250 ms — voir les chiffres mesurés). Benchmark reproductible :