Skip to main content

Documentation Index

Fetch the complete documentation index at: https://www.plain.com/docs/llms.txt

Use this file to discover all available pages before exploring further.

To answer a customer’s question, an agent needs facts. Rather than building and maintaining your own vector store, you can search the knowledge you’ve already added to Plain with the searchKnowledgeSources query. It runs a semantic search and returns the most relevant passages, ready to drop into a prompt. This is the retrieval half of a RAG (“retrieval-augmented generation”) agent.

What knowledge sources are

A knowledge source is any content in Plain that can be searched to answer a question. There are two kinds:
  • Help center articles — the self-serve articles you publish in Plain’s help center.
  • Indexed documents — external pages and documents you’ve indexed for AI, like your public docs or marketing site.
You manage both in Plain, and searchKnowledgeSources searches across them in a single call.

Search knowledge sources

Pass a natural-language searchQuery and Plain returns the passages most semantically relevant to it, ordered most-relevant first. Each result carries the matched content (a chunk of text) plus a reference to the source it came from. This operation requires the knowledgeSource:read permission.
const results = await plain.query.searchKnowledgeSources({
  searchQuery: "how do I reset my password?",
  pageSize: 5,
});

for (const result of results) {
  console.log(result.content);

  // Narrow on __typename to get a reference back to the source
  if (result.__typename === "HelpCenterArticleSearchResult") {
    const article = await result.helpCenterArticle;
    console.log(article.title);
  } else if (result.__typename === "IndexedDocumentSearchResult") {
    const doc = await result.indexedDocument;
    console.log(doc.url);
  }
}
The query returns a union of HelpCenterArticleSearchResult and IndexedDocumentSearchResult. Narrow with __typename (or instanceof) the same way as any other union type in the SDK.
pageSize defaults to 10 and can be between 1 and 50. searchQuery must be between 1 and 1000 characters.

Feeding results into a prompt

The content field is what you usually want for generation: it’s the matched passage, already trimmed to the relevant part of the source. Concatenate the top results into your prompt as context:
const results = await plain.query.searchKnowledgeSources({
  searchQuery: customerQuestion,
  pageSize: 5,
});

const knowledge = results.map((r) => r.content).join("\n\n---\n\n");

const reply = await myModel.generate({
  system: "You are a customer support agent. Answer only from the knowledge below.",
  prompt: `Knowledge:\n\n${knowledge}\n\nQuestion: ${customerQuestion}`,
});
From here you can reply directly, suggest a reply, or post a note with whatever the model produces. Keeping the source reference (the article title or document URL) alongside each passage lets your agent cite where an answer came from. The optional options argument lets you control what gets searched:
OptionTypeWhat it does
types[INDEXED_DOCUMENT | HELP_CENTER_ARTICLE]Restrict to one kind of source. Omit to search both.
labelTypeIds[ID!]Only return indexed documents tagged with these label types.
includeNonCustomerFacingBooleanInclude help centers marked as not customer-facing. Defaults to false.
For example, to search only your help center articles:
const results = await plain.query.searchKnowledgeSources({
  searchQuery: customerQuestion,
  options: { types: ["HELP_CENTER_ARTICLE"] },
});
If you pass labelTypeIds without specifying types, the search is limited to indexed documents, since labels only apply to them.

Resources