Een trace lezen¶
Het concept achter verbruik, audit en traces staat in Inzicht.
Een trace laat zien welk verzoek Core naar een modelleverancier stuurde en welk antwoord terugkwam. Core voegt daar een leesbare interpretatie aan toe. Gebruik traces om een onverwacht antwoord of een ontbrekende toolaanroep te onderzoeken.
Core kan meerdere modelaanroepen doen voor één beurt, bijvoorbeeld tijdens toolrondes. Elke
modelaanroep krijgt een eigen trace. Dat geldt ook voor verzoeken met store: false.
Je sleutel heeft hiervoor geen aparte capability nodig. De opslag van traces moet wel zijn ingeschakeld voor de installatie en de organisatie. Een trace kan de volledige invoer en uitvoer bevatten; houd daarmee rekening bij het instellen van opslag en bewaartermijnen.
De twee routes¶
| Route | Wat die beantwoordt |
|---|---|
GET /responses/{response_id}/trace |
de aanroepen van één beurt, oudste eerst, met een fallover-poging als eigen regel |
GET /traces/{call_id} |
één aanroep, met het document erachter |
De lijst is een pagina zoals elke andere lijst in deze API: ?limit= en ?cursor= erin,
{items, next_cursor} eruit (Verzoeken). Er wordt geen opgeslagen byte gelezen en
geen auditregel geschreven.
curl -s https://<jouw-core>/api/v1/responses/resp_01J.../trace \
-H "Authorization: Bearer $ARTIFIC_API_KEY"
Elke regel draagt het id van de aanroep, de soort, het model dat je vroeg en het model dat antwoordde, hoe het afliep, wanneer het begon en klaar was, de tokens die de leverancier meldde, de omvang van het document, en of dat document is afgekapt.
En de gereedschapsuitvoeringen waar het antwoord van die aanroep om vroeg, als tool_calls op
de regel zelf. Eén pagina van een beurt is daarmee de hele boom — beurt, ronde, en wat elke ronde
uitvoerde — zonder tweede verzoek. Elke uitvoering noemt het gereedschap, waar het vandaan kwam,
hoe het afliep (ok, error, denied of cancelled), de vaste code achter een mislukking, de
status die de bestemming van het gereedschap antwoordde als die er was, wanneer het liep, en welke
modelaanroep het resultaat ontving. Een aanroep waarvan het antwoord om geen gereedschap vroeg
draagt een lege lijst. Gereedschap dat je eigen toepassing uitvoert — een function-gereedschap —
heeft hier geen regel: Core heeft het nooit uitgevoerd. Een tool die het model via de
toolrouter bereikte, staat onder zijn eigen naam met routed: true,
en elke zoekopdracht van de router draagt in refs hoeveel tools hij rangschikte (candidates),
zijn hits met hun score, en keyword_only als hij alleen op trefwoord rangschikte.
Wat een document bevat¶
GET /traces/{call_id} antwoordt met dezelfde aanroep én een document ernaast, in drie delen.
request is de body die de leverancier kreeg, in de vorm van die leverancier zelf — een OpenAI
chat.completions-body, een Anthropic messages-body — en niet Core's kijk daarop. observed
zegt of dit de bytes zijn die op de lijn stonden of de payload die de client klaarzette, voor de
twee families waarvan Core de verbinding niet kan meekijken. headers_omitted is altijd true: er
wordt geen enkele request-header vastgelegd, en daarom kan geen sleutel van jou of van Core hierin
staan.
response is het rauwe antwoord van de leverancier: de uiteindelijke body, of — bij een
gestreamde aanroep — de fragmenten op volgorde en geen samengestelde body, want het samenstellen
van een event-stream is het protocol van de leverancier en niet haar antwoord. Een mislukte aanroep
draagt de eigen foutbody van de leverancier, waar Core die kan lezen.
interpretation is de lezing van Core van diezelfde aanroep:
elements— elk contextelement in de volgorde waarin het is verstuurd, metauthority(core,developer,delegate,user,model),trust(trustedofuntrusted), waar het vandaan kwam, de rijen erachter insource_ids, en een JSON-pointer naar de tekst ervan inrequest.body. Volgtext_refde body in en je leest de woorden van het element uit precies de bytes die de leverancier kreeg; de pointer wijst in de vorm van die leverancier, dus in een Anthropic-body leidt hij naarsystemof naar een blok vanmessagesen in een Gemini-body naarcontents. Een legetext_refbetekent dat Core het element niet kon plaatsen — nooit een gok.authorityentrustzijn wat Core over het element wist, niet wat het model te horen kreeg: de lijst begint alleen met een inleidingselement als de sleutel van de beurttrust_envelopeheeft, en zonder die capability is eenuntrusted-element als gewone tekst verstuurd.elements[].tool_calls— wat een ronde aanvroeg, als zij iets aanvroeg: de naam van het gereedschap, het aanroep-id van het model zelf, enarguments_ref, een pointer naar de argumenten zoals de leverancier ze kreeg. Een ronde die alleen gereedschap aanriep heeft geen eigen tekst, duscharactersis0entext_refis leeg — de aanroepen zijn wat die ronde was.pseudonyms— elke plaatshouder die in die elementen staat, met het soort gegeven en de posities (Persoonsgegevens verbergen).tools— elke tool waar deze aanroep over besliste, metoffered,denied_by_policy,withheld_by_capability,withheld_for_subject(bedoeld voor een ander subject, zoals de eigen mailbox van een serviceaccount),hidden_argumentsofrouted(achter de toolrouter) en de vaste reden erbij. Juist de tools die niet zijn aangeboden beantwoorden meestal "waarom gebruikte het model die tool niet".blocks— de geheugen- en samenvattingsblokken die naast je eigen berichten zijn ingevoegd, met de rijen waar elk blok van gemaakt is. Bij geheugen isdropped_by_counthet aantal passende records dat een aantal wegliet (de limiet van de sleutel, van een opslag of het plafond van de installatie),dropped_by_budgethet aantal dat niet in het tokenbudget paste of in wat het plafond van de beurt overliet, enestimated_tokenswat het blok kost. Eenskills-regel, zonder tekst, noemt de skills die op inhoud zijn toegevoegd: dedropped_by_countervan is het aantal passende skills datretrieval_top_kwegliet, enestimated_tokenswat de toegevoegde teksten kosten. Eentools-regel, zonder tekst, noemt inrecord_idsde tools die de router vooraf voor deze beurt koos, met dezelfde drie aantallen.routing— de keten waarlangs deze beurt mocht terugvallen, welk model is geprobeerd en welk model antwoordde (Terugvallen).answer— wat het model antwoordde: de tekst, een weigering, de samenvatting van de redenering en de tool-aanroepen die het vroeg, met hun argumenten. Alleen geschreven als de aanroepokeindigde en alleen voor een chataanroep, dus een mislukte aanroep, een embedding of een afbeelding heeft er geen.recovery— bij een aanroep die het model opnieuw vroeg om een antwoord waarvoor een live check faalde:attempt, de poging waarvoor de tekst van deze aanroep wordt gecontroleerd (vanaf 2), encheck, de eerste check waarvoor het eerdere antwoord faalde. Het afgewezen antwoord blijft in de trace van de eerdere aanroep en komt nooit in het gesprek. Null bij elke andere aanroep.
Een transcriptie¶
Een opname die een audiomodel transcribeerde, is een aanroep van de soort transcription. Maakte
de transcriptietool haar, dan hoort ze bij de beurt die de tool aanriep. Gemaakt op
POST /audio/transcriptions of voor een input_audio-deel is ze een eigen taak (job), van de
soort audio.transcription, met het request-id als id. Haar document verschilt op één punt van
dat van een modelaanroep: geen van de secties bevat wat de leverancier ontving of antwoordde.
request bevat Core's eigen samenvatting van wat er werd verstuurd (het model, het mediatype en de
grootte in bytes van de opname, de taal, de prompt en de temperatuur), en response bevat de
lengte van het transcript in tekens en de seconden audio. De opname en de woorden erin staan nooit
in een trace. Zie Audio transcriberen.
Nooit in een trace¶
- Geen enkele sleutel. Jouw API-sleutel, een leverancierssleutel, een credential-header van een tool: dat zijn allemaal headers, en er wordt geen header gelezen.
- Niet waar een plaatshouder voor staat. Een pseudoniem draagt de plaatshouder, het soort
gegeven en twee posities. Wil je de waarden, vraag dan de pseudoniemen van het gesprek zelf op
(Persoonsgegevens verbergen); die route bestaat daarvoor en legt het lezen
vast. Een beurt waarvan de gebeurtenis
pseudonymisation.appliedeenrenumberedboven nul heeft, is de uitzondering: de plaatshouders daarvan zijn daar niet op te zoeken. - Niets van een andere organisatie.
Traces zijn jouw inhoud¶
Een trace valt onder de bewaartermijn van je organisatie, net als al het andere dat je aanroepers stuurden, en je beheerder mag traces een kortere eigen termijn geven — nooit een langere, want Core ruimt een trace op bij de termijn die het eerst komt. Het wissen van één persoon neemt de traces van die persoon mee (Bouwen voor mensen); het verwijderen van de organisatie neemt ze allemaal mee.
Hun omvang wordt los van je bestanden gemeld, als trace_bytes op GET /usage/summary
(Gebruik en audit via de API): een maand gesprekken is klein en een maand aan de bodies erachter
niet, dus die twee getallen worden nooit bij elkaar opgeteld.
Een document lezen is een gebeurtenis¶
Zien dát een aanroep bestaat is gratis. Het document lezen niet: elke GET /traces/{call_id}
schrijft één trace.read-auditgebeurtenis met de lezer en het id van de aanroep, of die lezer nu
een sleutel is, iemand die is ingelogd in de console, of een operator. Het is de eerste
gebeurtenis in het spoor van Core die vastlegt wat er gezien is in plaats van wat er gedaan is,
en je vindt hem terug in je eigen auditspoor (Gebruik en audit via de API).
Een gesprek openen in de console is dezelfde daad, meerdere keren: daarbij wordt het document van
elke aanroep van de beurten op die pagina gelezen, dus schrijft het één trace.read-gebeurtenis
per aanroep in plaats van één voor de pagina.
Wat een sleutel mag lezen¶
Een sleutel leest de traces van de aanroepen die zij deed. Noemt je applicatie een persoon op haar
aanroepen (Bouwen voor mensen), dan leest een credential dat aan één
persoon vastzit de traces van die persoon, en -- waar je deployment groepsgesprekken op basis van
regels aanzet (threads_group_reach_by_rule, standaard uit) -- de traces van elke beurt in een
gesprek dat een regel die de persoon noemt haar laat zien: in een gesprek waarin meerdere mensen
schrijven leest ieder ook de
traces van de beurten van de anderen. De lijst met aanroepen van een beurt toont nooit een
aanroep waarvan het document lezen geweigerd zou worden. Een aanroep voor niemand blijft van je
sleutel: die van een indexeerrun overal, en in een gesprek dat een persoon mag lezen een
samenvatting van een lang gesprek of een beurt die je backend deed zonder een persoon te noemen.
Dat geldt ook voor elke aanroep in een gedeeld gesprek waarop geen regel de persoon noemt. Elke
keer dat een document wordt gelezen, wordt vastgelegd wie het las.
Heeft je organisatie het vastleggen uitgezet, dan worden nieuwe aanroepen niet vastgelegd; wat al vastligt blijft leesbaar tot een bewaartermijn het opruimt.
Dezelfde aanroepen in de console¶
Wie je organisatie beheert leest alles ervan in het onderdeel Traces van de organisatie, met filters en de drie weergaven van één document (Instellingen van een organisatie).

