Ga naar inhoud

Een waarde van je klant aan een tool meegeven

Het concept achter tools staat in Tools.

Soms hoort een waarde niet bij de tool en ook niet bij het model, maar bij het verzoek: het account-id van je klant in je eigen systeem, de regio die je per klant kiest, of het eigen token van je klant voor jouw API. Zo'n waarde is een aanroepvariabele. De tool declareert welke aanroepvariabelen hij leest, jouw applicatie stuurt de waarden mee in tool_variables, en Core vult ze in bij elke aanroep van die tool. Het model ziet ze nooit en kan ze niet veranderen.

Een tool kent zo drie soorten waarden:

Soort Teken in een sjabloon Wie geeft hem Wanneer
Argument {naam} het model bij elke aanroep, in de argumenten
Invulwaarde {$naam} de maker van de tool, of de organisatie die hem uit een bundel installeert bij het registreren of installeren (Waarden die je één keer vastlegt)
Aanroepvariabele {@naam} jouw applicatie bij elk verzoek, in tool_variables

Je declareert en wijzigt aanroepvariabelen via de API of in de console. De consolepagina's beschrijven dezelfde velden voor een API-koppeling, een MCP-server, een script, een workflow en een alias; een planning bewaart de waarden die ze meestuurt, en de console toont de variabelen die de tools van een agent nodig hebben.

Een aanroepvariabele is iets anders dan de variabelen van een agent of prompt. Die waarden (agent.variables) komen in de context die het model leest. Stuur een token van je klant daarom nooit in agent.variables, maar altijd in tool_variables.

Aanroepvariabelen declareren op een API-koppeling

Een API-koppeling declareert haar aanroepvariabelen in call_variables: een JSON Schema-object met één eigenschap per variabele. Elke eigenschap is een string, number, integer of boolean, met een optionele description, enum en default. required noemt de variabelen waarvoor een aanroep een waarde nodig heeft. Een naam bestaat uit kleine letters, cijfers en _, en begint met een letter of cijfer.

Dit voorbeeld leest de bestellingen van één klant uit jouw API, met het eigen token van die klant:

curl -s -X POST "$CORE_URL/api_connectors" \
    -H "Authorization: Bearer $CORE_KEY" -H "Content-Type: application/json" \
    -d '{"name": "orders",
         "http_url": "https://api.jouw-app.example/v1/accounts/{@account_id}/orders",
         "description": "De openstaande bestellingen van deze klant.",
         "parameters": {"type": "object", "properties": {"status": {"type": "string"}}},
         "request": {"method": "GET",
                     "query": {"status": "{status}"},
                     "headers": {"Authorization": "Bearer {@customer_token}"}},
         "call_variables": {
             "type": "object",
             "properties": {
                 "account_id": {"type": "string", "description": "Het account van de klant bij jou"},
                 "customer_token": {"type": "string", "x-secret": true}},
             "required": ["account_id", "customer_token"]},
         "auth": {"type": "none"}}'

customer_token is een geheim (x-secret: true, zie Geheime waarden), dus mag hij alleen in de header staan. auth blijft none, omdat het token per verzoek verschilt; een credential dat voor iedereen hetzelfde is, hoort in auth (Je legitimeren bij je endpoint).

Een aanroepvariabele mag op dezelfde plekken staan als een invulwaarde: in het pad en de query van http_url, en in een querywaarde, headerwaarde of string in de body van request. In de URL wordt de waarde percent-encoded, in een query- of headerwaarde is hij tekst, en een bodystring die precies één {@naam} is wordt de waarde zelf, van zijn eigen type. Een optionele variabele zonder waarde en zonder default wordt lege tekst, en null waar hij een hele bodywaarde is. Core vult eerst de invulwaarden in, dan de aanroepvariabelen, dan de argumenten van het model.

Registratie geeft 422 op call_variables bij:

  • een {@naam} die niet gedeclareerd is, of een declaratie die geen {@naam} gebruikt;
  • een {@naam} in het schema, de host, de poort of het fragment van de URL, of in een sleutel;
  • een naam die ook een argument of een invulwaarde is;
  • een geheime variabele in de URL of een querywaarde.

Een aanroepvariabele kiest dus nooit de host: een host die per verzoek verschilt, zou het credential van je organisatie naar een host van de aanroeper kunnen sturen.

