UNPKG

@openai/agents-core

Version:

The OpenAI Agents SDK is a lightweight yet powerful framework for building multi-agent workflows.

1,062 lines • 45 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.CLIENT_TOOL_SEARCH_EXECUTOR = exports.FUNCTION_TOOL_INVALID_OUTPUT_FAILURE_CALLBACK = exports.FUNCTION_TOOL_PARSED_INPUT_CALLBACK = void 0; exports.prepareFunctionToolInput = prepareFunctionToolInput; exports.setFunctionToolPreparedInput = setFunctionToolPreparedInput; exports.hasDynamicFunctionToolApprovalPolicy = hasDynamicFunctionToolApprovalPolicy; exports.hasInspectableFunctionToolArguments = hasInspectableFunctionToolArguments; exports.computerTool = computerTool; exports.resolveComputer = resolveComputer; exports.disposeResolvedComputers = disposeResolvedComputers; exports.shellTool = shellTool; exports.applyPatchTool = applyPatchTool; exports.hostedMcpTool = hostedMcpTool; exports.attachClientToolSearchExecutor = attachClientToolSearchExecutor; exports.getClientToolSearchExecutor = getClientToolSearchExecutor; exports.getToolSearchRuntimeToolKey = getToolSearchRuntimeToolKey; exports.getToolSearchRuntimeRoutingKey = getToolSearchRuntimeRoutingKey; exports.validateFunctionToolOutput = validateFunctionToolOutput; exports.invokeFunctionTool = invokeFunctionTool; exports.tool = tool; exports.toolNamespace = toolNamespace; const tools_1 = require("./utils/tools.js"); const functionToolApproval_1 = require("./utils/functionToolApproval.js"); const tools_2 = require("./utils/tools.js"); const typeGuards_1 = require("./utils/typeGuards.js"); const abortSignals_1 = require("./utils/abortSignals.js"); const errors_1 = require("./errors.js"); const toolInputError_1 = require("./toolInputError.js"); const toolOutputError_1 = require("./toolOutputError.js"); const logger_1 = __importStar(require("./logger.js")); const tracing_1 = require("./tracing/index.js"); const functionToolTracing_1 = require("./functionToolTracing.js"); const smartString_1 = require("./utils/smartString.js"); const mcpApproval_1 = require("./utils/mcpApproval.js"); const standardSchema_1 = require("./utils/standardSchema.js"); const toolIdentity_1 = require("./toolIdentity.js"); const toolGuardrail_1 = require("./toolGuardrail.js"); const toolCallers_1 = require("./utils/toolCallers.js"); exports.FUNCTION_TOOL_PARSED_INPUT_CALLBACK = Symbol('openai.agents.functionToolParsedInputCallback'); exports.FUNCTION_TOOL_INVALID_OUTPUT_FAILURE_CALLBACK = Symbol('openai.agents.functionToolInvalidOutputFailureCallback'); const FUNCTION_TOOL_OUTPUT_VALIDATOR = Symbol('openai.agents.functionToolOutputValidator'); const STATIC_FUNCTION_TOOL_APPROVAL_POLICIES = new WeakSet(); const functionToolInputParsers = new WeakMap(); const functionToolPreparedInputs = new WeakMap(); function parseFunctionToolInput(parser, input) { try { return { success: true, value: parser(input) }; } catch (error) { return { success: false, error }; } } /** Prepare input for SDK runners through the internal utilities entry point. */ function prepareFunctionToolInput(tool, input) { const registration = functionToolInputParsers.get(tool.invoke); if (!registration) { return undefined; } const result = parseFunctionToolInput(registration.parser, input); if (!result.success && (0, standardSchema_1.isAsyncStandardSchemaValidationError)(result.error)) { throw result.error; } const base = { consumed: false, input, token: registration.token, validationMode: registration.validationMode, }; if (result.success) { if (hasDynamicFunctionToolApprovalPolicy(tool)) { // Snapshot application-owned transform output before any policy can await. const value = (0, functionToolApproval_1.getFunctionToolApprovalInput)(result.value); return { ...base, result: { success: true, value } }; } return { ...base, result }; } return { ...base, result, disposition: (0, toolInputError_1.createInvalidToolInputDisposition)(), }; } /** Attach prepared input for SDK runners through the internal utilities entry point. */ function setFunctionToolPreparedInput(details, preparedInput) { functionToolPreparedInputs.set(details, preparedInput); } function copyFunctionToolPreparedInput(source, target) { if (!source || !target) { return; } const preparedInput = functionToolPreparedInputs.get(source); if (preparedInput) { functionToolPreparedInputs.set(target, preparedInput); } } function hasDynamicFunctionToolApprovalPolicy(tool) { return !STATIC_FUNCTION_TOOL_APPROVAL_POLICIES.has(tool.needsApproval); } function hasInspectableFunctionToolArguments(value) { return typeof value === 'object' && value !== null && !Array.isArray(value); } function isComputerProvider(candidate) { if (isComputerInstance(candidate)) { return false; } return (!!candidate && typeof candidate === 'object' && typeof candidate.create === 'function'); } function isComputerInstance(candidate) { if (!candidate || typeof candidate !== 'object') { return false; } const maybeComputer = candidate; return (typeof maybeComputer.screenshot === 'function' && typeof maybeComputer.click === 'function' && typeof maybeComputer.doubleClick === 'function' && typeof maybeComputer.drag === 'function' && typeof maybeComputer.keypress === 'function' && typeof maybeComputer.move === 'function' && typeof maybeComputer.scroll === 'function' && typeof maybeComputer.type === 'function' && typeof maybeComputer.wait === 'function'); } /** * Exposes a computer to the agent as a tool to be called. * * @param options Additional configuration for the computer tool like specifying the location of your agent * @returns a computer tool definition */ function computerTool(options) { if (!options.computer) { throw new errors_1.UserError('computerTool requires a computer instance or an initializer function.'); } const needsApproval = typeof options.needsApproval === 'function' ? options.needsApproval : async () => typeof options.needsApproval === 'boolean' ? options.needsApproval : false; const tool = { type: 'computer', name: options.name ?? 'computer_use_preview', computer: options.computer, needsApproval, onSafetyCheck: options.onSafetyCheck, customDataExtractor: options.customDataExtractor, }; if (typeof options.computer === 'function' || isComputerProvider(options.computer)) { computerInitializerMap.set(tool, options.computer); } return tool; } // Keeps per-tool cache of computer instances keyed by RunContext so each run gets its own instance. const computerCache = new WeakMap(); // Tracks the initializer so we do not overwrite the callable on the tool when we memoize the resolved instance. const computerInitializerMap = new WeakMap(); // Allows cleanup routines to find all resolved computer instances for a given run context. const computersByRunContext = new WeakMap(); function getComputerInitializer(tool) { const initializer = computerInitializerMap.get(tool); if (initializer) { return initializer; } if (typeof tool.computer === 'function' || isComputerProvider(tool.computer)) { computerInitializerMap.set(tool, tool.computer); return tool.computer; } return undefined; } function trackResolvedComputer(tool, runContext, resolved) { let resolvedByRun = computersByRunContext.get(runContext); if (!resolvedByRun) { resolvedByRun = new Map(); computersByRunContext.set(runContext, resolvedByRun); } resolvedByRun.set(tool, resolved); } /** * Returns a computer instance for the provided run context. Caches per run to avoid sharing across runs. * @internal */ async function resolveComputer(args) { const { tool, runContext } = args; // Cache instances per RunContext so a single Computer is not shared across simultaneous runs. const toolKey = tool; let perContext = computerCache.get(toolKey); if (!perContext) { perContext = new WeakMap(); computerCache.set(toolKey, perContext); } const cached = perContext.get(runContext); if (cached) { trackResolvedComputer(tool, runContext, cached); return cached.computer; } const initializerConfig = getComputerInitializer(tool); const lifecycle = initializerConfig && isComputerProvider(initializerConfig) ? initializerConfig : isComputerProvider(tool.computer) ? tool.computer : undefined; const initializer = typeof initializerConfig === 'function' ? initializerConfig : (lifecycle?.create ?? (typeof tool.computer === 'function' ? tool.computer : undefined)); const disposer = lifecycle?.dispose; const computer = initializer && typeof initializer === 'function' ? await initializer({ runContext }) : tool.computer; if (!computer) { throw new errors_1.UserError('The computer tool did not provide a computer instance.'); } const resolved = { computer, dispose: disposer, }; perContext.set(runContext, resolved); trackResolvedComputer(tool, runContext, resolved); tool.computer = computer; return computer; } /** * Disposes any computer instances created for the provided run context. * @internal */ async function disposeResolvedComputers({ runContext, }) { const resolvedByRun = computersByRunContext.get(runContext); if (!resolvedByRun) { return; } computersByRunContext.delete(runContext); const disposers = []; for (const [tool, resolved] of resolvedByRun.entries()) { const perContext = computerCache.get(tool); perContext?.delete(runContext); const storedInitializer = getComputerInitializer(tool); if (storedInitializer) { tool.computer = storedInitializer; } if (resolved.dispose) { disposers.push(async () => { await resolved.dispose?.({ runContext, computer: resolved.computer }); }); } } for (const dispose of disposers) { try { await dispose(); } catch (error) { (0, logger_1.logToolActionWarning)(logger_1.default, 'Failed to dispose computer for run context:', error); } } } function normalizeShellToolSkillReference(skill) { if (!skill.skillId) { throw new errors_1.UserError('shellTool skill_reference requires a skillId.'); } return skill; } function normalizeShellToolInlineSkill(skill) { const sourceCandidate = skill.source; if (!sourceCandidate || typeof sourceCandidate !== 'object') { throw new errors_1.UserError('shellTool inline skill source is required.'); } const source = sourceCandidate; if (source.mediaType !== 'application/zip') { throw new errors_1.UserError('shellTool inline skill source.mediaType must be application/zip.'); } return { type: 'inline', name: skill.name, description: skill.description, source: { type: 'base64', data: source.data, mediaType: source.mediaType, }, }; } function normalizeShellToolContainerSkill(skill) { if (skill.type === 'skill_reference') { return normalizeShellToolSkillReference(skill); } return normalizeShellToolInlineSkill(skill); } function normalizeShellToolContainerNetworkPolicy(policy) { if (!policy) { return undefined; } if (policy.type === 'disabled') { return policy; } return { type: 'allowlist', allowedDomains: policy.allowedDomains, domainSecrets: policy.domainSecrets, }; } function normalizeShellToolEnvironment(environment) { if (!environment || environment.type === 'local') { return environment ?? { type: 'local' }; } if (environment.type === 'container_auto') { return { type: 'container_auto', fileIds: environment.fileIds, memoryLimit: environment.memoryLimit, networkPolicy: normalizeShellToolContainerNetworkPolicy(environment.networkPolicy), skills: environment.skills?.map(normalizeShellToolContainerSkill), }; } const containerId = environment.containerId; if (!containerId) { throw new errors_1.UserError('shellTool with container_reference environment requires a containerId.'); } return { type: 'container_reference', containerId, }; } function shellTool(options) { const environment = normalizeShellToolEnvironment(options.environment); const allowedCallers = (0, toolCallers_1.normalizeToolAllowedCallers)(options.allowedCallers, options.name ?? 'shell'); const needsApproval = typeof options.needsApproval === 'function' ? options.needsApproval : async () => typeof options.needsApproval === 'boolean' ? options.needsApproval : false; if (environment.type === 'local') { const localShell = options.shell; if (!localShell) { throw new errors_1.UserError('shellTool with local environment requires a shell implementation.'); } return { type: 'shell', name: options.name ?? 'shell', environment, shell: localShell, needsApproval, onApproval: options.onApproval, ...(allowedCallers ? { allowedCallers } : {}), }; } if (typeof options.shell !== 'undefined') { throw new errors_1.UserError('shellTool with hosted environment does not accept a shell implementation.'); } if (typeof options.needsApproval !== 'undefined' || typeof options.onApproval !== 'undefined') { throw new errors_1.UserError('shellTool with hosted environment does not support needsApproval or onApproval.'); } return { type: 'shell', name: options.name ?? 'shell', environment, needsApproval, ...(allowedCallers ? { allowedCallers } : {}), }; } function applyPatchTool(options) { const name = options.name ?? 'apply_patch'; const allowedCallers = (0, toolCallers_1.normalizeToolAllowedCallers)(options.allowedCallers, name); const needsApproval = typeof options.needsApproval === 'function' ? options.needsApproval : async () => typeof options.needsApproval === 'boolean' ? options.needsApproval : false; return { type: 'apply_patch', name, editor: options.editor, needsApproval, onApproval: options.onApproval, ...(allowedCallers ? { allowedCallers } : {}), customDataExtractor: options.customDataExtractor, }; } /** * Creates a hosted MCP tool definition. * * @param options - Configuration for the hosted MCP tool, including server connection details * and approval requirements. */ function hostedMcpTool(options) { const allowedCallers = (0, toolCallers_1.normalizeToolAllowedCallers)(options.allowedCallers, options.serverLabel); const providerAllowedCallers = allowedCallers ? [...allowedCallers] : undefined; if ('serverUrl' in options) { // the MCP servers compatible with the specification const providerData = typeof options.requireApproval === 'undefined' || options.requireApproval === 'never' ? { type: 'mcp', server_label: options.serverLabel, server_url: options.serverUrl, authorization: options.authorization, require_approval: 'never', allowed_tools: toMcpAllowedToolsFilter(options.allowedTools), allowed_callers: providerAllowedCallers, defer_loading: options.deferLoading, headers: options.headers, server_description: options.serverDescription, } : { type: 'mcp', server_label: options.serverLabel, server_url: options.serverUrl, authorization: options.authorization, allowed_tools: toMcpAllowedToolsFilter(options.allowedTools), allowed_callers: providerAllowedCallers, defer_loading: options.deferLoading, headers: options.headers, require_approval: buildRequireApproval(options.requireApproval), on_approval: options.onApproval, server_description: options.serverDescription, }; return { type: 'hosted_tool', name: 'hosted_mcp', providerData, }; } else if ('connectorId' in options) { // OpenAI's connectors const providerData = typeof options.requireApproval === 'undefined' || options.requireApproval === 'never' ? { type: 'mcp', server_label: options.serverLabel, connector_id: options.connectorId, authorization: options.authorization, require_approval: 'never', allowed_tools: toMcpAllowedToolsFilter(options.allowedTools), allowed_callers: providerAllowedCallers, defer_loading: options.deferLoading, headers: options.headers, server_description: options.serverDescription, } : { type: 'mcp', server_label: options.serverLabel, connector_id: options.connectorId, authorization: options.authorization, allowed_tools: toMcpAllowedToolsFilter(options.allowedTools), allowed_callers: providerAllowedCallers, defer_loading: options.deferLoading, headers: options.headers, require_approval: buildRequireApproval(options.requireApproval), on_approval: options.onApproval, server_description: options.serverDescription, }; return { type: 'hosted_tool', name: 'hosted_mcp', providerData, }; } else { // the MCP servers compatible with the specification const providerData = typeof options.requireApproval === 'undefined' || options.requireApproval === 'never' ? { type: 'mcp', server_label: options.serverLabel, require_approval: 'never', allowed_tools: toMcpAllowedToolsFilter(options.allowedTools), allowed_callers: providerAllowedCallers, defer_loading: options.deferLoading, server_description: options.serverDescription, } : { type: 'mcp', server_label: options.serverLabel, allowed_tools: toMcpAllowedToolsFilter(options.allowedTools), allowed_callers: providerAllowedCallers, defer_loading: options.deferLoading, require_approval: buildRequireApproval(options.requireApproval), on_approval: options.onApproval, server_description: options.serverDescription, }; return { type: 'hosted_tool', name: 'hosted_mcp', providerData, }; } } exports.CLIENT_TOOL_SEARCH_EXECUTOR = Symbol('clientToolSearchExecutor'); function attachClientToolSearchExecutor(tool, executor) { Object.defineProperty(tool, exports.CLIENT_TOOL_SEARCH_EXECUTOR, { value: executor, enumerable: false, configurable: true, }); return tool; } function getClientToolSearchExecutor(tool) { if (tool.type !== 'hosted_tool') { return undefined; } return tool[exports.CLIENT_TOOL_SEARCH_EXECUTOR]; } function getToolSearchRuntimeToolKey(tool) { if (tool.type === 'function') { return (0, toolIdentity_1.getFunctionToolQualifiedName)(tool) ?? tool.name; } if (tool.type === 'hosted_tool' && tool.providerData?.type === 'mcp' && typeof tool.providerData.server_label === 'string' && tool.providerData.server_label.length > 0) { return `mcp:${tool.providerData.server_label}`; } return undefined; } /** @internal */ function getToolSearchRuntimeRoutingKey(tool) { if (tool.type === 'function') { return (0, toolIdentity_1.getFunctionToolLookupKeyForTool)(tool); } return getToolSearchRuntimeToolKey(tool); } const FUNCTION_TOOL_TIMEOUT_BEHAVIORS = [ 'error_as_result', 'raise_exception', ]; const FUNCTION_TOOL_TIMEOUT_ALREADY_ENFORCED = Symbol('functionToolTimeoutAlreadyEnforced'); /** * The default function to invoke when an error occurs while running the tool. * * Returns a fixed message without inspecting the exception. Provide a custom * `errorFunction` to return application-approved details to the model. */ function defaultToolErrorFunction() { return 'An error occurred while running the tool.'; } function defaultFunctionToolTimeoutErrorMessage(args) { return `Tool '${args.toolName}' timed out after ${args.timeoutMs}ms.`; } const MAX_FUNCTION_TOOL_TIMEOUT_MS = 2_147_483_647; function cloneObjectWithDescriptorsAndOverrides(value, overrides) { const descriptors = Object.getOwnPropertyDescriptors(value); for (const key of Reflect.ownKeys(overrides)) { delete descriptors[key]; } const clone = Object.create(Object.getPrototypeOf(value), descriptors); return Object.assign(clone, overrides); } function normalizeFunctionToolTimeoutConfig(args) { const { toolName, timeoutMs, timeoutBehavior, timeoutErrorFunction } = args; if (typeof timeoutMs !== 'undefined') { if (typeof timeoutMs !== 'number' || Number.isNaN(timeoutMs)) { throw new errors_1.UserError(`Function tool '${toolName}' timeoutMs must be a finite number in milliseconds.`); } if (!Number.isFinite(timeoutMs)) { throw new errors_1.UserError(`Function tool '${toolName}' timeoutMs must be finite.`); } if (timeoutMs <= 0) { throw new errors_1.UserError(`Function tool '${toolName}' timeoutMs must be greater than 0.`); } if (timeoutMs > MAX_FUNCTION_TOOL_TIMEOUT_MS) { throw new errors_1.UserError(`Function tool '${toolName}' timeoutMs must be less than or equal to ${MAX_FUNCTION_TOOL_TIMEOUT_MS}.`); } } const resolvedBehavior = timeoutBehavior ?? 'error_as_result'; if (!FUNCTION_TOOL_TIMEOUT_BEHAVIORS.includes(resolvedBehavior)) { throw new errors_1.UserError(`Function tool '${toolName}' timeoutBehavior must be one of: ${FUNCTION_TOOL_TIMEOUT_BEHAVIORS.join(', ')}.`); } if (typeof timeoutErrorFunction !== 'undefined' && typeof timeoutErrorFunction !== 'function') { throw new errors_1.UserError(`Function tool '${toolName}' timeoutErrorFunction must be a function when provided.`); } return { timeoutMs, timeoutBehavior: resolvedBehavior, timeoutErrorFunction, }; } async function invokeFunctionToolWithTimeout(args) { const { toolName, invoke, runContext, input, details, timeoutMs: configuredTimeoutMs, timeoutBehavior: configuredTimeoutBehavior, timeoutErrorFunction: configuredTimeoutErrorFunction, } = args; const { timeoutMs, timeoutBehavior, timeoutErrorFunction } = normalizeFunctionToolTimeoutConfig({ toolName, timeoutMs: configuredTimeoutMs, timeoutBehavior: configuredTimeoutBehavior, timeoutErrorFunction: configuredTimeoutErrorFunction, }); if (typeof timeoutMs === 'undefined') { return invoke(runContext, input, details); } let timeoutId; let timeoutTriggered = false; const timeoutController = new AbortController(); const { signal: invocationSignal, cleanup: cleanupAbortSignals } = (0, abortSignals_1.combineAbortSignals)(details?.signal, timeoutController.signal); const invokeDetails = invocationSignal ? details ? cloneObjectWithDescriptorsAndOverrides(details, { signal: invocationSignal, }) : { signal: invocationSignal } : details; copyFunctionToolPreparedInput(details, invokeDetails); const timeoutError = new errors_1.ToolTimeoutError({ toolName, timeoutMs, }); let invocationPromise; try { invocationPromise = Promise.resolve(invoke(runContext, input, invokeDetails)); return await Promise.race([ invocationPromise, new Promise((_, reject) => { timeoutId = setTimeout(() => { timeoutTriggered = true; reject(timeoutError); timeoutController.abort(timeoutError); }, timeoutMs); }), ]); } catch (error) { const isTimeoutError = error === timeoutError || (timeoutTriggered && timeoutController.signal.reason === timeoutError); if (!isTimeoutError) { throw error; } const siblingCancellationSignal = details?.signal; if (siblingCancellationSignal && (0, abortSignals_1.isSiblingCancellationSignal)(siblingCancellationSignal)) { throw siblingCancellationSignal.reason; } if (timeoutBehavior === 'raise_exception') { throw timeoutError; } if (timeoutErrorFunction) { try { return await timeoutErrorFunction(runContext, timeoutError, details); } catch (error) { const invalidOutputFailure = (0, toolOutputError_1.getInvalidToolOutputFailure)(error); if (invalidOutputFailure) { details?.[exports.FUNCTION_TOOL_INVALID_OUTPUT_FAILURE_CALLBACK]?.(invalidOutputFailure); if ((0, toolOutputError_1.refreshInvalidToolOutputFailure)(invalidOutputFailure)) { throw invalidOutputFailure.error; } } throw error; } } return defaultFunctionToolTimeoutErrorMessage({ toolName, timeoutMs, }); } finally { if (typeof timeoutId !== 'undefined') { clearTimeout(timeoutId); } cleanupAbortSignals(); } } /** * Validate a function tool output when the tool was created with a runtime * output schema. */ function validateFunctionToolOutput(args) { const validator = args.tool[FUNCTION_TOOL_OUTPUT_VALIDATOR]; if (!validator) { return args.output; } return validator(args.output, args.runContext, args.details); } /** * Invoke a function tool while enforcing optional per-tool timeout settings. */ async function invokeFunctionTool(args) { const { tool, runContext, input, details } = args; const invokeWithTimeoutFlag = (invocationRunContext, invocationInput, invocationDetails) => { const detailsWithFlag = typeof invocationDetails === 'undefined' ? undefined : cloneObjectWithDescriptorsAndOverrides(invocationDetails, { [FUNCTION_TOOL_TIMEOUT_ALREADY_ENFORCED]: true, }); copyFunctionToolPreparedInput(invocationDetails, detailsWithFlag); return tool.invoke(invocationRunContext, invocationInput, detailsWithFlag); }; return invokeFunctionToolWithTimeout({ toolName: tool.name, invoke: invokeWithTimeoutFlag, runContext, input, details, timeoutMs: tool.timeoutMs, timeoutBehavior: tool.timeoutBehavior, timeoutErrorFunction: tool.timeoutErrorFunction, }); } /** * Exposes a function to the agent as a tool to be called * * @param options The options for the tool * @returns A new tool */ function tool(options) { const name = options.name ? (0, tools_1.toFunctionToolName)(options.name) : (0, tools_1.toFunctionToolName)(options.execute.name); if (!name) { throw new Error('Tool name cannot be empty. Either name your function or provide a name in the options.'); } const strictMode = options.strict ?? true; if (!strictMode && (0, typeGuards_1.isZodObject)(options.parameters)) { throw new errors_1.UserError('Strict mode is required for Zod parameters'); } if (!strictMode && (0, standardSchema_1.isStandardSchemaWithJSON)(options.parameters)) { throw new errors_1.UserError('Strict mode is required for Standard Schema parameters'); } const hasOutputSchema = typeof options.outputSchema !== 'undefined'; const toolErrorFunction = typeof options.errorFunction === 'undefined' ? hasOutputSchema ? null : defaultToolErrorFunction : options.errorFunction; const { timeoutMs, timeoutBehavior, timeoutErrorFunction: configuredTimeoutErrorFunction, } = normalizeFunctionToolTimeoutConfig({ toolName: name, timeoutMs: options.timeoutMs, timeoutBehavior: options.timeoutBehavior ?? (hasOutputSchema ? 'raise_exception' : undefined), timeoutErrorFunction: options.timeoutErrorFunction, }); if (hasOutputSchema && timeoutBehavior === 'error_as_result' && !configuredTimeoutErrorFunction) { throw new errors_1.UserError(`Function tool '${name}' with an output schema requires timeoutErrorFunction when timeoutBehavior is 'error_as_result'.`); } const allowedCallers = (0, toolCallers_1.normalizeToolAllowedCallers)(options.allowedCallers, name); const { parser, schema: parameters } = (0, tools_2.getSchemaAndParserFromInputType)(options.parameters, name, { strict: strictMode }); const inputParserToken = {}; const zodOutputSchema = (0, typeGuards_1.isZodObject)(options.outputSchema) ? options.outputSchema : undefined; const outputSchema = zodOutputSchema ? (0, tools_2.getSchemaAndParserFromInputType)(zodOutputSchema, `${name}_output`, { strict: true, }).schema : options.outputSchema; function validateOutput(output, runContext, details) { if (!zodOutputSchema) { return output; } try { return zodOutputSchema.parse(output); } catch (error) { throw (0, toolOutputError_1.createInvalidToolOutputError)(`Invalid output for function tool '${name}'.`, error, { runContext, output, details }); } } const timeoutErrorFunction = configuredTimeoutErrorFunction ? async (runContext, error, details) => validateOutput(await configuredTimeoutErrorFunction(runContext, error, details), runContext, details) : undefined; async function _invoke(runContext, input, details) { const preparedInput = details ? functionToolPreparedInputs.get(details) : undefined; const canUsePreparedInput = preparedInput !== undefined && !preparedInput.consumed && preparedInput.input === input && preparedInput.token === inputParserToken; if (canUsePreparedInput) { preparedInput.consumed = true; } const parseResult = canUsePreparedInput && preparedInput ? preparedInput.result : parseFunctionToolInput(parser, input); if (!parseResult.success) { // supply the same context as options.execute for consuming // downstream code to implement self-healing and/or tracing const failure = (0, toolInputError_1.createInvalidToolInputFailure)({ message: 'Invalid JSON input for tool', originalError: parseResult.error, toolInvocation: { runContext, input, details }, disposition: canUsePreparedInput && preparedInput ? preparedInput.disposition : undefined, fatal: (0, standardSchema_1.isAsyncStandardSchemaValidationError)(parseResult.error), }); if (failure.redacted || logger_1.default.dontLogToolData) { (0, toolInputError_1.refreshInvalidToolInputFailure)(failure); logger_1.default.debug(`Invalid JSON input for tool ${name}`); } else { logger_1.default.debug(`Invalid JSON input for tool ${name}: ${input}`); } throw failure.error; } const parsed = parseResult.value; if (logger_1.default.dontLogToolData) { logger_1.default.debug(`Invoking tool ${name}`); } else { logger_1.default.debug(`Invoking tool ${name} with input ${input}`); } details?.[exports.FUNCTION_TOOL_PARSED_INPUT_CALLBACK]?.(parsed); const result = validateOutput(await options.execute(parsed, runContext, details), runContext, details); const stringResult = (0, smartString_1.toSmartString)(result); if (logger_1.default.dontLogToolData) { logger_1.default.debug(`Tool ${name} completed`); } else { logger_1.default.debug(`Tool ${name} returned: ${stringResult}`); } return result; } async function invokeWithoutTimeout(runContext, input, details) { return _invoke(runContext, input, details).catch(async (error) => { if (details?.signal?.aborted && ((0, abortSignals_1.isSiblingCancellationSignal)(details.signal) || error === details.signal.reason || (0, abortSignals_1.isAbortError)(error) || details.signal.reason instanceof errors_1.ToolTimeoutError)) { throw error; } if ((0, toolInputError_1.getInvalidToolInputFailure)(error)?.fatal) { throw error; } return resolveToolFailure(runContext, error, details); }); } async function resolveToolFailure(runContext, error, details) { const invalidOutputFailure = (0, toolOutputError_1.getInvalidToolOutputFailure)(error); if (invalidOutputFailure) { details?.[exports.FUNCTION_TOOL_INVALID_OUTPUT_FAILURE_CALLBACK]?.(invalidOutputFailure); } if (!toolErrorFunction) { if (invalidOutputFailure && (0, toolOutputError_1.refreshInvalidToolOutputFailure)(invalidOutputFailure)) { throw invalidOutputFailure.error; } throw error; } const invalidInputFailure = (0, toolInputError_1.getInvalidToolInputFailure)(error); const redactedInputBeforeCallback = invalidInputFailure ? (0, toolInputError_1.refreshInvalidToolInputFailure)(invalidInputFailure) : (0, toolInputError_1.isRedactedInvalidToolInputError)(error); const redactedOutputBeforeCallback = invalidOutputFailure ? (0, toolOutputError_1.refreshInvalidToolOutputFailure)(invalidOutputFailure) : (0, toolOutputError_1.isRedactedInvalidToolOutputError)(error); const redactedBeforeCallback = redactedInputBeforeCallback || redactedOutputBeforeCallback; const callbackError = invalidInputFailure?.error ?? invalidOutputFailure?.error ?? error; const errorDetails = redactedBeforeCallback ? undefined : details; const currentSpan = (0, tracing_1.getCurrentSpan)(); const includeErrorDetails = toolErrorFunction !== defaultToolErrorFunction && !redactedBeforeCallback && (0, functionToolTracing_1.includesFunctionToolErrorDetails)(details); currentSpan?.setError({ message: 'Error running tool (non-fatal)', data: { tool_name: name, error: includeErrorDetails ? callbackError.toString() : functionToolTracing_1.REDACTED_TOOL_ERROR_MESSAGE, }, }); try { const output = await toolErrorFunction(runContext, callbackError, errorDetails); if (invalidInputFailure && !redactedInputBeforeCallback && (0, toolInputError_1.refreshInvalidToolInputFailure)(invalidInputFailure)) { throw invalidInputFailure.error; } if (invalidOutputFailure && !redactedOutputBeforeCallback && (0, toolOutputError_1.refreshInvalidToolOutputFailure)(invalidOutputFailure)) { throw invalidOutputFailure.error; } const validatedOutput = validateOutput(output, runContext, errorDetails); if (invalidInputFailure && !redactedInputBeforeCallback && (0, toolInputError_1.refreshInvalidToolInputFailure)(invalidInputFailure)) { throw invalidInputFailure.error; } if (invalidOutputFailure && !redactedOutputBeforeCallback && (0, toolOutputError_1.refreshInvalidToolOutputFailure)(invalidOutputFailure)) { throw invalidOutputFailure.error; } return validatedOutput; } catch (callbackFailure) { if (invalidInputFailure && (0, toolInputError_1.refreshInvalidToolInputFailure)(invalidInputFailure)) { throw invalidInputFailure.error; } if (invalidOutputFailure && (0, toolOutputError_1.refreshInvalidToolOutputFailure)(invalidOutputFailure)) { throw invalidOutputFailure.error; } const callbackInvalidOutputFailure = (0, toolOutputError_1.getInvalidToolOutputFailure)(callbackFailure); if (callbackInvalidOutputFailure) { details?.[exports.FUNCTION_TOOL_INVALID_OUTPUT_FAILURE_CALLBACK]?.(callbackInvalidOutputFailure); if ((0, toolOutputError_1.refreshInvalidToolOutputFailure)(callbackInvalidOutputFailure)) { throw callbackInvalidOutputFailure.error; } } throw callbackFailure; } } async function invoke(runContext, input, details) { const detailsWithFlag = details; if (detailsWithFlag?.[FUNCTION_TOOL_TIMEOUT_ALREADY_ENFORCED]) { return invokeWithoutTimeout(runContext, input, details); } return invokeFunctionToolWithTimeout({ toolName: name, invoke: invokeWithoutTimeout, runContext, input, details, timeoutMs, timeoutBehavior, timeoutErrorFunction, }); } const needsApproval = typeof options.needsApproval === 'function' ? options.needsApproval : async () => typeof options.needsApproval === 'boolean' ? options.needsApproval : false; if (typeof options.needsApproval !== 'function') { STATIC_FUNCTION_TOOL_APPROVAL_POLICIES.add(needsApproval); } functionToolInputParsers.set(invoke, { parser, token: inputParserToken, validationMode: !(0, typeGuards_1.isZodObject)(options.parameters) && (0, standardSchema_1.isStandardSchemaWithJSON)(options.parameters) ? 'standard' : 'other', }); const isEnabled = typeof options.isEnabled === 'function' ? async (runContext, agent) => { const predicate = options.isEnabled; const result = await predicate({ runContext, agent }); return Boolean(result); } : async () => typeof options.isEnabled === 'boolean' ? options.isEnabled : true; return { type: 'function', name, description: options.description, parameters, strict: strictMode, deferLoading: options.deferLoading ?? false, providerData: options.providerData, ...(allowedCallers ? { allowedCallers } : {}), ...(outputSchema ? { outputSchema } : {}), invoke, ...(hasOutputSchema ? { errorFunction: toolErrorFunction, } : {}), needsApproval, timeoutMs, timeoutBehavior, timeoutErrorFunction, isEnabled, inputGuardrails: (0, toolGuardrail_1.resolveToolInputGuardrails)(options.inputGuardrails), outputGuardrails: (0, toolGuardrail_1.resolveToolOutputGuardrails)(options.outputGuardrails), customDataExtractor: options.customDataExtractor, ...(zodOutputSchema ? { [FUNCTION_TOOL_OUTPUT_VALIDATOR]: validateOutput } : {}), }; } /** * Responses API only. Group function tools under a shared namespace. * * @param options - Namespace metadata and function tools to attach. * @returns shallow-cloned function tools carrying namespace metadata. */ function toolNamespace(options) { if (typeof options !== 'object' || options === null) { throw new errors_1.UserError('toolNamespace() requires a namespace config object.'); } const { name, description, tools } = options; if (typeof name !== 'string' || name.trim().length === 0) { throw new errors_1.UserError('toolNamespace() requires a non-empty namespace name.'); } if (typeof description !== 'string' || description.trim().length === 0) { throw new errors_1.UserError('toolNamespace() requires a non-empty description because the Responses API requires namespace descriptions.'); } if (!Array.isArray(tools)) { throw new errors_1.UserError('toolNamespace() requires an array of function tools.'); } if (tools.some((tool) => tool?.type !== 'function')) { throw new errors_1.UserError('toolNamespace() only supports FunctionTool instances.'); } const namespaceName = (0, tools_1.toFunctionToolName)(name.trim()); if (tools.some((tool) => tool.name === namespaceName)) { throw new errors_1.UserError(`toolNamespace() does not allow a tool named "${namespaceName}" inside namespace "${namespaceName}" because Responses self-namespaced calls would be ambiguous.`); } const normalizedDescription = description.trim(); return tools.map((tool) => cloneObjectWithDescriptorsAndOverrides(tool, { [toolIdentity_1.FUNCTION_TOOL_NAMESPACE]: namespaceName, [toolIdentity_1.FUNCTION_TOOL_NAMESPACE_DESCRIPTION]: normalizedDescription, })); } function buildRequireApproval(requireApproval) { const normalized = (0, mcpApproval_1.normalizeHostedMcpRequireApproval)(requireApproval); if (normalized === 'never') { throw new errors_1.UserError('Invalid hosted MCP requireApproval: approval-required branch cannot normalize to "never".'); } return normalized; } function toMcpAllowedToolsFilter(allowedTools) { if (typeof allowedTools === 'undefined') { return undefined; } if (Array.isArray(allowedTools)) { return { tool_names: allowedTools }; } return { tool_names: allowedTools?.toolNames ?? [] }; } //# sourceMappingURL=tool.js.map