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

fix: #247 logging for a sub-agent w/ stopAtToolNames
14 changes: 14 additions & 0 deletions packages/agents-core/src/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,20 @@ export class Agent<
context,
...(runOptions ?? {}),
});

const usesStopAtToolNames =
typeof this.toolUseBehavior === 'object' &&
this.toolUseBehavior !== null &&
'stopAtToolNames' in this.toolUseBehavior;

if (
typeof customOutputExtractor !== 'function' &&
usesStopAtToolNames
) {
logger.debug(
`You're passing the agent (name: ${this.name}) with toolUseBehavior.stopAtToolNames configured as a tool to a different agent; this may not work as you expect. You may want to have a wrapper function tool to consistently return the final output.`,
);
}
const outputText =
typeof customOutputExtractor === 'function'
? await customOutputExtractor(result as any)
Expand Down
25 changes: 25 additions & 0 deletions packages/agents-core/test/agent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { z } from 'zod';
import { JsonSchemaDefinition, setDefaultModelProvider } from '../src';
import { FakeModelProvider } from './stubs';
import { Runner, RunConfig } from '../src/run';
import logger from '../src/logger';

describe('Agent', () => {
afterEach(() => {
Expand Down Expand Up @@ -186,6 +187,30 @@ describe('Agent', () => {
expect(result2).toBe('Hello World');
});

it('warns when using asTool with stopAtToolNames behavior without custom extractor', async () => {
const warnSpy = vi.spyOn(logger, 'debug').mockImplementation(() => {});
const runSpy = vi.spyOn(Runner.prototype, 'run').mockResolvedValue({
rawResponses: [{ output: [] }],
} as any);

const agent = new Agent({
name: 'Stopper Agent',
instructions: 'Stop instructions.',
toolUseBehavior: { stopAtToolNames: ['report'] },
});

const tool = agent.asTool({
toolDescription: 'desc',
});

await tool.invoke(new RunContext(), '{"input":"value"}');

expect(runSpy).toHaveBeenCalledTimes(1);
expect(warnSpy).toHaveBeenCalledWith(
`You're passing the agent (name: Stopper Agent) with toolUseBehavior.stopAtToolNames configured as a tool to a different agent; this may not work as you expect. You may want to have a wrapper function tool to consistently return the final output.`,
);
});

it('allows configuring needsApproval when using an agent as a tool', async () => {
const approval = vi.fn().mockResolvedValue(true);
const agent = new Agent({
Expand Down