tool function calling.md
For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to page URLs; this page is available as Markdown.
Tool/Function Calling
Overview
Tool (function) calling lets a model decide when to invoke an external function—a weather API, a database query, a calculator—and emit a structured request for it. Your application runs the function and feeds the result back to the model.
Parasail exposes tool calling through two OpenAI-compatible surfaces:
- Chat Completions API (
/v1/chat/completions)—the classic single-call interface. You passtools, inspectmessage.tool_calls, run the tool, and append atoolmessage for the next call. - Responses API (
/v1/responses)—the newer agentic interface built for multi-step loops. You passtools, inspectresponse.outputforfunction_callitems, and appendfunction_call_outputitems.
Both use the same base URL and API key:
https://api.parasail.io/v1
The tool schema (name, description, JSON Schema parameters) is the same in both APIs—only the wrapper shape and the response handling differ. Pick Chat Completions for simple one-shot tool calls, and the Responses API for multi-turn agentic workflows.
Supported models
The following models support tool calling and tool_choice as of June 2026. Verify current availability via the models endpoint.
Treat this table as a starting point for validation. Test your actual tool schema and prompt before depending on tool calls in production.
| Model | Tools | Tool Choice |
|---|---|---|
| parasail-llama-33-70b-fp8 | ✅ | ✅ |
| parasail-llama-4-scout-instruct | ✅ | ✅ |
| parasail-llama-4-maverick-instruct-fp8 | ✅ | ✅ |
| parasail-qwen3-30b-a3b | ✅ | ✅ |
| parasail-qwen3-235b-a22b | ✅ | ✅ |
| parasail-qwen3-32b | ✅ | ✅ |
| parasail-mistral-devstral-small | ✅ | ✅ |
{% tabs %}
{% tab title="Chat Completions API" %}
In the Chat Completions API, each tool must be wrapped as {"type": "function", "function": {...}}. The function object holds the name, description, and a JSON Schema parameters.
import os
import json
from openai import OpenAI
client = OpenAI(
base_url="https://api.parasail.io/v1",
api_key="<PARASAIL_API_KEY>",
)
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Retrieve weather information for a given location and date.",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string"},
"date": {"type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$"},
},
"required": ["location", "date"],
},
},
}
]
messages = [
{"role": "user", "content": "What's the weather like in Manhattan Beach on 2025-06-03?"}
]
response = client.chat.completions.create(
model="parasail-llama-4-scout-instruct",
messages=messages,
tools=tools,
tool_choice="auto",
)
tool_call = response.choices[0].message.tool_calls[0]
args = json.loads(tool_call.function.arguments)
print(json.dumps(args, indent=2))
Expected arguments:
{
"location": "Manhattan Beach",
"date": "2025-06-03"
}
Returning the tool result
Run your function, then append the assistant's tool call and a tool message with the result before calling the model again:
def get_weather(location, date):
# Replace with a real API call
return {"location": location, "date": date, "weather": "Sunny", "temperature": "75F"}
result = get_weather(**args)
messages.append(response.choices[0].message) # the assistant's tool call
messages.append(
{
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result),
}
)
final = client.chat.completions.create(
model="parasail-llama-4-scout-instruct",
messages=messages,
tools=tools,
)
print(final.choices[0].message.content)
{% endtab %}
{% tab title="Responses API" %}
In the Responses API, tools are defined with a flat shape—type, name, description, and parameters at the top level (no nested function object). Tool calls come back as function_call items in response.output, and you return results as function_call_output items.
import json
from openai import OpenAI
client = OpenAI(
base_url="https://api.parasail.io/v1",
api_key="<PARASAIL_API_KEY>",
)
tools = [
{
"type": "function",
"name": "get_weather",
"description": "Get the current weather for a city.",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "City name"},
"units": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"default": "celsius",
},
},
"required": ["city"],
},
}
]
def handle_tool_call(name, arguments):
args = json.loads(arguments)
if name == "get_weather":
return json.dumps({"city": args["city"], "temperature": 22, "condition": "sunny"})
return json.dumps({"error": "unknown function"})
# Initial request (store must be false on the Parasail gateway)
response = client.responses.create(
model="parasail-kimi-k25-elicit",
store=False,
tools=tools,
input=[{"role": "user", "content": "What's the weather in Tokyo?"}],
)
# Agentic loop—continue until the model stops calling tools
while response.output:
tool_calls = [item for item in response.output if item.type == "function_call"]
if not tool_calls:
break
next_input = list(response.output)
for tool_call in tool_calls:
result = handle_tool_call(tool_call.name, tool_call.arguments)
next_input.append(
{
"type": "function_call_output",
"call_id": tool_call.call_id,
"output": result,
}
)
response = client.responses.create(
model="parasail-kimi-k25-elicit",
store=False,
tools=tools,
input=next_input,
)
print(response.output_text)
The Responses API requires store=False on every request. See the Responses API reference for the full compatibility table.
{% endtab %}
Chat Completions tools vs. Responses tools
| Chat Completions | Responses API | |
|---|---|---|
| Tool definition | {"type": "function", "function": {name, description, parameters}} |
{"type": "function", name, description, parameters} (flat) |
| Where calls appear | message.tool_calls[] |
response.output[] items with type == "function_call" |
| Returning results | {"role": "tool", "tool_call_id": ..., "content": ...} |
{"type": "function_call_output", "call_id": ..., "output": ...} |
| Best for | One-shot tool calls | Multi-step agentic loops |
The underlying schema—the function name, description, and JSON Schema parameters—is identical between the two; only the wrapper and the result-handling differ.