Function Calling & Tools
Enable AI models to call external functions and APIs using the modern tools parameter.
Tool calling is the modern standard for function calling, with support for parallel tool execution and extensible tool types. ModelPilot uses the tools parameter internally for all providers.
Industry Standard
The tools parameter is the current standard across all major AI providers (OpenAI, Anthropic, etc.). The legacy functions parameter is deprecated by OpenAI and never supported by Anthropic.
Parallel Tool Execution
import ModelPilot from 'modelpilot';
const client = new ModelPilot({
apiKey: process.env.MODELPILOT_API_KEY,
routerId: process.env.MODELPILOT_ROUTER_ID,
});
const tools = [
{
type: 'function',
function: {
name: 'get_weather',
description: 'Get weather for a location',
parameters: {
type: 'object',
properties: {
location: { type: 'string' }
},
required: ['location']
}
}
},
{
type: 'function',
function: {
name: 'get_news',
description: 'Get latest news for a location',
parameters: {
type: 'object',
properties: {
location: { type: 'string' }
},
required: ['location']
}
}
}
];
const completion = await client.chat.completions.create({
messages: [{
role: 'user',
content: 'What\'s the weather and latest news in Boston?'
}],
tools: tools,
});
const message = completion.choices[0].message;
// Model may call multiple tools at once
if (message.tool_calls) {
console.log(`Model called ${message.tool_calls.length} tools`);
// Execute all tools in parallel
const results = await Promise.all(
message.tool_calls.map(async (toolCall) => {
const args = JSON.parse(toolCall.function.arguments);
if (toolCall.function.name === 'get_weather') {
return await getWeather(args.location);
} else if (toolCall.function.name === 'get_news') {
return await getNews(args.location);
}
})
);
}Complete Tool Pattern
async function chatWithTools(userMessage) {
const messages = [{ role: 'user', content: userMessage }];
const tools = [
{
type: 'function',
function: {
name: 'search_database',
description: 'Search product database',
parameters: {
type: 'object',
properties: {
query: { type: 'string' },
limit: { type: 'number' }
},
required: ['query']
}
}
}
];
// Initial request
let completion = await client.chat.completions.create({
messages: messages,
tools: tools,
});
let responseMessage = completion.choices[0].message;
messages.push(responseMessage);
// Handle tool calls
while (responseMessage.tool_calls) {
// Execute all tool calls
const toolResults = await Promise.all(
responseMessage.tool_calls.map(async (toolCall) => {
const functionName = toolCall.function.name;
const functionArgs = JSON.parse(toolCall.function.arguments);
// Execute the function
let result;
if (functionName === 'search_database') {
result = await searchDatabase(functionArgs);
}
return {
role: 'tool',
tool_call_id: toolCall.id,
content: JSON.stringify(result),
};
})
);
// Add all tool results to messages
messages.push(...toolResults);
// Get next response
completion = await client.chat.completions.create({
messages: messages,
tools: tools,
});
responseMessage = completion.choices[0].message;
messages.push(responseMessage);
}
return responseMessage.content;
}
// Usage
const response = await chatWithTools('Find laptops under $1000');
console.log(response);Tool Types
The tools API is designed to be extensible. Currently, only type: "function" is supported, but future versions may support additional tool types.
const tools = [
{
type: 'function', // Required
function: {
name: 'tool_name',
description: 'What this tool does',
parameters: {
// JSON Schema
}
}
}
];Error Handling
async function executeToolCallSafely(toolCall) {
try {
const functionName = toolCall.function.name;
const functionArgs = JSON.parse(toolCall.function.arguments);
// Execute function
const result = await executeTool(functionName, functionArgs);
return {
role: 'tool',
tool_call_id: toolCall.id,
content: JSON.stringify({ success: true, data: result }),
};
} catch (error) {
// Return error to model
return {
role: 'tool',
tool_call_id: toolCall.id,
content: JSON.stringify({
success: false,
error: error.message
}),
};
}
}Best Practices
- ✓Use parallel execution
Execute independent tool calls concurrently with Promise.all
- ✓Include tool_call_id in responses
Always include the tool_call_id when returning results
- ✓Return structured data
Use JSON objects for tool results, not plain strings
- ✓Handle timeouts
Set reasonable timeouts for long-running tools
- ✓Validate arguments
Always validate and sanitize tool arguments