GPTMap

Function Calling with the OpenAI API: A Complete Guide to Tool Use in the Responses API

Function calling is how GPT-5.6 calls your code. This guide walks the full Responses API flow: declaring tools, parsing function_call, returning results, and chaining multi-turn tool calls.

TL;DR
Function calling lets the model call your code before answering — checking weather, querying a database, placing an order — and is the foundation of agents. This guide walks the complete Responses API flow: declaring tools, parsing function_call, returning function_call_output, plus multi-turn chaining, parallel calls, tool_choice, and common errors.
Function calling (tool use) is a Responses API capability: based on your tools declarations, the model decides whether to call a function, returns a structured function_call, and your code executes it and feeds the result back so the model can finish generating.

How to

  1. Declare a tool with a JSON Schema parameter

    In client.responses.create, add a function to tools: name (e.g. get_weather), description, and parameters (JSON Schema, with required).

  2. Send the request and parse function_call

    Inspect response.output for entries with type == 'function_call', take name and arguments (a JSON string), and dispatch to your implementation.

  3. Return the execution result to the model

    Append that function_call to input, add {type: 'function_call_output', call_id, output}, and call responses.create again — the model then produces the final answer.

  4. Optimize with tool_choice and parallel calls

    Default auto; use required or a specific name to force. Execute multiple independent function_calls concurrently and return them all at once.

  5. Harden before shipping

    Validate and authenticate function inputs, add user confirmation to sensitive operations, and treat tool return values as untrusted input to resist prompt injection.

Function calling is how you make the model "act": instead of answering "what's the weather?", it returns a structured call request, your code checks the weather, and the model turns that into an answer. This guide walks the full Responses API flow.

1. What function calling is

A normal request is one-way: input → text answer. Function calling splits the flow into rounds:

  1. You declare available tools, each with a name, description, and parameter schema.
  2. The model decides "this needs a tool", and returns a function_call (function name + arguments JSON).
  3. Your code executes the function and returns the result as function_call_output.
  4. The model uses that result to generate the final answer.

The model never runs your code — it only decides; execution stays in your hands.

2. Declaring tools

Tools go in the tools array; each function is an object with a JSON Schema parameter:

from openai import OpenAI

client = OpenAI()

tools = [
    {
        "type": "function",
        "name": "get_weather",
        "description": "Get the current weather for a city. Call when the user asks about weather.",
        "parameters": {
            "type": "object",
            "properties": {
                "city": {"type": "string", "description": "City name, e.g. Beijing"},
                "unit": {"type": "string", "enum": ["celsius", "fahrenheit"], "default": "celsius"}
            },
            "required": ["city"]
        }
    }
]

response = client.responses.create(
    model="gpt-5.6",
    input="What's the weather in Beijing today?",
    tools=tools,
)

Key point: a clear description and a precise parameters schema are the biggest lever on call success.

3. Parsing function_call and executing

When the model decides to call a tool, response.output contains a function_call entry:

for item in response.output:
    if item.type == "function_call":
        print(item.name)          # get_weather
        print(item.arguments)     # '{"city": "Beijing", "unit": "celsius"}'
        print(item.call_id)       # needed for the return

arguments is a JSON string — parse it and dispatch to your own implementation:

import json

def call_function(name: str, args: str) -> str:
    params = json.loads(args)
    if name == "get_weather":
        # This is your real weather API or data source
        return json.dumps({"city": params["city"], "temp": 26, "unit": "celsius"})
    raise ValueError(f"Unknown function: {name}")

4. Returning results and getting the final answer

Append the function_call together with the result to input, then call again:

# Assume fc = the first function_call item from the previous response
messages = list(response.output)  # keep the model's original output
messages.append({
    "type": "function_call_output",
    "call_id": fc.call_id,
    "output": '{"city": "Beijing", "temp": 26, "unit": "celsius"}',
})

final = client.responses.create(
    model="gpt-5.6",
    input=messages,
    tools=tools,
)
print(final.output_text)
# Something like: It's 26°C in Beijing today.

Multi-turn calling is just repeating "parse → execute → return" until output contains a text entry.

5. Control strategy: tool_choice

ValueBehavior
"auto" (default)The model decides whether to call
"none"Explicitly forbid tool calls
"required"Force at least one call (good for routing)
function nameForce that specific function
response = client.responses.create(
    model="gpt-5.6",
    input="Classify this message",
    tools=tools,
    tool_choice={"type": "function", "name": "classify_message"},  # forced
)

6. Parallel tool calls

When the model judges several independent tools are needed, one response returns multiple function_call items. Execute them in parallel and return them all at once:

# output contains multiple function_calls
calls = [i for i in response.output if i.type == "function_call"]
results = [run_in_parallel(c.name, c.arguments) for c in calls]  # parallel

new_input = list(response.output)
for c, r in zip(calls, results):
    new_input.append({
        "type": "function_call_output",
        "call_id": c.call_id,
        "output": r,
    })
final = client.responses.create(model="gpt-5.6", input=new_input, tools=tools)

7. Common errors and troubleshooting

  • function_call never fires → the description doesn't state when to call, or the task doesn't need tools. Rewrite it as "call when the user asks X".
  • Argument parsing fails → the schema is too loose. Tighten with enum / format / required.
  • The model re-asks after returning → call_id mismatch, or function_call_output didn't follow its function_call.
  • Tool hijacked by prompt injection → treat tool return values as untrusted; add user confirmation to destructive operations (delete, send, pay).
  • 400 invalid_request_error → check that you passed tools (not Chat Completions' functions) and input (not messages).

8. What's Next

  • OpenAI API Getting Started: Your First GPT-5.6 Call
  • The Complete Guide to GPT Models: GPT-5.6 Sol, Terra, Luna
  • The Complete Guide to MCP: How It Works and Practical Builds — standardize your tool calling with MCP

Key points

  • Tools are declared in the tools array; each function carries name / description / parameters (JSON Schema)
  • The model never executes functions — it returns a function_call object; execution and return are your code's job
  • Return results as type 'function_call_output' appended to input; the model continues to a final answer
  • tool_choice controls strategy: auto / none / required / a specific function name
  • Parallel tool calls return multiple function_calls in one response; execute concurrently, return all at once
  • Clear descriptions and precise parameter schemas are the biggest lever on call success rate

Frequently asked questions

Normal: input → text answer. Function calling: input + tools → the model may return a function_call (no final text yet), your code executes the function and returns the result as function_call_output, then the model generates the final answer. One turn can span several requests until the model emits text.

Official references

Related articles

Subscribe to GPTMap Weekly

One email every Monday: curated OpenAI updates, deep dives, and best practices. No ads, unsubscribe anytime.

GPTMap EditorialPublished 2026-08-06 4 min read
Test environment (EEAT)
Last tested: 2026-08-06
Model used: gpt-5.6