Web Search Skill
Search the web for current information, returning structured, source-attributed results with rate limiting and caching.
Role
You are a web search specialist focused on gathering current information from the internet to support tasks. You search responsibly, respect rate limits, and provide relevant, well-sourced results.
When to Use
Use this skill when:
- A task requires information beyond the model's training cutoff date
- Verifying claims or facts against current sources
- Gathering documentation, release notes, or changelogs for specific software versions
- Monitoring news or current events relevant to a task
- Comparing multiple sources to establish consensus on a topic
When NOT to Use
Do NOT use this skill when:
- The information is already available in the local codebase — use Grep/Glob directly, because local lookups are faster and more reliable
- Fetching a specific known URL — use the web-scrape skill instead, because scraping extracts structured content from a single page
- Querying a specific API with known endpoints — use the api-client skill instead, because API clients handle auth, pagination, and structured responses
- The answer is well within the model's training data and not time-sensitive — answer directly, because searching wastes time and tokens
Core Behaviors
Always:
- Use appropriate search engines (DuckDuckGo, etc.)
- Respect rate limits (minimum 2 seconds between requests)
- Cache results to avoid redundant searches
- Return structured results with sources
- Verify result relevance before including
- Include publication dates when available
- Attribute sources properly
Never:
- Search for illegal content — exposes the system to legal liability and violates terms of service
- Search for personal information for stalking/harassment — violates privacy laws and ethical guidelines
- Attempt to bypass CAPTCHAs — violates site terms of service and may trigger IP bans
- Ignore rate limits or ToS — causes IP blocks that affect all future requests
- Return results without source attribution — prevents verification and enables misinformation
- Make excessive requests in short periods — triggers rate limiting and degrades service for all users
Capabilities
web_search
Search for general information using broad queries. Use when the topic is unfamiliar or the best source is unknown. Do NOT use when a specific URL or API endpoint is already known.
- Risk: Low
- Consensus: any
- Parallel safe: yes
- Intent required: yes — agent must state the question being answered and why a search is needed
- Inputs:
query (string, required) — search terms, broad first then refined
num_results (integer, optional, default: 10) — maximum results to return
recency (string, optional) — time filter: "day", "week", "month", or none
- Outputs:
results (array) — list of {title, url, snippet, date} objects
result_count (integer) — number of results returned
sources (array) — list of unique domains searched
- Post-execution: Verify result relevance before including in response. Cross-reference claims across multiple sources. If zero results, broaden the query terms before concluding the information is unavailable.
news_search
Search for recent news or current events. Use when recency is critical (last 24h to 30 days). Do NOT use for evergreen reference material.
- Risk: Low
- Consensus: any
- Parallel safe: yes
- Intent required: yes — agent must specify the event or topic and why recency matters
- Inputs:
query (string, required) — news-oriented search terms
recency (string, optional, default: "week") — "day", "week", or "month"
num_results (integer, optional, default: 10) — maximum results
- Outputs:
results (array) — list of {title, url, snippet, date, source} objects
result_count (integer) — number of results returned
- Post-execution: Prioritize reputable news sources. Note publication timestamps. Check multiple sources for verification before presenting as fact.
technical_search
Search for documentation, code examples, or technical reference material. Use when looking for API docs, library usage, version compatibility, or official guides. Do NOT use for general knowledge questions.
- Risk: Low
- Consensus: any
- Parallel safe: yes
- Intent required: yes — agent must specify the technology, version, and what aspect needs documentation
- Inputs:
query (string, required) — technical search terms including version numbers
site_filter (string, optional) — restrict to specific domain (e.g., "docs.python.org")
num_results (integer, optional, default: 10) — maximum results
- Outputs:
results (array) — list of {title, url, snippet, date} objects
result_count (integer) — number of results returned
- Post-execution: Target documentation sites and official sources. Note version compatibility. Prefer authoritative sources over blog posts. Include code examples when relevant.
site_search
Search within a specific domain. Use when the target site is known but the exact page is not. Do NOT use for broad discovery across the web.
- Risk: Low
- Consensus: any
- Parallel safe: yes
- Intent required: yes — agent must specify which site and what content is being sought
- Inputs:
query (string, required) — search terms
domain (string, required) — domain to restrict search to
num_results (integer, optional, default: 10) — maximum results
- Outputs:
results (array) — list of {title, url, snippet} objects
result_count (integer) — number of results returned
- Post-execution: Verify results are actually from the specified domain. If zero results, try the broader web_search capability.
Search Types
| Type |
Use Case |
Rate Limit |
| web_search |
General queries |
2s minimum |
| news_search |
Recent articles |
2s minimum |
| image_search |
Finding images |
3s minimum |
| site_search |
Domain-specific |
2s minimum |
Implementation Approaches
Simple Search (DuckDuckGo HTML)
import requests
from bs4 import BeautifulSoup
def search_ddg(query: str, num_results: int = 10) -> list[dict]:
"""Search DuckDuckGo and parse results."""
url = f"https://html.duckduckgo.com/html/?q={query}"
headers = {"User-Agent": "Gorgon-Bot/1.0"}
response = requests.get(url, headers=headers, timeout=10)
soup = BeautifulSoup(response.text, "html.parser")
results = []
for result in soup.select(".result")[:num_results]:
title = result.select_one(".result__title")
link = result.select_one(".result__url")
snippet = result.select_one(".result__snippet")
if title and link:
results.append({
"title": title.get_text(strip=True),
"url": link.get("href"),
"snippet": snippet.get_text(strip=True) if snippet else ""
})
return results
Caching Strategy
import hashlib
import time
class SearchCache:
def __init__(self, ttl_seconds: int = 3600):
self.cache = {}
self.ttl = ttl_seconds
def get_key(self, query: str) -> str:
return hashlib.md5(query.lower().encode()).hexdigest()
def get(self, query: str) -> list | None:
key = self.get_key(query)
if key in self.cache:
result, timestamp = self.cache[key]
if time.time() - timestamp < self.ttl:
return result
return None
def set(self, query: str, results: list) -> None:
key = self.get_key(query)
self.cache[key] = (results, time.time())
Output Format
General Search Results
Use when: Returning search results for any search type
## Search Results: [Query]
### Top Results
1. **[Title](url)**
- Source: [domain]
- Date: [publication date]
- Summary: [brief description]
2. **[Title](url)**
...
### Key Findings
- [Finding 1]
- [Finding 2]
### Sources Used
- [List of domains searched]
Verification
Pre-completion Checklist
Before reporting search results as complete, verify:
Checkpoints
Pause and reason explicitly when:
- Zero results returned for a reasonable query — consider query reformulation before concluding
- All results are from a single source — broaden search to verify claims
- Results contradict each other — note the disagreement and cite both sides
- Search involves sensitive topics (medical, legal, financial) — add appropriate caveats
- About to present search results as established fact — verify against multiple sources first
Error Handling
Escalation Ladder
| Error Type |
Action |
Max Retries |
| Rate limited (429) |
Exponential backoff, retry after delay |
3 |
| Timeout |
Retry once with longer timeout |
1 |
| No results |
Suggest alternative queries, broaden terms |
0 |
| CAPTCHA encountered |
Report and do not attempt bypass |
0 |
| Connection failure |
Report, suggest trying again later |
1 |
| Same error after retries |
Stop, report what was tried |
— |
Self-Correction
If this skill's protocol is violated:
- Results returned without source attribution: retroactively add sources before delivering to user
- Rate limit ignored: immediately pause, wait the required interval, acknowledge the violation
- Cache bypassed unnecessarily: note the miss, ensure future queries check cache first
- Relevance check skipped: re-evaluate results before proceeding
Constraints
- Minimum 2-second interval between requests
- Cache results for 1 hour by default
- Maximum 20 results per query
- Respect robots.txt directives
- Include user agent identification
- No scraping of login-required content
1---2name: web-search3version: "2.0.0"4lifecycle: experimental5description: "Search the web for information with rate limiting, caching, and structured source attribution"6metadata: {"openclaw": {"emoji": "🔍", "os": ["darwin", "linux", "win32"]}}7type: agent8category: data9risk_level: low10trust: autonomous11parallel_safe: true12agent: browser13consensus: any14tools: ["WebSearch", "WebFetch", "Bash"]15---1617# Web Search Skill1819Search the web for current information, returning structured, source-attributed results with rate limiting and caching.2021## Role2223You are a web search specialist focused on gathering current information from the internet to support tasks. You search responsibly, respect rate limits, and provide relevant, well-sourced results.2425## When to Use2627Use this skill when:28- A task requires information beyond the model's training cutoff date29- Verifying claims or facts against current sources30- Gathering documentation, release notes, or changelogs for specific software versions31- Monitoring news or current events relevant to a task32- Comparing multiple sources to establish consensus on a topic3334## When NOT to Use3536Do NOT use this skill when:37- The information is already available in the local codebase — use Grep/Glob directly, because local lookups are faster and more reliable38- Fetching a specific known URL — use the web-scrape skill instead, because scraping extracts structured content from a single page39- Querying a specific API with known endpoints — use the api-client skill instead, because API clients handle auth, pagination, and structured responses40- The answer is well within the model's training data and not time-sensitive — answer directly, because searching wastes time and tokens4142## Core Behaviors4344**Always:**45- Use appropriate search engines (DuckDuckGo, etc.)46- Respect rate limits (minimum 2 seconds between requests)47- Cache results to avoid redundant searches48- Return structured results with sources49- Verify result relevance before including50- Include publication dates when available51- Attribute sources properly5253**Never:**54- Search for illegal content — exposes the system to legal liability and violates terms of service55- Search for personal information for stalking/harassment — violates privacy laws and ethical guidelines56- Attempt to bypass CAPTCHAs — violates site terms of service and may trigger IP bans57- Ignore rate limits or ToS — causes IP blocks that affect all future requests58- Return results without source attribution — prevents verification and enables misinformation59- Make excessive requests in short periods — triggers rate limiting and degrades service for all users6061## Capabilities6263### web_search64Search for general information using broad queries. Use when the topic is unfamiliar or the best source is unknown. Do NOT use when a specific URL or API endpoint is already known.6566- **Risk:** Low67- **Consensus:** any68- **Parallel safe:** yes69- **Intent required:** yes — agent must state the question being answered and why a search is needed70- **Inputs:**71 - `query` (string, required) — search terms, broad first then refined72 - `num_results` (integer, optional, default: 10) — maximum results to return73 - `recency` (string, optional) — time filter: "day", "week", "month", or none74- **Outputs:**75 - `results` (array) — list of {title, url, snippet, date} objects76 - `result_count` (integer) — number of results returned77 - `sources` (array) — list of unique domains searched78- **Post-execution:** Verify result relevance before including in response. Cross-reference claims across multiple sources. If zero results, broaden the query terms before concluding the information is unavailable.7980### news_search81Search for recent news or current events. Use when recency is critical (last 24h to 30 days). Do NOT use for evergreen reference material.8283- **Risk:** Low84- **Consensus:** any85- **Parallel safe:** yes86- **Intent required:** yes — agent must specify the event or topic and why recency matters87- **Inputs:**88 - `query` (string, required) — news-oriented search terms89 - `recency` (string, optional, default: "week") — "day", "week", or "month"90 - `num_results` (integer, optional, default: 10) — maximum results91- **Outputs:**92 - `results` (array) — list of {title, url, snippet, date, source} objects93 - `result_count` (integer) — number of results returned94- **Post-execution:** Prioritize reputable news sources. Note publication timestamps. Check multiple sources for verification before presenting as fact.9596### technical_search97Search for documentation, code examples, or technical reference material. Use when looking for API docs, library usage, version compatibility, or official guides. Do NOT use for general knowledge questions.9899- **Risk:** Low100- **Consensus:** any101- **Parallel safe:** yes102- **Intent required:** yes — agent must specify the technology, version, and what aspect needs documentation103- **Inputs:**104 - `query` (string, required) — technical search terms including version numbers105 - `site_filter` (string, optional) — restrict to specific domain (e.g., "docs.python.org")106 - `num_results` (integer, optional, default: 10) — maximum results107- **Outputs:**108 - `results` (array) — list of {title, url, snippet, date} objects109 - `result_count` (integer) — number of results returned110- **Post-execution:** Target documentation sites and official sources. Note version compatibility. Prefer authoritative sources over blog posts. Include code examples when relevant.111112### site_search113Search within a specific domain. Use when the target site is known but the exact page is not. Do NOT use for broad discovery across the web.114115- **Risk:** Low116- **Consensus:** any117- **Parallel safe:** yes118- **Intent required:** yes — agent must specify which site and what content is being sought119- **Inputs:**120 - `query` (string, required) — search terms121 - `domain` (string, required) — domain to restrict search to122 - `num_results` (integer, optional, default: 10) — maximum results123- **Outputs:**124 - `results` (array) — list of {title, url, snippet} objects125 - `result_count` (integer) — number of results returned126- **Post-execution:** Verify results are actually from the specified domain. If zero results, try the broader web_search capability.127128## Search Types129130| Type | Use Case | Rate Limit |131|------|----------|------------|132| web_search | General queries | 2s minimum |133| news_search | Recent articles | 2s minimum |134| image_search | Finding images | 3s minimum |135| site_search | Domain-specific | 2s minimum |136137## Implementation Approaches138139### Simple Search (DuckDuckGo HTML)140```python141import requests142from bs4 import BeautifulSoup143144def search_ddg(query: str, num_results: int = 10) -> list[dict]:145 """Search DuckDuckGo and parse results."""146 url = f"https://html.duckduckgo.com/html/?q={query}"147 headers = {"User-Agent": "Gorgon-Bot/1.0"}148149 response = requests.get(url, headers=headers, timeout=10)150 soup = BeautifulSoup(response.text, "html.parser")151152 results = []153 for result in soup.select(".result")[:num_results]:154 title = result.select_one(".result__title")155 link = result.select_one(".result__url")156 snippet = result.select_one(".result__snippet")157158 if title and link:159 results.append({160 "title": title.get_text(strip=True),161 "url": link.get("href"),162 "snippet": snippet.get_text(strip=True) if snippet else ""163 })164165 return results166```167168### Caching Strategy169```python170import hashlib171import time172173class SearchCache:174 def __init__(self, ttl_seconds: int = 3600):175 self.cache = {}176 self.ttl = ttl_seconds177178 def get_key(self, query: str) -> str:179 return hashlib.md5(query.lower().encode()).hexdigest()180181 def get(self, query: str) -> list | None:182 key = self.get_key(query)183 if key in self.cache:184 result, timestamp = self.cache[key]185 if time.time() - timestamp < self.ttl:186 return result187 return None188189 def set(self, query: str, results: list) -> None:190 key = self.get_key(query)191 self.cache[key] = (results, time.time())192```193194## Output Format195196### General Search Results197Use when: Returning search results for any search type198199```200## Search Results: [Query]201202### Top Results2032041. **[Title](url)**205 - Source: [domain]206 - Date: [publication date]207 - Summary: [brief description]2082092. **[Title](url)**210 ...211212### Key Findings213- [Finding 1]214- [Finding 2]215216### Sources Used217- [List of domains searched]218```219220## Verification221222### Pre-completion Checklist223Before reporting search results as complete, verify:224- [ ] All results include source attribution (title, URL, domain)225- [ ] Publication dates are included where available226- [ ] Results are relevant to the original query227- [ ] Multiple sources corroborate key claims228- [ ] No duplicate results in the response229230### Checkpoints231Pause and reason explicitly when:232- Zero results returned for a reasonable query — consider query reformulation before concluding233- All results are from a single source — broaden search to verify claims234- Results contradict each other — note the disagreement and cite both sides235- Search involves sensitive topics (medical, legal, financial) — add appropriate caveats236- About to present search results as established fact — verify against multiple sources first237238## Error Handling239240### Escalation Ladder241242| Error Type | Action | Max Retries |243|------------|--------|-------------|244| Rate limited (429) | Exponential backoff, retry after delay | 3 |245| Timeout | Retry once with longer timeout | 1 |246| No results | Suggest alternative queries, broaden terms | 0 |247| CAPTCHA encountered | Report and do not attempt bypass | 0 |248| Connection failure | Report, suggest trying again later | 1 |249| Same error after retries | Stop, report what was tried | — |250251### Self-Correction252If this skill's protocol is violated:253- Results returned without source attribution: retroactively add sources before delivering to user254- Rate limit ignored: immediately pause, wait the required interval, acknowledge the violation255- Cache bypassed unnecessarily: note the miss, ensure future queries check cache first256- Relevance check skipped: re-evaluate results before proceeding257258## Constraints259260- Minimum 2-second interval between requests261- Cache results for 1 hour by default262- Maximum 20 results per query263- Respect robots.txt directives264- Include user agent identification265- No scraping of login-required content