| name | web-search |
| description | Implement web search capabilities using the z-ai-web-dev-sdk. Use this skill when the user needs to search for real-time information from the web, retrieve up-to-date content beyond the knowledge cutoff, or find the latest news and data. Returns structured search results with URLs, snippets, and metadata. |
| license | MIT |
Web Search Skill
This skill guides the implementation of web search functionality using the z-ai-web-dev-sdk package, enabling applications to search the web and retrieve current information.
Installation Path
Recommended Location: {project_path}/skills/web-search
Extract this skill package to the above path in your project.
Reference Scripts: Example test scripts are available in the {project_path}/skills/web-search/scripts/ directory for quick testing and reference. See {project_path}/skills/web-search/scripts/web_search.ts for a working example.
Overview
The Web Search skill allows you to build applications that can search the internet, retrieve current information, and access real-time data from web sources.
IMPORTANT: z-ai-web-dev-sdk MUST be used in backend code only. Never use it in client-side code.
Prerequisites
The z-ai-web-dev-sdk package is already installed. Import it as shown in the examples below.
CLI Usage (For Simple Tasks)
For simple web search queries, you can use the z-ai CLI instead of writing code. This is ideal for quick information retrieval, testing search functionality, or command-line automation.
Basic Web Search
z-ai function --name "web_search" --args '{"query": "artificial intelligence"}'
z-ai function -n web_search -a '{"query": "latest tech news"}'
Search with Custom Parameters
z-ai function \
-n web_search \
-a '{"query": "machine learning", "num": 5}'
z-ai function \
-n web_search \
-a '{"query": "cryptocurrency news", "num": 10, "recency_days": 7}'
Save Search Results
z-ai function \
-n web_search \
-a '{"query": "climate change research", "num": 5}' \
-o search_results.json
z-ai function \
-n web_search \
-a '{"query": "AI breakthroughs", "num": 3, "recency_days": 1}' \
-o ai_news.json
Advanced Search Examples
z-ai function \
-n web_search \
-a '{"query": "quantum computing applications", "num": 8}' \
-o quantum.json
z-ai function \
-n web_search \
-a '{"query": "genomics research", "num": 5, "recency_days": 30}' \
-o genomics.json
z-ai function \
-n web_search \
-a '{"query": "tech industry updates", "recency_days": 1}' \
-o today_tech.json
CLI Parameters
--name, -n: Required - Function name (use "web_search")
--args, -a: Required - JSON arguments object with:
query (string, required): Search keywords
num (number, optional): Number of results (default: 10)
recency_days (number, optional): Filter results from last N days
--output, -o <path>: Optional - Output file path (JSON format)
Search Result Structure
Each result contains:
url: Full URL of the result
name: Title of the page
snippet: Preview text/description
host_name: Domain name
rank: Result ranking
date: Publication/update date
favicon: Favicon URL
When to Use CLI vs SDK
Use CLI for:
- Quick information lookups
- Testing search queries
- Simple automation scripts
- One-off research tasks
Use SDK for:
- Dynamic search in applications
- Multi-step search workflows
- Custom result processing and filtering
- Production applications with complex logic
Search Result Type
Each search result is a SearchFunctionResultItem with the following structure:
interface SearchFunctionResultItem {
url: string;
name: string;
snippet: string;
host_name: string;
rank: number;
date: string;
favicon: string;
}
Basic Web Search
Simple Search Query
import ZAI from 'z-ai-web-dev-sdk';
async function searchWeb(query) {
const zai = await ZAI.create();
const results = await zai.functions.invoke('web_search', {
query: query,
num: 10
});
return results;
}
const searchResults = await searchWeb('What is the capital of France?');
console.log('Search Results:', searchResults);
Search with Custom Result Count
import ZAI from 'z-ai-web-dev-sdk';
async function searchWithLimit(query, numberOfResults) {
const zai = await ZAI.create();
const results = await zai.functions.invoke('web_search', {
query: query,
num: numberOfResults
});
return results;
}
const topResults = await searchWithLimit('artificial intelligence news', 5);
const moreResults = await searchWithLimit('JavaScript frameworks', 20);
Formatted Search Results
import ZAI from 'z-ai-web-dev-sdk';
async function getFormattedResults(query) {
const zai = await ZAI.create();
const results = await zai.functions.invoke('web_search', {
query: query,
num: 10
});
const formatted = results.map((item, index) => ({
position: index + 1,
title: item.name,
url: item.url,
description: item.snippet,
domain: item.host_name,
publishDate: item.date
}));
return formatted;
}
const results = await getFormattedResults('climate change solutions');
results.forEach(result => {
console.log(`${result.position}. ${result.title}`);
console.();
.();
.();
});
Advanced Use Cases
Search with Result Processing
import ZAI from 'z-ai-web-dev-sdk';
class SearchProcessor {
constructor() {
this.zai = null;
}
async initialize() {
this.zai = await ZAI.create();
}
async search(query, options = {}) {
const {
num = 10,
filterDomain = null,
minSnippetLength = 0
} = options;
const results = await this.zai.functions.invoke('web_search', {
query: query,
num: num
});
let filtered = results;
if (filterDomain) {
filtered = filtered.filter(item =>
item.host_name.includes(filterDomain)
);
}
if (minSnippetLength > 0) {
filtered = filtered.filter(item =>
item.snippet.length >= minSnippetLength
);
}
filtered;
}
() {
[... (results.( item.))];
}
() {
grouped = {};
results.( {
(!grouped[item.]) {
grouped[item.] = [];
}
grouped[item.].(item);
});
grouped;
}
() {
results.( {
dateA = (a.);
dateB = (b.);
ascending ? dateA - dateB : dateB - dateA;
});
}
}
processor = ();
processor.();
results = processor.(, {
: ,
:
});
.(, processor.(results));
.(, processor.(results));
.(, processor.(results));
News Search
import ZAI from 'z-ai-web-dev-sdk';
async function searchNews(topic, timeframe = 'recent') {
const zai = await ZAI.create();
const timeKeywords = {
recent: 'latest news',
today: 'today news',
week: 'this week news',
month: 'this month news'
};
const query = `${topic} ${timeKeywords[timeframe] || timeKeywords.recent}`;
const results = await zai.functions.invoke('web_search', {
query: query,
num: 10
});
const sortedResults = results.sort((a, b) => {
return new Date(b.date) - new Date(a.date);
});
return sortedResults;
}
const aiNews = await (, );
techNews = (, );
.();
aiNews.( {
.();
.();
});
Research Assistant
import ZAI from 'z-ai-web-dev-sdk';
class ResearchAssistant {
constructor() {
this.zai = null;
}
async initialize() {
this.zai = await ZAI.create();
}
async researchTopic(topic, depth = 'standard') {
const numResults = {
quick: 5,
standard: 10,
deep: 20
};
const results = await this.zai.functions.invoke('web_search', {
query: topic,
num: numResults[depth] || 10
});
const analysis = {
topic: topic,
totalResults: results.length,
sources: this.extractDomains(results),
topResults: results.slice(0, ).( ({
: r.,
: r.,
: r.
})),
: .(results)
};
analysis;
}
() {
domains = {};
results.( {
domains[item.] = (domains[item.] || ) + ;
});
domains;
}
() {
dates = results
.( (r.))
.( !(d));
(dates. === ) ;
{
: (.(...dates)),
: (.(...dates))
};
}
() {
[results1, results2] = .([
...(, { : topic1, : }),
...(, { : topic2, : })
]);
domains1 = (results1.( r.));
domains2 = (results2.( r.));
commonDomains = [...domains1].( domains2.(d));
{
: {
: topic1,
: results1.,
: domains1.
},
: {
: topic2,
: results2.,
: domains2.
},
: commonDomains
};
}
}
assistant = ();
assistant.();
research = assistant.(, );
.(, research);
comparison = assistant.(
,
);
.(, comparison);
Search Result Validation
import ZAI from 'z-ai-web-dev-sdk';
async function validateSearchResults(query) {
const zai = await ZAI.create();
const results = await zai.functions.invoke('web_search', {
query: query,
num: 10
});
const validated = results.map(item => {
let score = 0;
let flags = [];
if (item.snippet && item.snippet.length > 50) {
score += 20;
} else {
flags.push('short_snippet');
}
if (item.date && item.date !== 'N/A') {
score += 20;
} else {
flags.push('no_date');
}
try {
new URL(item.);
score += ;
} (e) {
flags.();
}
(!item..() &&
!item..()) {
score += ;
} {
flags.();
}
(item. && item.. > ) {
score += ;
} {
flags.();
}
{
...item,
: score,
: flags,
: score >=
};
});
validated.( b. - a.);
}
validated = ();
.(,
validated.( r.).
);
Best Practices
1. Query Optimization
const bad = await searchWeb('information');
const good = await searchWeb('JavaScript async/await best practices 2024');
const goodWithContext = await searchWeb('React hooks tutorial for beginners');
2. Error Handling
import ZAI from 'z-ai-web-dev-sdk';
async function safeSearch(query, retries = 3) {
let lastError;
for (let attempt = 1; attempt <= retries; attempt++) {
try {
const zai = await ZAI.create();
const results = await zai.functions.invoke('web_search', {
query: query,
num: 10
});
if (!Array.isArray(results) || results.length === 0) {
throw new Error('No results found or invalid response');
}
return {
success: true,
results: results,
attempts: attempt
};
} catch (error) {
lastError = error;
console.error(`Attempt ${attempt} failed:`, error.message);
if (attempt < retries) {
await ( (resolve, * attempt));
}
}
}
{
: ,
: lastError.,
: retries
};
}
3. Result Caching
import ZAI from 'z-ai-web-dev-sdk';
class CachedSearch {
constructor(cacheDuration = 3600000) {
this.cache = new Map();
this.cacheDuration = cacheDuration;
this.zai = null;
}
async initialize() {
this.zai = await ZAI.create();
}
getCacheKey(query, num) {
return `${query}_${num}`;
}
async search(query, num = 10) {
const cacheKey = this.getCacheKey(query, num);
const cached = this.cache.get(cacheKey);
if (cached && Date.now() - cached.timestamp < this.cacheDuration) {
.();
{
...cached.,
:
};
}
results = ...(, {
: query,
: num
});
..(cacheKey, {
: results,
: .()
});
{
: results,
:
};
}
() {
..();
}
() {
..;
}
}
search = ();
search.();
result1 = search.();
.(, result1.);
result2 = search.();
.(, result2.);
4. Rate Limiting
class RateLimitedSearch {
constructor(requestsPerMinute = 60) {
this.zai = null;
this.requestsPerMinute = requestsPerMinute;
this.requests = [];
}
async initialize() {
this.zai = await ZAI.create();
}
async search(query, num = 10) {
await this.checkRateLimit();
const results = await this.zai.functions.invoke('web_search', {
query: query,
num: num
});
this.requests.push(Date.now());
return results;
}
async checkRateLimit() {
const now = Date.now();
const oneMinuteAgo = now - 60000;
. = ..( time > oneMinuteAgo);
(.. >= .) {
oldestRequest = .[];
waitTime = - (now - oldestRequest);
.();
( (resolve, waitTime));
.();
}
}
}
Common Use Cases
- Real-time Information Retrieval: Get current news, stock prices, weather
- Research & Analysis: Gather information on specific topics
- Content Discovery: Find articles, tutorials, documentation
- Competitive Analysis: Research competitors and market trends
- Fact Checking: Verify information against web sources
- SEO & Content Research: Analyze search results for content strategy
- News Aggregation: Collect news from various sources
- Academic Research: Find papers, studies, and academic content
Integration Examples
Express.js Search API
import express from 'express';
import ZAI from 'z-ai-web-dev-sdk';
const app = express();
app.use(express.json());
let zaiInstance;
async function initZAI() {
zaiInstance = await ZAI.create();
}
app.get('/api/search', async (req, res) => {
try {
const { q: query, num = 10 } = req.query;
if (!query) {
return res.status(400).json({ error: 'Query parameter "q" is required' });
}
const numResults = Math.min(parseInt(num) || 10, 20);
const results = await zaiInstance.functions.invoke('web_search', {
query: query,
num: numResults
});
res.json({
success: true,
query: query,
: results.,
: results
});
} (error) {
res.().({
: ,
: error.
});
}
});
app.(, (req, res) => {
{
{ topic, timeframe = } = req.;
(!topic) {
res.().({ : });
}
timeKeywords = {
: ,
: ,
:
};
query = ;
results = zaiInstance..(, {
: query,
:
});
sortedResults = results.( {
(b.) - (a.);
});
res.({
: ,
: topic,
: timeframe,
: sortedResults
});
} (error) {
res.().({
: ,
: error.
});
}
});
().( {
app.(, {
.();
});
});
Search with AI Summary
import ZAI from 'z-ai-web-dev-sdk';
async function searchAndSummarize(query) {
const zai = await ZAI.create();
const searchResults = await zai.functions.invoke('web_search', {
query: query,
num: 10
});
const searchContext = searchResults
.slice(0, 5)
.map((r, i) => `${i + 1}. ${r.name}\n${r.snippet}`)
.join('\n\n');
const completion = await zai.chat.completions.create({
messages: [
{
role: 'assistant',
content: 'You are a research assistant. Summarize search results clearly and concisely.'
},
{
role: 'user',
content: `Query: "${query}"\n\nSearch Results:\n\n\nProvide a comprehensive summary of these results.`
}
],
: { : }
});
summary = completion.[]?.?.;
{
: query,
: summary,
: searchResults.(, ).( ({
: r.,
: r.
})),
: searchResults.
};
}
result = ();
.(, result.);
.(, result.);
Troubleshooting
Issue: "SDK must be used in backend"
- Solution: Ensure z-ai-web-dev-sdk is only imported and used in server-side code
Issue: Empty or no results returned
- Solution: Try different query terms, check internet connectivity, verify API status
Issue: Unexpected response format
- Solution: Verify the response is an array, check for API changes, add type validation
Issue: Rate limiting errors
- Solution: Implement request throttling, add delays between searches, use caching
Issue: Low quality search results
- Solution: Refine query terms, filter results by domain or date, validate result quality
Performance Tips
- Reuse SDK Instance: Create ZAI instance once and reuse across searches
- Implement Caching: Cache search results to reduce API calls
- Optimize Query Terms: Use specific, targeted queries for better results
- Limit Result Count: Request only the number of results you need
- Parallel Searches: Use Promise.all for multiple independent searches
- Result Filtering: Filter results on client side when possible
Security Considerations
- Input Validation: Sanitize and validate user search queries
- Rate Limiting: Implement rate limits to prevent abuse
- API Key Protection: Never expose SDK credentials in client-side code
- Result Filtering: Filter potentially harmful or inappropriate content
- URL Validation: Validate URLs before redirecting users
- Privacy: Don't log sensitive user search queries
Remember
- Always use z-ai-web-dev-sdk in backend code only
- The SDK is already installed - import as shown in examples
- Search results are returned as an array of SearchFunctionResultItem objects
- Implement proper error handling and retries for production
- Cache results when appropriate to reduce API calls
- Use specific query terms for better search results
- Validate and filter results before displaying to users
- Check
scripts/web_search.ts for a quick start example