Aller au contenu

Spec de l'enveloppe wire

Les trois SDK (Python, Node, Go) envoient exactement la même enveloppe JSON vers POST /api/v1/ai/ingest avec Authorization: Bearer aiv_.... Vous pouvez aussi poster directement sans SDK ; l’enveloppe est le contrat.

POST /api/v1/ai/ingest
Host: api.monsys.ai
Authorization: Bearer aiv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
{
"trace_id": "uuid", // UUIDv4 client (requis)
"root_op": "rag.chat", // texte libre (requis)
"status": "ok" | "error" | "partial", // (requis)
"started_at": "2026-05-12T09:50:00Z", // RFC3339 (requis)
"ended_at": "2026-05-12T09:50:01Z", // RFC3339 (optionnel)
"user_session_hash": "", // SHA256 de session id, optionnel
"sampling_decision": "full", // "full" | "head" | "summary"
"spans": [ ... ] // 1..N spans (requis)
}
{
"span_id": "uuid",
"parent_span_id": "uuid", // "" pour root
"op": "openai.chat",
"provider": "openai",
"model": "gpt-4o-mini",
"started_at": "...",
"ended_at": "...",
"status": "ok", // "ok" | "error" | "refused" | "partial"
"input_tokens": 42,
"output_tokens": 17,
"prompt": "...", // brut — rédigé sur le hub
"completion": "...", // brut — rédigé sur le hub
"system_msg": "...",
"tool_io": "...",
"attributes": { ... },
"events": [ { ... }, ... ]
}

Un agent, c’est plus qu’un prompt et une completion. Ce qu’un outil renvoie, quel schéma d’outil le modèle voit et ce qu’il écrit en mémoire sont les canaux par lesquels arrivent l’injection indirecte, l’empoisonnement d’outils MCP et l’empoisonnement de mémoire. Vous les consignez comme événements typés sur un span ; le hub hache et expurge le contenu comme pour les prompts, recherche des indicateurs d’injection déterministes et suit la dérive des schémas MCP. monsys ne bloque rien (ADR-0009, ADR-0029).

"events": [
{ "kind": "tool_call", "name": "read_email", "args": { "folder": "inbox" }, "at": "2026-10-30T09:00:00Z" },
{ "kind": "tool_result", "name": "read_email", "result": "…texte vu par le modèle…" },
{ "kind": "mcp_schema", "server": "crm", "name": "delete_user",
"description": "Deletes a user by id", "input_schema": { "type": "object", "properties": { "id": { "type": "string" } } } },
{ "kind": "memory_write", "store": "vector", "key": "customer-404", "content": "…" }
]
kind obligatoire traitement par le hub
tool_call name, args hash + expurgation ; statistiques d’outils
tool_result name, result hash + expurgation ; indicateurs d’injection
mcp_schema server, name, description, input_schema hash canonique ; alerte de dérive au changement ; indicateurs sur la description
memory_write store, key, content hash + expurgation ; indicateurs d’injection

Indicateurs (regex, pas de modèle) : ignore_previous, role_override, system_prompt_exfil, tool_invocation, secrecy, hidden_html, zero_width, markdown_exfil, shell_pipe, prompt_delimiters, base64_blob. Une correspondance crée une alerte ai_injection dans la boîte d’actions ; un schéma modifié crée ai_mcp_drift et compte comme dérive de configuration dans le Trust Score jusqu’à confirmation. Tout atterrit haché dans l’evidence pack (agent_events.jsonl, mcp_schemas.json).

Helpers SDK : Python span.tool_call(), span.tool_result(), span.mcp_schema(), span.memory_write() ; Node span.toolCall() etc. ; Go span.ToolCall() etc.

Provider Valeur provider
OpenAI openai
Anthropic Claude anthropic
Google Gemini google
Mistral AI mistral
Azure OpenAI azure
Local (Ollama) ollama

Les autres providers sont acceptés mais n’ont pas de lookup tarifaire (coût = 0).

À l’ingestion, le hub cherche ai_model_pricing par (provider, model). Match exact : les nouveaux modèles non présents dans la table donnent total_cost_micro_eur = 0. Demandez une mise à jour via info@be-hosted.be (changelog tarifaire : bientôt).

La ligne tarifaire utilisée est épinglée par span via une FK pricing_snapshot_id : un backfill des prix ne change pas les coûts historiques.

{
"received": true,
"trace_id": "uuid",
"spans": 3,
"pii_hits": 1,
"total_cost_micro_eur": 603290
}

Statuts HTTP :

  • 200 : traité (voir body)
  • 401 : token invalide ou révoqué
  • 403 : ai_observability_enabled = false
  • 400 : enveloppe invalide
  • 5xx : erreur côté hub ; le SDK ne retry pas
Fenêtre de terminal
curl -X POST https://api.monsys.ai/api/v1/ai/ingest \
-H "Authorization: Bearer aiv_xxxx" \
-H "Content-Type: application/json" \
-d '{ "trace_id": "0e22…", "root_op": "test", "status": "ok", ... }'

Nous mappons les conventions sémantiques OTel GenAI sur cette enveloppe en interne mais n’acceptons pas encore OTLP directement. Raison : l’overhead binaire OTLP/HTTP est surdimensionné pour un-call-par-trace. Si vous avez une stack OTel-only, écrivez un adaptateur léger OTel span → notre enveloppe (voir envelope-from-otel.md : bientôt).