Een PATCH met call_variables vervangt de hele declaratie en maakt een nieuwe versie van de koppeling.

Aanroepvariabelen declareren op een MCP-server

Een MCP-server accepteert aanroepvariabelen alleen in headerwaarden. Core leest de toollijst van een server op de achtergrond, zonder verzoek, dus een URL die een aanroepvariabele nodig heeft zou nooit gelezen kunnen worden.

curl -s -X POST "$CORE_URL/mcp_servers" \
    -H "Authorization: Bearer $CORE_KEY" -H "Content-Type: application/json" \
    -d '{"name": "crm", "url": "https://mcp.jouw-app.example/{$workspace}/mcp",
         "headers": {"X-Api-Key": "{$api_key}", "Authorization": "Bearer {@customer_token}"},
         "install_values": {
             "workspace": {"type": "string", "value": "acme"},
             "api_key": {"type": "secret", "value": "fake-api-key-for-docs-0001"}},
         "call_variables": {
             "type": "object",
             "properties": {"customer_token": {"type": "string", "x-secret": true}},
             "required": ["customer_token"]},
         "auth": {"type": "none"}}'
  • headers zijn de headers die elk verzoek aan de server draagt. Een waarde mag {$naam} invulwaarden en {@naam} aanroepvariabelen bevatten.
  • install_values werken zoals bij een API-koppeling. Een gewone invulwaarde mag in het pad en de query van de URL en in een headerwaarde staan; een secret alleen in een headerwaarde.
  • Een header met een aanroepvariabele laat Core weg bij het lezen van de toollijst, omdat daar geen verzoek is om een waarde uit te halen. Je server moet zijn toollijst dus ook zonder die header geven.
  • Authorization mag alleen in headers staan zolang auth van de server none is, zoals hierboven (De header Authorization). Proxy-Authorization, Cookie, een header die Core of het transport zelf zet en de header waarin het eigen auth van de server wordt verstuurd, worden altijd geweigerd (422 op headers).
  • Een {@naam} in de URL geeft 422 op call_variables.

Een PATCH die headers, install_values of call_variables noemt, vervangt dat veld in zijn geheel.

De waarden meesturen

Stuur de waarden mee in tool_variables: een plat object van namen naar strings, getallen of booleans.

curl -s -X POST "$CORE_URL/responses" \
    -H "Authorization: Bearer $CORE_KEY" -H "Content-Type: application/json" \
    -d '{"model": "<een model-id>",
         "input": "Welke bestellingen staan nog open?",
         "tools": [{"type": "tool", "name": "api__orders"}],
         "tool_variables": {"account_id": "A-10442",
                            "customer_token": "fake-token-for-docs-0001"}}'

Hetzelfde veld bestaat op:

Waar Hoe
POST /responses en POST /messages tool_variables naast de rest van het verzoek, ook voor een achtergrondbeurt
POST /tools/{name}/call {"arguments": {...}, "tool_variables": {...}}, gecontroleerd tegen die ene tool (Een tool rechtstreeks aanroepen)
Een planning tool_variables in de opgeslagen request; elke keer dat de planning afgaat, gaan ze mee
Een evaluatiescenario tool_variables op het scenario, meegestuurd bij elke stap; alleen waarden die geen geheim zijn
Een toolset als MCP-server in params._meta van elke aanroep (hieronder)

Een workflowrun krijgt zijn waarden bij de start in variables; zie Scripts, workflows en aliassen.

Wat er met een waarde gebeurt

  • Het model ziet hem nooit. De waarden staan niet in de context, niet in de beschrijving van een tool en niet in zijn argumenten.
  • Elke tool krijgt alleen wat hij declareert. Een tool die geen aanroepvariabelen declareert, krijgt er geen; geen enkele tool ziet de hele set van het verzoek.
  • Een naam die geen tool declareert, wordt genegeerd. Je kunt dus dezelfde set meesturen, ook als het beleid van je sleutel of een toolset een tool uit de beurt haalt. De trace noemt de genegeerde namen in interpretation.tool_variables_ignored, en bij elke toolaanroep de namen die die tool kreeg. Een waarde staat nooit in een trace, een logregel of de audit.
  • Het antwoord herhaalt ze niet. Het opgeslagen antwoord en GET /responses/{id} bevatten geen tool_variables.

