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 {
18 Self::default()
19 }
20
21 pub fn with_city(mut self, city: impl Into<String>) -> Self {
23 self.city = Some(city.into());
24 self
25 }
26
27 pub fn with_country(mut self, country: impl Into<String>) -> Self {
29 self.country = Some(country.into());
30 self
31 }
32
33 pub fn with_region(mut self, region: impl Into<String>) -> Self {
35 self.region = Some(region.into());
36 self
37 }
38
39 pub fn with_timezone(mut self, timezone: impl Into<String>) -> Self {
41 self.timezone = Some(timezone.into());
42 self
43 }
44
45 fn to_json(&self) -> Value {
46 json!({
47 "type": "approximate",
48 "city": self.city,
49 "country": self.country,
50 "region": self.region,
51 "timezone": self.timezone,
52 })
53 }
54}
55
56#[derive(Debug, Clone, Default)]
60pub struct WebSearchTool {
61 allowed_domains: Option<Vec<String>>,
62 blocked_domains: Option<Vec<String>>,
63 max_uses: Option<i32>,
64 user_location: Option<WebSearchUserLocation>,
65}
66
67impl WebSearchTool {
68 pub fn new() -> Self {
70 Self::default()
71 }
72
73 pub fn with_allowed_domains(
75 mut self,
76 domains: impl IntoIterator<Item = impl Into<String>>,
77 ) -> Self {
78 self.allowed_domains = Some(domains.into_iter().map(Into::into).collect());
79 self.blocked_domains = None;
80 self
81 }
82
83 pub fn with_blocked_domains(
85 mut self,
86 domains: impl IntoIterator<Item = impl Into<String>>,
87 ) -> Self {
88 self.blocked_domains = Some(domains.into_iter().map(Into::into).collect());
89 self.allowed_domains = None;
90 self
91 }
92
93 pub fn with_max_uses(mut self, max_uses: i32) -> Self {
95 self.max_uses = Some(max_uses);
96 self
97 }
98
99 pub fn with_user_location(mut self, user_location: WebSearchUserLocation) -> Self {
101 self.user_location = Some(user_location);
102 self
103 }
104}
105
106#[async_trait]
107impl Tool for WebSearchTool {
108 fn name(&self) -> &str {
109 "web_search"
110 }
111
112 fn description(&self) -> &str {
113 "Searches the web for current information (server-side)."
114 }
115
116 fn is_builtin(&self) -> bool {
117 true
118 }
119
120 fn declaration(&self) -> Value {
121 json!({
122 "name": self.name(),
123 "description": self.description(),
124 "x-adk-anthropic-tool": {
125 "type": "web_search_20250305",
126 "name": "web_search",
127 "allowed_domains": self.allowed_domains,
128 "blocked_domains": self.blocked_domains,
129 "max_uses": self.max_uses,
130 "user_location": self.user_location.as_ref().map(WebSearchUserLocation::to_json),
131 }
132 })
133 }
134
135 async fn execute(&self, _ctx: Arc<dyn ToolContext>, _args: Value) -> Result<Value> {
136 Err(adk_core::AdkError::tool("WebSearch is handled internally by Anthropic"))
137 }
138}