Ga naar inhoud

Agents via de API

Het concept achter agents staat in Agents.

Op deze pagina leg je een agent vast met de API, voeg je versies toe en roep je hem aan vanuit een verzoek. Een agent bewaart de instellingen van een modelaanroep onder een naam: een model, instructies, een promptversie, skills en tools. Je applicatie noemt de agent en geeft de invoer mee, zodat je de instellingen bijwerkt zonder de applicatie opnieuw uit te rollen.

Je sleutel heeft de capability agents nodig, en de capabilities van wat de agent gebruikt, bijvoorbeeld prompts voor een opgeslagen prompt. Hetzelfde doe je met de muis in Agents in de console.

Elke wijziging krijgt een versie. Een verzoek kan de nieuwste versie gebruiken of een specifieke versie vastzetten. Een veld dat de agent vastlegt houdt de waarde van de agent, wat het verzoek ook stuurt; skills, tools en een eigen instructie kun je wel aanvullen.

Een agent maken

curl -s -X POST "$CORE_URL/agents" \
    -H "Authorization: Bearer $CORE_KEY" -H "Content-Type: application/json" \
    -d '{"name": "triage",
         "description": "Classificeert een binnenkomend ticket.",
         "model": "<een model-id>",
         "instructions": "Antwoord in één zin.",
         "prompt": {"id": "triage", "version": 1},
         "skills": ["facturatie"],
         "tools": [{"type": "toolset", "name": "support"}],
         "temperature": 0.2}'

Een geslaagd verzoek geeft 201 en maakt de agent met versie 1 aan.

Veld Wat het doet
name uniek binnen je organisatie; waar een aanroep naar verwijst
description waar deze agent voor is; puur voor lezers
metadata een eigen ondoorzichtig object, maximaal 16 KiB geserialiseerd; Core bewaart en geeft het terug en leest het nooit
model het model-id waarop een beurt draait als het verzoek er zelf geen noemt
instructions een staande instructie met developer-autoriteit; {{ $naam }} markeert een invulwaarde
install_values optioneel: een waarde voor elke {{ $naam }} in instructions, zoals {"bedrijf": {"type": "string", "value": "Acme"}}, getypeerd zoals bij een prompt
prompt {"id": "<promptnaam of prm_-id>", "version": <nummer>}; version is verplicht
skills skillnamen of skill_-ids die deze agent aanbiedt
tools tool-, toolset- en agent-parameters; een function-tool hoort bij de aanroep, niet bij de agent
tool_choice, max_tool_rounds, temperature, max_output_tokens, text dezelfde velden als op een verzoek
tool_search of een beurt van deze agent zijn tools direct of achter de toolrouter aanbiedt, zoals op een verzoek; de eigen tool_search van een verzoek gaat erboven (Een agent met veel tools)
tool_approval welke tools op goedkeuring van een persoon wachten voordat ze worden uitgevoerd, per modus, zoals op een achtergrondverzoek. Een verzoek kan het alleen strenger maken: een default of modus die het stuurt en die losser is dan die van de agent, of een langere wachttijd, wordt genegeerd en staat in interpretation.agent.overridden van de trace; een verzoek zonder default neemt die van de agent. Een agenttool of builtin__subagent draait alleen zonder te wachten als elke optie die hem noemt, die van de agent en die van het verzoek, hem exact noemt met "never". Een agent met tool_approval draait alleen op de achtergrond: bij elke andere beurt geeft het verzoek 400 op agent, of op model als je de agent daar noemt
memory_injection optioneel: uit welke geheugenopslag een beurt van deze agent records krijgt, in de vorm van memory.injection van de sleutel; het vervangt het blok van de sleutel in zijn geheel voor die beurt, en "enabled": false geeft de beurt er geen (Elke assistent een eigen opslag geven)
routing_config_id optioneel: de routeringsconfiguratie waarlangs een beurt van deze agent terugvalt, een van je organisatie met een gepubliceerde versie; ze vervangt die van de sleutel voor de beurt, en een eigen routing_config_id op het verzoek gaat voor (Een configuratie voor één agent of één beurt)
live_checks hooguit 16 regels waaraan elke beurt van deze agent wordt gehouden, op de vraag van de beller of op het antwoord (Live checks via de API)
blocked_reply het standaardantwoord, hooguit 1000 tekens, waarmee een beurt antwoordt als een blokkerende check op de invoer faalt; verplicht zodra er een is
recover_attempts hoe vaak een antwoord dat faalde voor een check met recover opnieuw wordt gevraagd, 1 tot 3; 2 als je het weglaat
working_state_schema optioneel: een JSON Schema (Draft 2020-12) waaraan het werkgeheugen van het gesprek moet voldoen in een beurt van deze agent, gecontroleerd bij het opslaan; null laat elk JSON-object toe, en een verzegelde kopie leest het als null

