Ga naar inhoud

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 hij 400, 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_eur mee.
  • 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."}'
  • name is 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 elke mail__acme-support__-tool behalve search. Passen meerdere globs op één tool, dan telt de strengste modus (always, dan model, dan never), 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 400 met het item erbij. Daarom noemt het verzoek hierboven zijn tools.
  • Aanroepen van een agenttool en van builtin__subagent wachten altijd, welke modus ze ook hebben, tenzij een item die tool exact bij naam noemt met "never". Een glob of default laat ze niet door. Heeft de agent van de run zelf tool_approval, dan moet de exacte "never" in elke optie staan die de tool noemt, die van de agent en die van jou.
  • builtin__tool_search wacht 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 je reason, 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 met approval_expired. Laat hem weg om zonder deadline te wachten: een aanroep wacht dan zolang de run bestaat.
  • Zolang een aanroep wacht, geeft tool_outputs 409: beslis eerst en stuur daarna de resultaten in waar de run om vraagt.
  • tool_approval wordt alleen geaccepteerd met "background": true. Agenttaken die de run start, wachten op dezelfde manier op goedkeuring.
  • Een agent kan zelf tool_approval hebben (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_id van een upload. Gebruik een synchrone aanroep voor afbeeldingen of geef een tekstbeschrijving mee.