Function Calling & Tools
Let models decide when to call external functions and with what arguments. Your code executes the function and feeds the result back.
LLMs do not execute functions. They analyze the conversation and emit a structured request describing which function to call and with what parameters. Your code parses that request, executes the function, and optionally returns the result so the model can continue. Models marked with the tools capability in the Model Catalog are fine-tuned for this and expose a dedicated tools parameter; prompting a non-tool model to emit function calls is unreliable by comparison.
For background, see Hugging Face's guide on function calling.
Supported models
Tool use is model-specific. See the Model Catalog for the current set of tool-capable models. The catalog is the source of truth and is kept up to date as models are added or retired.
Function calling behavior varies between models (argument formatting, parallel tool calls, etc.). Consult the model's documentation on Hugging Face for specifics.
Defining a function
A function is described with a JSON schema containing:
- Name: Unique identifier for the function
- Description: What the function does (helps the model decide when to use it)
- Parameters: Input schema with types and descriptions
- Python
- cURL
from openai import OpenAIclient = OpenAI(api_key="sk-your-api-key-here",base_url="https://api.inference.nebul.io/v1")tools = [{"type": "function","function": {"name": "get_current_weather","description": "Get the current weather in a given location","parameters": {"type": "object","properties": {"location": {"type": "string","description": "The city and state, e.g. San Francisco, CA"},"unit": {"type": "string","enum": ["celsius", "fahrenheit"],"description": "The unit of temperature to use"}},"required": ["location"]}}}]response = client.chat.completions.create(model="openai/gpt-oss-120b",messages=[{"role": "user", "content": "What's the weather like in Boston?"}],tools=tools,tool_choice="auto" # Let the model decide when to use tools)print(response.choices[0].message.tool_calls)
curl https://api.inference.nebul.io/v1/chat/completions \-H "Content-Type: application/json" \-H "Authorization: Bearer sk-your-api-key-here" \-d '{"model": "openai/gpt-oss-120b","messages": [{"role": "user","content": "What'\''s the weather like in Boston?"}],"tools": [{"type": "function","function": {"name": "get_current_weather","description": "Get the current weather in a given location","parameters": {"type": "object","properties": {"location": {"type": "string","description": "The city and state, e.g. San Francisco, CA"},"unit": {"type": "string","enum": ["celsius", "fahrenheit"],"description": "The unit of temperature to use"}},"required": ["location"]}}}],"tool_choice": "auto"}'
Handling Function Calls
When the model decides to use a function, it returns a tool_calls object instead of a text response. The format depends on whether you are using the Python SDK or the raw API:
- Python
- cURL
The Python SDK returns a list of objects (not a dictionary):
[ChatCompletionMessageToolCall(id='call_abc123',function=Function(arguments='{"location": "Boston, MA", "unit": "fahrenheit"}',name='get_current_weather'),type='function')]
The raw API returns a JSON object:
{"tool_calls": [{"id": "call_abc123","type": "function","function": {"name": "get_current_weather","arguments": "{\"location\": \"Boston, MA\", \"unit\": \"fahrenheit\"}"}}]}
You then:
- Execute the function with the provided arguments
- Return the result to the model
- Get the final response
Complete Flow Example
- Python
- cURL
import jsonfrom openai import OpenAIclient = OpenAI(api_key="sk-your-api-key-here",base_url="https://api.inference.nebul.io/v1")# Define your function implementationdef get_current_weather(location: str, unit: str = "fahrenheit"):# In production, call a real weather APIreturn {"location": location,"temperature": 72,"unit": unit,"conditions": "sunny"}# Define the function schematools = [{"type": "function","function": {"name": "get_current_weather","description": "Get the current weather in a given location","parameters": {"type": "object","properties": {"location": {"type": "string","description": "The city and state, e.g. San Francisco, CA"},"unit": {"type": "string","enum": ["celsius", "fahrenheit"]}},"required": ["location"]}}}]messages = [{"role": "user", "content": "What's the weather in Boston and New York?"}]# First API callresponse = client.chat.completions.create(model="openai/gpt-oss-120b",messages=messages,tools=tools,tool_choice="auto")response_message = response.choices[0].messagemessages.append(response_message)# Check if the model wants to call functionsif response_message.tool_calls:for tool_call in response_message.tool_calls:function_name = tool_call.function.namefunction_args = json.loads(tool_call.function.arguments)# Call the functionif function_name == "get_current_weather":function_response = get_current_weather(**function_args)# Add function response to messagesmessages.append({"tool_call_id": tool_call.id,"role": "tool","name": function_name,"content": json.dumps(function_response)})# Get final response from modelfinal_response = client.chat.completions.create(model="openai/gpt-oss-120b",messages=messages)print(final_response.choices[0].message.content)
# Step 1: Initial request with toolsRESPONSE=$(curl -s https://api.inference.nebul.io/v1/chat/completions \-H "Content-Type: application/json" \-H "Authorization: Bearer sk-your-api-key-here" \-d '{"model": "openai/gpt-oss-120b","messages": [{"role": "user", "content": "What'\''s the weather in Boston?"}],"tools": [{"type": "function","function": {"name": "get_current_weather","description": "Get the current weather","parameters": {"type": "object","properties": {"location": {"type": "string"}},"required": ["location"]}}}],"tool_choice": "auto"}')# Step 2: Execute the function (example)FUNCTION_RESULT='{"location": "Boston, MA", "temperature": 72, "unit": "fahrenheit", "conditions": "sunny"}'# Step 3: Send function result back to modelcurl https://api.inference.nebul.io/v1/chat/completions \-H "Content-Type: application/json" \-H "Authorization: Bearer sk-your-api-key-here" \-d '{"model": "openai/gpt-oss-120b","messages": [{"role": "user", "content": "What'\''s the weather in Boston?"},{"role": "assistant","tool_calls": [{"id": "call_abc123","type": "function","function": {"name": "get_current_weather","arguments": "{\"location\": \"Boston, MA\"}"}}]},{"role": "tool","tool_call_id": "call_abc123","name": "get_current_weather","content": "'"$FUNCTION_RESULT"'"}]}'
Multiple Functions
You can provide multiple functions and the model will choose the appropriate one(s):
tools = [{"type": "function","function": {"name": "search_products","description": "Search for products in the database","parameters": {"type": "object","properties": {"query": {"type": "string"},"category": {"type": "string"},"max_price": {"type": "number"}},"required": ["query"]}}},{"type": "function","function": {"name": "get_product_details","description": "Get detailed information about a specific product","parameters": {"type": "object","properties": {"product_id": {"type": "string"}},"required": ["product_id"]}}}]
Tool Choice Options
Control when the model uses functions:
auto(default): Model decides whether to call functionsnone: Forces model to only generate text responsesrequired: Forces model to call at least one function{"type": "function", "function": {"name": "function_name"}}: Forces a specific function
Best Practices
- Clear descriptions: Write detailed descriptions that help the model understand when to use each function.
- Required parameters: Mark essential parameters as required.
- Validation: Validate function arguments before execution.
- Error handling: Return meaningful error messages to the model.
- Security: Never execute arbitrary code. Only call predefined, safe functions.
- Timeouts: Implement timeouts for external API calls.