Knowledge Base (RAG)
This content is not available in your language yet.
A Knowledge Base is a tenant-scoped collection of documents your agent can reference during conversation to ground its responses in your own data. Unlike tools, a knowledge base isn’t attached to an agent directly — it’s attached at the workflow LLM-node level, via LlmNodeConfig.knowledgeBaseId. The same knowledge base can be reused across multiple LLM nodes and multiple workflows within your tenant.
If you’d rather manage embeddings and retrieval yourself instead of using Wetel’s built-in knowledge base, see Embeddings.
Creating a knowledge base
Section titled “Creating a knowledge base”mutation CreateKB { createKnowledgeBase( input: { name: "Company Policies" description: "Employee handbook and guidelines" } ) { id name createdAt }}Ingesting documents
Section titled “Ingesting documents”There are two ways to get content into a knowledge base, depending on size.
Inline text (synchronous)
Section titled “Inline text (synchronous)”For small text snippets (up to 500 KB), ingest directly:
mutation IngestText { ingestDocument( input: { knowledgeBaseId: 123 fileName: "policies.txt" text: "All employees must complete onboarding within 30 days..." } )}ingestDocument returns the chunk count created, not an object. The text is chunked (roughly 512 words per chunk, with overlap between chunks), each chunk is embedded, and the knowledge base is queryable immediately.
File upload (asynchronous)
Section titled “File upload (asynchronous)”For larger documents (up to 20 MB), use the three-step upload flow. Supported formats, as of 2026-09-17: PDF, DOCX, Markdown (text/markdown), CSV (text/csv), and XLSX (application/vnd.openxmlformats-officedocument.spreadsheetml.sheet) — Markdown and CSV were previously unsupported entirely; XLSX previously required exporting to CSV first.
Each format is turned into plain text differently before chunking/embedding:
- PDF / DOCX — extracted as running plain text, same as before.
- Markdown — passed through as-is (no markdown-to-plaintext stripping). Headings, lists, and emphasis markers are left in place — they’re cheap, useful structural signal for retrieval and read fine in an LLM prompt as raw markdown.
- CSV — re-serialized row by row as
Header: value | Header: value | ...lines (the first row is always treated as the header row; a headerless file gets syntheticColumn Nlabels instead). This exists specifically so a chunk boundary landing mid-file doesn’t strand a value with no way to tell which column it came from — a flat comma-joined dump would lose that the moment the header row ends up in a different chunk. - XLSX — every worksheet is flattened into the same
Header: value | ...row format as CSV, with each sheet demarcated by a=== Sheet: <name> ===line so a chunk can still be attributed to the right sheet after a boundary cut.
The upload flow itself is the same regardless of format:
mutation RequestUpload { requestKnowledgeDocumentUpload( input: { knowledgeBaseId: 123 fileName: "employee_handbook.pdf" declaredSizeBytes: 2500000 mimeType: "application/pdf" } ) { objectStorageKey uploadUrl }}This returns a presigned upload URL (short expiry). Your client uploads the file directly to that URL — the file never passes through Wetel’s own servers. Once the upload completes, confirm it using the objectStorageKey you were given:
mutation ConfirmUpload { confirmKnowledgeDocumentUpload( input: { knowledgeBaseId: 123 fileName: "employee_handbook.pdf" mimeType: "application/pdf" objectStorageKey: "returned-storage-key" } ) { documentId parseStatus }}This creates the document record and queues it for background processing. Poll for status until it reaches READY (or FAILED):
query WatchStatus { knowledgeDocuments(knowledgeBaseId: 123) { id fileName parseStatus }}A document moves through PENDING → PARSING → READY. If text extraction fails (a corrupt PDF, an unsupported format, or the extraction step timing out), the document is marked FAILED and any storage quota reserved for it is released.
Wiring a knowledge base into an LLM node
Section titled “Wiring a knowledge base into an LLM node”Add knowledgeBaseId to an llm node’s config:
{ "id": "llm_answer_with_kb", "type": "llm", "label": "Answer Using Company Policies", "config": { "promptTemplate": "You are a helpful assistant. Answer using the provided reference material where relevant: {{userMessage}}", "knowledgeBaseId": 123, "outputVar": "response_text" }}At runtime, the current turn’s message is embedded and matched against that knowledge base’s chunks by similarity (the top handful of matches by default). The matching chunks are joined into a reference block and injected into the model’s context before it responds — the model sees them as grounding material, not as something the end user typed. See the workflow overview for the rest of the llm node’s configuration fields and how it fits into a graph.
Testing retrieval before wiring it into a workflow
Section titled “Testing retrieval before wiring it into a workflow”Before adding knowledgeBaseId to a live workflow, use the retrieveChunks diagnostic query to confirm your knowledge base actually surfaces relevant content for realistic questions:
query TestRetrieval { retrieveChunks( knowledgeBaseId: 123 query: "What is the onboarding process?" topK: 5 ) { chunkId documentId content score }}This runs the exact same retrieval logic an llm node uses at conversation time, so it’s a reliable way to validate real user phrasing before you depend on it in production.
Fail-open retrieval behavior
Section titled “Fail-open retrieval behavior”If retrieval fails at runtime — a transient network error, a quota limit, anything on the retrieval path — the llm node does not fail the turn. It logs the failure and proceeds without the extra context, so the agent still responds rather than the whole conversation turn erroring out.
This is a deliberate reliability choice, not a bug: a knowledge base being temporarily unreachable shouldn’t take your agent offline. The tradeoff is that knowledgeBaseId being configured on a node is not a guarantee that retrieval actually happened for any given reply — if you need to confirm whether it did, check that turn’s workflow run trace for the retrieval outcome, which distinguishes “retrieval ran and found nothing” from “retrieval didn’t run at all.” See Troubleshooting for how to inspect a run’s trace.
See also
Section titled “See also”- Workflow Overview — the full node/edge model, including where
llmnodes fit in a graph. - Embeddings — use Wetel purely as an embedding provider if you want to build your own retrieval pipeline instead.
- MCP Connectors — the other primary way to extend an agent, by calling external tools instead of retrieving reference text.
- Troubleshooting — general API error reference.