Function Calling
Enable structured outputs and tool use with on-device language models
Defining Tools
Tools are defined as JSON schemas that describe available functions:
const tools = [
{
name: 'get_weather',
description: 'Get weather for a location',
parameters: {
type: 'object',
properties: {
location: { type: 'string', description: 'City name' }
},
required: ['location']
}
}
];final tools = [
{
'name': 'get_weather',
'description': 'Get weather for a location',
'parameters': {
'type': 'object',
'properties': {
'location': {'type': 'string', 'description': 'City name'}
},
'required': ['location']
}
}
];val tools = listOf(
mapOf(
"name" to "get_weather",
"description" to "Get weather for a location",
"parameters" to mapOf(
"type" to "object",
"properties" to mapOf(
"location" to mapOf("type" to "string", "description" to "City name")
),
"required" to listOf("location")
)
)
)const char* tools = R"([
{
"name": "get_weather",
"description": "Get current weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string"}
},
"required": ["location"]
}
}
])";Calling with Tools
Pass tools to the completion call and parse the structured response:
import { CactusLM } from 'cactus-react-native';
const cactusLM = new CactusLM();
await cactusLM.download();
await cactusLM.init();
const result = await cactusLM.complete({
messages: [{ role: 'user', content: "What's the weather in SF?" }],
tools
});
console.log(result.functionCalls);
// [{ name: 'get_weather', arguments: { location: 'San Francisco' } }]final result = model.completeMessages(
[Message.user("What's the weather in Paris?")],
tools: tools,
);
if (result.functionCalls != null) {
for (final call in result.functionCalls!) {
print('Function: ${call['name']}');
print('Arguments: ${call['arguments']}');
}
}val result = model.complete(
messages = listOf(Message.user("What's the weather in Paris?")),
tools = tools
)
result.functionCalls?.forEach { call ->
println("Function: ${call["name"]}")
println("Arguments: ${call["arguments"]}")
}char response[4096];
cactus_complete(
model, messages, response, sizeof(response),
nullptr, // use default options
tools, // pass tools JSON
nullptr,
nullptr
);The response JSON includes parsed function calls:
{
"success": true,
"function_calls": [{
"name": "get_weather",
"arguments": {"location": "Paris"}
}],
"response": null,
"confidence": 0.91
}Multi-Tool Example
You can define multiple tools and the model will select the appropriate one:
const tools = [
{
name: 'get_weather',
description: 'Get weather for a location',
parameters: {
type: 'object',
properties: {
location: { type: 'string', description: 'City name' }
},
required: ['location']
}
},
{
name: 'search_web',
description: 'Search the web for information',
parameters: {
type: 'object',
properties: {
query: { type: 'string', description: 'Search query' }
},
required: ['query']
}
}
];
const result = await cactusLM.complete({
messages: [{ role: 'user', content: 'Look up the latest news about AI' }],
tools
});
// Model picks the right tool
// [{ name: 'search_web', arguments: { query: 'latest AI news' } }]Tool Schema Reference
interface Tool {
name: string;
description: string;
parameters: {
type: 'object';
properties: Record<string, {
type: string; // 'string', 'number', 'boolean', 'array', 'object'
description?: string;
}>;
required?: string[];
};
}Tips
- Keep descriptions clear — The model uses tool descriptions to decide which function to call
- Use required fields — Mark parameters as required when they are always needed
- Smaller models may struggle with complex multi-tool scenarios; use larger models for reliability
- Cloud handoff — If the model confidence is low on a tool call, consider routing to Cactus Cloud for better accuracy