Skip to main content

Tool Calling (Function Calling)

Tool calling allows models to invoke external functions, APIs, and tools during a conversation. The model decides when to call a function based on the user’s message and returns structured arguments you can use to execute the function in your application.
The Morpheus Inference API is fully OpenAI-compatible — tool calling works exactly like OpenAI’s function calling API. If you’ve used OpenAI tools before, you already know how to use this.

Supported Models

Most models on the Morpheus API support function calling. See the Available Models page for the full list — look for the Function Calling capability. Popular choices for tool calling:
ModelBest For
glm-5Complex multi-step tool orchestration
kimi-k2.5Parallel tool calls, agent workflows
minimax-m2.5Autonomous multi-tool agents
mistral-31-24bFast, efficient tool use
glm-4.7-flashLightweight agentic coding

How It Works

  1. Define tools — Describe available functions with names, descriptions, and JSON Schema parameters
  2. Send request — Include tools in your chat completion request
  3. Model responds — The model either answers directly or returns a tool_calls array with function names and arguments
  4. Execute functions — Run the requested functions in your application
  5. Return results — Send function results back to the model for a final response

Basic Example

Define a tool and let the model decide when to call it:
curl https://api.mor.org/api/v1/chat/completions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "glm-5",
    "messages": [
      {"role": "user", "content": "What is the weather like in San Francisco?"}
    ],
    "tools": [
      {
        "type": "function",
        "function": {
          "name": "get_weather",
          "description": "Get the current weather for a location",
          "parameters": {
            "type": "object",
            "properties": {
              "location": {
                "type": "string",
                "description": "The city name, e.g. San Francisco"
              },
              "unit": {
                "type": "string",
                "enum": ["celsius", "fahrenheit"],
                "description": "Temperature unit"
              }
            },
            "required": ["location"]
          }
        }
      }
    ]
  }'

Complete Tool Calling Loop

In a real application, you execute the function and send the result back to the model:
import json
from openai import OpenAI

client = OpenAI(
    api_key="YOUR_API_KEY",
    base_url="https://api.mor.org/api/v1"
)

# Define your tools
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Get the current weather for a location",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {"type": "string", "description": "City name"},
                    "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
                },
                "required": ["location"]
            }
        }
    }
]

# Your actual function implementation
def get_weather(location: str, unit: str = "fahrenheit") -> str:
    # Replace with a real weather API call
    return json.dumps({"temperature": 72, "unit": unit, "condition": "sunny"})

# Step 1: Send the user message with tools
messages = [{"role": "user", "content": "What's the weather in San Francisco?"}]

response = client.chat.completions.create(
    model="glm-5",
    messages=messages,
    tools=tools
)

message = response.choices[0].message

# Step 2: Check if the model wants to call a function
if message.tool_calls:
    # Add the assistant's response to the conversation
    messages.append(message)

    # Step 3: Execute each tool call and add results
    for tool_call in message.tool_calls:
        function_name = tool_call.function.name
        arguments = json.loads(tool_call.function.arguments)

        # Call your function
        result = get_weather(**arguments)

        # Add the function result to the conversation
        messages.append({
            "role": "tool",
            "tool_call_id": tool_call.id,
            "content": result
        })

    # Step 4: Get the final response with function results
    final_response = client.chat.completions.create(
        model="glm-5",
        messages=messages,
        tools=tools
    )

    print(final_response.choices[0].message.content)
else:
    print(message.content)

Response Format

When a model decides to call a tool, the response includes a tool_calls array:
{
  "choices": [
    {
      "message": {
        "role": "assistant",
        "content": " I'll check the current weather in San Francisco for you.  ",
        "tool_calls": [
          {
            "id": "call_abc123",
            "type": "function",
            "function": {
              "name": "get_weather",
              "arguments": "{\"location\": \"San Francisco\"}"
            }
          }
        ]
      },
      "finish_reason": "tool_calls"
    }
  ]
}
When finish_reason is "tool_calls", the model is requesting function execution. The content field may contain a brief message or be null — always check for tool_calls first regardless of whether content is present.

Multiple Tools

You can define multiple tools and the model will choose which to call:
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Get current weather for a location",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {"type": "string"}
                },
                "required": ["location"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "search_web",
            "description": "Search the web for information",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {"type": "string"}
                },
                "required": ["query"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "get_stock_price",
            "description": "Get the current stock price",
            "parameters": {
                "type": "object",
                "properties": {
                    "symbol": {"type": "string", "description": "Stock ticker symbol"}
                },
                "required": ["symbol"]
            }
        }
    }
]

Tips

The model uses the description field to decide when to call a function. Be specific about what the function does and when it should be used.
// Good
"description": "Get the current weather forecast for a specific city. Returns temperature, conditions, and humidity."

// Bad
"description": "weather"
Help the model provide the right arguments by describing each parameter clearly, including format expectations and valid values.
"location": {
  "type": "string",
  "description": "City and state, e.g. 'San Francisco, CA' or 'New York, NY'"
}
Always check finish_reason — if it’s "tool_calls", execute the functions and send results back. The model may call multiple functions in sequence before giving a final answer.

Next Steps