01Safety
0.0 / 30
What changed in the harness
Selection accuracy 100→100, token cost up 11%, unconfirmed writes 0%→0%.
Category breakdown
Earned points across the four signals Gradable measures. Safety and Legibility are scored out of 30; Economics and Discoverability are scored out of 20.
0.0 / 30
27.0 / 30
18.1 / 20
12.8 / 20
Highest-impact fix
Estimated gain +30 pointsExpose machine-readable principal/tenant confirmation and a non-mutating permission check so agents can verify both before destructive actions.
Description evidence
9 defects found across the exposed tool descriptions. Suggested rewrites make purpose, inputs, boundaries, and returns easier for an agent to understand.
| Tool | Defect types | Suggested rewrite |
|---|---|---|
search_places |
params_unexplained |
Search for places (businesses, points of interest, landmarks) by a natural-language `query` (e.g. "24-hour pharmacy"), optionally biased to a coordinate via `near` (a {latitude, longitude} point) and/or restricted to a country via `country`. `radiusMeters` sets the search radius in meters around `near`; `categories` restricts results to the given business types (e.g. "cafe", "restaurant"); `openNow` filters to places currently open; `limit` caps how many results are returned (default 10, max 50). `options` tunes provider behavior (strategy, providers, maxCostUSD, timeoutMs, language). Returns places ranked by relevance/distance, each with location, address, contact, opening hours, and its data source(s). Use this for "find X near Y" requests. Example: {"query": "24-hour pharmacy", "near": {"latitude": 10.7769, "longitude": 106.7009}, "radiusMeters": 2000}. To turn an address into coordinates use geocode_address instead; to look up one known place use get_place. |
get_place |
params_unexplained |
Fetch full details for a single place by its provider reference id, in the form "provider:providerPlaceId" (e.g. "google:ChIJN1t_tDeuEmsRUsoyG83frY4"), as found in a place's `sources`. Only providers that support getPlace can resolve a reference - currently Google (needs an API key). OpenStreetMap/Nominatim does not, so a "nominatim:..." reference returns nothing; use search_places or geocode_address for OSM instead. Internal "gwp_" ids cannot be resolved directly. `options` tunes the provider call (strategy, providers, maxCostUSD, timeoutMs, language). Example: {"id": "google:ChIJN1t_tDeuEmsRUsoyG83frY4"}. |
geocode_address |
params_unexplained |
Convert a street address or place name into latitude/longitude coordinates and a normalized address. `address` is the free-form address or place name to geocode; `country` restricts the search to a specific country; `limit` caps the number of candidate matches returned (default 5, max 20); `options` tunes provider behavior (strategy, providers, maxCostUSD, timeoutMs, language). Returns the matching coordinates and normalized address. Use this when you have an address string and need latitude/longitude. Example: {"address": "1600 Amphitheatre Parkway, Mountain View, CA"}. To search for businesses by name/category, use search_places. |
reverse_geocode |
params_unexplained |
Convert geographic coordinates into the nearest address / place. `location` is the {latitude, longitude} point to reverse-geocode; `options` tunes provider behavior (strategy, providers, maxCostUSD, timeoutMs, language). Returns the nearest address and place for the given coordinates. Example: {"location": {"latitude": 37.5665, "longitude": 126.9780}}. |
get_directions |
params_unexplained |
Get a route (driving directions) between two or more waypoints, with total distance, travel time, and per-leg breakdown. `waypoints` are ordered {latitude, longitude} pairs: (start, [via...], end). `mode` selects the travel mode (driving, walking, cycling - note the public OSRM server supports driving only); `alternatives` requests alternative routes in addition to the best one; `geometry` includes the route polyline when true; `options` tunes provider behavior (strategy, providers, maxCostUSD, timeoutMs, language). Works with no API key (OpenStreetMap routing via OSRM). Use this for "how do I get from A to B", "how far by car", or "how long to drive" questions. Example: {"waypoints": [{"latitude": 37.5665, "longitude": 126.9780}, {"latitude": 37.4979, "longitude": 127.0276}]}. |
distance_matrix |
params_unexplained |
Compute a matrix of travel distances and times from each origin to each destination (N origins x M destinations) in one call. `origins` is an array of {latitude, longitude} start points; `destinations` is an array of {latitude, longitude} end points; `mode` selects the travel mode (driving, walking, cycling - public OSRM supports driving only); `options` tunes provider behavior (strategy, providers, maxCostUSD, timeoutMs, language). Returns a matrix where rows[i][j] gives the distance and travel time from origins[i] to destinations[j]. No API key needed. Use this to rank/compare many candidates by drive time - e.g. "which of these 5 stores is closest to the customer" or delivery/logistics assignment. Example: {"origins": [{"latitude": 37.57, "longitude": 126.98}], "destinations": [{"latitude": 37.49, "longitude": 127.02}, {"latitude": 37.51, "longitude": 127.05}]}. |
analyze_area |
params_unexplained |
Analyze a commercial area / neighborhood: given a center point, radius, and business types, return how many of each exist nearby, their density (per km2), rating landscape, and top places. `center` is the {latitude, longitude} point at the center of the area; `radiusMeters` sets the search radius around it (max 50000); `categories` lists the business types to count, e.g. ["cafe", "restaurant", "convenience store"]; `limitPerCategory` caps how many places are sampled per category (default 50); `options` tunes provider behavior (strategy, providers, maxCostUSD, timeoutMs, language). Use this for market/competition questions. Works with any configured providers; richer with Google/Foursquare (ratings). Not demographic data - it's a place-density/competition view built from live search. Example: {"center": {"latitude": 37.4979, "longitude": 127.0276}, "radiusMeters": 1000, "categories": ["cafe", "restaurant", "convenience store"]}. |
get_demographics |
params_unexplained |
Get demographics (population, median age, median household income, households) for the area containing a coordinate. `location` is the {latitude, longitude} point whose containing area to look up; `options` tunes provider behavior (strategy, providers, maxCostUSD, timeoutMs, language). Returns the demographic figures for the containing area, or null outside coverage. Requires a demographics provider: US Census (free key, US only). Example: {"location": {"latitude": 37.7749, "longitude": -122.4194}}. For a full commercial picture combine with analyze_area, which folds this in automatically. |
get_isochrone |
params_unexplained |
Compute a travel-time reachability area (isochrone): from an origin, the region reachable within N minutes of driving/walking/cycling. `origin` is the {latitude, longitude} starting point; `mode` selects the travel mode (driving, walking, cycling); `minutes` sets the travel-time budget (max 60); `bearings` sets how many compass directions are sampled (default 16, between 8 and 24); `options` tunes provider behavior (strategy, providers, maxCostUSD, timeoutMs, language). Returns the reachable region as a GeoJSON polygon plus its area in km2. No API key (OpenStreetMap routing). Use for site selection / catchment questions. Note: it's an approximation (sampled bearings scored by a distance matrix), not a routing-engine isochrone. Example: {"origin": {"latitude": 37.7749, "longitude": -122.4194}, "minutes": 15, "mode": "driving"}. |
Selection evidence
4 pairs where similar names or overlapping descriptions may send an agent toward the wrong tool.
| Tool A | Tool B | Confidence | Why they collide |
|---|---|---|---|
geocode_address |
reverse_geocode |
medium | Both convert between addresses and coordinates in opposite directions; a task phrased as 'geocode this place/location/address' does not pin the conversion direction, so an agent can pick the wrong one. |
get_demographics |
get_isochrone |
low | Vague 'what's in the area around this coordinate' queries match both signatures (single coordinate input), though the returned data (demographics vs reachable region) is distinct. |
get_directions |
get_isochrone |
low | Both are driving/travel-time tools; 'what can I reach in 15 minutes' could be read as an A-to-B route rather than a catchment area, though descriptions mostly disambiguate. |
search_places |
get_place |
medium | 'Look up/get details for [place name]' without a provider reference id could send the agent to get_place, which only resolves provider ids, instead of search_places which accepts natural-language queries. |
Compare the field