Het veld name is verplicht; de velden van de definitie zijn optioneel. Een agent die alleen een model en een instructie vastlegt, is net zo geldig als een die een hele toolset meebrengt.

Een {{ $naam }} in instructions is een invulwaarde: een waarde die je één keer vastlegt in install_values, met zijn type (string, number of enum), en die Core invult voordat de instructie aan een beurt wordt toegevoegd, als deel van de instructie zelf. Elke {{ $naam }} heeft een waarde nodig, elke waarde moet worden gebruikt, en een waarde mag geen {{ of }} bevatten. Deel je de agent via een publicatie, dan vult wie hem installeert zijn eigen invulwaarden in (Delen).

De prompt wordt meteen bij het aanmaken opgezocht en op die versie vastgezet. Bestaat de prompt of de versie niet, of noemt het beleid van je sleutel die prompt niet, dan krijg je hetzelfde 404 als een beurt die de prompt rechtstreeks noemt.

metadata hoort bij de agent, niet bij één versie: een nieuwe versie die het veld weglaat, houdt wat er staat, en {} wist het. Zet er neer wat je eigen applicatie nodig heeft — een icoon, een kleur, een eigen referentie — Core kijkt er nooit in.

Een versie toevoegen

curl -s -X POST "$CORE_URL/agents/agt_5Nj2.../versions" \
    -H "Authorization: Bearer $CORE_KEY" -H "Content-Type: application/json" \
    -d '{"model": "<een model-id>", "instructions": "Antwoord in twee zinnen."}'

Versies worden genummerd vanaf 1 en kunnen na het aanmaken niet worden gewijzigd. Een versie is de hele definitie: wat je niet opnieuw meegeeft, staat er in die versie niet meer in.

Aanroep Antwoordt
GET /agents je agents, elk met de laatste versie voluit
GET /agents/{agent_id} één agent met zijn laatste versie
GET /agents/{agent_id}/versions zijn versies, gepagineerd op versienummer, oudste eerst; voeg ?order=desc toe voor nieuwste eerst
GET /agents/{agent_id}/versions/{version} één versie
DELETE /agents/{agent_id} 204; elke versie gaat mee

Een agent kopiëren

Wil je een nieuwe agent beginnen vanuit een die je al hebt, kopieer hem dan onder een nieuwe naam:

curl -s -X POST "$CORE_URL/agents/agt_5Nj2.../copy" \
    -H "Authorization: Bearer $CORE_KEY" -H "Content-Type: application/json" \
    -d '{"name": "support-desk-nl", "version": 2}'

Het antwoord is 201 met de nieuwe agent, op zijn eigen versie 1. Laat je version weg, dan kopieer je de laatste versie. De kopie neemt de hele definitie van die versie over, en de beschrijving, labels en metadata van de agent; hij pint dezelfde promptversie, dezelfde skillversies en dezelfde agents als tool, en kopieert die zelf niet. Vanaf dan is het je eigen agent: wat je eraan verandert, verandert het origineel niet, en latere versies van het origineel komen er niet in.

Je sleutel moet de agent die je kopieert kunnen lezen, en onder de nieuwe naam met dezelfde labels een agent mogen maken. Een kopie die een publicatie verzegeld installeerde, en een kopie waarvan de publicatie losmaken niet toestaat ('fork': false), hem voor haar eigen agents houdt of hergebruik niet toestaat, kun je niet kopiëren: 403. Een agent die zichzelf als tool noemt, noemt na het kopiëren de kopie.

Een agent aanroepen

{
  "input": "Mijn kaart is twee keer belast.",
  "agent": { "id": "triage", "variables": { "ticket": "Mijn kaart is twee keer belast." } }
}

