What is function calling / tool use in LLMs?
Function calling lets an LLM request the execution of a function you define - the model outputs a structured JSON call with arguments, you run the function, and feed the result back for the model to use.
AILLMAgents
Overview
Function calling (also called "tool use") is a feature where the model signals it wants to call a specific function rather than generating a text answer. You describe your functions (name, parameters, what they do), the model decides which one to call and with what arguments, you execute the function in your code, and return the result for the model to incorporate into its final answer. This bridges the gap between language and action.
Key Points
- •The model never actually executes code - it outputs a JSON object describing what to call. Your code does the execution.
- •Functions are described in JSON Schema. The model infers the right function and fills in the arguments.
- •Supports **parallel tool calls** - the model can call multiple functions in one turn when they are independent.
- •Common uses: live data lookup (weather, stocks), database queries, API calls, performing calculations, running searches.
- •Use `tool_choice: "required"` to force the model to always call a tool, or `tool_choice: { type: "function", function: { name } }` to force a specific one.
- •Anthropic's Claude, Google's Gemini, and OpenAI's models all support tool use with similar interfaces.
Examples
Full function calling round-trip
typescriptimport OpenAI from 'openai';
const client = new OpenAI();
// Define the tools the model can call
const tools: OpenAI.Chat.Completions.ChatCompletionTool[] = [
{
type: 'function',
function: {
name: 'search_products',
description: 'Search our product catalogue by keyword and category',
parameters: {
type: 'object',
properties: {
keyword: { type: 'string', description: 'Search term' },
category: { type: 'string', enum: ['electronics', 'clothing', 'books'] },
max_price:{ type: 'number', description: 'Maximum price in USD' },
},
required: ['keyword'],
},
},
},
];
// Step 1: initial request - model may decide to call a tool
const first = await client.chat.completions.create({
model: 'gpt-4o',
tools,
messages: [{ role: 'user', content: 'Find me a TypeScript book under $50' }],
});
const assistantMsg = first.choices[0].message;
if (assistantMsg.tool_calls) {
const call = assistantMsg.tool_calls[0];
const args = JSON.parse(call.function.arguments);
// args = { keyword: 'TypeScript', category: 'books', max_price: 50 }
// Step 2: execute the function in your own code
const products = await searchProducts(args.keyword, args.category, args.max_price);
// Step 3: send tool result back, get final answer
const second = await client.chat.completions.create({
model: 'gpt-4o',
tools,
messages: [
{ role: 'user', content: 'Find me a TypeScript book under $50' },
assistantMsg,
{
role: 'tool',
tool_call_id: call.id,
content: JSON.stringify(products),
},
],
});
console.log(second.choices[0].message.content);
// "I found 3 TypeScript books under $50. Here are the top picks:..."
}Parallel tool calls (model calls multiple tools at once)
typescript// When functions are independent, the model may call them in parallel
const response = await client.chat.completions.create({
model: 'gpt-4o',
tools: [weatherTool, stockTool, newsTool],
messages: [{
role: 'user',
content: 'Give me a morning brief: weather in London, AAPL stock price, and top tech news',
}],
});
// response.choices[0].message.tool_calls may have 3 calls at once
const toolCalls = response.choices[0].message.tool_calls ?? [];
// Execute all in parallel
const results = await Promise.all(
toolCalls.map(async call => {
const args = JSON.parse(call.function.arguments);
const result = await executeTool(call.function.name, args);
return { role: 'tool' as const, tool_call_id: call.id, content: JSON.stringify(result) };
})
);
// Feed all results back in a single follow-up call
const final = await client.chat.completions.create({
model: 'gpt-4o',
tools,
messages: [userMessage, response.choices[0].message, ...results],
});Anthropic Claude tool use (same concept, different API)
typescriptimport Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic();
const response = await client.messages.create({
model: 'claude-sonnet-4-6',
max_tokens: 1024,
tools: [{
name: 'get_exchange_rate',
description: 'Get the current exchange rate between two currencies',
input_schema: {
type: 'object',
properties: {
from: { type: 'string', description: 'Source currency code (e.g. USD)' },
to: { type: 'string', description: 'Target currency code (e.g. EUR)' },
},
required: ['from', 'to'],
},
}],
messages: [{ role: 'user', content: 'What is 100 USD in EUR and GBP?' }],
});
// Find tool_use blocks in the response
const toolUseBlocks = response.content.filter(b => b.type === 'tool_use');Pro Tip
Keep tool descriptions specific and accurate - the model uses them to decide WHEN to call each tool. Bad descriptions lead to wrong tool selection or unnecessary tool calls. If a tool is expensive (API call with cost), mention that in the description so the model knows to call it sparingly.