Planningen via de API¶
Het concept achter agents staat in Agents.
Op deze pagina maak je een planning met de API, lees je wat ze opleverde en wijzig of stop je haar. Een planning is werk dat je één keer opslaat en dat Core op een vast moment voor je doet: een verzoek dat Core verstuurt, of een evaluatiesuite die Core laat lopen (verderop). Het meeste van deze pagina gaat over het eerste: elke werkdag om zes uur een samenvatting, maandagochtend een weekoverzicht, of één herinnering op een moment dat jij noemt. Wat er verstuurd wordt is een gewoon responseverzoek, dus alles wat je zelf kunt vragen, kan een planning voor je vragen: vrije invoer, een opgeslagen prompt of een agent.
Je sleutel heeft de capability schedules nodig, en die heeft runs nodig: elke keer dat een
planning afgaat is dat een achtergrondbeurt, en je leest het antwoord
met GET /responses/{id}, net als bij een beurt die je zelf hebt gevraagd. Hetzelfde doe je met de
muis in Planningen in de console.
Een planning maken¶
curl -s -X POST "$CORE_URL/schedules" \
-H "Authorization: Bearer $CORE_KEY" -H "Content-Type: application/json" \
-d '{"name": "werkdag-samenvatting",
"description": "Gisteren, samengevat, voordat iemand binnen is",
"cron": "0 6 * * 1-5",
"timezone": "Europe/Amsterdam",
"request": {"agent": {"id": "agt_5Nj2..."},
"input": "Vat gisteren samen in vijf punten."}}'
Een geslaagd verzoek geeft 201 en een Location.
| Veld | Wat het doet |
|---|---|
name |
uniek binnen je organisatie |
cron |
vijf velden -- minuut, uur, dag van de maand, maand, dag van de week -- gelezen in timezone; 1#1 is de eerste maandag, 5L de laatste vrijdag |
timezone |
een IANA-zonenaam zoals Europe/Amsterdam; UTC als je er geen noemt |
at |
één moment om af te gaan in plaats van een cron; daarna zet de planning zichzelf uit |
enabled |
false slaat hem op zonder hem te laten lopen |
kind |
response (de standaard -- stuur request), evaluation (laat een suite lopen) of workflow (start een workflowrun) |
request |
het verzoek dat elke keer verstuurd wordt, bij kind: "response" |
evaluation_id |
de suite die elke keer gaat lopen, bij kind: "evaluation" |
subject_id |
de persoon voor wie elke beurt is (bouwen voor mensen). Verstuurd met X-Core-Subject voor dezelfde persoon, gelden de attributen die zij opgeeft 30 dagen lang voor elke beurt |
labels |
je eigen indeling, waarop je de lijst kunt filteren |
Noem precies één van cron en at. Allebei, of geen van beide, is 422.
Een request mag tool_variables bevatten, de waarden die elke keer meegaan voor de
aanroepvariabelen van zijn tools. Een waarde voor een naam die een tool van je organisatie als
geheim declareert, wordt versleuteld opgeslagen en nooit teruggelezen: een leesactie laat die naam
weg uit request.tool_variables en geeft hem in tool_variable_secrets als
{"has_value": true}, en een PATCH waarvan het verzoek de naam weglaat, houdt de opgeslagen
waarde.
Een opname in het opgeslagen verzoek noem je met file_id: een inline input_audio-deel wordt
geweigerd met 422 op request.input, omdat het schema de opname anders bij elke keer dat het
afgaat zou bewaren (Audio transcriberen).
Je sleutel plant als zichzelf. Er is geen veld om een andere sleutel te noemen: de beurten die deze planning afvuurt zijn van jouw sleutel, gaan van jouw budget af en bereiken precies wat jouw sleutel bereikt. Een beheerder die er een aanmaakt in de console kiest wél een sleutel, want een persoon heeft er zelf geen. Een planning die je met de eigen sleutel van een serviceaccount schrijft, gaat af voor het account, met zijn kenmerken (Het account vast werk geven).
Een planning die een persoon zelf schrijft, houdt haar attributen 30 dagen vast. Stuur het
aanmaken, of een latere PATCH, met de sleutel waaronder de planning loopt en met
X-Core-Subject voor dezelfde persoon als subject_id, en de attributen die zij opgeeft gelden voor elke beurt. Je regels over
die attributen beslissen haar geplande beurten dan zoals ze haar live beurten beslissen. Elke
zulke wijziging door haar laat de 30 dagen opnieuw ingaan, en een die geen attributen opgeeft,
haalt ze weg. Een andere sleutel van je organisatie die de planning aan- of uitzet, laat ze staan. subject_attributes_until staat bij
elke keer lezen en zegt tot wanneer; het is null als de beurten alleen haar subject_id
dragen. Dat geldt voor een planning die zonder haar is geschreven, een die op iemand anders is
gericht en een waarvan de 30 dagen voorbij zijn. De attributen zelf lees je nooit terug
(Bouwen voor mensen).
Wat een cron-expressie betekent¶
Vraag het voordat je hem opslaat:
curl -s -X POST "$CORE_URL/schedules/preview" \
-H "Authorization: Bearer $CORE_KEY" -H "Content-Type: application/json" \
-d '{"cron": "0 6 * * 1-5", "timezone": "Europe/Amsterdam"}'
Je krijgt de volgende vijf momenten waarop de expressie afgaat, in die zone, en er wordt niets opgeslagen. Eén planning lezen geeft de volgende drie, naast al het andere.
Een weekdag kan een plek in de maand krijgen. 1#1 is de eerste maandag, MON#2 de tweede, 5L
de laatste vrijdag en L in het veld dag-van-de-maand de laatste dag. Zo bekijk je "de eerste
maandag om negen uur":
curl -s -X POST "$CORE_URL/schedules/preview" \
-H "Authorization: Bearer $CORE_KEY" -H "Content-Type: application/json" \
-d '{"cron": "0 9 * * 1#1", "timezone": "Europe/Amsterdam"}'
1#5 is een vijfde maandag, en die hebben maar sommige maanden; in de andere wordt hij
overgeslagen. Voor de laatste maandag van elke maand schrijf je 1L.
Die zone is precies het punt: 0 6 * * * in Europe/Amsterdam is daar zes uur 's ochtends in
januari en in juli, en een planning voor half drie gaat af om drie uur in de nacht dat de klok
vooruit gaat, in plaats van te worden overgeslagen.
Wat er gebeurt, en wat niet¶
Op het moment dat je expressie noemt stuurt Core je opgeslagen verzoek als achtergrondbeurt. Vier
velden van dat verzoek zijn van de planning zelf en worden geweigerd als je ze meestuurt:
stream, background, store en previous_response_id. Een planning maakt altijd een
opgeslagen achtergrondrun. thread_id mag wél, en zo schrijf je een doorlopend gesprek: elke keer
komt er iets bij op dezelfde thread.
Een planning leest de klok in haar eigen timezone. Gebruikt het verzoek een prompt waarvan
een variabele de ingebouwde waarde date, time,
datetime of weekday heeft, dan leest Core die in de timezone van de planning, tenzij het
opgeslagen verzoek zelf een timezone noemt. Zo'n variabele hoeft niet in het verzoek te staan:
Core vult hem in op het moment dat de planning afgaat. Ook bij het opslaan telt hij niet als een
ontbrekende waarde.
Drie dingen om te weten voordat je erop vertrouwt:
- Niets loopt dubbel. Draait de beurt van de vorige keer nog als het volgende moment komt, dan wordt dat moment overgeslagen in plaats van erachter gezet.
- Er stapelt zich niets op. Lag Core plat over meerdere momenten heen, dan gaat de planning één keer af en pakt daarna de gewone cadans weer op.
- Een fout zet hem niet uit. Kan de beurt niet gemaakt worden -- je sleutel is ingetrokken, je beleid weigert het model, het maandbudget is op -- dan legt de planning vast waarom en probeert het op het volgende moment opnieuw.
Dat staat op de planning zelf:
{"last_fired_at": "2026-09-23T04:00:00Z",
"last_response_id": "resp_8Kd1...",
"last_outcome": "fired",
"last_error": null,
"next_run_at": "2026-09-24T04:00:00Z"}
last_outcome is fired, skipped of failed, en last_error is één kort woord, nooit een
zin:
last_error |
Wat de uitvoering tegenhield |
|---|---|
key_revoked |
de sleutel waarmee de planning afgaat is verwijderd of verlopen; kies een sleutel die werkt |
key_disabled |
de sleutel waarmee de planning afgaat is uitgeschakeld; schakel hem weer in met POST /keys/{key_id}/enable |
service_account_paused |
de sleutel is van een serviceaccount dat gepauzeerd is; hervat het account |
tenant_unavailable |
je organisatie is opgeschort of wordt verwijderd |
no_key_to_run_as |
de suite die deze planning laat lopen noemt geen sleutel meer |
evaluation_gone |
de suite is verwijderd terwijl de uitvoering werd voorbereid |
subject_erased |
de persoon voor wie de planning is, is gewist, waardoor hij uit staat |
tool_variables_unreadable |
de opgeslagen geheime toolvariabelen konden niet worden geopend; stuur ze opnieuw met een PATCH |
policy_refused |
het beleid van je organisatie weigerde de beurt |
cap_exceeded |
de sleutel bereikte zijn maandlimiet |
target_gone |
iets wat de planning noemt, zoals de agent of de workflow, bestaat niet meer |
request_invalid |
het opgeslagen verzoek is niet meer geldig |
capability_withdrawn |
de sleutel verloor een mogelijkheid die de uitvoering nodig heeft |
too_many_open |
je organisatie heeft al zoveel open runs als de installatie toestaat |
Een agent op de klok meten¶
Een planning kan ook een run van een evaluatiesuite in de wachtrij zetten in
plaats van een beurt te versturen. Zet kind: "evaluation" en noem de suite; er is geen request,
want wat er loopt zijn de gesprekken van de suite zelf:
curl -s -X POST "$CORE_URL/schedules" \
-H "Authorization: Bearer $CORE_KEY" -H "Content-Type: application/json" \
-d '{"name": "nachtelijke-kwaliteit",
"cron": "0 3 * * *",
"timezone": "Europe/Amsterdam",
"kind": "evaluation",
"evaluation_id": "ev_7Hq1..."}'
Elke keer dat hij afgaat komt er één run per agent die de suite meet in de wachtrij -- precies wat
POST /evaluations/{id}/runs ook doet, met dezelfde klokregels als elke andere planning: een
gemiste nacht gaat één keer af in plaats van in te halen, en een suite waarvan de run nog loopt
wordt overgeslagen in plaats van twee keer gemeten.
De runs lopen als de sleutel van de suite, niet als de jouwe. Elke evaluatierun loopt als de
sleutel die de suite noemt, dus die moet er zijn: een suite zonder run_as_key_id geeft 409 bij
het schrijven van de planning, en een sleutel die daarna wordt leeggehaald laat de planning falen
met no_key_to_run_as in last_error tot je hem opnieuw zet.
Lees wat hij heeft gedaan via de lijst van de suite zelf, beperkt tot deze planning:
curl -s "$CORE_URL/evaluations/ev_7Hq1.../runs?schedule_id=sch_3Qp8..." \
-H "Authorization: Bearer $CORE_KEY"
Elke run noemt schedule_id en fired_for, het moment dat aan de beurt was. Deze soort met de
hand laten lopen geeft de ids van de runs terug in plaats van de planning:
{"object": "schedule.evaluation_fire", "kind": "evaluation", "run_ids": ["evr_..."]}.
De soort ligt vast zodra hij geschreven is -- de geschiedenis van een planning hoort bij één soort,
dus PATCH met kind is 422 en het antwoord is: schrijf de andere planning. De suite
verwijderen verwijdert de planningen die ervoor stonden; de runs die ze in de wachtrij zetten
blijven.
Een workflow op de klok starten¶
Een planning kan ook een run van een workflow starten in plaats van een beurt
te versturen. Zet kind: "workflow", noem de workflow bij zijn naam en geef de invoer waarmee
elke run begint; je sleutel heeft naast schedules ook workflows nodig:
curl -s -X POST "$CORE_URL/schedules" \
-H "Authorization: Bearer $CORE_KEY" -H "Content-Type: application/json" \
-d '{"name": "ochtend-intake",
"cron": "0 6 * * 1-5",
"timezone": "Europe/Amsterdam",
"kind": "workflow",
"workflow": "intake",
"workflow_input": {"source": "mailbox"}}'
Een workflow die niet bestaat of die het beleid van je sleutel niet toestaat geeft 422 op
workflow, en invoer die het invoerschema van de workflow weigert geeft 422 met het veld onder
workflow_input. Elke keer dat de planning afgaat start er één run van de nieuwste versie van de
workflow, als de sleutel waaronder de planning loopt en voor de persoon in subject_id als de
planning er een noemt. Zolang de run die de planning het laatst startte nog open is, wordt de
volgende keer overgeslagen in plaats van ernaast gestart: een workflow die op iemands beslissing
wacht, houdt zijn planning dus vast tot hij klaar is.
last_run_id op de planning noemt de laatste run, en de lijst van runs is tot deze planning te
beperken:
curl -s "$CORE_URL/workflow_runs?trigger_id=sch_3Qp8..." \
-H "Authorization: Bearer $CORE_KEY"
Elke run heeft "trigger_kind": "schedule" en het id van de planning in trigger_id. Als er geen
run kon starten staat de reden in last_error: target_gone als de workflow is verwijderd,
request_invalid als de opgeslagen invoer niet meer past, too_many_open als je organisatie
zoveel open runs heeft als de installatie toestaat. Met PATCH vervang je workflow_input; de
workflow die een planning noemt ligt vast, net als de soort.
Lezen wat hij heeft opgeleverd¶
curl -s "$CORE_URL/schedules/sch_3Qp8.../responses" -H "Authorization: Bearer $CORE_KEY"
Nieuwste eerst, één regel per beurt die deze planning heeft afgevuurd, elk met het id waarmee je
hem volledig leest via GET /responses/{id}. De response zelf is het object van de leverancier en
noemt geen planning; deze lijst is de weg terug van een beurt naar de planning die hem afvuurde.
Een planning met kind: "evaluation" vuurt geen beurten af, dus voor die is deze lijst leeg -- lees
zijn runs via de suite (hierboven).
Een planning nu laten lopen¶
curl -s -X POST "$CORE_URL/schedules/sch_3Qp8.../run" -H "Authorization: Bearer $CORE_KEY"
202, en de beurt staat in de wachtrij precies zoals de klok hem er had gezet. Het verzet het
moment van de planning niet. Draait de vorige beurt nog, dan krijg je 409 -- en dat krijg je ook
als de planning helemaal niet kon afgaan: de detail begint dan met dezelfde korte soort die ook in
last_error van de planning staat, zoals policy_refused of no_key_to_run_as. Een 202
betekent dus altijd dat er echt iets in de wachtrij staat.
Wijzigen en stoppen¶
PATCH /schedules/{id} wijzigt wat je meestuurt en berekent het volgende moment opnieuw; je kunt
een cron-planning omzetten naar een eenmalige at en terug. "enabled": false zet hem stil
zonder hem kwijt te raken -- dat is wat je meestal wilt. DELETE /schedules/{id} verwijdert de
planning; de beurten die hij al heeft afgevuurd blijven gewoon staan.
De lijst filteren¶
curl -s "$CORE_URL/schedules?enabled=true&label=afdeling:salaris" \
-H "Authorization: Bearer $CORE_KEY"
?label= neemt naam:waarde en mag herhaald worden; herhalen betekent alle genoemde, en een
naam herhalen vraagt om al die waarden: ?label=afdeling:verkoop&label=afdeling:financien vindt
de planningen die met allebei gelabeld zijn. Een planning waarvan het label meerdere waarden heeft,
telt mee als de waarde daar een van is.
Veelgemaakte fouten¶
| Wat je ziet | Wat er aan de hand is |
|---|---|
422 op cron |
geen vijf velden, of een expressie die nooit kan afgaan (30 februari) |
422 op timezone |
geen IANA-zonenaam |
422 op at |
in het verleden, of zonder tijdzone-offset |
422 op request.model |
het model staat niet in de catalogus van deze installatie, of er wordt er geen genoemd |
404 bij aanmaken |
de agent of prompt die je noemt bestaat niet, of je sleutel mag er niet bij |
409 bij aanmaken |
je hebt al een planning met die naam, of de suite die je noemt loopt als niemand (run_as_key_id) |
422 op evaluation_id |
geen suite van jou heeft dat id |
422 op request |
je stuurde zowel een request als een evaluation_id, of geen van beide, of een request voor een planning die een suite laat lopen |
404 op elke route |
je sleutel heeft de capability schedules niet |