Een waarde die ontbreekt of niet past

Core controleert tool_variables tegen de declaraties van alle tools die de beurt aanbiedt, voordat er een model wordt aangeroepen. Er gaat dus niets naar het model en er wordt niets in rekening gebracht als een waarde niet klopt. Een tool die het beleid van je sleutel achterhoudt, telt niet mee.

Core weigert:

  • een verplichte variabele zonder waarde en zonder default;
  • een waarde die niet bij de declaratie past: het verkeerde type, of niet in de enum;
  • een waarde die niet past op de plek waar hij komt: een { of }, een stuurteken in een header, of . of .. in het pad van een URL.

De melding noemt de variabele en de tool. Op POST /responses is dat een 400 in de vorm van OpenAI:

{
  "error": {
    "message": "api__orders requires customer_token.",
    "type": "invalid_request_error",
    "param": "tool_variables.customer_token",
    "code": "invalid_request"
  }
}

POST /messages antwoordt 400 in de vorm van Anthropic, met tool_variables.customer_token: api__orders requires customer_token. als bericht. POST /tools/{name}/call antwoordt 422 met tool_variables.customer_token als field in de lijst errors (Foutformaat).

Een achtergrondbeurt controleert zijn waarden wanneer hij begint: ontbreekt er een, dan mislukt de run voordat er een model wordt aangeroepen, met dezelfde zin als fout.

Geneste agents, taken en workflows

Een beurt geeft zijn waarden door aan wat hij zelf start, omdat de aanroeper dezelfde blijft:

  • een agent die als tool wordt aangeroepen en een agent die als taak wordt gestart, krijgen de hele set en controleren hem tegen hun eigen tools;
  • een tool die als taak op de achtergrond draait, houdt het deel dat hij declareert;
  • een workflow die vanuit een beurt als taak start, houdt de waarden die hij zelf declareert;
  • core__call_tool, waarmee een beurt een andere tool aanroept, draagt de waarden van de beurt mee;
  • een tool achter de toolrouter krijgt zijn eigen deel, net als elke andere tool.

Het model kan zelf geen aanroepvariabelen zetten. Een verzoek dat een core__-tool namens het model naar Core stuurt, mag geen tool_variables bevatten; Core weigert het. builtin__subagent biedt geen tools aan en heeft dus niets door te geven.

Een toolset via MCP

Bied je een toolset als MCP-server aan, dan heeft de client geen veld voor tool_variables. Hij stuurt de waarden per aanroep mee in params._meta["artific/tool_variables"]:

{
  "jsonrpc": "2.0",
  "id": 7,
  "method": "tools/call",
  "params": {
    "name": "api__orders",
    "arguments": {"status": "open"},
    "_meta": {"artific/tool_variables": {"account_id": "A-10442",
                                         "customer_token": "fake-token-for-docs-0001"}}
  }
}

Core controleert de aanroep tegen die ene tool, zoals bij POST /tools/{name}/call. De lijst met tools toont ook de tools die een variabele vereisen. Ontbreekt een verplichte variabele, past een waarde niet, of is _meta geen plat object, dan antwoordt de aanroep zoals MCP een mislukte tool meldt: de zin van de weigering met isError, voordat er iets draait of in rekening wordt gebracht.

Geheime waarden

Een API-koppeling en een MCP-server kunnen beide soorten waarden geheim houden.

Een geheime aanroepvariabele is een eigenschap met x-secret: true: een string van hoogstens 8.192 tekens, zonder default en zonder enum, omdat iedereen die de tool kan lezen die leest.

Een geheime invulwaarde is {"type": "secret", "value": "..."}, voor een endpoint dat naast auth nog een credential nodig heeft. Voor een API-koppeling staat hij beschreven onder Waarden die je één keer vastlegt; op een MCP-server werkt hij hetzelfde:

  • je schrijft hem één keer en leest hem nooit terug: GET antwoordt {"type": "secret", "has_value": true, "description": "..."};
  • een PATCH die install_values vervangt, geeft elk geheim opnieuw, of {"$keep": true} om het bewaarde te houden;
  • een deployment zonder sleutel om te versleutelen antwoordt 503 op een body met een geheim.

