adk_tool/builtin/
web_search.rs1use adk_core::{Result, Tool, ToolContext};
2use async_trait::async_trait;
3use serde_json::{Value, json};
4use std::sync::Arc;
5
6#[derive(Debug, Clone, Default)]
8pub struct WebSearchUserLocation {
9 city: Option<String>,
10 country: Option<String>,
11 region: Option<String>,
12 timezone: Option<String>,
13}
14
15impl WebSearchUserLocation {
16 pub fn new() -> Self {
17 Self::default()
18 }
19
20 pub fn with_city(mut self, city: impl Into<String>) -> Self {
21 self.city = Some(city.into());
22 self
23 }
24
25 pub fn with_country(mut self, country: impl Into<String>) -> Self {
26 self.country = Some(country.into());
27 self
28 }
29
30 pub fn with_region(mut self, region: impl Into<String>) -> Self {
31 self.region = Some(region.into());
32 self
33 }
34
35 pub fn with_timezone(mut self, timezone: impl Into<String>) -> Self {
36 self.timezone = Some(timezone.into());
37 self
38 }
39
40 fn to_json(&self) -> Value {
41 json!({
42 "type": "approximate",
43 "city": self.city,
44 "country": self.country,
45 "region": self.region,
46 "timezone": self.timezone,
47 })
48 }
49}
50
51#[derive(Debug, Clone, Default)]
55pub struct WebSearchTool {
56 allowed_domains: Option<Vec<String>>,
57 blocked_domains: Option<Vec<String>>,
58 max_uses: Option<i32>,
59 user_location: Option<WebSearchUserLocation>,
60}
61
62impl WebSearchTool {
63 pub fn new() -> Self {
64 Self::default()
65 }
66
67 pub fn with_allowed_domains(
68 mut self,
69 domains: impl IntoIterator<Item = impl Into<String>>,
70 ) -> Self {
71 self.allowed_domains = Some(domains.into_iter().map(Into::into).collect());
72 self.blocked_domains = None;
73 self
74 }
75
76 pub fn with_blocked_domains(
77 mut self,
78 domains: impl IntoIterator<Item = impl Into<String>>,
79 ) -> Self {
80 self.blocked_domains = Some(domains.into_iter().map(Into::into).collect());
81 self.allowed_domains = None;
82 self
83 }
84
85 pub fn with_max_uses(mut self, max_uses: i32) -> Self {
86 self.max_uses = Some(max_uses);
87 self
88 }
89
90 pub fn with_user_location(mut self, user_location: WebSearchUserLocation) -> Self {
91 self.user_location = Some(user_location);
92 self
93 }
94}
95
96#[async_trait]
97impl Tool for WebSearchTool {
98 fn name(&self) -> &str {
99 "web_search"
100 }
101
102 fn description(&self) -> &str {
103 "Searches the web for current information (server-side)."
104 }
105
106 fn is_builtin(&self) -> bool {
107 true
108 }
109
110 fn declaration(&self) -> Value {
111 json!({
112 "name": self.name(),
113 "description": self.description(),
114 "x-adk-anthropic-tool": {
115 "type": "web_search_20250305",
116 "name": "web_search",
117 "allowed_domains": self.allowed_domains,
118 "blocked_domains": self.blocked_domains,
119 "max_uses": self.max_uses,
120 "user_location": self.user_location.as_ref().map(WebSearchUserLocation::to_json),
121 }
122 })
123 }
124
125 async fn execute(&self, _ctx: Arc<dyn ToolContext>, _args: Value) -> Result<Value> {
126 Err(adk_core::AdkError::tool("WebSearch is handled internally by Anthropic"))
127 }
128}