A policy result belongs to one specific request
Imagine a museum collection assistant using an AI workflow to locate approved handling rules for a fragile exhibit. The model asks a function tool for a rule about object A and another about object B. If the application combines the two results without preserving their identifiers, the answer may attach the wrong rule to the wrong exhibit. OpenAI Responses represents a custom function request as an output item with type function_call and a call_id. When the application returns the corresponding function_call_output, that same call_id connects the result to the request. Matching it is a basic integrity control, not evidence that the policy itself is correct.
Read function_call rather than guessing from final text
The model may produce one, several or no function calls. The Responses function calling guide shows each call as an output item with a name, JSON-encoded arguments and call_id. Do not assume the first response output is the final assistant message or that the first tool result belongs to the first exhibit in a user interface. Iterate the returned items, check their type and keep the call_id alongside the requested function and parsed argument values. The item ID and call_id are different identifiers; use the documented call_id for correlating the function result.

Validate each requested tool and its arguments
Before executing a lookup, confirm that the function name is in an application-controlled allowlist and its arguments satisfy the declared schema. An argument such as accession_id should identify a permitted catalog record; it should not grant access merely because a model included it. Resolve the record with the user’s actual permissions and check the active policy version. If two calls reference different collections, maintain a separate state record for each call_id and its authorization outcome. Treat model-generated arguments as untrusted input until validated. Never authorize a loan, release a restricted document or change a catalog record solely because a tool call was requested.
Send a result with the identical call_id
After the authorized function completes, return a function_call_output item with the same call_id as the original function_call. Its output is typically a string, which may contain a compact JSON result with status, document version and selected approved fields. For example, a hypothetical lookup might return status=found, policy_revision=2026-09 and a citation reference; the full confidential policy file can remain in controlled storage. Sending the wrong call_id creates an association error even if the text sounds plausible. Test the matching rule when two calls finish in the reverse order of their requests.
Represent a failure as a failure
A missing policy, permission denial or timed-out service is not a successful lookup. The function calling guide allows the result payload to use a format selected by the application, including strings containing structured error information. Return an explicit failure status with a non-sensitive description, and decide in application code whether a limited retry is authorized. Do not fabricate a policy paragraph to fill the gap. If the function sends a side-effecting request, make its idempotency and permission checks independent from model suggestions. A user-facing response should say which lookup could not be verified instead of presenting the missing result as approved.
Compare matched, mismatched and failed results
In a synthetic illustration, one request uses call_A and receives an output for call_A; a second example incorrectly labels a reply for call_B as call_A; a third preserves call_A while reporting an explicit not_found status. The first has an intact correlation, the second must be rejected, and the third must be treated as incomplete evidence. These are educational examples rather than observed OpenAI outputs. Build automated checks that reject unknown or duplicate call_id values, record the corresponding function name and warn when an expected result never arrives. The relationship is stronger than matching by list position.

Handle multiple calls without mixing records
The guide warns that a response can contain multiple function calls. A robust dispatcher maintains a mapping from call_id to the approved request, rather than a single mutable current_item variable. If lookups run in parallel, the completion order may differ from request order. Map every returned result back to its call_id, and preserve the requested catalog identifier in the controlled trace. When a tool result refers to a different accession number, flag it for review before showing a synthesized answer. Keeping separate request context also helps detect duplicate tool calls and accidental retries. Never use result arrival order as authorization evidence.
Continue the response with the verified outputs
After gathering tool outputs, the application sends them into the next Responses input so the model can produce a user-facing explanation. The official migration guide distinguishes a function_call output item from a function_call_output input item and explains the call_id link. In a stateful workflow, continuation may use prior response state; in a stateless workflow, the application must preserve the relevant item sequence as documented. In both cases, the model’s final explanation remains a draft. Require the response to cite the validated policy revision rather than assert that tool execution alone proves editorial or legal approval.
Make the audit trace concise and safe
An audit ledger for a hypothetical exhibit lookup can record response ID, function name, call_id, sanitized request parameters, result status, approved citation and whether a human reviewed the conclusion. The ledger should not duplicate private collection notes or visitor identities without a defined purpose. Provide separate access for operational debugging and curatorial review. Make the UI show a visible distinction between found, inaccessible and failed lookups; a polished paragraph must not conceal a tool failure. Test mismatch handling using synthetic call IDs and intentionally reordered responses before any public rollout.

Limits of this documented walkthrough
This article is based on the official OpenAI function calling guide, Responses API definition and migration guide. We checked the roles of function_call, call_id and function_call_output, including multi-call and error-handling guidance. We did not execute a live tool, inspect an actual museum policy store, measure tool success rates or capture vendor screenshots. The diagrams show hypothetical lookup states only. API behavior, storage controls and model capabilities can change; verify the current reference and tool schema in the target environment. Publication or operational decisions require source verification and authorized human approval beyond a correctly matched call_id.
How We Research
Our November 11, 2026 editorial review consulted these named primary references: OpenAI function calling guide; OpenAI Responses create API reference; OpenAI Responses migration guide. We compared the field definitions, scope, constraints, failure cases and feature-specific caveats against a hypothetical museum operations workflow. We did not access private accounts, send production API requests, record actual user information, measure benchmark outcomes, inspect a live WordPress instance, or present the drawings as real vendor screenshots. Illustrations show synthetic educational scenarios. Product settings, documentation and account entitlements may change; verify the current reference and obtain operational or privacy approval before applying any change.
Frequently Asked Questions
The function_call_output item uses the call_id from the original function_call output item.
Yes. The OpenAI guide advises developers to handle multiple calls, not just one assumed tool request.
No. Preserve the explicit call_id mapping; parallel calls can complete in a different order.
Return an explicit non-sensitive error or not_found status, then keep the user-facing answer qualified until authorized evidence exists.
No. It proves the result was paired with a request in your workflow, not that the underlying policy content or permission decision is correct.
