Skill v1.0.1
currentAutomated scan100/1002 files
version: "1.0.1" 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
# Simple search queryz-ai function --name "web_search" --args '{"query": "artificial intelligence"}'# Using short optionsz-ai function -n web_search -a '{"query": "latest tech news"}'
Search with Custom Parameters
# Limit number of resultsz-ai function \-n web_search \-a '{"query": "machine learning", "num": 5}'# Search with recency filter (results from last N days)z-ai function \-n web_search \-a '{"query": "cryptocurrency news", "num": 10, "recency_days": 7}'
Save Search Results
# Save results to JSON filez-ai function \-n web_search \-a '{"query": "climate change research", "num": 5}' \-o search_results.json# Recent news with file outputz-ai function \-n web_search \-a '{"query": "AI breakthroughs", "num": 3, "recency_days": 1}' \-o ai_news.json
Advanced Search Examples
# Search for specific topicsz-ai function \-n web_search \-a '{"query": "quantum computing applications", "num": 8}' \-o quantum.json# Find recent scientific papersz-ai function \-n web_search \-a '{"query": "genomics research", "num": 5, "recency_days": 30}' \-o genomics.json# Technology news from last 24 hoursz-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 keywordsnum(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 resultname: Title of the pagesnippet: Preview text/descriptionhost_name: Domain namerank: Result rankingdate: Publication/update datefavicon: 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; // Full URL of the resultname: string; // Title of the pagesnippet: string; // Preview text/descriptionhost_name: string; // Domain namerank: number; // Result rankingdate: string; // Publication/update datefavicon: string; // Favicon URL}
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;}// Usageconst 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;}// Usage - Get top 5 resultsconst topResults = await searchWithLimit('artificial intelligence news', 5);// Usage - Get top 20 resultsconst 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});// Format results for displayconst 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;}// Usageconst results = await getFormattedResults('climate change solutions');results.forEach(result => {console.log(`${result.position}. ${result.title}`);console.log(` ${result.url}`);console.log(` ${result.description}`);console.log('');});
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});// Filter resultslet filtered = results;if (filterDomain) {filtered = filtered.filter(item =>item.host_name.includes(filterDomain));}if (minSnippetLength > 0) {filtered = filtered.filter(item =>item.snippet.length >= minSnippetLength);}return filtered;}extractDomains(results) {return [...new Set(results.map(item => item.host_name))];}groupByDomain(results) {const grouped = {};results.forEach(item => {if (!grouped[item.host_name]) {grouped[item.host_name] = [];}grouped[item.host_name].push(item);});return grouped;}sortByDate(results, ascending = false) {return results.sort((a, b) => {const dateA = new Date(a.date);const dateB = new Date(b.date);return ascending ? dateA - dateB : dateB - dateA;});}}// Usageconst processor = new SearchProcessor();await processor.initialize();const results = await processor.search('machine learning tutorials', {num: 15,minSnippetLength: 50});console.log('Domains found:', processor.extractDomains(results));console.log('Grouped by domain:', processor.groupByDomain(results));console.log('Sorted by date:', processor.sortByDate(results));
News Search
import ZAI from 'z-ai-web-dev-sdk';async function searchNews(topic, timeframe = 'recent') {const zai = await ZAI.create();// Add time-based keywords to queryconst 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});// Sort by date (most recent first)const sortedResults = results.sort((a, b) => {return new Date(b.date) - new Date(a.date);});return sortedResults;}// Usageconst aiNews = await searchNews('artificial intelligence', 'today');const techNews = await searchNews('technology', 'week');console.log('Latest AI News:');aiNews.forEach(item => {console.log(`${item.name} (${item.date})`);console.log(`${item.snippet}\n`);});
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});// Analyze resultsconst analysis = {topic: topic,totalResults: results.length,sources: this.extractDomains(results),topResults: results.slice(0, 5).map(r => ({title: r.name,url: r.url,summary: r.snippet})),dateRange: this.getDateRange(results)};return analysis;}extractDomains(results) {const domains = {};results.forEach(item => {domains[item.host_name] = (domains[item.host_name] || 0) + 1;});return domains;}getDateRange(results) {const dates = results.map(r => new Date(r.date)).filter(d => !isNaN(d));if (dates.length === 0) return null;return {earliest: new Date(Math.min(...dates)),latest: new Date(Math.max(...dates))};}async compareTopics(topic1, topic2) {const [results1, results2] = await Promise.all([this.zai.functions.invoke('web_search', { query: topic1, num: 10 }),this.zai.functions.invoke('web_search', { query: topic2, num: 10 })]);const domains1 = new Set(results1.map(r => r.host_name));const domains2 = new Set(results2.map(r => r.host_name));const commonDomains = [...domains1].filter(d => domains2.has(d));return {topic1: {name: topic1,results: results1.length,uniqueDomains: domains1.size},topic2: {name: topic2,results: results2.length,uniqueDomains: domains2.size},commonDomains: commonDomains};}}// Usageconst assistant = new ResearchAssistant();await assistant.initialize();const research = await assistant.researchTopic('quantum computing', 'deep');console.log('Research Analysis:', research);const comparison = await assistant.compareTopics('renewable energy','solar power');console.log('Topic Comparison:', 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});// Validate and score resultsconst validated = results.map(item => {let score = 0;let flags = [];// Check snippet qualityif (item.snippet && item.snippet.length > 50) {score += 20;} else {flags.push('short_snippet');}// Check date availabilityif (item.date && item.date !== 'N/A') {score += 20;} else {flags.push('no_date');}// Check URL validitytry {new URL(item.url);score += 20;} catch (e) {flags.push('invalid_url');}// Check domain quality (not perfect, but basic check)if (!item.host_name.includes('spam') &&!item.host_name.includes('ads')) {score += 20;} else {flags.push('suspicious_domain');}// Check title qualityif (item.name && item.name.length > 10) {score += 20;} else {flags.push('short_title');}return {...item,qualityScore: score,validationFlags: flags,isHighQuality: score >= 80};});// Sort by quality scorereturn validated.sort((a, b) => b.qualityScore - a.qualityScore);}// Usageconst validated = await validateSearchResults('best programming practices');console.log('High quality results:',validated.filter(r => r.isHighQuality).length);
Best Practices
1. Query Optimization
// Bad: Too vagueconst bad = await searchWeb('information');// Good: Specific and targetedconst good = await searchWeb('JavaScript async/await best practices 2024');// Good: Include contextconst 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) {// Wait before retry (exponential backoff)await new Promise(resolve => setTimeout(resolve, 1000 * attempt));}}}return {success: false,error: lastError.message,attempts: retries};}
3. Result Caching
import ZAI from 'z-ai-web-dev-sdk';class CachedSearch {constructor(cacheDuration = 3600000) { // 1 hour defaultthis.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);// Check if cached and not expiredif (cached && Date.now() - cached.timestamp < this.cacheDuration) {console.log('Returning cached results');return {...cached.data,cached: true};}// Perform fresh searchconst results = await this.zai.functions.invoke('web_search', {query: query,num: num});// Cache resultsthis.cache.set(cacheKey, {data: results,timestamp: Date.now()});return {results: results,cached: false};}clearCache() {this.cache.clear();}getCacheSize() {return this.cache.size;}}// Usageconst search = new CachedSearch(1800000); // 30 minutes cacheawait search.initialize();const result1 = await search.search('TypeScript tutorial');console.log('Cached:', result1.cached); // falseconst result2 = await search.search('TypeScript tutorial');console.log('Cached:', result2.cached); // true
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;// Remove requests older than 1 minutethis.requests = this.requests.filter(time => time > oneMinuteAgo);if (this.requests.length >= this.requestsPerMinute) {const oldestRequest = this.requests[0];const waitTime = 60000 - (now - oldestRequest);console.log(`Rate limit reached. Waiting ${waitTime}ms`);await new Promise(resolve => setTimeout(resolve, waitTime));// Recheck after waitingreturn this.checkRateLimit();}}}
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,totalResults: results.length,results: results});} catch (error) {res.status(500).json({success: false,error: error.message});}});app.get('/api/search/news', async (req, res) => {try {const { topic, timeframe = 'recent' } = req.query;if (!topic) {return res.status(400).json({ error: 'Topic parameter is required' });}const timeKeywords = {recent: 'latest news',today: 'today news',week: 'this week news'};const query = `${topic} ${timeKeywords[timeframe] || timeKeywords.recent}`;const results = await zaiInstance.functions.invoke('web_search', {query: query,num: 15});// Sort by dateconst sortedResults = results.sort((a, b) => {return new Date(b.date) - new Date(a.date);});res.json({success: true,topic: topic,timeframe: timeframe,results: sortedResults});} catch (error) {res.status(500).json({success: false,error: error.message});}});initZAI().then(() => {app.listen(3000, () => {console.log('Search API running on port 3000');});});
Search with AI Summary
import ZAI from 'z-ai-web-dev-sdk';async function searchAndSummarize(query) {const zai = await ZAI.create();// Step 1: Search the webconst searchResults = await zai.functions.invoke('web_search', {query: query,num: 10});// Step 2: Create summary using chat completionsconst 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${searchContext}\n\nProvide a comprehensive summary of these results.`}],thinking: { type: 'disabled' }});const summary = completion.choices[0]?.message?.content;return {query: query,summary: summary,sources: searchResults.slice(0, 5).map(r => ({title: r.name,url: r.url})),totalResults: searchResults.length};}// Usageconst result = await searchAndSummarize('benefits of renewable energy');console.log('Summary:', result.summary);console.log('Sources:', result.sources);
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.tsfor a quick start example