Tools & Function Calling
Extend your assistants with web search, custom functions, and more.
Tools & Function Calling
Tools extend your assistant's capabilities beyond text generation. Enable web search, document retrieval, and custom functions.
Built-in Tools
| Tool | Description | Min Tier |
|---|---|---|
web_search | Search the web for current information | Pro |
file_search | Search uploaded documents (RAG) | Pro |
Enabling Built-in Tools
Tools are configured in the dashboard when creating or editing an assistant:
- Go to Assistants in the sidebar
- Click New Assistant or edit an existing one
- In the Tools section:
- Toggle Web Search for real-time web information
- Toggle File Search (RAG) for document retrieval
- Save the assistant
Web search is powered by Tavily and returns real-time results. File search uses your uploaded documents.
Using an Assistant with Tools
Once tools are enabled in the dashboard, they're automatically available when you call the API:
import OpenAI from 'openai';
const client = new OpenAI({
baseURL: 'https://api.assistantrouter.com/v1',
apiKey: process.env.ASSISTANTROUTER_API_KEY,
});
const response = await client.chat.completions.create({
// @ts-ignore
assistant_id: 'your-assistant-uuid', // Has web_search enabled
messages: [
{ role: 'user', content: 'What are the latest news about AI?' }
],
});
// The response will include information from web search
console.log(response.choices[0].message.content);
// Check which tools were used
console.log(response.x_assistantrouter.tools_used); // ["web_search"]Custom Function Calling
In addition to built-in tools, you can define custom functions that the model can call. This allows you to extend your assistant with any capability.
Defining Functions
Pass function definitions in the tools array:
const response = await client.chat.completions.create({
// @ts-ignore
assistant_id: 'your-assistant-uuid',
messages: [
{ role: 'user', content: 'What is the weather in Paris?' },
],
tools: [
{
type: 'function',
function: {
name: 'get_weather',
description: 'Get the current weather for a location',
parameters: {
type: 'object',
properties: {
location: {
type: 'string',
description: 'City and country, e.g., "Paris, France"',
},
unit: {
type: 'string',
enum: ['celsius', 'fahrenheit'],
description: 'Temperature unit',
},
},
required: ['location'],
},
},
},
],
});Handling Tool Calls
When the model wants to call a function, handle it in your code:
// Check if the model wants to call a function
if (response.choices[0].finish_reason === 'tool_calls') {
const toolCall = response.choices[0].message.tool_calls[0];
const args = JSON.parse(toolCall.function.arguments);
// Execute your function
const weather = await getWeather(args.location, args.unit);
// Continue the conversation with the result
const finalResponse = await client.chat.completions.create({
// @ts-ignore
assistant_id: 'your-assistant-uuid',
messages: [
{ role: 'user', content: 'What is the weather in Paris?' },
response.choices[0].message,
{
role: 'tool',
tool_call_id: toolCall.id,
content: JSON.stringify(weather),
},
],
});
console.log(finalResponse.choices[0].message.content);
}Parallel Tool Calls
The model can request multiple tool calls in a single response:
// Response with parallel tool calls
{
"choices": [{
"message": {
"tool_calls": [
{ "id": "call_1", "function": { "name": "get_weather", "arguments": "{\"location\":\"Paris\"}" }},
{ "id": "call_2", "function": { "name": "get_weather", "arguments": "{\"location\":\"London\"}" }}
]
},
"finish_reason": "tool_calls"
}]
}
// Execute all calls in parallel
const results = await Promise.all(
toolCalls.map(async (call) => {
const args = JSON.parse(call.function.arguments);
const result = await executeFunction(call.function.name, args);
return {
role: 'tool',
tool_call_id: call.id,
content: JSON.stringify(result),
};
})
);
// Continue with all results
const finalResponse = await client.chat.completions.create({
// @ts-ignore
assistant_id: 'your-assistant-uuid',
messages: [
...previousMessages,
...results,
],
});Controlling Tool Use
Use tool_choice to control when tools are called:
// Force a specific function
const response = await client.chat.completions.create({
// @ts-ignore
assistant_id: 'your-assistant-uuid',
messages: [{ role: 'user', content: 'Check Paris weather' }],
tools: [weatherTool],
tool_choice: { type: 'function', function: { name: 'get_weather' } },
});
// Disable tool use for this request
const response = await client.chat.completions.create({
// @ts-ignore
assistant_id: 'your-assistant-uuid',
messages: [{ role: 'user', content: 'What is the weather?' }],
tools: [weatherTool],
tool_choice: 'none',
});
// Let the model decide (default)
const response = await client.chat.completions.create({
// @ts-ignore
assistant_id: 'your-assistant-uuid',
messages: [{ role: 'user', content: 'What is the weather?' }],
tools: [weatherTool],
tool_choice: 'auto',
});Best Practices
- Clear descriptions - Write detailed function and parameter descriptions
- Validate inputs - Always validate function arguments before executing
- Handle errors - Return helpful error messages as tool results
- Limit scope - Don't expose more functionality than needed
- Log calls - Track tool usage for debugging and monitoring
- Use types - Define proper JSON schema types for parameters
Always validate and sanitize function arguments. Never pass untrusted input directly to sensitive operations.