Skip to navigation

Find, describe, invoke

The three steps every entry point uses
View as Markdown
StepHTTPMCP toolCLICharged
FindPOST /v1/findfind_toolsagentrouter find "<task>"No
DescribePOST /v1/describedescribe_toolagentrouter describe <tool_id>No
InvokePOST /v1/invokeinvoke_toolagentrouter invoke <tool_id> --input …Per the tool’s rules

Find and describe never execute a provider call and work without a key. Invoke needs a credential with the invoke scope.

Tools are addressed by tool_id

A tool id names one provider endpoint, for example anyapi.twitter.search or hunter.email_verifier. There are no domains, capabilities or routes to resolve first, and AgentRouter does not silently switch providers for you: the agent chooses the tool, and the receipt names the provider that ran.

Find

POST /v1/find
{ "query": "verify an email address", "limit": 5 }
  • query is a short task description (up to 500 characters). Matching is by keywords over tool ids, titles, tags, descriptions, use cases, and category/group names and aliases.
  • Optional filters: provider, category_ids (any), group_ids (any), tags (all must match), include_unavailable (tools in an outage are hidden by default).
  • match is exact, partial or none. With none, record the gap with feedback (kind: tool_request) instead of forcing an unrelated tool.
  • Each candidate includes required_inputs, price (summary, price_multiplier, free) and health (unknown means too few recent runs, not unavailable).

Browse the two-level catalog

GET /v1/catalog returns enabled tools plus groups and categories. Groups are top-level themes such as Social and GTM. Categories are second-level entries such as LinkedIn, Google Search, People Profiles or Web Search. There is no separate platform field. A category’s parent_ids refer only to groups.

Tools include category_ids and derived group_ids in catalog, find and describe responses. A tool may appear in more than one category; tool_count counts each tool once per category/group. Empty entries are omitted. GET filters use comma-separated IDs, for example /v1/catalog?category_ids=linkedin,people-data&provider=anyapi. Filters from different dimensions intersect.

POST /v1/find
{ "query": "person profile", "category_ids": ["linkedin"], "group_ids": ["gtm"] }

CLI: agentrouter find "person profile" --category linkedin --group gtm. MCP find_tools uses the same category_ids and group_ids arrays. Tags remain search keywords; they do not create categories or another navigation level.

Describe

POST /v1/describe
{ "tool_id": "hunter.email_verifier" }

The response is the tool’s contract:

FieldUse it for
input_schemaThe JSON Schema input must match. Invalid input is rejected with INPUT_INVALID before anything runs.
examplesKnown-good inputs.
limits, paginationMaximum results per call and how to request the next page.
executionmode (sync or async), stoppable, max_duration_ms.
pricingpricing_version, price_multiplier, max_per_call_usd or the rule that sets the maximum, the provider’s published price, and the charge rules for errors, empty results, timeouts and stops.
health, alternativesRecent success and latency, and related tools.

Health covers the full seven-day window in health.window, using each run’s finish time. samples is the number of completed, failed and timed-out logical calls; blocked requests and cancellations are excluded. success_rate is completed calls divided by samples, including legitimate empty results as completed calls.

health.latency reports exact nearest-rank p50 and p95 execution times for successful calls only. Its own samples excludes missing or invalid durations. Execution time includes asynchronous processing and polling waits, but excludes final settlement and delivery to the client. The flat p50_ms and p95_ms fields remain as aliases of these successful-call percentiles.

Health is calculated from stored runs on demand and cached for 60 seconds. computed_at and the window bounds identify the snapshot; reading health never calls the provider. Empty-result detection and the legacy empty_rate remain endpoint-specific.

You can reuse a describe result for many calls. Describe again when invoke reports PRICING_CHANGED or TOOL_VERSION_CHANGED.

Invoke

POST /v1/invoke
Idempotency-Key: research-7-step-3
{
"tool_id": "hunter.email_verifier",
"pricing_version": "<from describe>",
"input": { "email": "someone@example.com" },
"max_cost_usd": "0.05",
"session_id": "research-7"
}
FieldRequiredMeaning
tool_idyesThe tool to run.
pricing_versionyesThe price terms you accepted in describe. If the price changed since then, nothing runs and you get PRICING_CHANGED.
inputper schemaMatches input_schema; an object or an array.
max_cost_usdnoThe most this call may cost (default "0.50", lowered by budgets). If the tool’s maximum for this input is higher, the run is BLOCKED with MAX_COST_EXCEEDED and a hint with the amount needed.
session_idnoGroups the runs of one agent task; session budgets apply.
tool_versionnoPins a version; a change returns TOOL_VERSION_CHANGED.
Idempotency-Key headerrecommendedMakes retries safe. Same key and request → the original run (replayed: true, no new charge). Same key, different request → IDEMPOTENCY_KEY_CONFLICT.

Clients cannot send prices or multipliers; a request that includes them is rejected with PRICE_NOT_CLIENT_SETTABLE.

Invoke returns a Run. HTTP 200 means it finished (completed, failed, stopped or timed out), 202 means it is still running on the server, 402/409 mean it was blocked before execution and not charged.

Choosing between tools

When several tools fit, the agent decides within the task and the user’s spending rules: compare fit, the inputs you already have, max_per_call_usd and health. Do not stop just to ask the user to choose a provider. Respect a tool or entry the user named, and tools the user already has for the same job.