Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/heavy-crabs-start.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@openai/agents-openai': patch
'@openai/agents-core': patch
'@openai/agents': patch
---

fix: ugprade openai package from v5 to v6
2 changes: 1 addition & 1 deletion packages/agents-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
"@modelcontextprotocol/sdk": "^1.17.2"
},
"dependencies": {
"openai": "^5.20.2",
"openai": "^6",
"debug": "^4.4.0"
},
"peerDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/agents-core/src/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const METADATA = {
"version": "0.2.0",
"versions": {
"@openai/agents-core": "0.2.0",
"openai": "^5.20.2"
"openai": "^6"
}
};

Expand Down
134 changes: 110 additions & 24 deletions packages/agents-core/src/utils/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,44 @@ import {
import type { ZodObjectLike } from './zodCompat';
import { asZodType } from './zodCompat';

// TypeScript struggles to infer the heavily generic types returned by the OpenAI
// helpers, so we provide minimal wrappers that sidestep the deep instantiation.
type MinimalParseableResponseTool = {
parameters: unknown;
$parseRaw: (input: string) => unknown;
};

type ZodResponsesFunctionOptions = {
name: string;
parameters: unknown;
function?: (...args: any[]) => unknown;
description?: string;
};

const zodResponsesFunctionCompat: (
options: ZodResponsesFunctionOptions,
) => MinimalParseableResponseTool = zodResponsesFunction as unknown as (
options: ZodResponsesFunctionOptions,
) => MinimalParseableResponseTool;

type MinimalParseableTextFormat = {
type: 'json_schema';
name: string;
strict?: boolean;
schema: unknown;
};

// The `.schema` payload is all we need, so a lightweight signature keeps the compiler happy.
const zodTextFormatCompat: (
zodObject: unknown,
name: string,
props?: unknown,
) => MinimalParseableTextFormat = zodTextFormat as unknown as (
zodObject: unknown,
name: string,
props?: unknown,
) => MinimalParseableTextFormat;

export type FunctionToolName = string & { __brand?: 'ToolName' } & {
readonly __pattern?: '^[a-zA-Z0-9_]+$';
};
Expand Down Expand Up @@ -63,31 +101,45 @@ export function getSchemaAndParserFromInputType<T extends ToolInputParameters>(
const parser = (input: string) => JSON.parse(input);

if (isZodObject(inputType)) {
const formattedFunction = zodResponsesFunction({
name,
parameters: asZodType(inputType),
function: () => {}, // empty function here to satisfy the OpenAI helper
description: '',
});
const useFallback = (originalError?: unknown) => {
const fallbackSchema = buildJsonSchemaFromZod(inputType);
if (fallbackSchema) {
return {
schema: fallbackSchema,
parser: (rawInput: string) => inputType.parse(JSON.parse(rawInput)),
};
}

const errorMessage =
originalError instanceof Error
? ` Upstream helper error: ${originalError.message}`
: '';

throw new UserError(
`Unable to convert the provided Zod schema to JSON Schema. Ensure that the \`zod\` package is available at runtime or provide a JSON schema object instead.${errorMessage}`,
);
};

let formattedFunction: MinimalParseableResponseTool;
try {
formattedFunction = zodResponsesFunctionCompat({
name,
parameters: asZodType(inputType),
function: () => {}, // empty function here to satisfy the OpenAI helper
description: '',
});
} catch (error) {
return useFallback(error);
}

if (hasJsonSchemaObjectShape(formattedFunction.parameters)) {
return {
schema: formattedFunction.parameters as JsonObjectSchema<any>,
parser: formattedFunction.$parseRaw,
};
}

const fallbackSchema = buildJsonSchemaFromZod(inputType);

if (fallbackSchema) {
return {
schema: fallbackSchema,
parser: (rawInput: string) => inputType.parse(JSON.parse(rawInput)),
};
}

throw new UserError(
'Unable to convert the provided Zod schema to JSON Schema. Ensure that the `zod` package is available at runtime or provide a JSON schema object instead.',
);
return useFallback();
} else if (typeof inputType === 'object' && inputType !== null) {
return {
schema: inputType,
Expand All @@ -109,13 +161,47 @@ export function convertAgentOutputTypeToSerializable(
}

if (isZodObject(outputType)) {
const output = zodTextFormat(asZodType(outputType), 'output');
return {
type: output.type,
name: output.name,
strict: output.strict || false,
schema: output.schema as JsonObjectSchema<any>,
const useFallback = (
existing?: MinimalParseableTextFormat,
originalError?: unknown,
): JsonSchemaDefinition => {
const fallbackSchema = buildJsonSchemaFromZod(outputType);
if (fallbackSchema) {
return {
type: existing?.type ?? 'json_schema',
name: existing?.name ?? 'output',
strict: existing?.strict ?? false,
schema: fallbackSchema,
};
}

const errorMessage =
originalError instanceof Error
? ` Upstream helper error: ${originalError.message}`
: '';

throw new UserError(
`Unable to convert the provided Zod schema to JSON Schema. Ensure that the \`zod\` package is available at runtime or provide a JSON schema object instead.${errorMessage}`,
);
};

let output: MinimalParseableTextFormat;
try {
output = zodTextFormatCompat(asZodType(outputType), 'output');
} catch (error) {
return useFallback(undefined, error);
}

if (hasJsonSchemaObjectShape(output.schema)) {
return {
type: output.type,
name: output.name,
strict: output.strict || false,
schema: output.schema as JsonObjectSchema<any>,
};
}

return useFallback(output);
}

return outputType;
Expand Down
50 changes: 50 additions & 0 deletions packages/agents-core/test/utils/tools.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { describe, it, expect } from 'vitest';
import {
toFunctionToolName,
getSchemaAndParserFromInputType,
convertAgentOutputTypeToSerializable,
} from '../../src/utils/tools';
import { z } from 'zod';
import { z as z4 } from 'zod/v4';
Expand Down Expand Up @@ -50,4 +51,53 @@ describe('utils/tools', () => {
UserError,
);
});

it('falls back to compat schema when the helper rejects optional fields', () => {
const zodSchema = z.object({
required: z.string(),
optional: z.number().optional(),
});
const res = getSchemaAndParserFromInputType(
zodSchema,
'tool-with-optional',
);
expect(res.schema).toEqual({
type: 'object',
properties: {
required: { type: 'string' },
optional: { type: 'number' },
},
required: ['required'],
additionalProperties: false,
$schema: 'http://json-schema.org/draft-07/schema#',
});
expect(res.parser('{"required":"ok"}')).toEqual({ required: 'ok' });
expect(res.parser('{"required":"ok","optional":2}')).toEqual({
required: 'ok',
optional: 2,
});
});

it('convertAgentOutputTypeToSerializable falls back when helper rejects optional fields', () => {
const zodSchema = z.object({
required: z.string(),
optional: z.number().optional(),
});
const res = convertAgentOutputTypeToSerializable(zodSchema);
expect(res).toEqual({
type: 'json_schema',
name: 'output',
strict: false,
schema: {
type: 'object',
properties: {
required: { type: 'string' },
optional: { type: 'number' },
},
required: ['required'],
additionalProperties: false,
$schema: 'http://json-schema.org/draft-07/schema#',
},
});
});
});
2 changes: 1 addition & 1 deletion packages/agents-openai/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"dependencies": {
"@openai/agents-core": "workspace:*",
"debug": "^4.4.0",
"openai": "^5.20.2"
"openai": "^6"
},
"scripts": {
"prebuild": "tsx ../../scripts/embedMeta.ts",
Expand Down
2 changes: 1 addition & 1 deletion packages/agents-openai/src/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const METADATA = {
"versions": {
"@openai/agents-openai": "0.2.0",
"@openai/agents-core": "workspace:*",
"openai": "^5.20.2"
"openai": "^6"
}
};

Expand Down
2 changes: 1 addition & 1 deletion packages/agents/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"@openai/agents-openai": "workspace:*",
"@openai/agents-realtime": "workspace:*",
"debug": "^4.4.0",
"openai": "^5.20.2"
"openai": "^6"
},
"keywords": [
"openai",
Expand Down
2 changes: 1 addition & 1 deletion packages/agents/src/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const METADATA = {
"@openai/agents-core": "workspace:*",
"@openai/agents-openai": "workspace:*",
"@openai/agents-realtime": "workspace:*",
"openai": "^5.20.2"
"openai": "^6"
}
};

Expand Down
20 changes: 10 additions & 10 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.