Ga naar inhoud

Wire envelope spec

De drie SDK’s (Python, Node, Go) sturen exact hetzelfde JSON-envelope naar POST /api/v1/ai/ingest met Authorization: Bearer aiv_.... Je kan ook zonder SDK rechtstreeks posten; de envelope is het contract.

POST /api/v1/ai/ingest
Host: api.monsys.ai
Authorization: Bearer aiv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
{
"trace_id": "uuid", // client-generated UUIDv4 (required)
"root_op": "rag.chat", // free-text label (required)
"status": "ok" | "error" | "partial", // (required)
"started_at": "2026-05-12T09:50:00Z", // RFC3339 (required)
"ended_at": "2026-05-12T09:50:01Z", // RFC3339 (optional)
"user_session_hash": "", // SHA256 van session id, optioneel
"sampling_decision": "full", // "full" | "head" | "summary"
"spans": [ ... ] // 1..N spans (required)
}
{
"span_id": "uuid", // UUIDv4 (required)
"parent_span_id": "uuid", // "" voor root span
"op": "openai.chat", // free-text (required)
"provider": "openai", // canonieke provider naam
"model": "gpt-4o-mini", // model id
"started_at": "2026-05-12T09:50:00.001Z",
"ended_at": "2026-05-12T09:50:00.987Z",
"status": "ok", // "ok" | "error" | "refused" | "partial"
"input_tokens": 42,
"output_tokens": 17,
"prompt": "...", // raw — wordt op de hub geredacteerd
"completion": "...", // raw — wordt op de hub geredacteerd
"system_msg": "...",
"tool_io": "...", // tool calls of function-result
"attributes": { ... }, // optionele top-level metadata
"events": [ { ... }, ... ] // optionele event-stream
}

Een agent is meer dan prompt en completion. Wat een tool teruggeeft, welk toolschema het model te zien krijgt en wat het naar geheugen schrijft, zijn de kanalen waarlangs indirecte prompt-injectie, MCP tool poisoning en geheugenvergiftiging binnenkomen. Je legt ze vast als getypeerde events op een span; de hub hasht en redacteert de inhoud zoals bij prompts, scant op deterministische injectie-indicatoren en volgt MCP-schema’s op drift. monsys blokkeert niets (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": "…tekst die het model te zien krijgt…" },
{ "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 verplicht wat de hub ermee doet
tool_call name, args hash + redactie; telt mee in tool-statistiek
tool_result name, result hash + redactie; injectie-indicatoren
mcp_schema server, name, description, input_schema canonieke hash; drift-alert bij wijziging; indicatoren op de beschrijving
memory_write store, key, content hash + redactie; injectie-indicatoren

Indicatoren (regex, geen model): ignore_previous, role_override, system_prompt_exfil, tool_invocation, secrecy, hidden_html, zero_width, markdown_exfil, shell_pipe, prompt_delimiters, base64_blob. Een treffer geeft een melding ai_injection in de actie-inbox; een gewijzigd schema geeft ai_mcp_drift en telt, tot je de wijziging bevestigt, mee als configuratie-drift in de Trust Score. Alles landt gehasht in het evidence pack (agent_events.jsonl, mcp_schemas.json).

SDK-helpers: Python span.tool_call(), span.tool_result(), span.mcp_schema(), span.memory_write(); Node span.toolCall() enz.; Go span.ToolCall() enz.

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

Andere providers worden geaccepteerd maar krijgen geen pricing-lookup (cost wordt 0).

Op ingest doet de hub een lookup in ai_model_pricing op (provider, model). De match is exact: voor nieuwe modellen die nog niet in de tabel staan, krijg je total_cost_micro_eur = 0. Vraag een update aan via info@be-hosted.be (pricing changelog page: coming soon).

De gebruikte pricing-rij wordt gepind per span via een pricing_snapshot_id FK: backfills van de prijzen veranderen historische kosten niet.

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

HTTP status:

  • 200: verwerkt (zie body)
  • 401: token ongeldig of intrekken
  • 403: tenant heeft ai_observability_enabled = false
  • 400: envelope niet geldig (zie error veld in body)
  • 5xx: hub-zijde fout; SDK retried niet (failures zijn silent)
Terminal window
curl -X POST https://api.monsys.ai/api/v1/ai/ingest \
-H "Authorization: Bearer aiv_xxxx" \
-H "Content-Type: application/json" \
-d '{
"trace_id": "0e2216d5-7b6d-448a-924c-c7a08b1a7e4a",
"root_op": "manual_test",
"status": "ok",
"started_at": "2026-05-12T09:50:00Z",
"ended_at": "2026-05-12T09:50:01Z",
"sampling_decision": "full",
"spans": [{
"span_id": "a1b2c3d4-e5f6-4789-9abc-def012345678",
"parent_span_id": "",
"op": "openai.chat",
"provider": "openai", "model": "gpt-4o-mini",
"started_at": "2026-05-12T09:50:00.001Z",
"ended_at": "2026-05-12T09:50:00.987Z",
"status": "ok",
"input_tokens": 22, "output_tokens": 12,
"prompt": "Mijn IBAN is BE68 5390 0754 7034.",
"completion": "Ik kan niet helpen met bank-details.",
"attributes": {}, "events": []
}]
}'

We mappen OTel GenAI semantic conventions intern op deze envelope, maar accepteren OTLP nog niet rechtstreeks. Reden: OTLP/HTTP-binary overhead is overkill voor 1-call-per-trace. Als je een OTel-only stack hebt, schrijf een dunne adapter van OTel span → onze envelope (zie envelope-from-otel.md: coming soon).