Universal Search & Streaming

Updated

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.

[@portabletext/react] Unknown block type "callout", specify a component for it in the `components.types` prop

universal(params) executes a multi-engine search with fine-grained control. All options besides query are optional.

Parameters (UniversalSearchParams):

ParamTypeDefaultDescription
querystringrequiredThe search query
limitnumberMaximum total results
enginesSupportedEngine[]allWhich engines to query
score_resultsbooleanEnable relevance scoring
modeSearchMode'fast' for speed, 'deep' for thoroughness
fan_outbooleanGenerate sub-queries for broader coverage
fan_out_limitnumberMax sub-queries when fan-out is enabled
engine_configsRecord<SupportedEngine, EngineConfig>Per-engine configuration overrides
include_sitesstring[]Only return results from these domains
exclude_sitesstring[]Exclude results from these domains

Returns: SearchResults — contains search_id, results, key_highlights, and related_questions.

universal-search.ts
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`);
}
site-filtering.ts
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 TypeFieldsDescription
resultsengine_id, results, elapsed_ms?A batch of results from one engine
metadatakey_highlights?, related_questions?Summary metadata for the search
donesearch_id, total_resultsAll engines have finished
errorengine_id, messageAn engine encountered an error
streaming.ts
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`);
[@portabletext/react] Unknown block type "callout", specify a component for it in the `components.types` prop
streaming-no-callback.ts
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}`);
}
Was this helpful?