Skip to main content

Overview

The Semantic Search Agent performs intelligent semantic search on customer feedback and feature requests. It uses embeddings-based vector search when available, falling back to recent open requests when vector search is unavailable. Location: packages/ai/src/agents/search/index.ts

Purpose

Analyzes search queries and finds matching feature requests by:
  • Creating embeddings for semantic understanding
  • Searching vector database for similar requests
  • Ranking results by relevance and confidence
  • Filtering by product areas when specified

Agent Configuration

Model: Claude Haiku (via claudeHaiku) Tools: Optional (uses tools when candidates are not pre-provided) Output: Structured object with matched requests and confidence scores

System Prompt

The agent operates with the following instructions:
You an AI agent that performs semantic search on customer feedback.

Your job is to find feature requests that match a search query.

Workflow:
1. If candidates are not provided, use the searchRequests tool to find matching items
2. Analyze the results and rank by relevance to the query
3. Return matches with requestId, title, description, confidence, and reason

Confidence scoring:
- 0.9-1.0: Query describes the exact same feature/issue
- 0.8-0.89: Strong match, same general feature with minor differences
- 0.7-0.79: Moderate match, related but not identical
- 0.5-0.69: Weak match but potentially relevant
- Below 0.5: Not a match, don't include

Return all matches with confidence >= 0.5, ordered by highest confidence first.
Be comprehensive but accurate - include potential matches rather than miss relevant ones.

Available Tools

searchRequests

Search for request items matching a query using semantic search.
query
string
required
The search query
limit
number
default:50
Max results to return
excludeIds
string[]
IDs to exclude from results

createEmbedding

Create an embedding vector for semantic search.
text
string
required
The text to create an embedding for

searchSimilar

Search for similar requests using vector similarity.
embedding
number[]
required
The embedding vector to search with
limit
number
default:100
Max results to return
excludeIds
string[]
IDs to exclude from results

getRequestsByIds

Fetch full request details for a list of IDs.
ids
string[]
required
Request IDs to fetch

storeEmbedding

Store an embedding for a request item in the vector database.
requestId
string
required
The request ID
embedding
number[]
required
The embedding vector
metadata
object
required
Metadata to store with the embedding
title
string
required
description
string
required
areaIds
string[]

Input

query
string
required
The search query to find matching requests
candidates
object[]
Optional pre-filtered list of candidate requests to search within
id
string
required
title
string
required
description
string
required
areaIds
string[]
context
string
Additional context to help understand the query
scope
object
Filter scope for the search
areaIds
string[]
Filter to these product areas

Output

output
object
matches
object[]
Matches ordered by highest confidence first
requestId
string
The matching request ID
title
string
The request title
description
string
The request description
confidence
number
Confidence score from 0.0 to 1.0
reason
string
Brief explanation of why this matches
usage
object
inputTokens
number
outputTokens
number
steps
number
Number of tool loop iterations

Usage Example

import { agent } from "@feedback/ai/agents";

const result = await agent.search.generate({
  query: "Users need to export analytics data",
  context: "Customer is requesting CSV export functionality",
  scope: {
    areaIds: ["analytics-area-id"]
  }
});

const matches = result.output.matches.sort((a, b) => b.confidence - a.confidence);
console.log(`Found ${matches.length} matches`);

for (const match of matches) {
  console.log(`${match.title} (${match.confidence})`);
  console.log(`  Reason: ${match.reason}`);
}

Real-World Usage

From apps/www/src/workflows/shared/semantic-search-requests.ts:
import { agent } from "@feedback/ai/agents";

export async function semanticSearchRequests(
  query: string,
  options?: {
    context?: string;
    candidates?: RequestItem[];
  },
) {
  "use step";

  const result = await agent.search.generate({
    query,
    candidates: options?.candidates,
    context: options?.context,
  });

  return {
    matches: result.output.matches.sort((a, b) => b.confidence - a.confidence),
  };
}

Context Configuration

Customize the search behavior by providing a SearchToolContext:
import { createSearchAgent } from "@feedback/ai/agents";

const searchAgent = createSearchAgent({
  createEmbedding: async (text: string) => {
    // Custom embedding logic
    return await myEmbeddingService.create(text);
  },
  searchSimilar: async (embedding, limit, excludeIds) => {
    // Custom vector search logic
    return await myVectorDB.search(embedding, limit, excludeIds);
  },
  fetchRequestsByIds: async (ids) => {
    // Custom request fetching logic
    return await myDB.getRequests(ids);
  }
});

Build docs developers (and LLMs) love