Tool Recommendation
Tool Recommendation lets an agent describe a task and get back only the tools that fit it, instead of holding every tool on a gateway in its context. This page is for agent developers and platform operators who run gateways with many tools. It explains what an client gets when is on, how the finds and calls , and what decides the quality of the results. Read it before you turn Tool Recommendation on for a gateway.
Why it exists
An client normally lists every tool on a gateway and passes all of their names, descriptions, and input schemas to the model. A gateway that federates a handful of can expose hundreds of tools. At that size the tool definitions consume a large share of the window, and the model picks the wrong more often because it has too many near-matches to choose from.
With on, the gateway lists a small, fixed set of Arcade tools. The asks for the it needs when it needs them, and Arcade returns the few that match.
What an MCP client gets
When is on for a gateway, the gateway’s list contains these Arcade tools instead of the allowed tools:
| Tool | What it does |
|---|---|
Arcade.SelectTools | Takes one or more task descriptions and returns the tools that match each task most closely, with their full input schemas. |
Arcade.UseTool | Runs a tool by name with the inputs you pass. |
The list spells these names with an underscore separator, for example Arcade_SelectTools. Arcade accepts either form in a tool call.
How an agent finds and calls a tool
The works in two steps.
First, it calls Arcade.SelectTools with the tasks it wants to complete. Each entry in tasks describes one separate action:
{
"tasks": ["send a Slack message to a channel", "create a GitHub issue"],
"context": "The user is triaging a production incident"
}Arcade returns up to five tools per task, ranked by how well they match. Each result includes the ’s name, description, and input schema, plus a query_id for the whole request.
When a task gets no , its result includes an empty_reason. The uses it to decide whether to retry:
no_match: Arcade finished the lookup and found no tool the may use for that task. Retrying the same task returns the same answer.unavailable: The lookup for that task didn’t complete. Retrying may succeed.
Second, the calls Arcade.UseTool with the it picked and that tool’s own arguments nested inside inputs:
{
"tool_name": "Slack.SendMessage",
"inputs": {
"channel_name": "incidents",
"message": "Investigating elevated error rates on checkout."
},
"query_id": "the query_id returned by Arcade.SelectTools"
}query_id is optional. Arcade uses it to connect the to the recommendation that surfaced it.
The tool descriptions that Arcade serves tell the model how to use this flow, so most need no extra prompting.
How selection works
Arcade.SelectTools matches each task against the tools the gateway allows, using both the words in the task and its meaning, and returns the closest matches first. Matching on meaning finds a even when the task shares no words with it, for example “let the team know the deploy finished” matching a Slack tool. The optional context helps Arcade rank the matches.
What Arcade can recommend
doesn’t change which tools an can use. Arcade.SelectTools returns only that the gateway allows, and Arcade.UseTool runs any tool that the gateway allows, whether or not Arcade.SelectTools returned it.
Policy enforcement and authorization work the same way with on or off. See Contextual Access for how access rules decide which each can see and use, and Authorized Tool Calling for how tools run as the end user.
Use it over the REST API
Agents and apps that don’t connect through can call the same operations as REST endpoints of the Arcade API:
| Endpoint | MCP tool | What it does |
|---|---|---|
POST /v1/tools/select | Arcade.SelectTools | Returns the tools that match each task. |
POST /v1/tools/search | None | Ranks tools by how well their words match a keyword query. |
POST /v1/tools/execute | Arcade.UseTool | Runs a tool by name. |
GET /v1/apps | Arcade.ListApps | Lists the apps the user can act on, and whether each is connected. |
Authenticate with your key as a bearer token. With an , name the end Arcade acts for in user_id. These endpoints don’t read a gateway’s setting. If Recommendation isn’t available in your deployment, select and search return 503.
Select tools
curl -X POST "https://api.arcade.dev/v1/tools/select" \
-H "Authorization: Bearer $ARCADE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tasks": ["send a Slack message to a channel", "create a GitHub issue"],
"context": "The user is triaging a production incident",
"user_id": "{user_id}",
"gateway_id": "{gateway_id}",
"top_k": 3
}'tasksis required. Each task gets one entry inresults, in the order you sent them.top_ksets the number of per task. It defaults to 5, and values above 20 return 20.gateway_idis optional. With it, Arcade considers only the tools that gateway allows. Without it, Arcade considers every tool the user can access in the .
{
"query_id": "8b0f6a52-3c1e-4d4e-9a57-2f1c0e6d9b21",
"results": [
{
"task": "send a Slack message to a channel",
"suggestions": [
{
"tool_name": "Slack.SendMessage",
"description": "Send a message to a Slack channel or user.",
"input_schema": {
"type": "object",
"properties": {
"channel_name": { "type": "string" },
"message": { "type": "string" }
}
}
}
]
},
{
"task": "create a GitHub issue",
"suggestions": []
}
]
}An empty suggestions list means no the may use matched that task. If the lookup fails for any task, the whole request fails: 503 means the service is temporarily unavailable and a retry may succeed.
Search tools
POST /v1/tools/search takes a query and returns results, a list of in the same shape as suggestions, ranked by keyword match. top_k defaults to 10, and values above 50 return 50. It accepts the same user_id and gateway_id as select.
Run a tool
POST /v1/tools/execute runs a by tool_name with its arguments in input. Pass the query_id from select to connect the execution to the recommendation that surfaced it:
{
"tool_name": "Slack.SendMessage",
"input": {
"channel_name": "incidents",
"message": "Investigating elevated error rates on checkout."
},
"user_id": "{user_id}",
"query_id": "8b0f6a52-3c1e-4d4e-9a57-2f1c0e6d9b21"
}This endpoint doesn’t take a gateway, so it isn’t limited to what select returned or to one gateway’s tools. It can run any tool in the that the can access, and your access rules apply to every call. See Authorized Tool Calling for what happens when a needs the user to authorize first.
List apps
GET /v1/apps?user_id={user_id} returns one entry per app the user can act on through the , sorted by app_id, with limit and offset for paging. connected is true when the user can call the app’s without authorizing first. When it is, account and permissions show the the connected and the scopes that connection grants. It reports the same apps as Arcade.ListApps.
Errors from these endpoints use the ’s error body, with a name such as service_unavailable and a message. A request that fails validation also lists field_errors.
How it works with MCP clients
Tool Recommendation runs inside the gateway and speaks standard . The Arcade tools are ordinary MCP tools, so any MCP client that can connect to an Arcade can use them. You don’t need an Arcade SDK, a client plugin, or code changes in your .
What makes recommendations good
Arcade matches a task against each ’s name and description. The input parameters are not part of the match, and Arcade reads only the first line of each description.
That makes descriptions the main factor you control. A tool with a vague or empty first line is hard to recommend, however useful the tool is. When you build your own tools or register a remote MCP server:
- Start each description with one sentence that says what the does and to what, for example “Send a message to a Slack channel or .”
- Name the service or object the acts on. “Create an issue in a GitHub repository” matches more tasks than “Create an item.”
- Give that do different jobs descriptions that read differently. Two tools whose first lines are nearly identical compete for the same tasks.