webSearchTool function
Creates the web_search tool.
Parameters:
query(string, required): the search query.count(integer, optional): max results (default WebSearchConfig.maxResults, clamped to 1..20).site(string, optional): restrict results to one domain (appended as asite:filter, which all ported providers support).
Implementation
AgentTool webSearchTool({required WebSearchConfig config}) {
return AgentTool(
name: 'web_search',
label: 'web_search',
tier: ApprovalTier.read,
description:
'Search the web and return ranked results with [n] citation markers, '
'titles, URLs, and snippets. Runs a provider chain (DuckDuckGo first, '
'keyed providers when configured) and falls through on failure. '
'Follow up with web_fetch on a result URL to read the full page.',
parameters: const {
'type': 'object',
'properties': {
'query': {'type': 'string', 'description': 'The search query'},
'count': {
'type': 'integer',
'description':
'Maximum number of results to return (default: 10, max: 20)',
},
'site': {
'type': 'string',
'description':
"Restrict results to a single domain, e.g. 'pub.dev' "
'(appended as a site: filter)',
},
},
'required': ['query'],
},
execute: (arguments, cancelToken, onUpdate) async {
cancelToken?.throwIfCancelled();
final query = (arguments['query'] as String).trim();
if (query.isEmpty) throw StateError('query must not be empty');
final count = clampWebSearchCount(
(arguments['count'] as num?)?.toInt() ?? config.maxResults,
);
final site = (arguments['site'] as String?)?.trim();
final effectiveQuery = site != null && site.isNotEmpty
? '$query site:$site'
: query;
final secrets = await config.secrets?.readAll() ?? const {};
final chain = resolveWebSearchChain(config.providers, secrets: secrets);
if (chain.isEmpty) {
throw StateError(
'No web search provider configured. DuckDuckGo needs no key; set '
'BRAVE_API_KEY or TAVILY_API_KEY for the keyed providers.',
);
}
final client = config.httpClient ?? http.Client();
try {
final request = WebSearchRequest(
query: effectiveQuery,
count: count,
client: client,
timeout: config.timeout,
secrets: secrets,
);
return await _executeChain(chain, request, query, cancelToken);
} finally {
if (config.httpClient == null) client.close();
}
},
);
}