Implementing Function Calling and Tool Use
1. Understanding Tool Calling Concepts
| Concept | Description | Usage |
|---|---|---|
| Function Calling | Process where an AI model invokes a predefined function with specific parameters to perform actions or retrieve data. | Used in AI agents to execute tasks like API calls, database queries, or external tool integrations. |
| Tool Use | Enables AI models to interact with external systems or services by defining tools that can be invoked during conversation. | Allows AI to perform real-world actions like booking a flight, sending an email, or retrieving weather data. |
| Schema Definition | Defines the structure of a tool, including its name, parameters, and return values using JSON schema. | Ensures that the AI model understands how to correctly format and call tools. |
Example: Tool Schema Definition
{
"name": "get_weather",
"description": "Fetches current weather for a given location",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "The city to get weather for"
}
},
"required": ["city"]
}
}
Note: Tool calling is a core feature in LLMs that enables dynamic interaction with external systems.
2. Defining Tool Schemas
| Property | Description | Example |
|---|---|---|
| name | Name of the tool, used for identification | "get_weather" |
| description | Human-readable description of what the tool does | "Fetches current weather for a given location" |
| parameters | Object defining input parameters for the tool | |
| required | Array of parameter names that must be provided | ["location"] |
Example: Tool Schema Definition
{
"name": "get_weather",
"description": "Fetches current weather for a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name"
},
"unit": {
"type": "string",
"description": "Temperature unit (celsius or fahrenheit)",
"default": "celsius"
}
},
"required": ["location"]
}
}
3. Registering Custom Tools with Agents
Custom tools can be registered with AI agents to extend their functionality and enable them to perform specific tasks. This section outlines how to register custom tools with agents in AI-assisted development environments.
| Tool Property | Description | Example |
|---|---|---|
| name | Name of the tool, used for identification and logging. | "send_email" |
| description | Human-readable description of the tool's purpose and functionality. | "Sends an email to a specified recipient." |
| parameters | Schema defining input parameters for the tool. | {to: {type: "string"}, subject: {type: "string"}} |
| function | The actual function or method to be executed when the tool is invoked. | async (params) => { /* send email logic */ } |
Example: Registering a Custom Tool
const agent = new AIAssistant();
agent.registerTool({
name: "send_email",
description: "Sends an email to a specified recipient.",
parameters: {
to: { type: "string" },
subject: { type: "string" },
body: { type: "string" }
},
function: async (params) => {
const { to, subject, body } = params;
// Simulate sending an email
console.log(`Sending email to ${to} with subject: ${subject}`);
return { success: true, message: "Email sent" };
}
});
Note: Ensure that the function registered for a tool is properly asynchronous if it involves I/O operations or external API calls.
4. Handling Tool Call Responses
| Response Type | Description | Example |
|---|---|---|
| tool_call | Indicates a tool call request from the AI | |
| tool_response | Response from a tool call, returned to the AI | |
Example: Processing Tool Call Response
const toolCallResponse = {
tool_call_id: "call_123",
result: {
temperature: 72,
unit: "F"
}
};
// Send result back to AI
const aiResponse = {
tool_response: toolCallResponse
};
console.log(JSON.stringify(aiResponse, null, 2));
Note: The
tool_call_id must match the ID from the original tool call to ensure proper response routing.
5. Chaining Sequential Tool Calls
| Tool | Description | Usage | Notes |
|---|---|---|---|
| tool1 | Initial tool for data retrieval | { "name": "tool1", "arguments": { "query": "latest news" } } |
Must return structured data for next tool |
| tool2 | Processes retrieved data | { "name": "tool2", "arguments": { "data": "{...}" } } |
Uses output from tool1 as input |
| tool3 | Generates final response | { "name": "tool3", "arguments": { "processed_data": "{...}" } } |
Final step in the chain |
Example: Chaining Tool Calls
const toolChain = [
{ name: "getWeather", arguments: { city: "New York" } },
{ name: "getForecast", arguments: { weatherData: "{...}" } },
{ name: "generateReport", arguments: { forecast: "{...}" } }
];
await executeToolChain(toolChain);
Note: Each tool in the chain must return data compatible with the next tool's expected input format.
Warning: If any tool in the chain fails, subsequent tools will not execute. Implement error handling for each step.
6. Handling Tool Call Errors
| Error Type | Description | Handling Strategy | Example |
|---|---|---|---|
| ToolExecutionError | Occurs when a tool fails to execute due to invalid input or runtime issues. | Log error details and provide fallback behavior or retry logic. | |
| TimeoutError | Tool call exceeds configured timeout limits. | Implement timeout handling with graceful degradation or alerting. | |
| ValidationError | Input parameters do not meet required schema or validation rules. | Return structured error response with validation details to the AI agent. | |
Example: Error Recovery Strategy
async function handleToolCall(tool, input) {
try {
const result = await tool.execute(input);
return { success: true, data: result };
} catch (error) {
if (error.name === 'ToolExecutionError') {
// Log and attempt recovery
console.warn('Recovering from tool error:', error.message);
return { success: false, error: error.message };
} else if (error.name === 'TimeoutError') {
// Alert and retry logic
console.error('Tool timed out:', error.message);
return { success: false, error: 'Timeout occurred' };
} else {
throw error; // Re-throw unknown errors
}
}
}
Best Practices for Tool Call Error Handling
- Implement structured error responses to guide AI agents in correcting inputs.
- Use timeouts to prevent indefinite hanging of tool calls.
- Log detailed error information for debugging and monitoring purposes.
7. Restricting Tool Access by Permission
| Permission Level | Description | Allowed Tools | Notes |
|---|---|---|---|
| admin | Full administrative access | All tools | Can execute any tool with full permissions |
| developer | Developer-level access with limited tool use | Development and testing tools | Cannot access production or sensitive tools |
| viewer | Read-only access to tool information | Documentation and logging tools | Cannot execute or modify any tool |
| restricted | Restricted access with specific tool allowances | Selected tools based on role | Requires explicit configuration for tool access |
Example: Configuring Tool Access by Permission
{
"permissions": {
"admin": {
"tools": ["all"],
"access": "full"
},
"developer": {
"tools": ["code_editor", "debugger", "test_runner"],
"access": "limited"
},
"viewer": {
"tools": ["documentation", "logs"],
"access": "read_only"
},
"restricted": {
"tools": ["code_review"],
"access": "custom"
}
}
}
Note: Permission levels should be defined in a centralized configuration to ensure consistency across the AI-assisted development environment.
8. Testing Tool Call Reliability
Example: Basic Reliability Test
const toolCall = {
name: "fetchUserById",
arguments: { id: 123 }
};
async function testToolReliability(toolCall) {
try {
const result = await executeToolCall(toolCall);
console.log("Success: ", result);
return true;
} catch (error) {
console.log("Failure: ", error);
return false;
}
}
| Test Type | Description | Expected Outcome | Notes |
|---|---|---|---|
| Consistency Check | Repeatedly call the same tool with identical inputs | Same output every time | Use assert to validate |
| Timeout Test | Measure execution time under load | Execution completes within threshold | Use setTimeout to detect hangs |
| Error Handling | Simulate network or API failures | Graceful failure with error logs | Validate catch blocks |
Reliability Testing Best Practices
- Run tests in parallel to simulate concurrent usage
- Log all tool call inputs and outputs for debugging
- Use retry logic with exponential backoff for transient errors
- Monitor tool call success rate over time
Warning: Tool call reliability can degrade over time due to external API changes or network instability.