AI agents
Agent observability: zeven signalen vóór de eerste klant
Elke agent die we live zetten krijgt dezelfde zeven dashboards voordat een klant 'm ziet. Dit is wat we monitoren, welke Grafana-queries we draaien, en de drempels die ons wakker maken.

Het is 02:17 's nachts als de on-call telefoon afgaat. Een invoice-chase agent heeft de afgelopen veertig minuten €1.400 aan modelkosten verstookt. Een Shopify-webhook begon om 01:31 lege arrays terug te geven, en de agent besloot dat hij in de volgende loop de ontbrekende order wel zou vinden. Hij vond 'm nooit. Hij bleef zoeken, en hij bleef betalen voor het voorrecht.
Dat is het faalmodel dat agent observability moet onderscheppen voordat het gebeurt. Niet het model dat in de war raakt. De infrastructuur onder het model die scheef gaat terwijl het model gewoon blijft doorpraten.
Dit is de veldgids voor de zeven observability-panels die we in elk agent-dashboard inbouwen voordat er één klant bij komt. Elk panel met de Grafana-query die we daadwerkelijk draaien en de drempel die ons daadwerkelijk paget.
De instrumentatie onder de panels
Vóór de zeven panels eerst even over wat de data oplevert. Elke agent die we in 2026 uitrollen stuurt OpenTelemetry-traces uit per gesprek en Prometheus-metrics vanuit een dunne middleware die de modelclient en elke tool omhult. De tracing-laag geeft ons forensisch inzicht per gesprek als er een alert afgaat. De metrics-laag geeft ons de dashboards.
De counters en histogrammen hieronder zitten allemaal in die middleware. Je schrijft ze één keer. Elke agent die het team daarna oplevert erft het dashboard gratis. Als je één structurele keuze uit dit stuk meeneemt, neem dan deze.
1. Kosten per opgelost gesprek
Tokenverbruik is geen factureringsweetje. Het is het schoonste kostensignaal in agent observability, en het schoonste teken dat een agent vastloopt.
Een gezonde customer-support agent kost ons in de studio rond de €0,04 per opgelost gesprek op Sonnet 4.5, met een lange staart die loopt tot ongeveer €0,12. Alles boven €0,30 is óf een echt lastig ticket óf een loop. Hoe dan ook, we willen het weten.
sum by (agent_id) (
rate(agent_tokens_total{kind="output"}[5m]) * 15
+ rate(agent_tokens_total{kind="input"}[5m]) * 3
) / 1e6Rates in dollars per seconde, met per-model pricing ingebakken in de constants (die updaten we als de provider de prijzen wijzigt). We pagen wanneer het gemiddelde per gesprek over een venster van vijf minuten boven 4× de zeven-daagse baseline uitkomt. Geen absolute drempel. De baseline schuift mee met feature-werk, en je wilt dat de alert daarin meeschuift. Hetzelfde panel vangt ook een stiller faalgeval: een agent geconfigureerd voor Sonnet die stilletjes naar Opus routeert omdat een fallback afging. De kosten per gesprek verdrievoudigen en de grafiek vertelt je waarom.
2. Foutmarge per tool
De grootste bron van stille agent-fouten is een tool die ineens onzin teruggeeft. Lege arrays in plaats van orders. 200 OK met een HTML-foutpagina in de body. Een schemawijziging waar de agent geen weet van heeft.
We instrumenteren elke tool call met zowel een counter als een histogram, getagd met tool en error_class. Het panel splitst de foutmarge uit per tool, één lijn per tool, want 6% fouten over alle tools kan één tool op 60% zijn en de rest op nul. Dat moet je op hetzelfde scherm zien.
sum by (tool) (rate(agent_tool_call_errors_total[5m]))
/
sum by (tool) (rate(agent_tool_call_total[5m]))Alert-drempel: elke individuele tool die tien minuten lang boven 5% fouten zit, paget de on-call. We hebben lossere drempels geprobeerd. Elke keer dat we dat deden, ging een externe API onderuit en hoorden we het van de klant.
3. p95 turn-latency
Mediane latency is een troostende leugen. Mensen haken af op de lange staart, niet op de mediaan.
histogram_quantile(0.95,
sum by (le, agent_id) (
rate(agent_turn_duration_seconds_bucket[5m])
)
)Drempel: chat-agents pagen boven 8 seconden op p95. Voice agents pagen boven 1,2 seconden. Voice is meedogenloos, en een pauze van twee seconden klinkt alsof de lijn dood is. Allebei vijf-minuten schuivende vensters, zodat één trage request de page niet activeert. Ben je nieuw met histogram-quantielen in Prometheus, dan zijn de officiële notities over bucketkeuze twintig minuten van je tijd waard voordat je het dashboard live zet. Verkeerde buckets en je p95 is fictie.
4. Stappen per sessie
Als je maar één observability-panel in de gaten houdt, kies dan dit. Stap-aantal is waar loops zich verstoppen.
We sturen een histogram uit van hoeveel planning-iteraties elk gesprek nodig had voordat het werd opgelost of werd doorgegeven. Een gezonde verdeling heeft een lange, dunne staart. Een ongezonde verdeling heeft een piek op de maximale step-limit, wat betekent dat een serieus deel van de gesprekken het plafond raakt en opgeeft.
histogram_quantile(0.99,
sum by (le) (rate(agent_session_steps_bucket[30m]))
)Drempel: p99 boven 12 stappen paget. De interessante alert hier is niet de page. Het is de grafiek. Als de p99 in een week klimt van 8 naar 11, is er iets aan het degraderen. Meestal is een retrieval-bron verouderd geraakt en zoekt de agent harder naar hetzelfde antwoord. Stap-aantal beweegt eerder dan recall, eerder dan latency, eerder dan kosten. Het is de vroegste waarschuwing die we hebben.
Lever kosten nooit op als je enige alert. Wij deden dat bij onze eerste drie agents. Kosten zijn een achterloop-indicator van elk ander probleem. Tegen de tijd dat de rekening omhoog springt, praat de klant al een uur tegen een kapotte agent.
5. Foutmarge op schemavalidatie
Structured outputs falen op twee manieren. Het model geeft malformed JSON terug, of het geeft valide JSON terug die niet bij je schema past. Beide zijn op te lossen met een retry. Beide blazen stilletjes je kosten- en latency-budget op als je ze niet meet.
sum(rate(agent_schema_validation_failures_total[5m]))
/
sum(rate(agent_structured_outputs_total[5m]))Drempel: boven 2% over vijf minuten is ongebruikelijk. Boven 5% is bijna altijd een prompt-wijziging of een schemawijziging die zonder backfill is geland. We pagen op 5%. We tekenen 2% in als waarschuwingslijn, zodat de on-call de klim ziet voordat het paget.
6. Doorgeven aan een mens
Dit is het businesssignaal. De engineering-signalen zeggen je dat de agent werkt. De handoff-ratio zegt je dat de agent helpt.
Elke agent die we opleveren heeft een expliciete uitweg: een functie die het model kan aanroepen als het besluit het probleem van de klant niet op te kunnen lossen. We tellen die aanroepen en delen door afgeronde gesprekken.
sum(rate(agent_handoff_total[1h]))
/
sum(rate(agent_conversation_completed_total[1h]))Drempel: 2× de zeven-daagse baseline over één uur. Het interessante aan dit signaal is dat het stijgt voordat de kwaliteit zakt. Het model begint agressiever door te geven, misschien een uur of twee voordat recall op de eval-set er lelijk uit gaat zien. Benut die voorsprong.
7. Prompt injection en verdachte input
Prompt injection is het faalmodel waar je je niet volledig met een prompt uit kunt redden. Input die het model behandelt als instructie in plaats van data: instruction overrides, role hijacks, exfiltratie van verborgen data, encoded payloads. OWASP houdt een levende catalogus bij van deze faalmodellen in hun LLM Top 10, en dat is de juiste plek om te beginnen met kiezen wat je wilt detecteren.
Elke agent die we opleveren stuurt binnenkomende gebruikersberichten door een snelle classifier, een klein model getraind op een corpus van bekende injectiepatronen. Hij stuurt een counter uit zodra hij afgaat. We blokkeren niet op de classifier. We loggen, tellen en alerten.
sum by (agent_id, signal) (
rate(agent_input_classifier_total{class="suspicious"}[5m])
)Drempel: elke aanhoudende rate boven baseline gedurende dertig minuten paget de security-rotatie, niet de engineering-rotatie. Andere mensen, ander runbook. Het eerste wat ze doen is de ruwe input uit de logs trekken en beslissen of het verkeer één nieuwsgierige gebruiker is of een gecoördineerde probe.
Wat we bewust niet meten
We tracken geen 'accuracy' als live observability-metric. Accuracy meet je offline op een gelabelde eval-set, na elke prompt- of modelwijziging. Het in productie willen berekenen betekent gesprekken samplen, ze naar een judge-model sturen, en die judge vertrouwen. Drie dingen erbij die stuk kunnen.
We alerten ook niet op tokenverbruik in absolute termen. We alerten op kosten per opgelost gesprek. Een campagne die 10× zoveel verkeer brengt mag 10× zoveel kosten brengen, zonder dat iemand om drie uur 's nachts gepaged wordt.
De volgorde van het dashboard telt
Stap-aantal en foutmarge per tool gaan linksboven. Daar kijkt de on-call als eerste. Kosten staan rechtsboven, want kosten zijn de vraag van de CFO en je wilt 'm beantwoord hebben voordat hij hem stelt. Latency en handoff komen in de middelste rij. Schemafouten en injectiesignalen gaan onderaan, want als een van die twee beweegt, ben je al aan het triageren.
Niks aan dit observability-werk is exotisch. Het is Prometheus, Grafana, een counter op elke betekenisvolle function call, en een histogram op elke duur. De discipline zit in het inbouwen vóór de lancering, niet na het eerste incident om 02:00.
Toen we eerder dit jaar de e-mailagent bouwden voor een Nederlandse logistieke klant, was stap-aantal het signaal dat ons redde: kosten en latency zagen er twee dagen prima uit terwijl p99 stappen omhoog kropen, omdat een leverancier stilletjes had veranderd hoe hun tracking-API multi-leg zendingen teruggaf. We bouwen dezelfde zeven panels in elke AI-agent die we opleveren.
Kleinste ding dat je vandaag kunt doen: open je bestaande agent-dashboard. Tel de panels. Heb je er minder dan zeven, dan zijn de ontbrekende exact degene die je wakker gaan maken.
Kern
Kosten zijn een achterloop-indicator. Stap-aantal is waar loops zich het eerst laten zien, en daarom staat dat linksboven op elk agent-dashboard dat we opleveren.
FAQ
Wat is een verstandige bovengrens voor stap-aantal bij een productie-agent?
We cappen op 15 met een harde kill op 20. De interessante drempel is p99 boven 12, wat meestal betekent dat er iets is gedegradeerd en de agent harder werkt voor hetzelfde antwoord.
Leggen jullie metrics vast voor elk gesprek of sampelen jullie?
Elk gesprek levert metrics op. Alleen volledige OpenTelemetry-traces worden gesampled (10% in stabiele toestand, 100% zodra er een alert afgaat). Counters zijn goedkoop. Volledige traces niet.
Welke alerting-backend zit boven op Grafana?
Grafana Alerting routeert naar PagerDuty voor engineering-signalen en naar een aparte Slack-gedreven rotatie voor security-signalen. Andere urgentie, andere on-call rotatie, andere runbooks.
Hoe voorkom je alert-moeheid bij zeven signalen?
Page op de verandersnelheid ten opzichte van baseline, niet op absolute drempels. Bespreek elke page in een wekelijkse meeting. Een alert waar niemand op heeft gehandeld, wordt diezelfde week verwijderd of bijgesteld.