Dat onderdeel opent op Gesprekken in plaats van op de aanroepen: de aanroepen van de organisatie, gegroepeerd naar het gesprek, de losse beurt of de klus waar ze bij horen, met de laatste activiteit eerst, en per groep de beurten, aanroepen en gereedschappen met de mislukkingen daaronder gemarkeerd. Een gesprek opent als de pagina hieronder; een losse beurt en een klus openen de weergave Aanroepen, teruggeknipt tot precies hun eigen aanroepen, want geen van beide heeft een eigen pagina. Beide weergaven nemen dezelfde filters, dus ze gaan altijd over dezelfde aanroepen: de periode staat in de paginabalk, soort, afloop en model in de rij boven de lijst, en Meer filters opent de persoon, het gereedschap, de uitkomst daarvan, de klus en de response. Elk filter dat geldt is een chip die je los weghaalt, en Wis filters haalt ze allemaal weg. Op een telefoon opent Filters in de balk alle filters tegelijk.
Zoek in de berichten met het vak boven Gesprekken: typ woorden en kies Zoeken, en de lijst toont de berichten waarin ze staan in plaats van de groepen, nieuwste eerst, elk met wie het schreef, de woorden rond de overeenkomst gemarkeerd, de persoon en een link naar het gesprek. De periode, de persoon en de response beperken de zoekopdracht; soort, afloop, model en tool gaan over aanroepen en tellen niet mee zolang je zoekt. Een pagina leest een vast deel van de geschiedenis, dus als ze nog niets vond zegt ze hoe ver terug ze keek en biedt ze Zoek verder terug aan. Elke zoekopdracht komt in het auditlog met de gevonden berichten, nooit met de woorden die je typte.

