Tool Calling
Define tools once with the OpenAI Chat Completions format, send function results back to the model, and account for model-specific tool-choice support.
What is tool calling?#
Tool calling lets a model request a function in its response. Your application—not OpenGateway—runs the function, then sends the result back in a follow-up message. Chat Completions accepts the OpenAI-style tools and tool_choice fields; the provider adapter maps them where supported.
Define a function#
Describe the function and its JSON Schema in the Chat Completions request:
import osfrom openai import OpenAIclient = OpenAI(api_key=os.environ["OPENGATEWAY_API_KEY"],base_url="https://apis.opengateway.ai/v1",)model = "deepseek/deepseek-v4.1-flash-ultrafast"tools = [{"type": "function","function": {"name": "get_weather","description": "Get the current weather for a city.","parameters": {"type": "object","properties": {"city": {"type": "string"}},"required": ["city"],"additionalProperties": False,},},}]response = client.chat.completions.create(model=model,messages=[{"role": "user", "content": "What is the weather in Seoul?"}],tools=tools,tool_choice="auto",)
A tool call appears in the assistant message as tool_calls. The function arguments are JSON encoded in function.arguments:
{"tool_calls": [{"id": "call_example","type": "function","function": {"name": "get_weather","arguments": "{\"city\":\"Seoul\"}"}}]}
Run the function and return its result#
Parse the arguments, run your own function, then send a role: "tool" message with the matching tool_call_id:
import jsondef get_weather(city):return {"city": city, "temperature_c": 18, "condition": "clear"}assistant_message = response.choices[0].messagetool_call = assistant_message.tool_calls[0]arguments = json.loads(tool_call.function.arguments)result = get_weather(**arguments)follow_up = client.chat.completions.create(model=model,messages=[{"role": "user", "content": "What is the weather in Seoul?"},assistant_message.model_dump(exclude_none=True),{"role": "tool","tool_call_id": tool_call.id,"content": json.dumps(result),},],tools=tools,)print(follow_up.choices[0].message.content)
Choose tools#
tool_choice accepts these OpenAI-style choices:
| Value | Behavior |
|---|---|
"auto" | Let the model decide whether to call a tool. |
"none" | Do not call a tool. |
"required" | Require a tool call. |
{"type":"function","function":{"name":"get_weather"}} | Require the named function. |
Forced choices such as "required" need at least one tool definition. Some models also restrict forced tool calls while reasoning is enabled; use a supported choice or disable reasoning only when the model allows it.
Stream tool calls#
With stream: true, function-call data arrives in choices[].delta.tool_calls. The arguments may be split across chunks, so accumulate each call’s deltas by index and parse the completed JSON only after the stream finishes. See streaming.
Model-specific support#
Tool features and accepted schemas vary by model. Use a model whose catalog entry includes chat_completions, and check its provider support before relying on forced tool choice or provider-native tool features. The gateway does not execute tools on your behalf.