developers.openai.com/api/docs/guides/function-calling, as of June 2026). Examples for both endpoints are copy-paste ready.
The Full Call Loop
1
Define tools
Send function names, descriptions, and parameter JSON Schemas with the request
2
Model returns a call
When the model decides to call, it returns the function name and JSON arguments
3
Execute locally
Your code parses the arguments and actually runs the function (query a DB, hit an external API…)
4
Send the result back
Send the result with the conversation in a second request; the model answers based on it
Key Format Differences Between the Two Endpoints
Same feature, different field formats on/v1/chat/completions vs /v1/responses — the most common integration trap:
Full Example: Chat Completions
A weather lookup through the complete define → call → execute → return loop:Full Example: Responses
Note the three differences: tool definitions are flat, calls come back as top-levelfunction_call items, and results return as function_call_output. With previous_response_id, the second request doesn’t need to resend the full history:
strict Mode (Structured Outputs)
strict: true guarantees the model’s arguments conform exactly to your JSON Schema — no hallucinated or missing fields. Three requirements:
- The schema must include
"additionalProperties": false - Every field must appear in
required(express optionality with"type": ["string", "null"]) - Only the supported JSON Schema subset (primitive types, enum, arrays, nested objects, …)
parallel_tool_calls and tool_choice
Parallel calls
parallel_tool_calls defaults to on: the model may request several functions in one turn (e.g. weather for Beijing and Shanghai simultaneously). Execute each, then return all results before the next request — every result must pair with its call_id (responses) or tool_call_id (chat).
tool_choice strategies
allowed_tools subsets
When you have many tools but want to expose only some this turn, use theallowed_tools form of tool_choice to restrict the callable subset — it doesn’t modify the tools list itself, so it doesn’t break the stable prefix for caching:
Function Calls in Streaming
Chat Completions: assemble by index
Function arguments stream in fragments. Accumulate thearguments string per index, then json.loads after the stream ends:
Responses: listen for semantic events
response.function_call_arguments.delta events carry argument increments, and response.function_call_arguments.done delivers the complete arguments — no manual index assembly.
Best Practices and Pitfalls
Writing good tool definitions:- Names and descriptions are written for the model: spell out “when to call me”, e.g.
"Get real-time weather; call only when the user explicitly asks about weather" - Narrow parameters with enum: if values are enumerable, don’t use free-form strings — it eliminates most hallucinated arguments
- Keep tool definitions early in the prompt and stable: tools participate in the cache prefix; stable definitions mean 90%-off input (see Cache Billing)
- Cap your agent loop: set a max number of rounds so the model can’t burn money cycling call → return → call
Model Support and Selection
The entire gpt-5 series supports function calling. By scenario:Related Links
- This group: Native Calls · Compatible Mode · Cache Billing
- Get / manage tokens:
https://api.apiyi.com/token - Official OpenAI docs:
developers.openai.com/api/docs/guides/function-calling