Voor beide soorten geldt:

  • Alleen in een headerwaarde of een string in de body, nooit in de URL of een querywaarde, want die komen in logbestanden van proxy's en servers terecht. Op een MCP-server alleen in een headerwaarde.
  • Core maskeert ze in resultaten. Voordat het model of de trace een resultaat ziet, vervangt Core elke letterlijke echo van een geheime waarde van 8 tekens of meer door [secret]. Een kortere waarde, of een waarde die het endpoint heeft bewerkt (in base64 gecodeerd, gehasht, in stukken), herkent Core niet. Stuur een geheim dus niet terug in je antwoord.
  • Versleuteld opgeslagen. Een achtergrondrun en een planning bewaren een geheime waarde versleuteld; de run gooit hem weg zodra hij klaar is. Een planning geeft de namen in tool_variable_secrets terug als {"has_value": true} en laat ze weg uit request.tool_variables; een wijziging die zo'n naam weglaat, houdt de bewaarde waarde. Een achtergrondverzoek met een geheim op een deployment zonder sleutel om te versleutelen geeft 503.
  • Niet in een evaluatiescenario. Een scenario is testdata die iedereen met toegang tot de suite leest. Een waarde voor een geheime naam geeft 422 op tool_variables.<naam>. Core beschouwt een naam als geheim zodra een API-koppeling of MCP-server van je organisatie hem x-secret declareert.
  • Scripts, workflows en aliassen accepteren geen geheimen. Hun registratie weigert een x-secret aanroepvariabele en een secret invulwaarde met 422. Een tool achter een workflow of alias die een geheim nodig heeft, krijgt het met het verzoek dat die tool bereikt.

De header Authorization

Het sjabloon van een API-koppeling en de headers van een MCP-server mogen de header Authorization alleen schrijven als het eigen credential van de tool, auth, none is. Zo werken beide voorbeelden hierboven: "Bearer {@customer_token}" met een geheime aanroepvariabele. Naast een credential zou het een tweede credential zijn, en dat geeft 422, op request bij een koppeling en op headers bij een MCP-server. Een koppeling of server die je via een publicatie deelt en waarvan het credential meereist of door de installateur wordt ingevuld, telt als een tool met een credential.

Cookie en Proxy-Authorization worden altijd geweigerd, net als de header waarin auth wordt verstuurd. Er is geen manier om auth per verzoek te vervangen: een credential per verzoek is een geheime aanroepvariabele, op de plek die de maker van de tool in het sjabloon zette.

Scripts, workflows en aliassen

Ook deze soorten declareren install_values en call_variables, alleen zonder geheimen:

Soort Invulwaarde Aanroepvariabele
Script het bestand dat ARTIFIC_INSTALL noemt, alleen-lezen het bestand dat ARTIFIC_VARIABLES noemt, met alleen de variabelen die de versie declareert
Workflow install.<naam> in een expressie run.variables.<naam> in een expressie; een toolstap geeft ze door aan zijn tool
Alias een vast argument dat precies "{$naam}" is een vast argument dat precies "{@naam}" is

Een workflowrun krijgt zijn waarden bij de start in variables (POST /workflows/{id}/runs), niet in tool_variables; een waarde die niet past geeft 422 op variables.<naam>. Een toolstap waarvan de tool een variabele vereist die de run niet heeft, eindigt met de code variable_missing:<naam>.

Met een alias geef je elke andere tool een waarde per verzoek, zonder dat het model hem ziet: een vast argument "{@customer_id}" geeft bijvoorbeeld een zoektool een filter per klant.

Limieten

Wat Limiet
Namen in tool_variables 64
Eén string 4.096 tekens; 8.192 voor een geheim
Het hele object, als compacte JSON 64 KiB
call_variables op één versie 64

Een verzoek met te veel namen, te veel bytes in totaal of een string van meer dan 8.192 tekens wordt geweigerd op tool_variables voordat er een tool wordt bekeken. Een gewone string van 4.097 tot 8.192 tekens wordt geweigerd wanneer de tools van de beurt worden gecontroleerd, op tool_variables.<naam>, met de tool die hem declareert; voor een naam die geen tool declareert, wordt hij genegeerd. Je deployment kan andere limieten hebben ingesteld.