Skip to Content
DocumentationFunction Calling

Function Calling

Function calling allows models on Stacknet to invoke structured tools during inference. The model decides when to call a function, what arguments to pass, and how to incorporate the results.

Users can default to Stacknet’s tool layer or inject their own.

How it works

┌─────────────────────────────────────────────────────┐ │ 1. You send a message with tool definitions │ │ │ │ "What's the weather in SF?" │ │ tools: [{ name: "get_weather", ... }] │ └──────────────────────┬──────────────────────────────┘ ┌─────────────────────────────────────────────────────┐ │ 2. Model decides to call the tool │ │ │ │ tool_calls: [{ │ │ function: { name: "get_weather", │ │ arguments: '{"city":"SF"}' } │ │ }] │ └──────────────────────┬──────────────────────────────┘ ┌─────────────────────────────────────────────────────┐ │ 3. You execute the function and return results │ │ │ │ role: "tool" │ │ content: '{"temp": 65, "condition": "foggy"}' │ └──────────────────────┬──────────────────────────────┘ ┌─────────────────────────────────────────────────────┐ │ 4. Model generates final response │ │ │ │ "It's currently 65°F and foggy in San Francisco." │ └─────────────────────────────────────────────────────┘

Basic example

Step 1: Define your tools

const tools = [ { type: 'function', function: { name: 'get_weather', description: 'Get the current weather for a location', parameters: { type: 'object', properties: { city: { type: 'string', description: 'The city name', }, unit: { type: 'string', enum: ['celsius', 'fahrenheit'], description: 'Temperature unit', }, }, required: ['city'], }, }, }, ]

Step 2: Send the request

const response = await client.chat.completions.create({ model: 'preview', messages: [ { role: 'user', content: "What's the weather in Tokyo?" } ], tools, tool_choice: 'auto', })

Step 3: Handle tool calls

const message = response.choices[0].message if (message.tool_calls) { const toolResults = await Promise.all( message.tool_calls.map(async (call) => { const args = JSON.parse(call.function.arguments) const result = await executeFunction(call.function.name, args) return { role: 'tool' as const, tool_call_id: call.id, content: JSON.stringify(result), } }) ) // Send results back for final response const finalResponse = await client.chat.completions.create({ model: 'preview', messages: [ { role: 'user', content: "What's the weather in Tokyo?" }, message, ...toolResults, ], tools, }) }

Parallel tool calls

Models can request multiple tool calls in a single response:

{ "tool_calls": [ { "function": { "name": "get_weather", "arguments": "{\"city\":\"SF\"}" } }, { "function": { "name": "get_weather", "arguments": "{\"city\":\"NYC\"}" } } ] }

Execute them in parallel for faster responses.

Tool choice

Control when the model uses tools:

ValueBehavior
autoModel decides whether to call tools (default)
noneModel will not call any tools
requiredModel must call at least one tool
{ "type": "function", "function": { "name": "..." } }Force a specific tool

Structured outputs

Combine function calling with structured output for reliable data extraction:

const response = await client.chat.completions.create({ model: 'preview', messages: [ { role: 'user', content: 'Extract: John Doe, 30, engineer' } ], tools: [{ type: 'function', function: { name: 'extract_person', description: 'Extract person details', parameters: { type: 'object', properties: { name: { type: 'string' }, age: { type: 'number' }, occupation: { type: 'string' }, }, required: ['name', 'age', 'occupation'], additionalProperties: false, }, strict: true, }, }], tool_choice: { type: 'function', function: { name: 'extract_person' } }, })

On Stacknet

Function calling on Stacknet follows standard practices. The key difference: tool definitions are included in the fingerprint, enabling attribution tracking for creators.

When a registered skill is invoked via function calling, the skill creator is automatically credited via the Promp Contract.

Last updated on