Tool registry
Tools are what the agent acts with. On each turn, the intent classifier picks a subset, and the tool loop lets the model call them until it can answer. This page lists the built-in registry and the tools with behaviour worth knowing. Customizing tools covers removing, replacing and adding them.
The ToolEntry shape
DEFAULT_TOOLS is a flat record of named tools. Each ToolEntry defines what a tool does and how the agent uses it:
{ description: string; // Full tool description for the model inputSchema: ZodType; // Validated input parameters outputSchema?: ZodType; // Structured output (improves reliability) execute: (input, state, options?) => Promise<any>; // never throws — returns { error } instead
// Classifier and help metadata classificationPrompt?: string; // One line: when to activate this tool — what the classifier reads tags?: string[]; // Category labels (e.g. 'route', 'traffic') examples?: string[]; // Usage examples, in the metadata a custom classifier receives examplePrompts?: string[]; // Natural-language prompts shown by the help tool relatedTools?: string[]; // Tools often used together, listed by help dependsOn?: string[]; // Tools that must run first, shown to the classifier
// Loop control alwaysActive?: boolean; // Offered every step, whatever the classifier picked endsTurnOnCall?: boolean; // Calling it ends the turn
// Per-turn scope — see Scope-aware data tools scopeSchema?: ZodType; // Shape of `toolScopes[<name>]` the classifier emits scopePrompt?: string; // Explains the scope shape to the classifier}If the entry must be rebuilt per turn, a tool can also be a ToolEntryBuilder, a function from ToolBuildOptions to
ToolEntry. Add a scopable custom tool shows one.
Cancellation
execute’s third argument carries the AI SDK’s abortSignal for the call, which fires when the turn is cancelled:
type ToolExecuteOptions = { signal?: AbortSignal };Forward it to every service call your tool makes, so a cancelled turn also cancels the HTTP request. An aborted call
rejects with SDKAbortError. Because execute must never throw, catch it and return an error shape:
import { SDKAbortError, discoverPlaces } from '@tomtom-org/maps-sdk/services';
execute: async ({ query }, state, options) => { try { const results = await discoverPlaces({ query, signal: options?.signal }); return { count: results.features.length }; } catch (error) { if (error instanceof SDKAbortError) return { error: 'Cancelled.' }; return { error: `Search failed: ${error instanceof Error ? error.message : String(error)}` }; }},Do not forward it into work that outlives the turn, such as a monitor’s recurring tick. That work runs after the signal has aborted. A monitor treats a rejected tick as fatal and clears its interval, so a leaked signal stops the monitor.
What’s in the registry
| Category | Tools |
|---|---|
| Location | locatePlace, reverseGeocode, getCurrentLocation, getViewport, calculateBBox |
| Places & search | discoverPlaces, getPOICategoryCodes |
| Routing | setRoute, addWaypointsToRoute, removeWaypointsFromRoute, replaceWaypointInRoute, getCurrentWaypoints, startRouteMonitor, stopRouteMonitor |
| Reachable areas | findReachableAreas, for isochrones and isodistances. It needs an API key with Calculate Reachable Range access (private preview) |
| Your own data | addByodSource, setByodLayers, updateByodDisplay — see Bring your own data |
| Traffic incidents | getTrafficIncidents, setTrafficIncidentsMonitor, clusterIncidents, focusIncidents |
| Traffic area analytics | getTrafficAreaAnalytics, updateTrafficAreaAnalyticsDisplay, which shows and hides the entries. setMapStyling sets their look |
| Trackers (geofence and proximity alerts) | createTracker, getTrackers, getTrackerHistory, clearTracker |
| Data tools | analyseData, processData, monitorAnalysis — see Scope-aware data tools |
| Map display | updatePlacesDisplay, updateRoutesDisplay, updateWaypointsDisplay, clearMap — which entries show. setMapStyling sets how they look |
| Map control | flyTo, zoomInOrOut, setPitchBearing, setMapStandardStyle, getStandardMapStyles, setLanguage, setGeopoliticalView (whose view of disputed territories the map and later searches follow) |
| Map styling | setMapStyling — what the base map shows and how it looks, every knob by its map-wide id: Styling Foundations, whole base-map layer groups such as 3D buildings (groups.buildings3D.visible), the POI icons and their categories pois., the live traffic overlays and their filters traffic.flow. / traffic.incidents., hillshade terrain.hillshade. and 3D terrain terrain.elevation.. It also applies a map preset, a reset or a theme from a few colours or an image whose accent also recolours routes and place pins. It also styles every layer the agent drew, shown now or later: found places places., routes routes. (colour, width, waypoints, sections), polygons and place boundaries geometries., reachable areas ranges., area analytics traffic.areaAnalytics. (display mode, metric, palette, height, filters) and fetched incidents traffic.incidentDetails.. Showing them, a places entry’s marker type and a polygon’s fill style stay with the display tools. Each turn lists only the knob families it touches. See Scope-aware data tools |
| MapLibre direct | executeMaplibreCode, getMapStyleLayers, setLayerProperties, which sets the paint and layout properties of named style layers |
| State | recallState, setEntryMode, resetState |
| Utilities | clarifyIntent, help |
analyseData and processData take JavaScript as a parameter instead of a fixed argument list, as
Code generation explains. The
Agent Toolkit Plugin API Reference has every tool’s input and output schema.
The help tool
When a user asks “what can you do?” or “show me routing examples”, the model calls help (summary or detail, filtered
by tag or query) to surface tool descriptions, example prompts and related tools.
In your own code, getDefaultToolPrompts() returns every tool’s examplePrompts as a Record<ToolName, readonly string[]>.
They make starter suggestions for your chat UI that stay in sync with the registry.
Tools that read state vs. fetch data
Some tools fetch fresh data from TomTom services, and others read state. recallState reads and never
fetches:
- No arguments - A snapshot of the session, with the places, routes and ranges loaded, entry modes, map style, POIs and traffic.
{ kind }- The index of one kind:places,routes,ranges,geometries,byod,incidentsortrafficAreaAnalytics.{ kind, id }- One entry, summarised.
When a user asks “what were those places?” an hour into a session, the model calls recallState instead of guessing.
Asking the user with clarifyIntent
clarifyIntent asks the user to choose among a few options before the agent acts. It is alwaysActive, so the model can
ask mid-task. By default, the model also writes the questions as prose, for UIs without a form. If your UI renders the
tool call’s questions as a form, build the tool with rendersForm: true:
import { createClarifyIntentTool, createMapAgent } from '@tomtom-org/maps-sdk-plugin-agent-toolkit';
createMapAgent(map, { model, tools: { clarifyIntent: createClarifyIntentTool({ rendersForm: true }) },});- The turn then ends on the call, with no prose. Render the call’s
introandquestions(each withid,question,optionsandmultiSelect), and send the user’s choices as the next message. createClarifyIntentToolalso overridesdescription,classificationPrompt,examples,examplePromptsandalwaysActive.
What getCurrentLocation sends
getCurrentLocation asks for the user’s position through the browser’s permission prompt, and returns it to the model.
The model provider you configured receives the position with the rest of the conversation. The prompt
names only your site, not the model, so tell users in your UI that the position goes to the assistant.
By default, the tool sends only what a “near me” query needs:
| Field | Default | With fullPrecision: true |
|---|---|---|
position | [lng, lat] rounded to 3 decimals (about 100 m) | the exact fix |
accuracy | 111 m, or the device’s accuracy when that is coarser | the device’s accuracy |
timestamp | not sent | the fix’s timestamp |
| Fix requested | enableHighAccuracy: false, a fix up to 60 s old | enableHighAccuracy: true, a fresh fix |
To send the exact position, replace the default with createGetCurrentLocationTool:
import { createGetCurrentLocationTool, createMapAgent } from '@tomtom-org/maps-sdk-plugin-agent-toolkit';
createMapAgent(map, { model, tools: { getCurrentLocation: createGetCurrentLocationTool({ fullPrecision: true }) },});To never ask for the position, remove the tool. “Near me” queries then fall back to the map view:
createMapAgent(map, { model, tools: { getCurrentLocation: false } });getTrafficIncidents where schema
getTrafficIncidents takes its area as where: { mode: 'within', … }, with the same multi-region fields as
discoverPlaces: viewport, boundingBox, queries, placeIds, geometries, range, route. They resolve to
bounding boxes, combined into one of at most 10,000 km². Without where, the tool uses the viewport.
// Current viewportgetTrafficIncidents({});
// Named area (geocoded → polygon bbox)getTrafficIncidents({ where: { mode: 'within', queries: [{ query: 'Paris', queryAs: 'place' }] } });
// Buffered corridor around the latest routegetTrafficIncidents({ where: { mode: 'within', route: { widthMeters: 1000 } } });
// Multi-source uniongetTrafficIncidents({ where: { mode: 'within', queries: [{ query: 'Amsterdam' }], placeIds: ['G55fc4abe-...'] },});- A named area wins over
viewport: truewhen the model sends both. Strict-mode providers such as Azure and OpenAI fill every field. - By default, the tool monitors (
monitor) the incidents shown on the map every 60 s (monitorIntervalMs). It fetches only present incidents, unlesstimeValidityFiltersays otherwise.
Related
- Customizing tools — remove, replace or add tools.
- Bring your own data — your GeoJSON as agent layers.
- Scope-aware data tools —
analyseData/processDataper-turn scope. - Code generation — JavaScript-as-parameter tools and their threat model.
- State — what each tool reads from and writes to.
- How it works — the classifier and tool loop.
- Securing your agent — the caps on tool arguments, and what bounds a turn.