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-hotels-do.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@openai/agents-openai': patch
'@openai/agents-core': patch
---

Fix #393 add domain filtering and sources to web search tool & upgrade openai package to the latest version
1 change: 1 addition & 0 deletions examples/tools/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"start:computer-use": "tsx computer-use.ts",
"start:file-search": "tsx file-search.ts",
"start:web-search": "tsx web-search.ts",
"start:web-search-filters": "tsx web-search-filters.ts",
"start:code-interpreter": "tsx code-interpreter.ts",
"start:image-generation": "tsx image-generation.ts"
}
Expand Down
58 changes: 58 additions & 0 deletions examples/tools/web-search-filters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Agent, run, webSearchTool, withTrace } from '@openai/agents';

async function main() {
const agent = new Agent({
name: 'OAI website searcher',
model: 'gpt-5-nano',
instructions:
'You are a helpful agent that can search openai.com resources.',
tools: [
webSearchTool({
// https://platform.openai.com/docs/guides/tools-web-search?api-mode=responses#domain-filtering
filters: {
allowedDomains: [
'openai.com',
'developer.openai.com',
'platform.openai.com',
'help.openai.com',
],
},
searchContextSize: 'medium',
}),
],
modelSettings: {
providerData: {
reasoning: { effort: 'low' },
text: { verbosity: 'low' },
// https://platform.openai.com/docs/guides/tools-web-search?api-mode=responses#sources
include: ['web_search_call.action.sources'],
},
},
});

await withTrace('OpenAI website search example', async () => {
const today = new Date().toISOString().split('T')[0];
const query = `Write a summary of the latest OpenAI Platform updates for developers in the last few weeks (today is ${today}).`;
const result = await run(agent, query);
console.log('\n----- Sources -----\n');
for (const item of result.history) {
if (
item.type === 'hosted_tool_call' &&
item.name === 'web_search_call' &&
item.providerData?.action?.sources
) {
console.log(
JSON.stringify(
item.providerData.action.sources.map((s: any) => s.url),
null,
2,
),
);
}
}
console.log('\n----- Final Output -----\n');
console.log(result.finalOutput);
});
}

main().catch(console.error);
18 changes: 17 additions & 1 deletion packages/agents-openai/src/openaiResponsesModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,16 @@ import {
import { camelOrSnakeToSnakeCase } from './utils/providerData';
import { ProviderData } from '@openai/agents-core/types';

type ToolChoice = ToolChoiceOptions | ToolChoiceTypes | ToolChoiceFunction;
type ToolChoice =
| ToolChoiceOptions
| ToolChoiceTypes
// TOOD: remove this once the underlying ToolChoiceTypes include this
| { type: 'web_search' }
| ToolChoiceFunction;

const HostedToolChoice = z.enum([
'file_search',
'web_search',
'web_search_preview',
'computer_use_preview',
'code_interpreter',
Expand Down Expand Up @@ -137,6 +143,16 @@ function converTool<_TContext = unknown>(
};
} else if (tool.type === 'hosted_tool') {
if (tool.providerData?.type === 'web_search') {
return {
tool: {
type: 'web_search',
user_location: tool.providerData.user_location,
filters: tool.providerData.filters,
search_context_size: tool.providerData.search_context_size,
},
include: undefined,
};
} else if (tool.providerData?.type === 'web_search_preview') {
return {
tool: {
type: 'web_search_preview',
Expand Down
22 changes: 17 additions & 5 deletions packages/agents-openai/src/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,25 @@ export const ImageGenerationStatus = z

/**
* The built-in Web search tool
*
* see https://platform.openai.com/docs/guides/tools-web-search?api-mode=responses
*/
export type WebSearchTool = {
type: 'web_search';
name?: 'web_search_preview' | string;
name?: 'web_search' | 'web_search_preview' | string;
/**
* Optional location for the search. Lets you customize results to be relevant to a location.
*/
userLocation?: OpenAI.Responses.WebSearchTool.UserLocation;
userLocation?: OpenAI.Responses.Tool.WebSearchTool.UserLocation;

/**
* Optional filters for the search.
*/
filters?: { allowedDomains?: Array<string> | null };

/**
* The amount of context to use for the search.
* High level guidance for the amount of context window space to use for the
* search. One of `low`, `medium`, or `high`. `medium` is the default.
*/
searchContextSize: 'low' | 'medium' | 'high';
};
Expand All @@ -53,13 +62,16 @@ export function webSearchTool(
): HostedTool {
const providerData: ProviderData.WebSearchTool = {
type: 'web_search',
name: options.name ?? 'web_search_preview',
name: options.name ?? 'web_search',
user_location: options.userLocation,
filters: options.filters?.allowedDomains
? { allowed_domains: options.filters.allowedDomains }
: undefined,
search_context_size: options.searchContextSize ?? 'medium',
};
return {
type: 'hosted_tool',
name: options.name ?? 'web_search_preview',
name: options.name ?? 'web_search',
providerData,
};
}
Expand Down
7 changes: 5 additions & 2 deletions packages/agents-openai/src/types/providerData.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import OpenAI from 'openai';

export type WebSearchTool = Omit<OpenAI.Responses.WebSearchTool, 'type'> & {
export type WebSearchTool = Omit<
OpenAI.Responses.Tool.WebSearchTool,
'type'
> & {
type: 'web_search';
name: 'web_search_preview' | string;
name: 'web_search' | 'web_search_preview' | string;
};

export type FileSearchTool = Omit<OpenAI.Responses.FileSearchTool, 'type'> & {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ describe('getToolChoice', () => {

it('handles hosted tool choices', () => {
expect(getToolChoice('file_search')).toEqual({ type: 'file_search' });
expect(getToolChoice('web_search')).toEqual({
type: 'web_search',
});
expect(getToolChoice('web_search_preview')).toEqual({
type: 'web_search_preview',
});
Expand Down Expand Up @@ -77,7 +80,7 @@ describe('converTool', () => {
},
} as any);
expect(web.tool).toEqual({
type: 'web_search_preview',
type: 'web_search',
user_location: {},
search_context_size: 'low',
});
Expand Down
2 changes: 1 addition & 1 deletion packages/agents-openai/test/tools.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ describe('Tool', () => {
});
expect(t).toBeDefined();
expect(t.type).toBe('hosted_tool');
expect(t.name).toBe('web_search_preview');
expect(t.name).toBe('web_search');
});

it('fileSearchTool', () => {
Expand Down