Stel id in op de agentnaam of het agt_-id. Laat version weg om de nieuwste versie op het moment van aanroepen te gebruiken. Geef een versienummer op om die versie te blijven gebruiken nadat er nieuwe zijn gepubliceerd. variables vult de prompt die deze agentversie vastzette.

model mag je weglaten zodra de agent er een vastlegt. Noemt het verzoek zelf geen model en legt de agent er geen vast, dan is dat 400 met model in error.param.

Een sleutel waarvan het beleid settings.agents_required zet, moet in elke beurt een agent noemen, en voor een beurt zonder agent wordt geen model aangeroepen: POST /responses antwoordt 403 met agent in error.param, en POST /messages antwoordt 403 met een melding die begint met agent: (de fout van Anthropic heeft geen param).

Zo'n sleutel draait zijn agents ook zoals ze zijn gedefinieerd, dus de regel in het volgende onderdeel geldt voor hem niet: een beurt die eigen tools, skills, instructions of een prompt toevoegt (op POST /messages: system, tools of skills) is op dezelfde manier 403 met dat veld erbij. Instructies die gelijk zijn aan die van de agent voegen niets toe en gaan door, behalve bij een verzegelde kopie, die ze allemaal weigert. Een model uit de catalogus dat afwijkt van dat van de agent blijft de 400 die het onder elke sleutel is; de temperatuur en de tokenlimiet mag je nog zetten waar de agent ze openlaat, en waar hij ze vastlegt draait de beurt op zijn waarde. De agent als model noemen telt als hem noemen. Een codeeromgeving die een eigen systeemprompt meestuurt wordt op zo'n sleutel geweigerd: geef hem een gewone sleutel waarvan het beleid de agent bereikt.

Tooluitvoer insturen zet de beurt voort waar die bij hoort; dat gaat door als die beurt een agent noemde en wordt geweigerd als dat niet zo was. Een planning onder zo'n sleutel moet in haar verzoek een agent noemen, en de sleutel kan geen tool rechtstreeks aanroepen. Een agent noemen die de regels van de sleutel niet toestaan, blijft 404. Zie Sleutels.

Wil je alleen van sommige personen een agent eisen, schrijf dan in plaats daarvan een forbid over de soort direct_turn met een voorwaarde op de persoon (Een persoon niet met een kaal model laten praten). Hun beurten die geen agent noemen krijgen dezelfde 403 op agent, terwijl hun rechtstreekse toolaanroepen en kenniszoekopdrachten toegestaan blijven.

Noem de agent als model

Een client die alleen een model, zijn eigen instructies en zijn eigen tools kan sturen — een codeeromgeving, een SDK die je niet zelf in de hand hebt — bereikt een agent via model: agent:<naam>, of het agt_-id van de agent. GET /models noemt elke agent die je sleutel zo kan gebruiken, na de modellen, met owned_by: "agent".

from openai import OpenAI

client = OpenAI(base_url="https://<jouw-omgeving>/api/v1", api_key="ack_...")
response = client.responses.create(
    model="agent:triage",
    instructions="Je draait in mijn editor.",
    input="Mijn kaart is twee keer belast.",
)
print(response.model)  # het model van de agent, nooit "agent:triage"

Het is dezelfde verwijzing als het veld agent en wordt op dezelfde manier geweigerd: 404 voor een agent die je sleutel niet mag gebruiken. Een kale naam zoals triage wordt nooit als agent gelezen, want het kan een model zijn, en iets na agt_ dat geen id van Core is evenmin. De agent moet zelf een model vastleggen — een agent die dat niet doet is 400 op model en staat niet in de lijst; noem hem dan in agent naast een model. Stuur je beide vormen, dan moeten ze dezelfde agent noemen, anders is de aanroep 400 op model. Hetzelfde werkt op POST /messages met de SDK van Anthropic, waar je system je eigen instructie is.

Een verzoek vult aan, het overschrijft niet

skills en tools van het verzoek komen bij die van de agent. Noemen beide dezelfde tool, dan telt die één keer. Je instructions komen er ook bij: het model leest eerst die van jou en dan die van de agent, als twee aparte instructies, en het antwoord geeft alleen de jouwe terug. Een instructie die gelijk is aan die van de agent wordt één keer verstuurd.

