-
Notifications
You must be signed in to change notification settings - Fork 0
Function Calling
Amayyas edited this page Jul 7, 2026
·
3 revisions
Flutter AI SDK supports function/tool calling, allowing AI models to interact with external systems.
Tools let you define functions that the AI can call to perform actions or retrieve information. The AI decides when to use tools based on the conversation.
final weatherTool = Tool(
name: 'get_weather',
description: 'Get the current weather for a location',
parameters: ToolParameters(
properties: {
'location': ToolProperty.string(
description: 'The city and country, e.g., "Paris, France"',
),
'unit': ToolProperty.enumeration(
description: 'Temperature unit',
values: ['celsius', 'fahrenheit'],
),
},
required: ['location'],
),
);// String
ToolProperty.string(
description: 'A text value',
)
// Number
ToolProperty.number(
description: 'A numeric value',
)
// Integer
ToolProperty.integer(
description: 'An integer value',
)
// Boolean
ToolProperty.boolean(
description: 'A true/false value',
)
// Enum
ToolProperty.enumeration(
description: 'One of the allowed values',
values: ['option1', 'option2', 'option3'],
)
// Array
ToolProperty.array(
description: 'A list of items',
items: ToolProperty.string(description: 'Each item'),
)
// Object
ToolProperty.object(
description: 'A complex object',
properties: {
'name': ToolProperty.string(description: 'Name'),
'age': ToolProperty.integer(description: 'Age'),
},
required: ['name'],
)final response = await ai.chatWithTools(
'What is the weather in Paris?',
tools: [weatherTool],
);if (response.hasToolCalls) {
for (final call in response.toolCalls!) {
print('Tool: ${call.name}');
print('Arguments: ${call.arguments}');
}
}for (final call in response.toolCalls!) {
// Execute the function
final result = await executeToolCall(call);
// Submit result back to AI
final finalResponse = await ai.submitToolResult(
toolCallId: call.id,
name: call.name,
result: result,
);
print('AI: ${finalResponse.text}');
}// Define tools
final weatherTool = Tool(
name: 'get_weather',
description: 'Get weather for a location',
parameters: ToolParameters(
properties: {
'location': ToolProperty.string(
description: 'City name',
),
},
required: ['location'],
),
);
final calculatorTool = Tool(
name: 'calculate',
description: 'Perform calculations',
parameters: ToolParameters(
properties: {
'expression': ToolProperty.string(
description: 'Math expression like "2 + 2"',
),
},
required: ['expression'],
),
);
// Initialize AI
final ai = FlutterAI(
provider: AIProvider.openai,
config: AIConfig(
apiKey: 'your-key',
model: 'gpt-5.5',
),
);
// Function implementations
Future<Map<String, dynamic>> executeToolCall(ToolCallContent call) async {
switch (call.name) {
case 'get_weather':
final location = call.arguments['location'] as String;
// Call real weather API here
return {
'temperature': 22,
'condition': 'sunny',
'humidity': 45,
'location': location,
};
case 'calculate':
final expr = call.arguments['expression'] as String;
// Evaluate expression here
return {'result': evaluateExpression(expr)};
default:
return {'error': 'Unknown tool'};
}
}
// Main flow
Future<void> main() async {
final response = await ai.chatWithTools(
'What is the weather in Paris and calculate 25 * 4',
tools: [weatherTool, calculatorTool],
);
if (response.hasToolCalls) {
for (final call in response.toolCalls!) {
final result = await executeToolCall(call);
final finalResponse = await ai.submitToolResult(
toolCallId: call.id,
name: call.name,
result: result,
);
print(finalResponse.text);
}
} else {
print(response.text);
}
ai.dispose();
}Control how the model uses tools:
// Let the model decide (default)
final config = AIConfig(
apiKey: 'key',
toolChoice: ToolChoice.auto,
);
// Force tool use
final config = AIConfig(
apiKey: 'key',
toolChoice: ToolChoice.required,
);
// Never use tools
final config = AIConfig(
apiKey: 'key',
toolChoice: ToolChoice.none,
);
// Force specific tool
final config = AIConfig(
apiKey: 'key',
toolChoice: ToolChoice.function('get_weather'),
);You can also set tools in the config:
final ai = FlutterAI(
provider: AIProvider.openai,
config: AIConfig(
apiKey: 'your-key',
tools: [weatherTool, calculatorTool],
toolChoice: ToolChoice.auto,
),
);
// Now all chat calls can use these tools
final response = await ai.chat('What is the weather in London?');class ToolCallContent {
final String id; // Unique call ID
final String name; // Function name
final Map<String, dynamic> arguments; // Parsed arguments
}Handle tool execution errors:
for (final call in response.toolCalls!) {
try {
final result = await executeToolCall(call);
await ai.submitToolResult(
toolCallId: call.id,
name: call.name,
result: result,
);
} catch (e) {
// Report error back to AI
await ai.submitToolResult(
toolCallId: call.id,
name: call.name,
result: {'error': e.toString()},
isError: true,
);
}
}await for (final chunk in ai.streamChatWithTools(
'What is the weather?',
tools: [weatherTool],
)) {
if (chunk.type == StreamEventType.toolCallDelta) {
print('Tool call: ${chunk.toolCallDelta}');
}
if (chunk.isDelta) {
print(chunk.delta);
}
}final searchTool = Tool(
name: 'web_search',
description: 'Search the web for current information',
parameters: ToolParameters(
properties: {
'query': ToolProperty.string(
description: 'Search query',
),
'num_results': ToolProperty.integer(
description: 'Number of results to return',
),
},
required: ['query'],
),
);final dbTool = Tool(
name: 'query_database',
description: 'Query the user database',
parameters: ToolParameters(
properties: {
'table': ToolProperty.enumeration(
description: 'Table to query',
values: ['users', 'orders', 'products'],
),
'conditions': ToolProperty.object(
description: 'Query conditions',
properties: {
'field': ToolProperty.string(description: 'Field name'),
'operator': ToolProperty.enumeration(
description: 'Comparison operator',
values: ['=', '>', '<', '>=', '<=', 'like'],
),
'value': ToolProperty.string(description: 'Value to compare'),
},
required: ['field', 'operator', 'value'],
),
},
required: ['table'],
),
);final emailTool = Tool(
name: 'send_email',
description: 'Send an email',
parameters: ToolParameters(
properties: {
'to': ToolProperty.string(description: 'Recipient email'),
'subject': ToolProperty.string(description: 'Email subject'),
'body': ToolProperty.string(description: 'Email body'),
},
required: ['to', 'subject', 'body'],
),
);- Clear Descriptions: Write detailed descriptions for tools and parameters
- Validate Arguments: Always validate the arguments before executing
- Handle Errors: Return error information when tools fail
- Limit Tools: Only provide relevant tools for the task
- Use Enums: Use enumeration for limited choices
| Provider | Function Calling | Parallel Calls |
|---|---|---|
| OpenAI | ✅ | ✅ |
| Anthropic | ✅ | ✅ |
| Google AI | ✅ | ✅ |
- API-Tools - Full API reference
- Example-Function-Calling - Complete example
Instead of handling tool_calls manually, let ToolRunner drive the loop:
it executes every requested tool, feeds results back to the model and stops
when the model produces a final answer.
final runner = ToolRunner.create(
provider: AIProvider.anthropic,
config: AIConfig(apiKey: 'sk-ant-...'),
tools: [
ExecutableTool(
definition: weatherTool,
executor: (args) async => fetchWeather(args['location'] as String),
),
],
maxIterations: 5,
);
final result = await runner.run('What is the weather in Paris?');
print(result.text); // Final answer
print(result.iterations); // Tool rounds executed
print(result.messages); // Full transcriptBehavior:
- Tool calls within one model turn run in parallel
- A failing executor is reported to the model as an error result
- The loop throws
ToolRunnerExceptionaftermaxIterationsrounds -
onToolCall/onToolResultcallbacks allow logging/observability
Getting Started
Core Concepts
Advanced Features
API Reference
Examples
Other