Function calling
Let the model decide whether to call functions you define, with a complete two-round example. Works via Chat Completions, and also via the Claude-native Messages format.
Function calling (tool calls) lets the model decide whether to call a function you defined and with which arguments. The model never runs the function itself: your code runs it and hands the result back to the model.
Flow:
- Describe the available functions with
toolsin the request. - The model returns
tool_calls(function name + JSON arguments). - Your code runs the function and appends the result to the conversation as a
role: "tool"message. - Send another request; the model gives the final answer.
Function calling works through Chat Completions; just change model in the examples below. Models that support the Claude-native format can also use it through the Anthropic Messages format; see the last section of this page. Function-calling support depends on the model; pick a suitable one on the model square.
Replace your-model-id in the samples with a model ID from the model square (or call GET /v1/models).
Complete example
import json
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["MYAIEXP_API_KEY"],
base_url="https://ai.myaiexp.com/v1",
)
model = "your-model-id" # replace with a model ID from the model square
def get_weather(city: str) -> str:
# mock data instead of a real weather API
return json.dumps({"city": city, "weather": "sunny", "temperature_c": 22})
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a city",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string", "description": "City name, e.g. Beijing"}},
"required": ["city"],
},
},
}
]
messages = [{"role": "user", "content": "What's the weather in Beijing right now?"}]
# round 1: the model decides whether to call a function
first = client.chat.completions.create(model=model, messages=messages, tools=tools)
msg = first.choices[0].message
if not msg.tool_calls:
print(msg.content)
else:
messages.append(msg)
for call in msg.tool_calls:
args = json.loads(call.function.arguments)
result = get_weather(**args)
messages.append({"role": "tool", "tool_call_id": call.id, "content": result})
# round 2: hand the function result back to get the final answer
final = client.chat.completions.create(model=model, messages=messages, tools=tools)
print(final.choices[0].message.content)Raw response of round 1
To look at round 1 only, use curl:
# function calling: the model returns tool_calls, your code runs the function
curl -sS https://ai.myaiexp.com/v1/chat/completions \
-H "Authorization: Bearer $MYAIEXP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "your-model-id",
"messages": [
{"role": "user", "content": "What'\''s the weather in Beijing right now?"}
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a city",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "City name, e.g. Beijing"}
},
"required": ["city"]
}
}
}
]
}'When the model decides to call a function, finish_reason is tool_calls (structure shown for illustration; content may be empty or contain a short sentence):
{
"choices": [
{
"message": {
"role": "assistant",
"content": "",
"tool_calls": [
{
"id": "call_...",
"type": "function",
"function": { "name": "get_weather", "arguments": "{\"city\": \"Beijing\"}" }
}
]
},
"finish_reason": "tool_calls"
}
]
}Tool use in the Anthropic Messages format
When calling /v1/messages, tool definitions and responses use the native Anthropic format:
- A tool is described with
name,descriptionandinput_schema(no outerfunctionwrapper). - When the model wants a tool,
stop_reasonistool_useandcontentcontains atype: "tool_use"block whose arguments are ininput(already a JSON object, not a string). - Return the result in a
tool_resultblock of the nextusermessage, withtool_use_idset to the previous block'sid.
import json
import os
import anthropic
client = anthropic.Anthropic(
api_key=os.environ["MYAIEXP_API_KEY"],
base_url="https://ai.myaiexp.com", # note: no /v1
)
tools = [
{
"name": "get_weather",
"description": "Get the current weather for a city",
"input_schema": {
"type": "object",
"properties": {"city": {"type": "string", "description": "City name, e.g. Beijing"}},
"required": ["city"],
},
}
]
messages = [{"role": "user", "content": "What's the weather in Beijing right now?"}]
# round 1
first = client.messages.create(model="your-model-id", max_tokens=1024, tools=tools, messages=messages)
if first.stop_reason == "tool_use":
messages.append({"role": "assistant", "content": first.content})
results = []
for block in first.content:
if block.type == "tool_use":
# mock data instead of a real weather API
data = {"city": block.input["city"], "weather": "sunny", "temperature_c": 22}
results.append({"type": "tool_result", "tool_use_id": block.id, "content": json.dumps(data)})
messages.append({"role": "user", "content": results})
# round 2
final = client.messages.create(model="your-model-id", max_tokens=1024, tools=tools, messages=messages)
print(final.content[0].text)Notes
- In Chat Completions,
argumentsis a JSON string. Parse it withjson.loads/JSON.parseand handle errors; models occasionally produce invalid arguments. - In round 2, put the assistant message from round 1 (including
tool_calls) back intomessagesunchanged, then append thetoolmessages; eachtool_call_idmust match. - The model may return several
tool_callsat once; run each one and return each result separately. - Function-calling support depends on the model itself; if unsure, try it in the Playground or with the curl above first.
Streaming
Add stream=true to receive output as it is generated. Ideal for chat UIs and avoiding timeouts on long answers.
Anthropic SDK / Messages format
Call the Claude-native /v1/messages endpoint with the official Anthropic SDK. This is also how Claude Code connects.
This service is provided for learning and research purposes only. Please follow each model provider's usage policies.