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:

  1. Describe the available functions with tools in the request.
  2. The model returns tool_calls (function name + JSON arguments).
  3. Your code runs the function and appends the result to the conversation as a role: "tool" message.
  4. 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

tools.py
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:

tools.sh
# 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, description and input_schema (no outer function wrapper).
  • When the model wants a tool, stop_reason is tool_use and content contains a type: "tool_use" block whose arguments are in input (already a JSON object, not a string).
  • Return the result in a tool_result block of the next user message, with tool_use_id set to the previous block's id.
anthropic_tools.py
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, arguments is a JSON string. Parse it with json.loads / JSON.parse and handle errors; models occasionally produce invalid arguments.
  • In round 2, put the assistant message from round 1 (including tool_calls) back into messages unchanged, then append the tool messages; each tool_call_id must match.
  • The model may return several tool_calls at 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.

This service is provided for learning and research purposes only. Please follow each model provider's usage policies.

On this page