Function calling

Early access
Copy Page as Markdown

Function calling (also known as tool calling) lets SubQ models interface with external systems and data outside their training data. Pass function tools defined by a JSON schema in the tools parameter; the model may return a tool call, and your application executes the function and sends the tool call output back so the model can finish the reply. The shape differs by endpoint: Responses uses a flattened tool object (type/name/parameters directly on it), while Chat Completions nests those fields under a function object.

How it works

Tools — functionality you give the model. A function tool is a JSON Schema definition the model can choose to call, for example get_stock_quote, account lookup, or issuing a refund.

Tool calls — requests from the model to use a tool. If the prompt needs live data, the model returns one or more calls, each with a function name and JSON-encoded arguments.

Tool call outputs — results your application sends back so the model can finish the reply.

The tool calling flow

  1. Make a request to the model with tools it could call
  2. Receive a tool call from the model
  3. Execute code on the application side with input from the tool call
  4. Make a second request to the model with the tool output
  5. Receive a final response from the model (or more tool calls)

Field reference

Responses APIChat Completions
Tool shapetype, name, description, parameters, strict directly on the tool objecttype: "function" plus a nested function: { name, description, parameters, strict }
Tool callfunction_call output item — call_id, name, argumentstool_calls[] on the assistant message — id, function: { name, arguments }
Sending the resultfunction_call_output input item — call_id, outputA message with role: "tool", tool_call_id, content
Streamingresponse.function_call_arguments.delta/.done eventsdelta.tool_calls[], keyed by index
Continuing the loopprevious_response_id (or conversation)Resend the full messages[], including the assistant and tool messages

Both accept the same JSON Schema shape in parameters, and the same strict mode requirements.

Example

End-to-end flow for a get_stock_quote function: the first request declares the tool, the model returns a tool call, your code runs the function and sends the result back for a final answer.

cURLTypeScriptPython

Accumulate any text preamble, execute every function_call in the turn, then continue with one function_call_output per call_id:

TypeScriptPython

A response can contain more calls after receiving outputs, so keep looping until the model returns a final message — cap the number of rounds to avoid runaway loops. Execute every call in a turn concurrently (the model may call in parallel).

Strict mode

Set strict to true so function arguments adhere to the schema. Recommended for production. Strict schemas require:

  1. additionalProperties set to false on every object in parameters
  2. Every key in properties listed in required

Mark a field optional by allowing null in its type (for example "type": ["string", "null"]) while still listing it in required.

Handling function calls

Assume zero, one, or many tool calls in a turn — see Dispatching multiple tool calls above.

  1. Add the model's tool call(s) to your ongoing context (the assistant message on Chat Completions, or nothing extra to add on Responses — just continue via previous_response_id/conversation)
  2. For each call, parse the arguments, run your code, and send back a result keyed by call_id (Responses) or tool_call_id (Chat Completions)
  3. Call the model again with the result — the full messages[] on Chat Completions, or just the function_call_output items on Responses

The result is typically a string — JSON, plain text, or a short success/failure token for side-effect-only functions (for example "success").

Tool choice

By default the model decides when to call tools. On Chat Completions, control that with tool_choice:

ValueBehavior
"auto"Default. Call zero, one, or multiple functions
"required"Call one or more functions
"none"Do not call tools (same as omitting tools)
{"type":"function","function":{"name":"get_stock_quote"}}Force that specific function
{
  "tool_choice": {
    "type": "function",
    "function": { "name": "get_stock_quote" }
  }
}

Responses accepts the same "auto"/"required"/"none" string values (defaulting to "auto" once tools is set) but doesn't support forcing one specific function by name.

Best practices

  • Write clear names and descriptions. Say when to use the function, what each parameter means, and what the output represents. Use the system message or instructions for when not to call a tool.
  • Keep the tool list small. Fewer tools usually improve accuracy; prefer a focused set over a large catalog in one turn.
  • Offload known values in code. Do not ask the model to fill arguments you already know (for example an order_id from session state).
  • Enable strict mode and validate parsed arguments in your application before executing side effects.