Op de pagina van een gesprek toont de kaart van een gereedschap onder Variabelen bij de aanroep de
namen van de aanroepvariabelen die het gereedschap uit de tool_variables van het verzoek kreeg, de
geheime gemarkeerd, en nooit een waarde: geen enkele trace bewaart er een (Een waarde van je klant
aan een tool meegeven).
De pagina van één aanroep toont daar hetzelfde document, maar dan om te lezen. De kop noemt het
model dat antwoordde en hoe de aanroep afliep, dan de gegevens van de aanroep als tegels —
leverancier, keten, tokens, duur, time to first token en tokensnelheid, de grootte van het
document, de ronde, de fout en de klus — en het request-id en trace-id om te kopiëren; elke
aanroep van dezelfde beurt is één klik weg. Op de weergave Context staan een lang element en
elk gereedschapsresultaat ingeklapt met een knop en hun eerste regels, de gereedschapsaanroepen van
een ronde staan er mét hun argumenten, en naast de elementen staan de gereedschappen die deze
aanroep kreeg of niet kreeg, de blokken die Core invoegde en de placeholders die de aanroep
droeg. De <untrusted source="…">-omslag waarin Core onvertrouwde tekst verpakt voor een sleutel
met trust_envelope is daar in de labels gevouwen — de
weergave Verzoek houdt de bytes precies zoals ze verstuurd zijn. Een beurt waarvan de sleutel
de capability niet heeft, kreeg geen omslag mee: daar wordt niets gevouwen en staat elk element er
als de tekst die het is, onder dezelfde labels voor autoriteit en vertrouwen. Een melding boven de
elementen, en op de pagina van het gesprek bij het bericht van die beurt, zegt dat de aanroep
zonder omslag ging, en elk label Onvertrouwd luidt daar Onvertrouwd · niet ingepakt: de tekst
kwam van buiten, maar het model kreeg dat niet te horen. De weergave
Antwoord toont interpretation.answer — wat het model zei, een weigering, de samenvatting van
de redenering en de aanroepen waar het antwoord om vroeg, het enige deel van een gestreamde aanroep
dat nergens anders bestaat — naast de bytes die terugkwamen. Kwamen de eerste en de laatste byte
minder dan 100 ms na elkaar, dan staat bij Tokens per seconde niet gestreamd: een snelheid
over zo'n kort venster heeft niemand gemeten. De time to first token staat er wel.
En een gesprek lees je als gesprek. Het gesprek op een rij opent een eigen pagina, in twee kolommen. Links staat het gesprek zelf, de oudste bovenaan en de nieuwste onderaan, en de pagina opent onderaan: de instructies die het gesprek meekreeg, dan een groep per beurt — het bericht van de persoon, en daaronder wat het model deed: het denkwerk, elk gereedschap dat het draaide als één blok van wat er gevraagd werd en wat terugkwam, en het antwoord dat terugging. Een compaction-run die Core zelf startte is een eigen groep, op de plek waar hij gebeurde. Klap een groep in tot zijn kop, of toon met de chips boven de lijst alleen de asynchrone tools, de toolaanroepen, de kenniszoekacties, de geheugengereedschappen, de compactionstappen of wat mislukte. Rechts staat de kaart die je aanklikt, helemaal uitgeschreven en alleen die kaart: een bericht toont wat de persoon stuurde en niet het antwoord, en het denkwerk van de aanroep die antwoordde houdt op vóór het antwoord, want het antwoord is een eigen kaart. De kaart staat in de link, en op een telefoon opent hij op een eigen scherm. Elke kaart zegt van wie de woorden zijn en of Core ervoor kon instaan, en precies daarom draagt het blok van een gereedschap twee sets labels: het model schreef de argumenten, en voor wat een gereedschap teruggeeft staat niemand in. Een gereedschap dat het niet deed zegt waarom in de vaste woorden van Core, naast de status die de bestemming zelf antwoordde, en elke pseudoniem-placeholder is gemarkeerd waar hij staat — nooit waar hij voor staat. Een modelaanroep leidt naar haar eigen pagina, en een gereedschap leidt naar de aanroep wiens antwoord erom vroeg. Eerdere beurten laad je bovenaan, waar ze horen.
Gereedschap dat je eigen toepassing uitvoert, staat er ook in. Core voert een
function-gereedschap nooit uit, dus het heeft geen uitvoering, maar het gesprek tekent de aanroep
waar het model erom vroeg, als een blok met Uitgevoerd door je app: de argumenten die het model
schreef, en als resultaat wat je toepassing als function_call_output terugstuurde, zoals de
volgende aanroep het kreeg. Zolang je toepassing niets terugstuurde, of als de aanroep die het
ontving niet op de pagina staat, zegt het resultaat dat. De kaart van het bericht van een beurt
noemt ook de Aangeboden tools: elke tool waar de eerste aanroep over besliste, met waar hij
vandaan kwam — system, http, mcp, retrieval of client — zoals de pagina van een aanroep
ze noemt.
Beantwoordt je toepassing zo'n aanroep door de response voort te zetten met alleen haar
function_call_output, dan heeft de beurt die volgt geen eigen bericht: de kop zegt Je app gaf
het resultaat van show_chart terug. in plaats van te herhalen wat de persoon de beurt ervoor zei.
Een gereedschap dat op de achtergrond loopt, staat er van start tot resultaat. Startte een beurt een asynchrone tool, dan zegt het blok daarvan Asynchroon met het job-id, en een regel Later eronder zegt hoeveel later het resultaat binnenkwam en of dezelfde beurt of een latere het las, dat nog geen beurt het las, dat de taak zonder resultaat eindigde, of dat het nog loopt, wat een melding boven het gesprek dan ook zegt. De beurt die het resultaat las, toont waar het landde, met de weg terug naar de start, en een beurt die Core zelf startte om een resultaat te beantwoorden staat er met een bel en Gewekt door een asynchroon resultaat, en de kaart leidt terug met Naar de beurt die het startte. Hoe een tool zo gaat draaien, staat op Een tool op de achtergrond draaien.
Deze pagina leest de documenten, en dat wordt vastgelegd. De lijst van Traces leest alleen rijen en
schrijft niets; een gesprek openen leest per aanroep van de pagina één document, en elk daarvan is
een regel trace.read in het audittrail met de naam van de lezer erbij. De pagina zegt dat boven de
kolommen.
Publiceert jouw omgeving een telemetrieconsole, dan is het trace-id van een aanroep ook een link rechtstreeks naar de spans van die trace; publiceert ze er geen, dan is het id tekst die je kopieert naar de console die je wél gebruikt.