Elk ander veld dat de agentversie vastlegt — temperature, max_output_tokens, max_tool_rounds, tool_choice, text, reasoning — houdt de waarde van de agent. Zet je verzoek er een op een andere waarde, dan draait de beurt toch, op de waarde van de agent, en noemt de trace van de aanroep het veld onder interpretation.agent.overridden, zodat je ziet wat niet is gebruikt. De definitie is het punt van een agent; de beurt wordt niet geweigerd zodat een client die altijd zijn eigen standaardwaarden meestuurt er toch een kan gebruiken.

{ "agent": { "id": "triage" }, "temperature": 0.9 }

Legt triage een temperature van 0.2 vast, dan draait deze beurt op 0.2 en is overridden in de trace ["temperature"]. Wil je een andere waarde, maak dan een nieuwe versie van de agent of gebruik een andere agent.

Twee dingen worden nog wel geweigerd. Een model uit de catalogus dat afwijkt van dat van de agent is 400 op model: noem alleen de agent, of noem hem als model. En jouw skills en die van de agent samen zijn er hoogstens 32, dezelfde grens die een verzoek op zichzelf heeft; meer is 400 op skills.

Niets meesturen voor een vastgelegd veld, null, "auto" voor tool_choice (de standaard) of dezelfde waarde als de agent vastlegt verandert niets en wordt niet als overschreven genoemd, dus een client die zijn hele verzoekobject serialiseert werkt gewoon.

Wat de agent meebrengt, wordt op precies dezelfde manier gecontroleerd als wat je zelf opschrijft. Een skill, tool of prompt die het beleid van je sleutel niet noemt, blijft buiten bereik, ook als de agent hem noemt.

Een agent als tool aan een beurt geven

Een beurt kan een andere agent als één tool aan haar model geven. Noem hem in tools, op het verzoek of in de definitie van een agent zelf — dat tweede is hoe de ene agent werk doorgeeft aan de andere:

{
  "model": "<een model-id>",
  "input": "Een klant is twee keer afgeschreven.",
  "tools": [{ "type": "agent", "name": "facturatie" }]
}

Het model ziet een tool agent__facturatie, beschreven met de description van de agent. De argumenten zijn de variabelen van de prompt die de agent vastzet, elk van het type en met de enum die het invoerschema declareert, plus input: vrije tekst met wat het model de agent vraagt. input is alleen verplicht als de agent geen prompt vastzet. version werkt als bij agent: laat hem weg voor de laatste.

Roept het model de tool aan, dan draait Core één beurt van die agent, met het eigen model, de eigen instructie, prompt en skills van de agent, en geeft het antwoord van de agent terug als resultaat van de tool. Die beurt:

  • draait onder jouw sleutel: elk model, elke prompt, skill en tool die ze bereikt, wordt getoetst aan het beleid van je sleutel, precies zoals wanneer je de agent zelf op agent noemt;
  • krijgt de eigen tools van de agent, behalve andere agents, builtin__subagent en core__-tools, zodat een agent die als tool draait nooit op zijn beurt weer een agent aanroept. Agents mogen elkaar dus in een kring noemen, of zichzelf: Core slaat dat op zoals het er staat, en de kring breekt na één aanroep;
  • telt als één niveau in een keten van beurten die beurten aanroepen. Een keten die via verzoeken doorgaat -- een tool van een agent die de eigen API van Core bereikt, die een beurt start die weer een agent aanroept -- stopt op vijf niveaus: daar leest het model This turn is too deep in a chain of calls to start another. als resultaat van de tool, en de beurt gaat door (de grenzen op core__-tools);
  • heeft een eigen antwoord-id en eigen verbruik, en de auditgebeurtenis van de aanroep noemt die als agent_response_id; de modelaanroepen staan in de trace van de aanroepende beurt;
  • mag standaard tot twee minuten duren. Een fout, een weigering voordat ze begon of te weinig rondes bereikt het model als één vaste zin, nooit als fout op jouw verzoek.

Het antwoord van de agent wordt behandeld als het resultaat van elke tool: als informatie voor het model, nooit als instructie. Je sleutel heeft agents nodig, en het tools-beleid van je sleutel moet de naam agent__<naam> toestaan.

