Tools & Function Calling
Use tools and function calling with the Sansa API
Overview
Tools let the model call functions you define. The model decides when to call a tool and generates the arguments — your code executes it and sends the result back.
Tool Definition Format
{
"tools": [{
"type": "function",
"function": {
// Descriptive name, snake_case recommended.
"name": "get_weather",
// Detailed description helps the model decide when to use it.
"description": "Get current weather for a location",
// JSON Schema object.
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name or coordinates"
},
"units": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "Temperature unit"
}
},
"required": ["location"]
}
}
}]
}Three-Step Flow
Step 1: Send request with tools
Include tools in your request. The model may respond with text or with tool_calls.
Step 2: Model responds with tool_calls
When the model wants to call a tool, content is null and tool_calls contains the calls. The model generates a unique id for each tool call — your code will use this ID in Step 3:
{
"choices": [{
"message": {
"role": "assistant",
"content": null,
"tool_calls": [{
"id": "call12345", // Model generates this ID
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"location\": \"Tokyo\", \"units\": \"celsius\"}"
}
}]
},
"finish_reason": "tool_calls"
}]
}Step 3: Send tool result back
Append the assistant message (from Step 2) and a tool message with the result. The tool_call_id must match the id from the assistant's tool call. Include tools in every request — not just the first one.
{
"messages": [
{"role": "user", "content": "What's the weather in Tokyo?"},
{
"role": "assistant",
"content": null,
"tool_calls": [{
"id": "call12345", // ID generated by the model
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"location\": \"Tokyo\", \"units\": \"celsius\"}"
}
}]
},
{
"role": "tool",
"tool_call_id": "call12345", // Use the same ID from above
"content": "{\"temperature\": 22, \"conditions\": \"sunny\"}"
}
],
"tools": [/* same tool definitions */]
}Tool Call IDs
The model generates tool call IDs automatically. When the model decides to call a tool, it returns a response with tool_calls containing unique IDs. Your code should:
- Extract the
idfrom each tool call - Execute the function
- Send the result back using that exact same ID in
tool_call_id
You do not create or format these IDs — simply use whatever the model returns.
// 1. Model returns tool calls with IDs
const toolCall = response.choices[0].message.tool_calls[0];
const toolCallId = toolCall.id; // e.g., "call12345"
// 2. Execute your function
const result = await myFunction(toolCall.function.arguments);
// 3. Send result back with the SAME ID
messages.push({
role: "tool",
tool_call_id: toolCallId, // Use the exact ID from step 1
content: JSON.stringify(result)
});Note: Sansa normalizes tool call IDs internally for cross-provider compatibility. Just pass back the exact ID from the model's response — you do not need to worry about ID format.
tool_choice
Controls which tool (if any) the model calls.
// Default. Model decides whether to call a tool or generate text.
"auto"
// Model will not call any tool.
"none"
// Model must call at least one tool.
"required"
// Forces the model to call the named function.
{ type: "function", function: { name: "my_function" } }parallel_tool_calls
Default: true.
- When
true, the model may request multiple tool calls in a single response. - When
false, the model makes one tool call at a time. - Each tool call has a unique
id— match results bytool_call_id.
Streaming with Tool Calls
delta.tool_calls[].idanddelta.tool_calls[].function.namearrive first.delta.tool_calls[].function.argumentsstreams as partial JSON fragments.- Client must accumulate argument fragments, then
JSON.parsethe complete string. finish_reason: "tool_calls"signals all tool calls are complete.
Best Practices
- Use descriptive function names and detailed descriptions.
- Include property descriptions in the JSON Schema.
- Design tools that compose well (search → get details → take action).
- Set a max iteration limit in agentic loops.
- Handle errors in tool execution gracefully (return error info as tool content).