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
6 changes: 6 additions & 0 deletions .changeset/two-squids-smell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@openai/agents-openai': patch
'@openai/agents-core': patch
---

Add a quick opt-in option to switch to gpt-5
3 changes: 2 additions & 1 deletion examples/basic/hello-world-gpt-5.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ async function main() {
outputType: output,
});

const prompt = 'Tell me about recursion in programming.';
const prompt =
'Tell me about recursion in programming. Quickly responding with a single answer is fine.';
const result = await run(agent, prompt);
console.log(result.finalOutput);

Expand Down
5 changes: 4 additions & 1 deletion examples/basic/hello-world.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ async function main() {
instructions: 'You only respond in haikus.',
});

const result = await run(agent, 'Tell me about recursion in programming.');
const result = await run(
agent,
'Tell me about recursion in programming. Quickly responding with a single answer is fine.',
);
console.log(result.finalOutput);
// Example output:
// Function calls itself,
Expand Down
5 changes: 4 additions & 1 deletion examples/basic/reasoning.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ const THINKING_PREFIX = styleText(['bgGray', 'black'], 'Thought');
async function main() {
const agent = new Agent({
name: 'Agent',
model: 'o3',
model: 'gpt-5',
modelSettings: {
providerData: {
reasoning: {
effort: 'high',
summary: 'auto',
},
text: {
verbosity: 'high',
},
},
},
});
Expand Down
5 changes: 3 additions & 2 deletions examples/financial-research-agent/agents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export type FinancialSearchPlan = z.infer<typeof FinancialSearchPlan>;
export const plannerAgent = new Agent({
name: 'FinancialPlannerAgent',
instructions: plannerPrompt,
model: 'o3-mini',
model: 'gpt-5-mini',
outputType: FinancialSearchPlan,
});

Expand All @@ -69,6 +69,7 @@ Focus on key numbers, events, or quotes that will be useful to a financial analy
export const searchAgent = new Agent({
name: 'FinancialSearchAgent',
instructions: searchAgentPrompt,
model: 'gpt-4.1',
tools: [webSearchTool()],
modelSettings: { toolChoice: 'required' },
});
Expand All @@ -92,7 +93,7 @@ export type VerificationResult = z.infer<typeof VerificationResult>;
export const verifierAgent = new Agent({
name: 'VerificationAgent',
instructions: verifierPrompt,
model: 'gpt-4o',
model: 'gpt-4.1',
outputType: VerificationResult,
});

Expand Down
7 changes: 7 additions & 0 deletions examples/handoffs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
HandoffInputData,
handoff,
withTrace,
isGpt5Default,
} from '@openai/agents';
import { removeAllTools } from '@openai/agents-core/extensions';
import { z } from 'zod';
Expand All @@ -23,6 +24,12 @@ const randomNumberTool = tool({

// Message filter for handoff (removes tool messages and first two history items)
function spanishHandoffMessageFilter(handoffMessageData: HandoffInputData) {
if (isGpt5Default()) {
console.log(
'GPT-5 models do not work if you remove the toll call results, so this filter does nothing.',
);
return handoffMessageData;
}
// Remove all tool-related messages
return removeAllTools(handoffMessageData);
}
Expand Down
3 changes: 2 additions & 1 deletion examples/mcp/hosted-mcp-human-in-the-loop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ async function main(verbose: boolean, stream: boolean): Promise<void> {
};
const agent = new Agent({
name: 'MCP Assistant',
instructions: 'You must always use the MCP tools to answer questions.',
instructions:
'You must always use the MCP tools to answer questions. The mcp server knows which repo to investigate, so you do not need to ask the user about it.',
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gpt-5 models tend to be confused with this MCP server tools' rule (having the repo name in the MCP server URL), so added additional instructions. This works for both gpt-4 and gpt-5.

tools: [
hostedMcpTool({
serverLabel: 'gitmcp',
Expand Down
3 changes: 2 additions & 1 deletion examples/mcp/hosted-mcp-on-approval.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ async function main(verbose: boolean, stream: boolean): Promise<void> {
};
const agent = new Agent({
name: 'MCP Assistant',
instructions: 'You must always use the MCP tools to answer questions.',
instructions:
'You must always use the MCP tools to answer questions. The mcp server knows which repo to investigate, so you do not need to ask the user about it.',
tools: [
hostedMcpTool({
serverLabel: 'gitmcp',
Expand Down
3 changes: 2 additions & 1 deletion examples/mcp/hosted-mcp-simple.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ async function main(verbose: boolean, stream: boolean): Promise<void> {
withTrace('Hosted MCP Example', async () => {
const agent = new Agent({
name: 'MCP Assistant',
instructions: 'You must always use the MCP tools to answer questions.',
instructions:
'You must always use the MCP tools to answer questions. The mcp server knows which repo to investigate, so you do not need to ask the user about it.',
tools: [
hostedMcpTool({
serverLabel: 'gitmcp',
Expand Down
49 changes: 0 additions & 49 deletions examples/mcp/streamable-http-custom-fetch-example.ts

This file was deleted.

2 changes: 1 addition & 1 deletion examples/mcp/streamable-http-example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ async function main() {
await mcpServer.connect();
const result = await run(
agent,
'Which language is this repo written in?',
'Which language is this repo written in? The MCP server knows which repo to investigate.',
);
console.log(result.finalOutput);
});
Expand Down
3 changes: 2 additions & 1 deletion examples/model-providers/custom-example-agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const getWeatherTool = tool({
description: 'Get the weather for a given city',
parameters: z.object({ city: z.string() }),
execute: async (input) => {
console.log(`[debug] Getting weather for ${input.city}\n`);
return `The weather in ${input.city} is sunny`;
},
});
Expand All @@ -28,7 +29,7 @@ const agent = new Agent({
async function main() {
await withTrace('ChatCompletions Assistant Example', async () => {
const result = await run(agent, "What's the weather in Tokyo?");
console.log(`\n\nFinal response:\n${result.finalOutput}`);
console.log(`[Final response]\n${result.finalOutput}`);
});
}

Expand Down
23 changes: 22 additions & 1 deletion examples/tools/file-search.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,32 @@
import { Agent, run, fileSearchTool, withTrace } from '@openai/agents';
import OpenAI, { toFile } from 'openai';

async function main() {
const client = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});

const text = `Arrakis, the desert planet in Frank Herbert's "Dune," was inspired by the scarcity of water
as a metaphor for oil and other finite resources.`;
const upload = await client.files.create({
file: await toFile(Buffer.from(text, 'utf-8'), 'cafe.txt'),
purpose: 'assistants',
});
const vectorStore = await client.vectorStores.create({
name: 'Arrakis',
});
console.log(vectorStore);
const indexed = await client.vectorStores.files.createAndPoll(
vectorStore.id,
{ file_id: upload.id },
);
console.log(indexed);

const agent = new Agent({
name: 'File searcher',
instructions: 'You are a helpful agent.',
tools: [
fileSearchTool(['vs_67bf88953f748191be42b462090e53e7'], {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replaced a specific vector store id

fileSearchTool([vectorStore.id], {
maxNumResults: 3,
includeSearchResults: true,
}),
Expand Down
2 changes: 1 addition & 1 deletion examples/tools/image-generation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ async function main() {
console.log('Generating image, this may take a while...');
const result = await run(
agent,
'Create an image of a frog eating a pizza, comic book style.',
'Create an image of a frog eating a pizza, comic book style. Return a text description of the image as a message too.',
);
console.log(result.finalOutput);

Expand Down
30 changes: 27 additions & 3 deletions packages/agents-core/src/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import type { InputGuardrail, OutputGuardrail } from './guardrail';
import { AgentHooks } from './lifecycle';
import { getAllMcpTools, type MCPServer } from './mcp';
import type { Model, ModelSettings, Prompt } from './model';
import {
getDefaultModelSettings,
gpt5ReasoningSettingsRequired,
isGpt5Default,
} from './defaultModel';
import type { RunContext } from './runContext';
import {
type FunctionTool,
Expand Down Expand Up @@ -165,8 +170,10 @@ export interface AgentConfiguration<
handoffOutputTypeWarningEnabled?: boolean;

/**
* The model implementation to use when invoking the LLM. By default, if not set, the agent will
* use the default model configured in modelSettings.defaultModel
* The model implementation to use when invoking the LLM.
*
* By default, if not set, the agent will use the default model returned by
* getDefaultModel (currently "gpt-4.1").
*/
model: string | Model;

Expand Down Expand Up @@ -348,7 +355,7 @@ export class Agent<
this.handoffDescription = config.handoffDescription ?? '';
this.handoffs = config.handoffs ?? [];
this.model = config.model ?? '';
this.modelSettings = config.modelSettings ?? {};
this.modelSettings = config.modelSettings ?? getDefaultModelSettings();
this.tools = config.tools ?? [];
this.mcpServers = config.mcpServers ?? [];
this.inputGuardrails = config.inputGuardrails ?? [];
Expand All @@ -359,6 +366,23 @@ export class Agent<
this.toolUseBehavior = config.toolUseBehavior ?? 'run_llm_again';
this.resetToolChoice = config.resetToolChoice ?? true;

if (
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I image reviewers may think "Is this necessary?" but it's necessary for smoother developer experience. See also: openai/openai-agents-python#1534

// The user sets a non-default model
config.model !== undefined &&
// The default model is gpt-5
isGpt5Default() &&
// However, the specified model is not a gpt-5 model
(typeof config.model !== 'string' ||
!gpt5ReasoningSettingsRequired(config.model)) &&
// The model settings are not customized for the specified model
config.modelSettings === undefined
) {
// In this scenario, we should use a generic model settings
// because non-gpt-5 models are not compatible with the default gpt-5 model settings.
// This is a best-effort attempt to make the agent work with non-gpt-5 models.
this.modelSettings = {};
}

// --- Runtime warning for handoff output type compatibility ---
if (
config.handoffOutputTypeWarningEnabled === undefined ||
Expand Down
56 changes: 56 additions & 0 deletions packages/agents-core/src/defaultModel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { loadEnv } from './config';
import { ModelSettings } from './model';

export const OPENAI_DEFAULT_MODEL_ENV_VARIABLE_NAME = 'OPENAI_DEFAULT_MODEL';

/**
* Returns True if the model name is a GPT-5 model and reasoning settings are required.
*/
export function gpt5ReasoningSettingsRequired(modelName: string): boolean {
if (modelName.startsWith('gpt-5-chat')) {
// gpt-5-chat-latest does not require reasoning settings
return false;
}
// matches any of gpt-5 models
return modelName.startsWith('gpt-5');
}

/**
* Returns True if the default model is a GPT-5 model.
* This is used to determine if the default model settings are compatible with GPT-5 models.
* If the default model is not a GPT-5 model, the model settings are compatible with other models.
*/
export function isGpt5Default(): boolean {
return gpt5ReasoningSettingsRequired(getDefaultModel());
}

/**
* Returns the default model name.
*/
export function getDefaultModel(): string {
const env = loadEnv();
return (
env[OPENAI_DEFAULT_MODEL_ENV_VARIABLE_NAME]?.toLowerCase() ?? 'gpt-4.1'
);
}

/**
* Returns the default model settings.
* If the default model is a GPT-5 model, returns the GPT-5 default model settings.
* Otherwise, returns the legacy default model settings.
*/
export function getDefaultModelSettings(model?: string): ModelSettings {
const _model = model ?? getDefaultModel();
if (gpt5ReasoningSettingsRequired(_model)) {
return {
providerData: {
// We chose "low" instead of "minimal" because some of the built-in tools
// (e.g., file search, image generation, etc.) do not support "minimal"
// If you want to use "minimal" reasoning effort, you can pass your own model settings
reasoning: { effort: 'low' },
text: { verbosity: 'low' },
},
};
}
return {};
}
7 changes: 7 additions & 0 deletions packages/agents-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,13 @@ export {
SerializedTool,
SerializedOutputType,
} from './model';
export {
OPENAI_DEFAULT_MODEL_ENV_VARIABLE_NAME,
gpt5ReasoningSettingsRequired,
getDefaultModel,
getDefaultModelSettings,
isGpt5Default,
} from './defaultModel';
export { setDefaultModelProvider } from './providers';
export { RunResult, StreamedRunResult } from './result';
export {
Expand Down
Loading