Tools and approvals
Purpose and Scope
Tools let a model request work outside its own text generation loop. In this SDK, that can mean built-in hosted tools on the Responses surface, function definitions supplied to Chat Completions, deferred tool discovery through tool search, or remote integration surfaces such as MCP servers. Approvals are the policy layer around those actions: before a workflow performs a side effect, writes to an external system, issues a shell-like command, or calls a sensitive connector, the application can pause and decide whether the action should continue. This page explains how those concepts map onto the OpenAI TypeScript and JavaScript SDK, with emphasis on the public client surfaces, helper behavior, and test signals that keep tool-oriented flows stable. Sources: README.md, api.md, tests/lib/ChatCompletionRunFunctions.test.ts, tests/helpers/zod.test.ts
The SDK itself is a generated TypeScript and JavaScript library for the OpenAI REST API, and the README positions the Responses API as the primary model interaction surface while also documenting Chat Completions as the previous standard supported indefinitely. That matters for tool workflows because new applications usually begin with Responses, where model output, input items, built-in tools, and continuation patterns are designed around a single response object. Existing applications may still rely on Chat Completions, where the message list and chat completion helpers are central. Tool and approval designs should therefore be written so the runtime loop is explicit, auditable, and portable between these two surfaces when possible. Sources: README.md, api.md
Relevant Source Files
- README.md — Introduces the SDK, installation, client construction, the Responses-first usage path, Chat Completions compatibility, and the warning that manual Responses conversation history must preserve replayable output items rather than only message text.
- api.md — Serves as the generated API reference for the package and is the place to confirm concrete request and response types, resource namespaces, method names, and examples for tool-capable endpoints.
- tests/lib/ChatCompletionRunFunctions.test.ts — Provides regression coverage for chat-completion helper behavior around function execution loops, which is the compatibility surface most relevant to tool-oriented Chat Completions applications.
- tests/helpers/zod.test.ts — Tests schema helper behavior for Zod v3 and v4, including strict JSON schema generation, discriminated-union conversion, and stable definition references that are important when schemas shape model-visible structured contracts.
Core Primitives
A tool definition is a contract the model can see. For a function tool, that contract normally includes a name, description, and parameter schema. For hosted tools, it may identify a built-in capability such as file search. For tool search, the model receives a lighter description first and can load deferred tool definitions only when needed. The official OpenAI tools guidance describes tool search as useful when an application has many possible functions, namespaces, or MCP server tools and does not want to spend tokens loading every detailed schema up front. The practical SDK implication is that the application still passes tool configuration in the request, but the design of those definitions affects cost, latency, and model context pressure.
An approval is not the same thing as a schema. A schema tells the model what arguments are valid; an approval decision tells the application whether a proposed action is acceptable. The official agent guidance separates automatic guardrails from human review: guardrails validate input, output, or tool behavior, while human review can pause a run before sensitive side effects. In an SDK integration, that usually means your code inspects the model’s requested tool call, validates the arguments, checks policy, optionally asks a person or service for approval, and only then executes the function or connector. The OpenAI client carries the request and response objects; the approval gate belongs in the application loop around those objects.
System-to-Code Mapping
The README’s first Responses example constructs an OpenAI client and calls the Responses resource with a model, instructions, and input. That same shape is the starting point for tool-enabled Responses calls: add a tools array, preserve response output items when continuing manually, and read the response object rather than treating the model as a plain string generator. The README’s conversation-state warning is especially relevant for tools because filtering output down to messages can drop reasoning or tool-call items that the next request needs. If a tool call is produced in one turn and the application omits it from the replayed history, the next request may not have enough context to resolve the workflow correctly. Sources: README.md
Chat Completions remains important because many existing tool-calling integrations were built around message arrays and function execution loops. The generated API reference is the canonical place to verify the exact names and types for chat completion request parameters, including model, messages, streaming flags, and tool-choice-related fields. The dedicated chat function-runner tests show that the repository treats helper behavior as more than a documentation example: there is test coverage for the compatibility path where the SDK helps coordinate chat-completion function execution. That does not remove responsibility from the application. Your code still decides which functions are available, how arguments are validated, what permissions are required, and how function results are returned to the model. Sources: api.md, tests/lib/ChatCompletionRunFunctions.test.ts
The Zod helper tests map to a different but adjacent concern: reliable contracts. When a model must produce structured arguments or structured output, the schema seen by the model should be strict, deterministic, and compatible across supported Zod versions. The tests import helpers from the package’s Zod helper entrypoint and verify behavior such as strict response-format schemas, conversion of Zod v4 discriminated unions away from unsupported one-of shapes, and reference names that avoid whitespace. For tool workflows, that kind of schema discipline reduces ambiguity before an approval gate. If a cancellation tool requires an order identifier and a reason, strict schemas make it easier to reject incomplete or malformed calls before any side effect occurs. Sources: tests/helpers/zod.test.ts
Execution Flow for Tool-Oriented Workflows
A safe tool flow starts before the request is sent. First, decide which capabilities the model should see in this turn. Small applications may provide a short list of function tools directly. Larger applications should consider namespaces, MCP servers, or tool search when the available action catalog is large, because the model does not need every parameter schema in its prompt for every turn. Second, choose whether the model may select tools automatically or whether the application should constrain tool choice for the turn. Tool-choice configuration is useful when a workflow stage is known: for example, a lookup stage may allow retrieval tools, while a final answer stage may disallow side-effecting actions.
After the model responds, treat tool calls as proposed actions rather than completed actions. Parse the tool name and arguments, validate them against the schema, and run any guardrails that should apply around the call. For read-only functions, the approval policy may be automatic. For state-changing functions, the workflow should pause and record enough detail for review: tool name, arguments, user request, relevant conversation context, and expected side effect. If approved, execute the function and send the result back through the appropriate API continuation pattern. If rejected, return a clear refusal or alternative result so the model can continue without pretending the action happened.
Responses conversation state deserves special care during this loop. The README explicitly warns that when manually managing Responses history, developers should preserve output items in order and use the SDK helper that normalizes replayable output items, rather than filtering to only messages. Tool workflows are one of the reasons this warning exists. A tool call, tool result, reasoning item, or other non-message item can be part of the causal chain that makes the next request valid. For simple continuation, the previous response identifier can avoid manual reconstruction, but if you build a custom approval queue you should store the original response data faithfully. Sources: README.md
API Components and Configuration Reference
The primary SDK entrypoint is the OpenAI client imported from the package. The README shows construction with an API key read from the environment and then calls the Responses and Chat Completions resources through that client. For tool workflows, the relevant request-level configuration lives on the resource method call: model selection, instructions or messages, input content, tools, streaming flags, and any tool-choice constraints defined by the generated API surface. The generated API reference should be treated as the exact contract for names and types, because this repository is generated from the OpenAPI specification and exposes strongly typed request objects for TypeScript users. Sources: README.md, api.md
Compact reference for this page:
| Component | Where to look | Role in tool workflows |
|---|---|---|
| OpenAI client | README.md | Constructs the SDK client used to call Responses and Chat Completions. |
| Responses API | README.md, api.md | Preferred model interaction surface for new workflows, including tool-enabled response creation and continuation. |
| Chat Completions API | README.md, api.md | Compatibility surface for message-based generation and existing function-calling flows. |
| Chat completion function helpers | tests/lib/ChatCompletionRunFunctions.test.ts | Regression-tested helper path for coordinating chat function execution loops. |
| Zod schema helpers | tests/helpers/zod.test.ts | Produce strict, stable JSON-schema-style contracts for structured model interactions. |
A minimal Responses-style tool request follows the same client pattern as the README’s first request, with a tools array added according to the generated API reference:
import OpenAI from 'openai';
const client = new OpenAI({
apiKey: process.env['OPENAI_API_KEY'],
});
const response = await client.responses.create({
model: 'gpt-5.5',
input: 'Search my product files for the warranty policy.',
tools: [
{
type: 'file_search',
vector_store_ids: ['<vector_store_id>'],
},
],
});
console.log(response.output_text);For a side-effecting function, place the approval gate between the model’s proposed call and the local function execution. The SDK call obtains the model output; your application owns the policy decision and audit trail. In practice, teams often implement this as a dispatcher that maps tool names to handlers, a validator that checks the arguments, and an approver that returns approved, rejected, or needs-human-review. The important design constraint is that the function should not run simply because its name appears in model output. Treat the model as requesting an action, not authorizing it.
Implementation Details and Edge Cases
Tool search changes how much tool detail is visible at the beginning of a request. Official OpenAI guidance says it is supported only by later model families and requires adding a tool-search entry while marking functions or MCP server definitions for deferred loading. That distinction matters when designing approval flows. If the model discovers a tool later in the context, your application should still apply the same validation and approval policy as it would for a fully loaded function. Deferred loading is an optimization for context and discovery, not a bypass around authorization, logging, or human review.
Schema generation has its own edge cases. The Zod tests show that the helper layer cares about strict schemas, cross-version compatibility, and valid internal references. That is a useful signal for applications that generate tool or output contracts from TypeScript validation libraries. Names that contain whitespace, recursive definitions, or discriminated unions can create JSON schema details that affect model behavior and downstream validators. The tested helpers reduce those risks for supported structured-output paths, but developers should still keep tool argument schemas small, explicit, and policy-aware. A precise schema is easier to review than a permissive object with free-form fields. Sources: tests/helpers/zod.test.ts
Streaming adds another operational concern. Chat and Responses streaming can expose partial progress before the final state is known. When tools and approvals are involved, do not execute side effects from partial text. Wait until the SDK surface has produced the finalized tool-call information required by the generated types or helper flow. If a UI streams assistant text while a tool call is pending approval, make the pending state visible to the user and avoid implying that an external action has already completed. This keeps the user experience aligned with the actual execution state and preserves a clean audit record.
Testing Signals
The repository’s test selection for this page gives two important confidence signals. First, chat completion function-runner tests exist as a named area of coverage, which indicates that helper behavior for legacy function execution workflows is intentionally maintained. Second, Zod helper tests validate schemas across both supported major Zod import paths. Together, these tests support the main integration advice: keep the model-visible contract explicit, use SDK helpers where they match the workflow, and put policy decisions in your own execution layer. Sources: tests/lib/ChatCompletionRunFunctions.test.ts, tests/helpers/zod.test.ts
When adding or changing a tool workflow in an application, test the full loop rather than only the initial model call. Include a case where the model calls the expected tool, a case where arguments are incomplete, a case where approval is rejected, and a case where the tool result is returned for a final answer. If you manually persist Responses history, test that replayed input includes the necessary non-message output items. If you use Chat Completions helpers, test both successful function execution and handler failure behavior. The SDK gives typed surfaces and helper coverage, but correctness depends on how your application connects those surfaces to real systems.
Next Steps
Start with the Responses API for new tool-enabled workflows, especially when you need built-in tools, response items, and continuation support. Use Chat Completions when maintaining an existing message-based function-calling integration or when its helper flow already fits your application. For large tool catalogs, review tool search, namespaces, and MCP-style connectors before placing every function schema in every request. For sensitive actions, design the approval gate first, then connect it to the SDK request loop. Read the Responses API, Chat Completions, MCP integrations, Connections, Structured outputs, and Function calling with Zod pages next for deeper implementation details.