Een agent met veel tools¶
Het concept achter deze pagina staat in De toolrouter.
Op deze pagina zet je de toolrouter aan voor een sleutel, kies je hem voor een agent of één verzoek, en controleer je in de trace en met een evaluatie of het model zijn tools nog vindt. Gebruik de router wanneer een agent meer tools krijgt dan zijn model in één aanroep aankan, of zo veel dat het model slecht kiest.
Je hebt nodig:
- een sleutel met de capability
tooling; - een organisatie die tool search toestaat. Doet ze dat niet, dan zet alleen de organisatie erboven of de operator het aan, op Instellingen, tabblad Toegang & policy, kaart Tools laten zoeken (Instellingen van een organisatie);
- een embeddingmodel dat de sleutel mag gebruiken. Zonder dat werkt de router ook, maar zoekt hij alleen op trefwoord.
De router aanzetten op een sleutel¶
De router hoort bij de configuratie van tooling op de sleutel:
{
"capabilities": {
"tooling": {
"system_tools": ["web_fetch"],
"tool_search": {
"enabled": true,
"default_mode": "direct",
"top_k": 5,
"budget_tokens": 4000
}
}
}
}
Stuur dit met PATCH /keys/{key_id}. capabilities vervangt de hele set van de sleutel, dus lees
hem eerst met GET /keys/{key_id} en stuur alle capabilities terug met je wijziging erin.
| Veld | Wat het doet |
|---|---|
enabled |
maakt de router beschikbaar voor de beurten van deze sleutel. Standaard uit |
default_mode |
direct of router: de modus als agent en verzoek niets zeggen. Standaard direct |
top_k |
hoeveel tools één zoekopdracht teruggeeft als het model zelf geen top_k noemt, van 1 tot 20. Standaard 5. Het model mag zelf om 1 tot 20 vragen |
budget_tokens |
hoe groot één zoekresultaat mag zijn, van 100 tot 32.000 tokens, welke top_k het model ook vraagt. Standaard 4.000 |
preload |
tools vooraf kiezen, zie hieronder |
Met enabled alleen verandert er nog niets: een beurt gebruikt de router pas als het verzoek, de
agent of default_mode om router vraagt.
In de console staat hetzelfde op de pagina van de sleutel, onder de systeemtools van tooling: de schakelaar Tool zoeken, daaronder Standaard met Direct of Via zoeken, en de getallen Resultaten per zoekopdracht en Ruimte voor een resultaat (tokens). Een leeg getal betekent de standaard van Core. Staat tool search voor de organisatie uit, dan is de schakelaar vergrendeld en staat erbij waarom (Sleutels).
De router kiezen voor een agent¶
Een agentversie kiest de modus voor elke beurt die de agent draait. Maak een nieuwe versie met
tool_search:
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>",
"tools": [{"type": "toolset", "name": "orders"}],
"tool_search": {"mode": "router"}}'
top_k en budget_tokens mag je ernaast zetten; laat je ze weg, dan gelden die van de sleutel.
null laat de keuze aan de sleutel. In de console heet dit Tools aanbieden, bij de
modelinstellingen van de versie, met Standaard van de sleutel, Direct of Via zoeken.
Noemt de versie router terwijl de sleutel die het verzoek doet tool search niet aan heeft, dan
weigert Core elk verzoek met deze agent op tool_search.mode ("Tool search is not enabled for
this key."). Een agent die als tool in een andere beurt draait, volgt zijn eigen modus.
De router kiezen voor één verzoek¶
tool_search op een verzoek gaat boven de agent en de sleutel:
curl -s -X POST "$CORE_URL/responses" \
-H "Authorization: Bearer $CORE_KEY" -H "Content-Type: application/json" \
-d '{"agent": {"id": "support"},
"input": "Zet de bestelling van klant 4411 op pauze.",
"tool_search": {"mode": "router", "top_k": 8}}'
{"mode": "direct"} biedt voor deze beurt elke tool weer direct aan, ook als de agent router
kiest. Op /messages werkt hetzelfde veld. Een geweigerde router krijgt een 400: op
/responses met tool_search.mode in error.param, op /messages met een error.message dat
begint met tool_search.mode:.
Een client die de velden van de leverancier stuurt, krijgt dezelfde router zonder dat je iets
aanpast: defer_loading: true op een tool, het item {"type": "tool_search"} van OpenAI op
/responses of tool_search_tool_bm25 of tool_search_tool_regex van Anthropic op /messages.
Elk daarvan vraagt om router voor het hele verzoek, nooit voor één tool. Een tool_search die het
verzoek zelf meestuurt, gaat boven die velden (Een codeeragent
aansluiten).
De router via MCP¶
Een MCP-client buiten Core, zoals Claude Code of Cursor, kiest de router met ?tool_search=router
op het sleuteladres of het adres van een toolset:
https://<jouw Core-adres>/api/v1/mcp?tool_search=router
https://<jouw Core-adres>/api/v1/mcp/toolsets/<naam>?tool_search=router
De server toont dan alleen builtin__tool_search en builtin__tool_run, met de top_k en
budget_tokens van de sleutel. default_mode van de sleutel geldt hier niet: zonder de parameter
krijgt de client alle tools (Core gebruiken vanuit een
MCP-client).
Tools vooraf kiezen¶
Met preload begint een beurt in de modus router met de tools die het best bij het bericht
passen, als zoekresultaat dat het model meteen kan gebruiken. Dat bespaart een zoekronde wanneer
het bericht duidelijk zegt wat er moet gebeuren.
{
"tool_search": {
"enabled": true,
"preload": { "enabled": true, "limit": 5, "budget_tokens": 1500 }
}
}
| Veld | Wat het doet |
|---|---|
preload.enabled |
zet het vooraf kiezen aan. Standaard uit |
preload.limit |
hoeveel tools een beurt hoogstens vooraf krijgt, van 1 tot 20. Standaard 5 |
preload.budget_tokens |
hoe groot dat resultaat mag zijn, van 100 tot 8.000 tokens. Standaard 1.500 |
Het is een instelling van de sleutel alleen; een agentversie of verzoek kan het niet aan- of uitzetten. In de console staat het onder de schakelaar Tool zoeken, zolang die aan staat: Tools vooraf kiezen, met Tools per beurt en Ruimte voor de vooraf gekozen tools (tokens).
Controleren of het werkt¶
Lees de trace van een beurt met GET /responses/{response_id}/trace en open een aanroep met GET
/traces/{call_id} (Een trace lezen):
- In
interpretation.toolsstaat elke tool die achter de router zat met de beslissingrouted. Een tool die je mist en die daardenied_by_policyofwithheld_by_capabilityheeft, kon het model ook niet vinden. - In
tool_callsstaat elke zoekopdracht alsbuiltin__tool_search, met inrefshoeveel tools er doorzocht zijn (candidates), welke hij vond met hun score (hits) en of hij alleen op trefwoord rangschikte (keyword_only). - Een uitvoering staat in
tool_callsonder de naam van de echte tool, metrouted: true. - Vooraf gekozen tools staan in
interpretation.blocksals blok metsource: "tools": inrecord_idsde gekozen tools, indropped_by_countendropped_by_budgethoeveel tools de grenzen weglieten, en inestimated_tokenswat het resultaat kostte. In het gesprek zelf staan ze als een aanroep vanbuiltin__tool_searchmet de argumenten{"preloaded": true}en het resultaat erbij.
In de console staat dezelfde informatie op de pagina van een aanroep onder Traces: in Welke tools zijn aangeboden hebben de tools achter de router Achter de router, en bij een zoekopdracht staat het blok Zoekopdracht van de router met Gezocht op en de gevonden tools. Een uitvoering is gemarkeerd met Via de router gevonden.
Vindt het model een tool niet die het wel had moeten vinden, verbeter dan de beschrijving van die tool: een zoekopdracht vergelijkt de vraag van het model met de naam, de beschrijving en de parameters van elke tool.
Meten met een evaluatie¶
Met een evaluatie zie je of de router je agent beter of slechter maakt. Daarvoor dienen twee checks:
| Check | Slaagt wanneer |
|---|---|
tool_found |
een builtin__tool_search in de beurt, of de vooraf gekozen tools, expected onder de resultaten had |
must_use_tool |
de beurt expected aanriep, direct of via de router |
Dit is één stap in de steps van een scenario (Een scenario
schrijven):
{"input": "Zet de bestelling van klant 4411 op pauze.",
"checks": [{"kind": "tool_found", "expected": "api__orders_pause", "required": false},
{"kind": "must_use_tool", "expected": "api__orders_pause"}]}
Samen vertellen ze waar het misgaat: faalt tool_found, dan vond de zoekopdracht de tool niet;
slaagt tool_found en faalt must_use_tool, dan vond het model de tool maar gebruikte het hem
niet. Een beurt zonder zoekopdracht faalt op tool_found, dus in de modus direct faalt elke stap
erop en meet alleen must_use_tool iets. Daarom staat tool_found hierboven op "required":
false: in een run in de modus direct geeft hij alleen een waarschuwing, en slaagt of faalt de
stap op must_use_tool.
Om de router aan en uit te vergelijken:
- Start een run van de suite terwijl de laatste versie van de agent
directis. - Maak een nieuwe versie met
"tool_search": {"mode": "router"}en start nog een run. - Vergelijk de twee runs op
must_use_tool. Elke run legt de agentversie vast waarmee hij draaide.
Fouten¶
| Antwoord | Betekenis | Wat je doet |
|---|---|---|
400 op tool_search.mode (error.param op /responses, het begin van error.message op /messages), "Tool search is not enabled for this key." |
een verzoek of agent vraagt om router, maar de sleutel heeft tool_search.enabled niet of de organisatie staat tool search niet toe |
zet de schakelaar op de sleutel aan, of vraag de organisatie erboven om tool search toe te staan |
422 op tool_search op een MCP-adres |
hetzelfde, voor ?tool_search=router |
idem |
422 op tools (400 op /responses en /messages), "This request offers more than … tools; model '…' accepts at most …." |
de beurt biedt meer tools aan dan het model aankan | zet de router aan, of bied minder tools aan |
422 op tools, "This request offers more tools than a turn may carry." |
meer dan 128 tools direct, of meer dan 2.048 achter de router | bied minder tools aan, of zet de router aan |