Universal Search & Streaming
Universal search queries multiple engines simultaneously and returns unified results. You can control which engines to use, enable relevance scoring, filter by domain, and fan out queries for broader coverage. The streaming variant lets you process results as each engine responds rather than waiting for all engines to finish.
Universal Search
universal(params) executes a multi-engine search with fine-grained control. All options besides query are optional.
Parameters (UniversalSearchParams):
| Param | Type | Default | Description |
|---|---|---|---|
query | string | required | The search query |
limit | number | — | Maximum total results |
engines | SupportedEngine[] | all | Which engines to query |
score_results | boolean | — | Enable relevance scoring |
mode | SearchMode | — | 'fast' for speed, 'deep' for thoroughness |
fan_out | boolean | — | Generate sub-queries for broader coverage |
fan_out_limit | number | — | Max sub-queries when fan-out is enabled |
engine_configs | Record<SupportedEngine, EngineConfig> | — | Per-engine configuration overrides |
include_sites | string[] | — | Only return results from these domains |
exclude_sites | string[] | — | Exclude results from these domains |
Returns: SearchResults — contains search_id, results, key_highlights, and related_questions.
import { Chaos } from '@chaoslabs/ai-sdk';
const chaos = new Chaos({ apiKey: process.env.CHAOS_API_KEY! });
// Deep search with scoring and fan-out
const { results, search_id, key_highlights } = await chaos.search.universal({
query: 'ETH staking yields comparison across protocols',
limit: 20,
mode: 'deep',
engines: ['vector', 'keyword'],
score_results: true,
fan_out: true,
fan_out_limit: 5,
});
console.log(`Search ${search_id}: ${results.length} results`);
console.log(`Highlights: ${key_highlights}\n`);
for (const r of results) {
console.log(`[${r.engine_id}] ${r.title} (${r.elapsed_ms}ms)`);
console.log(` ${r.description}\n`);
}import { Chaos } from '@chaoslabs/ai-sdk';
const chaos = new Chaos({ apiKey: process.env.CHAOS_API_KEY! });
// Only search specific protocol documentation sites
const docsOnly = await chaos.search.universal({
query: 'Morpho Blue vault creation',
include_sites: ['docs.morpho.org', 'morpho.org'],
mode: 'fast',
});
console.log(`Results from Morpho docs: ${docsOnly.results.length}`);
// Exclude social media from results
const noSocial = await chaos.search.universal({
query: 'DeFi lending risks 2025',
exclude_sites: ['reddit.com', 'twitter.com', 'x.com'],
score_results: true,
});
console.log(`Results excluding social: ${noSocial.results.length}`);Streaming Results
universalStream(params, onEvent?) streams search results in real time as each engine responds. It accepts the same UniversalSearchParams as universal(), plus an optional callback that fires for each event.
The method returns a promise that resolves to the full array of SearchStreamEvent objects once all engines have finished. If you provide an onEvent callback, you can process events incrementally as they arrive.
Stream event types:
| Event Type | Fields | Description |
|---|---|---|
results | engine_id, results, elapsed_ms? | A batch of results from one engine |
metadata | key_highlights?, related_questions? | Summary metadata for the search |
done | search_id, total_results | All engines have finished |
error | engine_id, message | An engine encountered an error |
import { Chaos } from '@chaoslabs/ai-sdk';
const chaos = new Chaos({ apiKey: process.env.CHAOS_API_KEY! });
const collectedResults: Array<{ engine: string; title: string }> = [];
const events = await chaos.search.universalStream(
{
query: 'Morpho Blue vault strategies',
mode: 'deep',
score_results: true,
},
(event) => {
switch (event.type) {
case 'results':
console.log(`Engine ${event.engine_id}: +${event.results.length} results (${event.elapsed_ms}ms)`);
for (const r of event.results) {
collectedResults.push({ engine: event.engine_id, title: r.title ?? '(untitled)' });
}
break;
case 'metadata':
if (event.key_highlights) {
console.log(`\nHighlights: ${event.key_highlights}`);
}
break;
case 'done':
console.log(`\nSearch complete: ${event.total_results} total results (ID: ${event.search_id})`);
break;
case 'error':
console.error(`Engine ${event.engine_id} failed: ${event.message}`);
break;
}
},
);
console.log(`\nProcessed ${events.length} stream events`);
console.log(`Collected ${collectedResults.length} results across all engines`);import { Chaos } from '@chaoslabs/ai-sdk';
const chaos = new Chaos({ apiKey: process.env.CHAOS_API_KEY! });
// Without a callback — just await the full result
const events = await chaos.search.universalStream({
query: 'Aave governance proposals',
mode: 'fast',
engines: ['vector'],
});
// Process events after the stream completes
const resultEvents = events.filter((e) => e.type === 'results');
const doneEvent = events.find((e) => e.type === 'done');
for (const e of resultEvents) {
if (e.type === 'results') {
console.log(`${e.engine_id}: ${e.results.length} results`);
}
}
if (doneEvent && doneEvent.type === 'done') {
console.log(`Total: ${doneEvent.total_results}`);
}