Een agent waarvan de versie background heeft met de modus allowed of always, kan ook als taak worden gestart: het model krijgt meteen een taak-id en het antwoord van de agent komt later terug in de thread. Zie Een tool op de achtergrond draaien.

Een agent met tool_approval kan niet als tool draaien: zijn beurt kan niet op een persoon wachten, dus die wordt geweigerd voor hij begint en het model leest de vaste zin Agent could not be run. als resultaat van de tool.

Een agent verwijderen waaraan een andere agent werk doorgeeft, geeft 409, met de agents die hem nog gebruiken.

Dezelfde tool staat in je toolcatalogus, dus je bereikt hem ook bij naam. GET /tools toont agent__facturatie met de argumenten hierboven; een toolsetpatroon zoals agent__* biedt hem aan een beurt aan precies zoals het agent-item dat doet (een agent die op beide manieren genoemd wordt, wordt één keer aangeboden); en POST /tools/agent__facturatie/call draait de beurt van de agent voor je en geeft zijn antwoord terug. Zo gebruikt een applicatie buiten Core, of een MCP-client die een van je toolsets krijgt, hem. Alleen de agents die je sleutel mag gebruiken worden getoond of aangeroepen; een agent die alleen op de achtergrond draait, kun je buiten een beurt niet aanroepen. Zie Een tool rechtstreeks aanroepen.

Fouten

Status Oorzaak
404 geen zo'n agent, geen zo'n vastgezette versie, een agent die het beleid van je sleutel niet noemt, of agents geldt niet voor je sleutel — ook voor een agent die in tools staat
403 de naam die je aanmaakt, valt buiten wat het beleid van je sleutel noemt; er wordt niets opgeslagen
403 op agent de beurt noemt geen agent terwijl het beleid van je sleutel er een vereist (settings.agents_required), of een forbid over direct_turn geldt voor de persoon voor wie de beurt is
403 op tools, skills, instructions of prompt het beleid van je sleutel vereist een agent, en de beurt voegt dat veld eraan toe
409 de naam is al bezet — of, op DELETE /prompts/{id}, een agentversie zet een versie van die prompt nog vast — of, op DELETE /agents/{id}, een andere agent geeft nog werk door aan deze
400 op model het verzoek noemt geen model en de agent legt er geen vast, noemt een ander catalogusmodel dan dat van de agent, noemt als model een agent die er geen vastlegt, of noemt twee verschillende agents in model en agent
400 op agent of model tool_approval requires background: de agent heeft tool_approval en de beurt draait niet op de achtergrond; op model als je de agent daar noemde
400 op prompt het verzoek noemt een prompt terwijl de agentversie er al een vastzet
400 op agent.variables er zijn variabelen meegegeven terwijl deze agentversie geen prompt rendert, een verplichte variabele van de vastgezette prompt heeft geen waarde, of een waarde past niet bij zijn property in het invoerschema van de prompt
400 op skills jouw skills en die van de agent samen zijn er meer dan 32
422 op live_checks, blocked_reply of recover_attempts een live check die de versie niet kan hebben; zie Live checks via de API
422 op install_values bij het schrijven: een {{ $naam }} zonder waarde, een waarde die instructions niet gebruikt, een waarde met {{ of }}, of een waarde die niet bij zijn type past

In een beurt komt elk van deze weigeringen binnen in het foutobject van OpenAI, met het veld in error.param; dezelfde weigeringen bij het schrijven naar /agents zijn problem+json, met het veld in errors.

Een prompt verwijderen die een agentversie vastzet, lukt niet: verwijder eerst de agent, dan komt de prompt vrij.

Terugvinden welke agent er draaide

Een opgeslagen antwoord bewaart de agent die daadwerkelijk draaide — id, naam en versie — naast de skills en tools waarmee de beurt liep; de trace van elke aanroep draagt hetzelfde als interpretation.agent, met in overridden de velden van je verzoek die niet zijn gebruikt ([] als dat er geen zijn). response.model is altijd het model dat draaide. Bij een achtergrondrun draait het hervatten verder op diezelfde vastgelegde combinatie, dus een nieuwe agentversie verandert een run die al loopt niet.