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 returns real-time results from the web. 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.