yao/agent/docs/search.md
Max bdfe7e83e8 Revise Agent and SUI Documentation for Clarity and Consistency
- Updated the Agent API documentation to reflect a new structure, emphasizing quick start instructions and reorganizing content for better readability.
- Renamed the main documentation title to "Yao Agent" and streamlined sections, including API endpoints and file management.
- Adjusted the SUI documentation to align with the Yao App Engine license, ensuring consistency across project documentation.
2026-01-01 11:08:30 +08:00

5.2 KiB

Search

The agent search system provides automatic search across web, knowledge base (KB), and database (DB).

Auto Search Flow

  1. Intent Detection - __yao.needsearch agent analyzes user message
  2. Search Execution - Executes web/kb/db searches based on intent
  3. Context Injection - Results injected as system message
  4. Citation - LLM can cite results using [1], [2] format

Configuration

Global (agent/search.yml)

web:
  provider: tavily  # tavily, serper, serpapi
  api_key_env: TAVILY_API_KEY
  max_results: 10

kb:
  threshold: 0.7
  graph: true

db:
  max_results: 20

keyword:
  max_keywords: 5
  language: en

citation:
  format: "[{index}]"
  auto_inject_prompt: true

Per Assistant (package.yao)

{
  "search": {
    "web": { "max_results": 5 },
    "kb": { "threshold": 0.8 },
    "citation": { "format": "[{index}]" }
  },
  "kb": {
    "collections": ["docs", "faq"]
  },
  "db": {
    "models": ["articles", "products"]
  }
}

Controlling Search in Hooks

function Create(ctx: agent.Context, messages: agent.Message[]): agent.Create {
  return {
    messages,
    search: false
  };
}

Enable Specific Types

function Create(ctx: agent.Context, messages: agent.Message[]): agent.Create {
  return {
    messages,
    search: {
      need_search: true,
      search_types: ["kb", "db"],  // Only KB and DB
      confidence: 1.0,
      reason: "controlled by hook"
    }
  };
}

Disable via Uses

function Create(ctx: agent.Context, messages: agent.Message[]): agent.Create {
  return {
    messages,
    uses: { search: "disabled" }
  };
}
const result = ctx.search.Web("query", {
  limit: 10,
  sites: ["example.com", "docs.example.com"],
  time_range: "week",  // day, week, month, year
  rerank: { top_n: 5 }
});
const result = ctx.search.KB("query", {
  collections: ["docs", "faq"],
  threshold: 0.7,
  limit: 10,
  graph: true,
  rerank: { top_n: 5 }
});
const result = ctx.search.DB("query", {
  models: ["articles"],
  wheres: [{ column: "status", value: "published" }],
  orders: [{ column: "created_at", option: "desc" }],
  select: ["id", "title", "content"],
  limit: 20,
  rerank: { top_n: 10 }
});
// Wait for all
const results = ctx.search.All([
  { type: "web", query: "topic" },
  { type: "kb", query: "topic", collections: ["docs"] },
  { type: "db", query: "topic", models: ["articles"] }
]);

// First success with results
const results = ctx.search.Any([
  { type: "web", query: "topic" },
  { type: "kb", query: "topic" }
]);

// First to complete
const results = ctx.search.Race([
  { type: "web", query: "topic" },
  { type: "kb", query: "topic" }
]);

Result Structure

interface SearchResult {
  type: "web" | "kb" | "db";
  query: string;
  source: "hook" | "auto" | "user";
  items: SearchItem[];
  error?: string;
}

interface SearchItem {
  citation_id: string;  // "1", "2", etc.
  title: string;
  url: string;
  content: string;
  score: number;
}

Custom Search in Hooks

function Create(ctx: agent.Context, messages: agent.Message[]): agent.Create {
  const query = messages[messages.length - 1]?.content || "";

  // Custom KB search
  const kbResult = ctx.search.KB(query, {
    collections: ["internal_docs"],
    threshold: 0.8
  });

  if (kbResult.items?.length > 0) {
    // Format results as context
    const context = kbResult.items
      .map((item, i) => `[${i + 1}] ${item.title}\n${item.content}`)
      .join("\n\n");

    // Inject as system message
    const contextMsg = {
      role: "system",
      content: `Reference information:\n${context}`
    };

    return {
      messages: [contextMsg, ...messages],
      search: false  // Skip auto search
    };
  }

  return { messages };
}

Authorization

KB Collections

Collections are filtered by user authorization:

// Only collections user has access to are searched
const result = ctx.search.KB("query", {
  collections: ["public", "internal", "secret"]
  // User without "secret" access won't search that collection
});

DB Models

Database queries include permission filters:

// Auth filters are automatically added
// e.g., { column: "__yao_created_by", value: user_id }
const result = ctx.search.DB("query", {
  models: ["user_documents"]
});

Web Search Providers

Tavily

web:
  provider: tavily
  api_key_env: TAVILY_API_KEY

Serper

web:
  provider: serper
  api_key_env: SERPER_API_KEY

SerpAPI

web:
  provider: serpapi
  api_key_env: SERPAPI_API_KEY

Citation

LLM responses can include citations:

Based on the documentation [1], the feature works by... [2]

References:
[1] Getting Started Guide - https://docs.example.com/start
[2] API Reference - https://docs.example.com/api

Citation Format

citation:
  format: "[{index}]"  # or "({index})" or "[^{index}]"
  auto_inject_prompt: true
  custom_prompt: |
    When citing sources, use the format [N] where N is the reference number.