From 7965061021c32185c4be277e5dd8532c9aa6e115 Mon Sep 17 00:00:00 2001 From: Andrew Petersen Date: Sun, 8 Jun 2025 00:29:01 -0600 Subject: [PATCH 1/4] fix: TypeScript workarounds to get build working --- packages/agents-core/src/shims/shims-node.ts | 1 + packages/agents-extensions/src/aiSdk.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/agents-core/src/shims/shims-node.ts b/packages/agents-core/src/shims/shims-node.ts index 96a9aa4a..78198138 100644 --- a/packages/agents-core/src/shims/shims-node.ts +++ b/packages/agents-core/src/shims/shims-node.ts @@ -6,6 +6,7 @@ export { EventEmitter as RuntimeEventEmitter } from 'node:events'; declare global { interface ImportMeta { + // @ts-expect-error - env is not defined in the type env?: Record; } } diff --git a/packages/agents-extensions/src/aiSdk.ts b/packages/agents-extensions/src/aiSdk.ts index 2829ab46..5daf7e75 100644 --- a/packages/agents-extensions/src/aiSdk.ts +++ b/packages/agents-extensions/src/aiSdk.ts @@ -70,7 +70,7 @@ export function itemsToLanguageV1Messages( } if (c.type === 'input_image') { const url = new URL(c.image); - return { type: 'image', image: url }; + return { type: 'image', image: url as unknown as URL }; } if (c.type === 'input_file') { if (typeof c.file !== 'string') { From 40b5b50336a4ac86c494fd42f8840d4d1978c7f0 Mon Sep 17 00:00:00 2001 From: Andrew Petersen Date: Sun, 8 Jun 2025 00:34:25 -0600 Subject: [PATCH 2/4] fix(agents-core): prevent premature agent termination with text and tool calls - Continue agent loop when function results or computer results are present - Ensures agent continues processing when models return both text and tool calls - Add comment explaining the logic for future maintainers --- .changeset/modern-bananas-greet.md | 5 +++++ packages/agents-core/src/runImplementation.ts | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 .changeset/modern-bananas-greet.md diff --git a/.changeset/modern-bananas-greet.md b/.changeset/modern-bananas-greet.md new file mode 100644 index 00000000..f6cc8236 --- /dev/null +++ b/.changeset/modern-bananas-greet.md @@ -0,0 +1,5 @@ +--- +'@openai/agents-core': patch +--- + +Prevent premature agent termination when models return both text and tool calls diff --git a/packages/agents-core/src/runImplementation.ts b/packages/agents-core/src/runImplementation.ts index c41a6f47..fe60474c 100644 --- a/packages/agents-core/src/runImplementation.ts +++ b/packages/agents-core/src/runImplementation.ts @@ -404,7 +404,13 @@ export async function executeToolsAndSideEffects( : undefined; // if there is no output we just run again - if (!potentialFinalOutput) { + // Some models return both text and tool calls, + // So If there //are tool results, we should continue the agent loop + if ( + !potentialFinalOutput || + functionResults.length > 0 || + computerResults?.length > 0 + ) { return new SingleStepResult( originalInput, newResponse, From 2c248b98f404aec3d94fa802d4b57ccdfbe3d0ec Mon Sep 17 00:00:00 2001 From: Andrew Petersen Date: Sun, 8 Jun 2025 00:50:23 -0600 Subject: [PATCH 3/4] test(agents-core): add test for continued processing with text and tool calls --- .../test/runImplementation.test.ts | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/packages/agents-core/test/runImplementation.test.ts b/packages/agents-core/test/runImplementation.test.ts index fdcf8ac9..5d67c0a2 100644 --- a/packages/agents-core/test/runImplementation.test.ts +++ b/packages/agents-core/test/runImplementation.test.ts @@ -25,6 +25,7 @@ import { executeFunctionToolCalls, executeComputerActions, executeHandoffCalls, + executeToolsAndSideEffects, } from '../src/runImplementation'; import { FunctionTool, FunctionToolResult, tool } from '../src/tool'; import { handoff } from '../src/handoff'; @@ -40,6 +41,7 @@ import { TEST_MODEL_RESPONSE_WITH_FUNCTION, TEST_TOOL, FakeModelProvider, + fakeModelMessage, } from './stubs'; import { computerTool } from '../src/tool'; import * as protocol from '../src/types/protocol'; @@ -790,3 +792,39 @@ describe('empty execution helpers', () => { expect(comp).toEqual([]); }); }); + +describe('executeToolsAndSideEffects with text and tool calls', () => { + it('continues agent loop when model returns both text and tool calls', async () => { + const runner = new Runner({ tracingDisabled: true }); + const state = new RunState(new RunContext(), '', TEST_AGENT, 1); + + const responseWithBothTextAndTool: ModelResponse = { + output: [ + TEST_MODEL_FUNCTION_CALL, + fakeModelMessage('Some text response'), + ], + usage: new Usage(), + }; + + const processedResponse = processModelResponse( + responseWithBothTextAndTool, + TEST_AGENT, + [TEST_TOOL], + [], + ); + + const result = await withTrace('test', () => + executeToolsAndSideEffects( + TEST_AGENT, + '', + [], + responseWithBothTextAndTool, + processedResponse, + runner, + state, + ), + ); + + expect(result.nextStep.type).toBe('next_step_run_again'); + }); +}); From 5ff80271c250c2ee8850fc957d0d3973ced8fd45 Mon Sep 17 00:00:00 2001 From: Andrew Petersen Date: Sun, 8 Jun 2025 21:48:39 -0600 Subject: [PATCH 4/4] reverted TS workarounds - they fixed local build but broke CI build --- packages/agents-core/src/shims/shims-node.ts | 1 - packages/agents-extensions/src/aiSdk.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/agents-core/src/shims/shims-node.ts b/packages/agents-core/src/shims/shims-node.ts index 78198138..96a9aa4a 100644 --- a/packages/agents-core/src/shims/shims-node.ts +++ b/packages/agents-core/src/shims/shims-node.ts @@ -6,7 +6,6 @@ export { EventEmitter as RuntimeEventEmitter } from 'node:events'; declare global { interface ImportMeta { - // @ts-expect-error - env is not defined in the type env?: Record; } } diff --git a/packages/agents-extensions/src/aiSdk.ts b/packages/agents-extensions/src/aiSdk.ts index 5daf7e75..2829ab46 100644 --- a/packages/agents-extensions/src/aiSdk.ts +++ b/packages/agents-extensions/src/aiSdk.ts @@ -70,7 +70,7 @@ export function itemsToLanguageV1Messages( } if (c.type === 'input_image') { const url = new URL(c.image); - return { type: 'image', image: url as unknown as URL }; + return { type: 'image', image: url }; } if (c.type === 'input_file') { if (typeof c.file !== 'string') {