Skip to content

Commit 31fb787

Browse files
committed
enhancement(agent): include interruptions in run result when using agent-as-tool
1 parent a591077 commit 31fb787

File tree

4 files changed

+45
-3
lines changed

4 files changed

+45
-3
lines changed

.changeset/cuddly-poets-refuse.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@openai/agents-core': patch
3+
---
4+
5+
Add `returnRunResult` option to `agent.asTool()` to expose full RunResult, including interruptions such as approvals.

docs/src/content/docs/guides/tools.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ Under the hood the SDK:
8585
- Creates a function tool with a single `input` parameter.
8686
- Runs the sub‑agent with that input when the tool is called.
8787
- Returns either the last message or the output extracted by `customOutputExtractor`.
88+
- If `returnRunResult` is set, returns the full `RunResult` so nested interruptions can be inspected.
8889

8990
---
9091

packages/agents-core/src/agent.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -444,8 +444,22 @@ export class Agent<
444444
customOutputExtractor?: (
445445
output: RunResult<TContext, Agent<TContext, any>>,
446446
) => string | Promise<string>;
447-
}): FunctionTool {
448-
const { toolName, toolDescription, customOutputExtractor } = options;
447+
/**
448+
* If true, the invoked tool will return the {@link RunResult} of the agent
449+
* run instead of just the extracted output text.
450+
*/
451+
returnRunResult?: boolean;
452+
}): FunctionTool<
453+
TContext,
454+
any,
455+
string | RunResult<TContext, Agent<TContext, any>>
456+
> {
457+
const {
458+
toolName,
459+
toolDescription,
460+
customOutputExtractor,
461+
returnRunResult,
462+
} = options;
449463
return tool({
450464
name: toolName ?? toFunctionToolName(this.name),
451465
description: toolDescription ?? '',
@@ -469,6 +483,9 @@ export class Agent<
469483
const result = await runner.run(this, data.input, {
470484
context: context?.context,
471485
});
486+
if (returnRunResult) {
487+
return result as RunResult<TContext, Agent<TContext, any>>;
488+
}
472489
if (typeof customOutputExtractor === 'function') {
473490
return customOutputExtractor(result as any);
474491
}

packages/agents-core/test/agent.test.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ import { Agent } from '../src/agent';
33
import { RunContext } from '../src/runContext';
44
import { Handoff, handoff } from '../src/handoff';
55
import { z } from 'zod/v3';
6-
import { JsonSchemaDefinition, setDefaultModelProvider } from '../src';
6+
import {
7+
JsonSchemaDefinition,
8+
setDefaultModelProvider,
9+
RunResult,
10+
} from '../src';
711
import { FakeModelProvider } from './stubs';
812

913
describe('Agent', () => {
@@ -198,6 +202,21 @@ describe('Agent', () => {
198202
const result1 = agent.processFinalOutput('{"message": "Hi, how are you?"}');
199203
expect(result1).toEqual({ message: 'Hi, how are you?' });
200204
});
205+
206+
it('should return a RunResult when returnRunResult option is true', async () => {
207+
const agent = new Agent({
208+
name: 'Test Agent',
209+
instructions: 'You do tests.',
210+
});
211+
const tool = agent.asTool({ returnRunResult: true });
212+
setDefaultModelProvider(new FakeModelProvider());
213+
const result = await tool.invoke({} as any, '{"input":"hello"}');
214+
expect(result).toBeInstanceOf(RunResult);
215+
expect((result as RunResult<any, Agent<any, any>>).finalOutput).toBe(
216+
'Hello World',
217+
);
218+
});
219+
201220
it('should process final output (json schema)', async () => {
202221
const agent = new Agent({
203222
name: 'Test Agent',

0 commit comments

Comments
 (0)