search-layer
Original:🇨🇳 Chinese
Translated
4 scripts
DEFAULT search tool for ALL search/lookup needs. Multi-source search and deduplication layer with intent-aware scoring. Integrates Brave Search (web_search), Exa, Tavily, and Grok to provide high-coverage, high-quality results. Automatically classifies query intent and adjusts search strategy, scoring weights, and result synthesis. Use for ANY query that requires web search — factual lookups, research, news, comparisons, resource finding, "what is X", status checks, etc. Do NOT use raw web_search directly; always route through this skill.
3installs
Added on
NPX Install
npx skill4agent add aaaaqwq/claude-code-skills search-layerTags
Translated version includes tags in frontmatterSKILL.md Content (Chinese)
View Translation Comparison →Search Layer v2.2 — Intent-Aware Multi-Source Retrieval Protocol
Four parallel sources: Brave () + Exa + Tavily + Grok. Automatically select strategies, adjust weights, and synthesize results based on intent.
web_searchExecution Flow
用户查询
↓
[Phase 1] 意图分类 → 确定搜索策略
↓
[Phase 2] 查询分解 & 扩展 → 生成子查询
↓
[Phase 3] 多源并行检索 → Brave + search.py (Exa + Tavily + Grok)
↓
[Phase 4] 结果合并 & 排序 → 去重 + 意图加权评分
↓
[Phase 5] 知识合成 → 结构化输出Phase 1: Intent Classification
After receiving a search request, first determine the intent type, then decide the search strategy. Do not ask users which mode to use.
| Intent | Recognition Signals | Mode | Freshness | Weight Bias |
|---|---|---|---|---|
| Factual | "what is X", "definition of X", "What is X" | answer | — | Authority 0.5 |
| Status | "latest progress of X", "current status of X", "latest X" | deep | pw/pm | Freshness 0.5 |
| Comparison | "X vs Y", "difference between X and Y" | deep | py | Keyword 0.4 + Authority 0.4 |
| Tutorial | "how to do X", "X tutorial", "how to X" | answer | py | Authority 0.5 |
| Exploratory | "learn X in depth", "X ecosystem", "about X" | deep | — | Authority 0.5 |
| News | "X news", "X this week", "X this week" | deep | pd/pw | Freshness 0.6 |
| Resource | "X official website", "X GitHub", "X documentation" | fast | — | Keyword 0.5 |
Seefor detailed classification guidelinesreferences/intent-guide.md
Judgment Rules:
- Scan for signal words in the query
- Select the most specific type when multiple types match
- Default to if unable to judge
exploratory
Phase 2: Query Decomposition & Expansion
Expand the user query into a set of sub-queries based on the intent type:
General Rules
- Automatic technical synonym expansion: k8s→Kubernetes, JS→JavaScript, Go→Golang, Postgres→PostgreSQL
- Chinese technical queries: generate English variants simultaneously (e.g. "Rust 异步编程" → additionally search for "Rust async programming")
Expansion by Intent
| Intent | Expansion Strategy | Example |
|---|---|---|
| Factual | Add "definition", "explained" | "WebTransport" → "WebTransport", "WebTransport explained overview" |
| Status | Add year, "latest", "update" | "Deno progress" → "Deno 2.0 latest 2026", "Deno update release" |
| Comparison | Split into 3 sub-queries | "Bun vs Deno" → "Bun vs Deno", "Bun advantages", "Deno advantages" |
| Tutorial | Add "tutorial", "guide", "step by step" | "Rust CLI" → "Rust CLI tutorial", "Rust CLI guide step by step" |
| Exploratory | Split into 2-3 perspectives | "RISC-V" → "RISC-V overview", "RISC-V ecosystem", "RISC-V use cases" |
| News | Add "news", "announcement", date | "AI news" → "AI news this week 2026", "AI announcement latest" |
| Resource | Add specific resource type | "Anthropic MCP" → "Anthropic MCP official documentation" |
Phase 3: Multi-source Parallel Retrieval
Step 1: Brave (All Modes)
Call for each sub-query. If the intent has freshness requirements, pass the parameter:
web_searchfreshnessweb_search(query="Deno 2.0 latest 2026", freshness="pw")Step 2: Exa + Tavily + Grok (Deep / Answer Mode)
Call search.py for sub-queries, pass intent and freshness:
bash
python3 /home/node/.openclaw/workspace/skills/search-layer/scripts/search.py \
--queries "子查询1" "子查询2" "子查询3" \
--mode deep \
--intent status \
--freshness pw \
--num 5Source Participation Matrix by Mode:
| Mode | Exa | Tavily | Grok | Description |
|---|---|---|---|---|
| fast | ✅ | ❌ | fallback | Exa first; use Grok when no Exa key is available |
| deep | ✅ | ✅ | ✅ | Three sources run in parallel |
| answer | ❌ | ✅ | ❌ | Tavily only (includes AI answer) |
Parameter Description:
| Parameter | Description |
|---|---|
| Multiple sub-queries executed in parallel (single query can also be passed as positional parameter) |
| fast / deep / answer |
| Intent type, affects scoring weight (no scoring if not passed, behavior consistent with v1) |
| pd(24h) / pw(week) / pm(month) / py(year) |
| Comma separated domain names, matching results get +0.2 authority score |
| Number of results per source per query |
Grok Source Description:
- Call Grok model () via completions API, return structured search results using its real-time knowledge
grok-4.1-fast - Automatically detect time-sensitive queries and inject current time context
- Run in parallel with Exa and Tavily in deep mode
- Need to configure Grok's ,
apiUrl,apiKeyinmodel(or via environment variables~/.openclaw/credentials/search.json,GROK_API_URL,GROK_API_KEY)GROK_MODEL - Automatically downgrade to Exa + Tavily dual sources if Grok configuration is missing
Step 3: Merge
Merge Brave results with search.py output. Deduplicate by canonical URL, mark sources.
If search.py returns the field, use it for sorting; if Brave results have no score, calculate it using the same intent weight formula.
scorePhase 3.5: Reference Tracking (Thread Pulling)
When search results include GitHub issue/PR links and the intent is Status or Exploratory, automatically trigger reference tracking.
Automatic Trigger Conditions
- Intent is or
statusexploratory - Search results include or
github.com/.../issues/URLsgithub.com/.../pull/
Method 1: search.py --extract-refs (Batch)
Extract reference graph directly from search results without additional calls:
bash
python3 search.py "OpenClaw config validation bug" --mode deep --intent status --extract-refsThere will be an additional field in the output, containing the reference list for each result URL.
refsYou can also skip searching and extract references directly for known URLs:
bash
python3 search.py --extract-refs-urls "https://github.com/owner/repo/issues/123" "https://github.com/owner/repo/issues/456"Method 2: fetch-thread (Single URL Deep Crawl)
Pull complete discussion stream + structured references for a single URL:
bash
python3 fetch_thread.py "https://github.com/owner/repo/issues/123" --format json
python3 fetch_thread.py "https://github.com/owner/repo/issues/123" --format markdown
python3 fetch_thread.py "https://github.com/owner/repo/issues/123" --extract-refs-onlyGitHub scenario (issue/PR): Pull body + all comments + timeline events (cross-references, commits) via API, extract:
- Issue/PR references (#123, owner/repo#123)
- Duplicate markers
- Commit references
- Associated PR/issue (timeline cross-references)
- External URLs
General web scenario: web fetch + regex extraction of reference links.
Agent Execution Flow
Step 1: search-layer search → Get initial results
Step 2: search.py --extract-refs or fetch-thread → Extract clue graph
Step 3: Agent filters high-value clues (LLM judges which are worth tracking)
Step 4: fetch-thread deeply crawls each high-value clue
Step 5: Repeat Step 2-4 until information is closed or depth limit is reached (recommended max_depth=3)Phase 4: Result Sorting
Scoring Formula
score = w_keyword × keyword_match + w_freshness × freshness_score + w_authority × authority_scoreWeights are determined by intent (see Phase 1 table). Each item:
- keyword_match (0-1): Coverage of query terms in title + abstract
- freshness_score (0-1): Based on publication date, newer is higher (no date = 0.5)
- authority_score (0-1): Based on domain authority level
- Tier 1 (1.0): github.com, stackoverflow.com, official documentation sites
- Tier 2 (0.8): HN, dev.to, well-known technical blogs
- Tier 3 (0.6): Medium, Juejin, InfoQ
- Tier 4 (0.4): Others
Seefor full domain rating tablereferences/authority-domains.json
Domain Boost
Manually specify domains to be weighted via the parameter (matching results get +0.2 authority score):
--domain-boostbash
search.py "query" --mode deep --intent tutorial --domain-boost dev.to,freecodecamp.orgRecommended combinations:
- Tutorial →
dev.to, freecodecamp.org, realpython.com, baeldung.com - Resource →
github.com - News →
techcrunch.com, arstechnica.com, theverge.com
Phase 5: Knowledge Synthesis
Select synthesis strategy based on the number of results:
Small result set (≤5 items)
Display one by one, each with source tag and score:
1. [Title](url) — snippet... `[brave, exa]` ⭐0.85
2. [Title](url) — snippet... `[tavily]` ⭐0.72Medium result set (5-15 items)
Cluster by theme + summary per group:
**Theme A: [Description]**
- [Result 1] — Key points... `[source]`
- [Result 2] — Key points... `[source]`
**Theme B: [Description]**
- [Result 3] — Key points... `[source]`Large result set (15+ items)
High-level overview + Top 5 + in-depth prompt:
[An overview summarizing the main findings]
**Top 5 most relevant results:**
1. ...
2. ...
Found N results in total, covering [source list]. Which aspect do you want to explore in depth?Synthesis Rules
- Give the answer first, then list sources (don't start with "I searched for...")
- Aggregate by theme, not by source (don't do "Brave results: ... Exa results: ...")
- Explicitly mark conflicting information: clearly point out when different sources have contradictory statements
- Confidence expression:
- Multi-source consistent + fresh → state directly
- Single source or older → "According to [source], ..."
- Conflicting or uncertain → "There are different opinions: A believes..., B believes..."
Degradation Strategy
- Exa 429/5xx → continue with Brave + Tavily + Grok
- Tavily 429/5xx → continue with Brave + Exa + Grok
- Grok timeout/error → continue with Brave + Exa + Tavily
- Overall search.py failure → use only Brave (always available)
web_search - Never block the main process because of a single source failure
Backward Compatibility
When the parameter is not included, the behavior of search.py is exactly the same as v1 (no scoring, output in original order).
--intentExisting callers (e.g. github-explorer) do not need modification.
Quick Reference
| Scenario | Command |
|---|---|
| Quick fact check | |
| In-depth research | |
| Latest updates | |
| Comparative analysis | |
| Find resources | |