Een beurt op de achtergrond draaien¶
Stel "background": true in om een beurt te starten en het resultaat later op te halen. Core geeft
direct een antwoord-id terug. Gebruik achtergrondruns voor lange taken, zoals meerdere toolrondes of
grote zoekopdrachten, of voor geplande taken.
Je sleutel heeft zowel runs als threads nodig. Een verzoek met background geeft 400 op
background terug als runs is uitgeschakeld. Achtergrondruns moeten worden opgeslagen; stel daarom geen store:
false in.
Wil je de uitvoer tonen terwijl die binnenkomt, gebruik dan streamen. Streamen en uitvoeren op de achtergrond kunnen niet samen in één verzoek.
Werk dat je een serviceaccount geeft, draait als achtergrondrun.
Een taak starten¶
curl -s -X POST "$CORE_URL/responses" \
-H "Authorization: Bearer $CORE_KEY" -H "Content-Type: application/json" \
-d '{"model": "<een model-id>", "background": true,
"input": "Vat elk open ticket van Acme samen.",
"callback_url": "https://jouw-app.example/core-callbacks"}'
Core geeft 201, een Location-header en "status": "queued" terug. De modelaanroep begint zodra
de run wordt opgepakt. De optionele callback_url ontvangt statusmeldingen.
Een kostenlimiet instellen¶
Voeg cost_limit_eur toe om te begrenzen wat één run mag uitgeven, in euro: een getal of een
decimale string boven nul, hoogstens 1.000.000, met hoogstens zes decimalen.
curl -s -X POST "$CORE_URL/responses" \
-H "Authorization: Bearer $CORE_KEY" -H "Content-Type: application/json" \
-d '{"model": "<een model-id>", "background": true, "cost_limit_eur": "2.50",
"input": "Vat elk open ticket van Acme samen."}'
De limiet geldt voor de run zelf, de agenttaken die hij start en hun runs, de agents die hij als
tool aanroept, en de beurten die Core start om op zijn taken te antwoorden. Voor elke modelaanroep
telt Core op wat die samen hebben uitgegeven, tegen de prijzen van je organisatie. Zodra dat de
limiet bereikt, stopt de run: hij eindigt incomplete met incomplete_details.reason:
"cost_limit", en wat hij tot dan toe opleverde blijft bewaard en wordt afgerekend. Een modelaanroep
die al loopt, wordt eerst afgemaakt, dus wat er uiteindelijk is uitgegeven kan iets boven de limiet
uitkomen. Een taak waarvan de run door de limiet is gestopt, mislukt met cost_limit.
- De limiet wordt alleen geaccepteerd met
"background": true; bij elk ander verzoek geeft hij400, net als een bedrag buiten de grenzen. - Core stelt zelf geen limiet in. Wil je elke run begrenzen, stuur dan bij elk verzoek
cost_limit_eurmee. - Het antwoord laat de limiet terugzien als
cost_limit_eur. - De maandlimieten van je sleutel en je organisatie gelden ernaast gewoon door.
Het resultaat opvragen¶
curl -s "$CORE_URL/responses/resp_0KQ2mR..." -H "Authorization: Bearer $CORE_KEY"
Vraag de status om de paar seconden op. Het endpoint ondersteunt geen long polling. Een geslaagde
run gaat van queued naar in_progress en daarna naar completed. Het veld usage wordt tijdens
de uitvoering bijgewerkt.
status |
Volgende stap |
|---|---|
queued, in_progress |
Vraag de status later opnieuw op. |
completed |
Lees output. |
failed |
Lees error.code. |
incomplete |
De run heeft de limiet voor toolrondes of zijn kostenlimiet bereikt, of het model bereikte zijn uitvoerlimiet (Een afgekapt antwoord). incomplete_details.reason zegt welke. |
requires_action |
Stuur de resultaten van de openstaande toolaanroepen in, of beslis over elk mcp_approval_request in output (Een toolaanroep laten goedkeuren). |
cancelled |
Je hoeft niets meer te doen. |
Callbacks ontvangen¶
Core stuurt een statusmelding naar callback_url als de run eindigt of wacht op toolresultaten:
{ "type": "response.status", "response_id": "resp_...", "status": "completed", "request_id": "req_..." }
Haal het resultaat op met GET /responses/{id} en je API-sleutel. De callback bevat een verwijzing
naar het antwoord, niet de uitvoer zelf.
Elke aflevering bevat User-Agent: artific-core en een vaste Idempotency-Key. Gebruik die sleutel
om herhaalde afleveringen van dezelfde melding te herkennen. Heeft je sleutel een callbackgeheim,
dan bevat elke aflevering ook Artific-Signature; zie
Een callback verifiëren.
Wil je over elke run van je organisatie horen via één verbinding of één webhook, in plaats van één callback per run, gebruik dan events.
De host van de callback moet een http- of https-host zijn die bij de
toegestane hosts van je organisatie
staat; regels over hosts in de policy van je sleutel gelden er ook voor. Core stuurt een callback
nooit naar een adres op een privénetwerk. Een sleutel met een regiobeperking bereikt
alleen een callbackhost die de policy in een van die regio's plaatst. Core controleert de host bij
het aanmaken van de run en opnieuw voor het versturen van de callback. Wordt de host bij het
aanmaken geweigerd, dan krijg je 403 en wordt er geen run aangemaakt. Geeft de callback geen
2xx-antwoord, dan probeert Core het opnieuw met steeds langere wachttijden. Core stopt met herhalen
als de host niet meer is toegestaan.
Een callback verifiëren¶
Een callback wordt alleen ondertekend voor een sleutel die een callbackgeheim heeft. Maak er een aan voor de sleutel waarmee je runs start:
curl -s -X POST "$CORE_URL/key/callback-secret" \
-H "Authorization: Bearer $CORE_KEY"
{ "object": "api_key.callback_secret", "key_id": "key_...", "secret": "whsec_..." }
Bewaar het geheim meteen; Core toont het niet opnieuw. GET /key zegt alleen
callback_secret_set. Een sleutel met management doet hetzelfde voor een andere sleutel van zijn
organisatie met POST /keys/{key_id}/callback-secret, en voor een sleutel van een organisatie
eronder met POST /organisations/{organisation_id}/keys/{key_id}/callback-secret
(Sleutels uitgeven, roteren en intrekken).
Wordt het verzoek geweigerd, dan is er niets opgeslagen en houdt de sleutel het geheim dat hij had:
| Status | Wat het betekent | Wat je doet |
|---|---|---|
503 |
deze installatie heeft geen sleutel om het geheim mee te verzegelen | vraag het de operator van de installatie |
409 |
de sleutel wordt door een ander verzoek gewijzigd | probeer het opnieuw |
403 |
op /key/callback-secret: het verzoek is met een subject-token gedaan. Op een route die een sleutel noemt: de bovenliggende organisatie heeft sleutelbeheer voorbehouden |
roep aan met de API-sleutel zelf, of vraag het de bovenliggende organisatie |
404 |
op een route die een sleutel noemt: de sleutel is er geen die je kunt bereiken, of je sleutel heeft geen management |
controleer het sleutel-id en de capabilities van de aanroepende sleutel |
Vanaf dat moment bevat elke callback van die sleutel
Artific-Signature: t=<unix-seconden>,v1=<handtekening>, dezelfde header en dezelfde handtekening
als een event-webhook. Controleer hem met de functie onder
De handtekening controleren, over de ruwe bytes van de body, en weiger een
callback die zonder de header binnenkomt.
- Een sleutel zonder callbackgeheim blijft callbacks zonder handtekening sturen. Zie zo'n callback als een seintje om de run op te halen, en lees het resultaat met je eigen sleutel in plaats van op de inhoud te vertrouwen.
- Roep je de route opnieuw aan, dan vervangt Core het geheim. Callbacks die daarna worden verstuurd, ook herhalingen, kloppen alleen nog met het nieuwe geheim.
- Het callbackgeheim staat los van de secret van de sleutel zelf: de sleutel roteren laat het ongemoeid, en de sleutel verwijderen verwijdert het.
- Kan Core het opgeslagen geheim niet lezen, dan stuurt het voor die run geen callback in plaats
van een callback zonder handtekening. Vraag
GET /responses/{id}op als een verwachte callback uitblijft.
Toolresultaten indienen¶
Een run pauzeert op requires_action als je applicatie een tool moet uitvoeren. Stuur de resultaten
in om de run te hervatten:
curl -s -X POST "$CORE_URL/responses/resp_0KQ2mR.../tool_outputs" \
-H "Authorization: Bearer $CORE_KEY" -H "Content-Type: application/json" \
-d '{"outputs": [{"call_id": "call_9x...", "output": "{\"open\": 12}"}]}'
Lever precies één resultaat per openstaande aanroep aan. Ontbrekende of extra resultaten geven
400. Wacht de run niet op resultaten, dan krijg je 409. Na een geaccepteerde inzending gaat de
run terug naar queued.
Core controleert het huidige beleid bij het hervatten. Tools waar je sleutel geen toegang meer toe heeft, worden niet uitgevoerd.
De runs van een serviceaccount opvragen¶
Een serviceaccount werkt zelfstandig op de achtergrond:
de schema's ervan gaan af, andere sleutels geven het werk, en de eigen sleutel start beurten. Een
sleutel met management en threads haalt alle runs van het account op, de nieuwste eerst. Een eigen index
bijhouden is dus niet nodig:
curl -s "$CORE_URL/service-accounts/sva_0KQ2mR.../responses?status=requires_action" \
-H "Authorization: Bearer $CORE_KEY"
Elk item noemt het id van de run, de status, created_at, completed_at, thread_id, het
schedule_id dat de run startte, en de sleutel en persoon die het werk overdroegen
(instructed_by_key_id, instructed_by_subject_id). De uitvoer lees je met
GET /responses/{id}. Je beperkt de lijst met:
| Parameter | Houdt over |
|---|---|
status |
runs met die status; herhaal de parameter voor meer statussen, bijvoorbeeld ?status=requires_action&status=failed |
schedule_id |
runs die dat schema startte |
from, to |
runs gemaakt vanaf from (inclusief) tot to (exclusief); een to vóór from geeft 422 |
De lijst pagineert met limit en cursor, zoals elke andere lijst. Je ziet alleen de runs die de
regels van je sleutel laten zien, net als bij GET /responses/{id}. Een account van een andere
organisatie geeft 404. De eigen sleutel van het account, die nooit management heeft, en een
subjecttoken kunnen deze route niet gebruiken.
Een toolaanroep laten goedkeuren¶
Voeg tool_approval toe als een persoon toolaanroepen moet goedkeuren voordat ze worden
uitgevoerd. Geef elke tool een modus: always wacht elke keer op een persoon, never wordt meteen
uitgevoerd en model laat het model beslissen, volgens je instructies. Tools die je niet noemt,
krijgen default, en dat is never.
curl -s -X POST "$CORE_URL/responses" \
-H "Authorization: Bearer $CORE_KEY" -H "Content-Type: application/json" \
-d '{"model": "<een model-id>", "background": true,
"tools": [{"type": "tool", "name": "mail__acme-support__search"},
{"type": "tool", "name": "mail__acme-support__send"},
{"type": "tool", "name": "api__acme-crm"}],
"tool_approval": {"timeout_seconds": 2592000,
"tools": [{"name": "mail__acme-support__*", "approval": "always"},
{"name": "mail__acme-support__search", "approval": "never"},
{"name": "api__acme-crm", "approval": "model"}]},
"instructions": "Vraag goedkeuring voordat je een klantrecord wijzigt.",
"input": "Stuur Acme de herinnering voor de achterstallige factuur."}'
nameis de naam van een tool zoals het verzoek die aanbiedt, of een glob over namen in dezelfde vorm als bij een toolset (*,?,[...]). Een API-connector is één tool,api__<connector>; een mailconnector heeft één tool per bewerking,mail__<connector>__<bewerking>. Een exacte naam gaat voor elke glob, dus hierboven wacht elkemail__acme-support__-tool behalvesearch. Passen meerdere globs op één tool, dan telt de strengste modus (always, danmodel, dannever), in welke volgorde ze ook staan.- Elke naam mag één keer voorkomen en elk item moet passen op een tool die het verzoek aanbiedt;
anders geeft het verzoek
400met het item erbij. Daarom noemt het verzoek hierboven zijn tools. - Aanroepen van een agenttool en van
builtin__subagentwachten altijd, welke modus ze ook hebben, tenzij een item die tool exact bij naam noemt met"never". Een glob ofdefaultlaat ze niet door. Heeft de agent van de run zelftool_approval, dan moet de exacte"never"in elke optie staan die de tool noemt, die van de agent en die van jou. builtin__tool_searchwacht nooit, welke modus het ook heeft: het zoekt alleen in de tools die je sleutel mag gebruiken en voert er geen uit.
Voor een tool in de modus model voegt Core één extra verplichte parameter toe, request_approval.
Het model zet die op true voor een aanroep die goedkeuring nodig heeft. Core haalt de parameter
weg voordat de aanroep wordt uitgevoerd, dus je tools krijgen hem nooit. Een aanroep met true, of
een waarbij het model de parameter wegliet, wacht; alleen false wordt meteen uitgevoerd. Een
custom (freeform) tool in de modus model krijgt geen request_approval-parameter en wacht altijd.
Gewijzigd op 2026-10-23: wat {} betekent
Vóór de modus per tool liet "tool_approval": {} het model voor elke tool beslissen. Nu wacht
niets, behalve aanroepen van agenttools en builtin__subagent. Stuur {"default": "model"}
voor het oude gedrag. Runs die vóór de wijziging in de wachtrij stonden en schema's die toen
al bestonden, houden het gedrag dat ze hadden.
Wacht een aanroep, dan gaat de run naar requires_action, krijgt je callback_url bericht en staat
run.approval.requested in de eventfeed. De output van de run toont elke wachtende aanroep als een
mcp_approval_request-item:
{"id": "apr_0KQ3...", "type": "mcp_approval_request", "server_label": "api",
"name": "api__mailer__send", "arguments": "{\"to\":\"billing@acme.example\"}"}
Beslis met de id van het item:
curl -s -X POST "$CORE_URL/responses/resp_0KQ2mR.../approvals/apr_0KQ3..." \
-H "Authorization: Bearer $CORE_KEY" -H "Content-Type: application/json" \
-d '{"approve": false, "reason": "Wacht tot de betaalrun van vrijdag."}'
{"approve": true}voert de aanroep uit.{"approve": false}voert hem nooit uit; het model leest jereason, hoogstens 2.000 tekens, als resultaat van de aanroep.- De eerste beslissing telt. Een tweede beslissing over dezelfde aanroep, of een beslissing over een
run die niet meer wacht, geeft
409. - Is over elke wachtende aanroep beslist, dan gaat de run terug naar
queued. Goedgekeurde aanroepen worden uitgevoerd vóór de volgende stap van het model, onder het beleid dat je sleutel op dat moment heeft. timeout_seconds(60 tot 31.536.000) is hoe lang één keer wachten mag duren. Is die tijd om, dan mislukt de run metapproval_expired. Laat hem weg om zonder deadline te wachten: een aanroep wacht dan zolang de run bestaat.- Zolang een aanroep wacht, geeft
tool_outputs409: beslis eerst en stuur daarna de resultaten in waar de run om vraagt. tool_approvalwordt alleen geaccepteerd met"background": true. Agenttaken die de run start, wachten op dezelfde manier op goedkeuring.- Een agent kan zelf
tool_approvalhebben (Agents via de API). Je verzoek kan het dan alleen strenger maken.
Wie er gevraagd wordt, hoe die herinnerd wordt en op welk scherm die antwoordt, bepaalt je applicatie.
Een taak annuleren¶
curl -s -X POST "$CORE_URL/responses/resp_0KQ2mR.../cancel" -H "Authorization: Bearer $CORE_KEY"
Annuleren werkt tussen toolrondes. Een lopende aanroep wordt afgerond voordat de run stopt. Een run
annuleren die al is afgelopen geeft 409. Een run die al geannuleerd was, geeft zichzelf terug,
zonder fout. Een gestreamde beurt annuleer je op dezelfde manier; zie
Een gestreamde beurt stoppen.
Mislukte taken¶
Een run kan mislukken als rechten of resources tijdens de uitvoering veranderen:
error.code |
Betekenis |
|---|---|
key_revoked |
De sleutel is verwijderd. |
tenant_unavailable |
De organisatie, of een organisatie erboven, is opgeschort, of de organisatie wordt verwijderd. De run wordt niet alsnog opgepakt als de opschorting wordt opgeheven; stuur hem opnieuw. |
usage_cap_exceeded |
De maandlimiet van je sleutel of van je organisatie was bereikt voordat een ronde begon. De rondes die de run al had afgerond blijven bewaard. Een ronde die de limiet halverwege stopt, eindigt de run in plaats daarvan incomplete, met incomplete_details.reason: "usage_cap_exceeded". |
capability_withdrawn |
runs of threads is uitgeschakeld voor de sleutel. |
tool_unavailable |
Een tool die aan de run is aangeboden bestaat niet meer. |
egress_denied |
Een benodigde bestemming is niet meer toegestaan. |
agent_required |
Terwijl deze run wachtte, is het beleid van de sleutel een agent gaan vereisen, of is een regel een beurt zonder agent gaan verbieden voor de persoon voor wie hij is, en het verzoek noemde er geen. Stuur het opnieuw met een van de agents van de sleutel. |
model_denied |
Het model mag niet meer door deze sleutel worden gebruikt, of draait niet meer in de regio die het verzoek vroeg. Kijk met GET /models welke modellen de sleutel nu mag aanroepen, en laat hosting.region weg of kies een regio die past. |
approval_expired |
Een aanroep wachtte langer dan timeout_seconds op goedkeuring en niemand besliste erover. Na die aanroep zette de run geen stap meer. |
reaped_too_often |
De worker die de response uitvoerde stopte drie keer achter elkaar zonder een ronde af te maken, dus heeft Core hem opgegeven in plaats van het eindeloos opnieuw te proberen. Stuur hem opnieuw; mislukt hij op dezelfde manier, dan is het verzoek zelf wat de worker laat stoppen, dus meld het bij je beheerder. |
Beperkingen¶
- MCP-autorisatieheaders per verzoek. Core slaat deze headers niet op. Gebruik een MCP-server die geen inloggegevens per verzoek nodig heeft.
- Afbeeldingen. Achtergrondtaken kunnen momenteel geen afbeeldingsinhoud laden, ook niet via een
file_idvan een upload. Gebruik een synchrone aanroep voor afbeeldingen of geef een tekstbeschrijving mee.