PageSourceSearch

https://bastio.com/assets/knowledge-base-PNCZM0iA.js

js bastio.com collected 2026-10-09 22:56:19 UTC 19,952 bytes, 177 lines download raw bytes

1import{j as e}from"./index-BkgFiefw.js";let a={title:"Knowledge base",description:"Upload, attach, and cite — RAG for the Workspace chat product."},r=[{href:"/docs/api-reference"},{href:"/docs/cloud/workspace/for-admins"},{href:"/docs/cloud/workspace/for-employees"}],o={contents:[{heading:void 0,content:`The knowledge base is how you make Workspace smarter about your
2specific business. Upload PDFs, paste in policies, point at URLs;
3attach them to assistants; chats with that assistant cite the
4sources inline.`},{heading:"lifecycle",content:`Upload. Workspace → Knowledge Base → Upload PDF or paste
5text. Each source gets a UUID and a pending status.`},{heading:"lifecycle",content:`Ingest. The worker chunks the source into ~1000-char
6windows, embeds each chunk via OpenAI text-embedding-3-small,
7stores them in PostgreSQL (with pgvector when available).
8Status flips pending → processing → ready.`},{heading:"lifecycle",content:`Attach. Edit an assistant → Knowledge base sources →
9check the source. The join table records the attachment.`},{heading:"lifecycle",content:`Retrieve. When a user sends a message in a chat with
10that assistant, the gateway runs RAG: top-K most relevant
11chunks (by cosine similarity, falling back to keyword match)
12are pulled and added to the system prompt.`},{heading:"lifecycle",content:`Cite. The assistant's reply is persisted 
12with the unique
13sources used as metadata. The chat UI renders source chips
14below the response.`},{heading:"supported-formats",content:"PDF (extracted via pdftotext)"},{heading:"supported-formats",content:"Plain text (markdown supported, just paste it in)"},{heading:"supported-formats",content:`URL (Bastio fetches and extracts the readable content; useful
15for public documentation pages)`},{heading:"supported-formats",content:`Word docs, slides, and image-OCR are not yet supported. Convert
16to PDF first.`},{heading:"sizing--limits",content:"Max file size: 25 MB"},{heading:"sizing--limits",content:`Max chunks per source: 5,000 (covers ~3,000 pages of plain
17text)`},{heading:"sizing--limits",content:`Workspace-wide chunk total drives retrieval latency. Up to
18~10k chunks runs in-process; pgvector's HNSW index kicks in
19beyond that and scales to ~1M chunks per workspace.`},{heading:"vector-vs-keyword-retrieval",content:`If your environment has OPENAI_API_KEY configured (cloud:
20always; OSS: optional), embeddings drive retrieval — much
21better recall. Without embeddings, Bastio falls back to a
22keyword-overlap search that handles ~80% of practical cases.`},{heading:"vector-vs-keyword-retrieval",content:`The chat surface looks identical either way; the source chips
23still render the same.`},{heading:"attaching-multiple-sources",content:`One assistant, many sources. The workspace handbook and the
24brand guide can both attach to the "Acme Helper" assistant —
25when a user asks "what's our return policy + how do we phrase
26it on social?" both show up as citations.`},{heading:"citations-in-the-ui",content:"The assistant's reply persists with metadata like:"},{heading:"citations-in-the-ui",content:`The chat UI renders one chip per unique source under the reply.
27Hover for the full source name. (Click-to-open is on the
28roadmap.)`},{heading:"what-gets-retrieved",content:`Bastio retrieves chunks at message-send time, not at attach
29time, so the context reflects the current user's prompt:`},{heading:"what-gets-retrieved",content:`"What's our PTO policy?" → handbook chunks about PTO win.`},{heading:"what-gets-retrieved",content:`"How do I greet a customer?" → brand-guide chunks about tone
30win, even though the same handbook is attached.`},{heading:"what-gets-retrieved",content:"Top-K defaults to 5 chunks. Tunable per workspace in settings."},{heading:"updating-a-source",content:`Re-uploading the same name re-ingests with a fresh chunk set.
31Old chunks are archived (not deleted), so existing
32conversations that cited them still display the citation
33correctly. Only new conversations see the new content.`},{heading:"detaching-a-source",content:`Edit the assistant → uncheck the source. The join row is
34removed. Existing conversations with that assistant continue to
35show old citations in their history, but new turns won't
36retrieve from the detached source.`},{heading:"archiving-a-source",content:`Knowledge Base tab → trash icon. Sets archived_at = NOW().
37The source no longer appears in the picker for new attachments,
38but rows that were already attached keep working until the
39admin detaches them. Audited as knowledge.archived.`},{heading:"common-pitfalls",content:`No assistant attached → no RAG. A workspace with KB
40uploaded but no assistant attached gets no citations. Make
41sure the assistant the user picks has at least one source
42attached.`},{heading:"common-pitfalls",content:`Chat says "stuck on pending" for a PDF upload. Check that
43the worker is running. In dev, all-in-one mode handles this
44automatically; in split-binary prod, ensure cmd/worker is
45up. River migrations run on every server start since v2.`},{heading:"common-pitfalls",content:`Citations list is empty for a chat with KB attached. The
46retrieval found no relevant chunks. Either the question is
47far from your corpus, or your top-K threshold is too high.
48Look at the assistant's "Trace" tab for the retrieval scores
49per chunk.`},{heading:"api-surface",content:"For CI / programmatic use:"},{heading:"api-surface",content:"GET /v1/workspace/knowledge — list sources"},{heading:"api-surface",content:"POST /v1/workspace/knowledge/upload — multipart upload"},{heading:"api-surface",content:"POST /v1/workspace/knowledge — inline-text source"},{heading:"api-surface",content:"DELETE /v1/workspace/knowledge/{id} — archive"},{heading:"api-surface",content:`PATCH /v1/workspace/assistants/{id} with
50knowledge_source_ids: ["uuid1", "uuid2"] — attach (replaces
51the full set)`},{heading:"api-surface",content:`See the API reference on your running
52gateway for the full schema.`},{heading:"next",content:`For admins — the rest of
53the admin surface.`},{heading:"next",content:`For employees — what
54the citation chips look like to your team.`}],headings:[{id:"lifecycle",content:"Lifecycle"},{id:"supported-formats",content:"Supported formats"},{id:"sizing--limits",content:"Sizing + limits"},{id:"vector-vs-keyword-retrieval",content:"Vector vs. keyword retrieval"},{id:"attaching-multiple-sources",content:"Attaching multiple sources"},{id:"citations-in-the-ui",content:"Citations in the UI"},{id:"what-gets-retrieved",content:"What gets retrieved"},{id:"updating-a-source",content:"Updating a source"},{id:"detaching-a-source",content:"Detaching a source"}
54,{id:"archiving-a-source",content:"Archiving a source"},{id:"common-pitfalls",content:"Common pitfalls"},{id:"api-surface",content:"API surface"},{id:"next",content:"Next"}]};const h=[{depth:2,url:"#lifecycle",title:e.jsx(e.Fragment,{children:"Lifecycle"})},{depth:2,url:"#supported-formats",title:e.jsx(e.Fragment,{children:"Supported formats"})},{depth:2,url:"#sizing--limits",title:e.jsx(e.Fragment,{children:"Sizing + limits"})},{depth:2,url:"#vector-vs-keyword-retrieval",title:e.jsx(e.Fragment,{children:"Vector vs. keyword retrieval"})},{depth:2,url:"#attaching-multiple-sources",title:e.jsx(e.Fragment,{children:"Attaching multiple sources"})},{depth:2,url:"#citations-in-the-ui",title:e.jsx(e.Fragment,{children:"Citations in the UI"})},{depth:2,url:"#what-gets-retrieved",title:e.jsx(e.Fragment,{children:"What gets retrieved"})},{depth:2,url:"#updating-a-source",title:e.jsx(e.Fragment,{children:"Updating a source"})},{depth:2,url:"#detaching-a-source",title:e.jsx(e.Fragment,{children:"Detaching a source"})},{depth:2,url:"#archiving-a-source",title:e.jsx(e.Fragment,{children:"Archiving a source"})},{depth:2,url:"#common-pitfalls",title:e.jsx(e.Fragment,{children:"Common pitfalls"})},{depth:2,url:"#api-surface",title:e.jsx(e.Fragment,{children:"API surface"})},{depth:2,url:"#next",title:e.jsx(e.Fragment,{children:"Next"})}];function n(s){const t={a:"a",code:"code",em:"em",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",span:"span",strong:"strong",ul:"ul",...s.components};return e.jsxs(e.Fragment,{children:[e.jsx(t.p,{children:`The knowledge base is how you make Workspace smarter about your
55specific business. Upload PDFs, paste in policies, point at URLs;
56attach them to assistants; chats with that assistant cite the
57sources inline.`}),`
58`,e.jsx(t.h2,{id:"lifecycle",children:"Lifecycle"}),`
59`,e.jsx(e.Fragment,{children:e.jsx(t.pre,{className:"shiki shiki-themes github-light github-dark",style:{"--shiki-light":"#24292e","--shiki-dark":"#e1e4e8","--shiki-light-bg":"#fff","--shiki-dark-bg":"#24292e"},tabIndex:"0",icon:'<svg viewBox="0 0 24 24"><path d="M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z" fill="currentColor" /></svg>',children:e.jsx(t.code,{children:e.jsx(t.span,{className:"line",children:e.jsx(t.span,{children:"upload → ingest → ready → attach → retrieve → cite"})})})})}),`
60`,e.jsxs(t.ol,{children:[`
61`,e.jsxs(t.li,{children:[e.jsx(t.strong,{children:"Upload."}),` Workspace → Knowledge Base → Upload PDF or paste
62text. Each source gets a UUID and a `,e.jsx(t.code,{children:"pending"})," status."]}),`
63`,e.jsxs(t.li,{children:[e.jsx(t.strong,{children:"Ingest."}),` The worker chunks the source into ~1000-char
64windows, embeds each chunk via OpenAI text-embedding-3-small,
65stores them in PostgreSQL (with pgvector when available).
66Status flips `,e.jsx(t.code,{children:"pending → processing → ready"}),"."]}),`
67`,e.jsxs(t.li,{children:[e.jsx(t.strong,{children:"Attach."}),` Edit an assistant → Knowledge base sources →
68check the source. The join table records the attachment.`]}),`
69`,e.jsxs(t.li,{children:[e.jsx(t.strong,{children:"Retrieve."}),` When a user sends a message in a chat with
70that assistant, the gateway runs RAG: top-K most relevant
71chunks (by cosine similarity, falling back to keyword match)
72are pulled and added to the system prompt.`]}),`
73`,e.jsxs(t.li,{children:[e.jsx(t.strong,{children:"Cite."}
73),` The assistant's reply is persisted with the unique
74sources used as metadata. The chat UI renders source chips
75below the response.`]}),`
76`]}),`
77`,e.jsx(t.h2,{id:"supported-formats",children:"Supported formats"}),`
78`,e.jsxs(t.ul,{children:[`
79`,e.jsx(t.li,{children:"PDF (extracted via pdftotext)"}),`
80`,e.jsx(t.li,{children:"Plain text (markdown supported, just paste it in)"}),`
81`,e.jsx(t.li,{children:`URL (Bastio fetches and extracts the readable content; useful
82for public documentation pages)`}),`
83`]}),`
84`,e.jsx(t.p,{children:`Word docs, slides, and image-OCR are not yet supported. Convert
85to PDF first.`}),`
86`,e.jsx(t.h2,{id:"sizing--limits",children:"Sizing + limits"}),`
87`,e.jsxs(t.ul,{children:[`
88`,e.jsx(t.li,{children:"Max file size: 25 MB"}),`
89`,e.jsx(t.li,{children:`Max chunks per source: 5,000 (covers ~3,000 pages of plain
90text)`}),`
91`,e.jsx(t.li,{children:`Workspace-wide chunk total drives retrieval latency. Up to
92~10k chunks runs in-process; pgvector's HNSW index kicks in
93beyond that and scales to ~1M chunks per workspace.`}),`
94`]}),`
95`,e.jsx(t.h2,{id:"vector-vs-keyword-retrieval",children:"Vector vs. keyword retrieval"}),`
96`,e.jsxs(t.p,{children:["If your environment has ",e.jsx(t.code,{children:"OPENAI_API_KEY"}),` configured (cloud:
97always; OSS: optional), embeddings drive retrieval — much
98better recall. Without embeddings, Bastio falls back to a
99keyword-overlap search that handles ~80% of practical cases.`]}),`
100`,e.jsx(t.p,{children:`The chat surface looks identical either way; the source chips
101still render the same.`}),`
102`,e.jsx(t.h2,{id:"attaching-multiple-sources",children:"Attaching multiple sources"}),`
103`,e.jsx(t.p,{children:`One assistant, many sources. The workspace handbook and the
104brand guide can both attach to the "Acme Helper" assistant —
105when a user asks "what's our return policy + how do we phrase
106it on social?" both show up as citations.`}),`
107`,e.jsx(t.h2,{id:"citations-in-the-ui",children:"Citations in the UI"}),`
108`,e.jsx(t.p,{children:"The assistant's reply persists with metadata like:"}),`
109`,e.jsx(e.Fragment,{children:e.jsx(t.pre,{className:"shiki shiki-themes github-light github-dark",style:{"--shiki-light":"#24292e","--shiki-dark":"#e1e4e8","--shiki-light-bg":"#fff","--shiki-dark-bg":"#24292e"},tabIndex:"0",icon:'<svg viewBox="0 0 24 24"><path d="M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z" fill="currentColor" /></svg>',children:e.jsxs(t.code,{children:[e.jsx(t.span,{className:"line",children:e.jsx(t.span,{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"},children:"{"})}),`
110`,e.jsxs(t.span,{className:"line",children:[e.jsx(t.span,{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"},children:'  "citations"'}),e.jsx(t.span,{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"},children:": ["})]}),`
111`,e.jsxs(t.span,{className:"line",children:[e.jsx(t.span,{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"},children:"    { "}),e.jsx(t.span,{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"},children:'"source_id"'}),e.jsx(t.span,{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"},children:": "}),e.jsx(t.span,{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"},children:'"0193-…"'}),e.jsx(t.span,{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"},children:", "}),e.jsx(t.span,{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"},children:'"source_name"'}),e.jsx(t.span,{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"},children:": "}),e.jsx(t.span,{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"},children:'"employee-handbook.pdf"'}),e.jsx(t.span,{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"},children:" },"})]}),`
112`,e.jsxs(t.span,{className:"line",children:[e.jsx(t.span,{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"},children:"    { "}),e.jsx(t.span,{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"},children:'"source_id"'}),e.jsx(t.span,{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"},children:": "}),e.jsx(t.span,{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"},children:'"0193-…"'}),e.jsx(t.span,{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"},children:", "}),e.jsx(t.span,{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"},children:'"source_name"'}),e.jsx(t.span,{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"},children:": "}),e.jsx(t.span,{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"},children:'"brand-guide.md"'}),e.jsx(t.span,{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"},children:" }"})]}),`
113`,e.jsx(t.span,{className:"line",children:e.jsx(t.span,{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"},children:"  ]"})}),`
114`,e.jsx(t.span,{className:"line",children:e.jsx(t.span,{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"},children:"}"})})]})})}),`
115`,e.jsx(t.p,{children:`The chat UI renders one chip per unique source under the reply.
116Hover for the full source name. (Click-to-open is on the
117roadmap.)`}),`
118`,e.jsx(t.h2,{id:"what-gets-retrieved",children:"What gets retrieved"}),`
119`,e.jsxs(t.p,{children:[`Bastio retrieves chunks at message-send time, not at attach
120time, so the context reflects the `,e.jsx(t.em,{children:"current"})," user's prompt:"]}),`
121`,e.jsxs(t.ul,{children:[`
122`,e.jsx(t.li,{children:`"What's our PTO policy?" → handbook chunks about PTO win.`}),`
123`,e.jsx(t.li,{children:`"How do I greet a customer?" → brand-guide chunks about tone
124win, even though the same handbook is attached.`}),`
125`]}),`
126`,e.jsx(t.p,{children:"Top-K defaults to 5 chunks. Tunable per workspace in settings."}),`
127`,e.jsx(t.h2,{id:"updating-a-source",children:"Updating a source"}),`
128`,e.jsx(t.p,{children:`Re-uploading the same name re-ingests with a fresh chunk set.
129Old chunks are archived (not deleted), so existing
130conversations that cited them still display the citation
131correctly. Only new conversations see the new content.`}),`
132`,e.jsx(t.h2,{id:"detaching-a-source",children:"Detaching a source"}),`
133`,e.jsx(t.p,{children:`Edit the assistant → uncheck the source. The join row is
134removed. Existing conversations with that assistant continue to
135show old citations in their history, but new turns won't
136retrieve from the detached source.`}),`
137`,e.jsx(t.h2,{id:"archiving-a-source",children:"Archiving a source"}),`
138`,e.jsxs(t.p,{children:["Knowledge Base tab → trash icon. Sets ",e.jsx(t.code,{children:"archived_at = NOW()"}),`.
139The source no longer appears in the picker for new attachments,
140but rows that were already attached keep working until the
141admin detaches them. Audited as `,e.jsx(t.code,{children:"knowledge.archived"}),"."]}),`
142`,e.jsx(t.h2,{id:"common-pitfalls",children:"Common pitfalls"}),`
143`,e.jsxs(t.ul,{children:[`
144`,e.jsxs(t.li,{children:[e.jsx(t.strong,{children:"No assistant attached → no RAG."}),` A workspace with KB
145uploaded but no assistant attached gets no citations. Make
146sure the assistant the user picks has at least one source
147attached.`]}),`
148`,e.jsxs(t.li,{children:[e.jsx(t.strong,{children:'Chat says "stuck on pending" for a PDF upload.'}),` Check that
149the worker is running. In dev, all-in-one mode handles this
150automatically; in split-binary prod, ensure `,e.jsx(t.code,{children:"cmd/worker"}),` is
151up. River migrations run on every server start since v2.`]}),`
152`,e.jsxs(t.li,{children:[e.jsx(t.strong,{children:"Citations list is empty for a chat with KB attached."}),` The
153retrieval found no relevant chunks. Either the question is
154far from your corpus, or your top-K threshold is too high.
155Look at the assistant's "Trace" tab for the retrieval scores
156per chunk.`]}),`
157`]}),`
158`,e.jsx(t.h2,{id:"api-surface",children:"API surface"}),`
159`,e.jsx(t.p,{children:"For CI / programmatic use:"}),`
160`,e.jsxs(t.ul,{children:[`
161`,e.jsxs(t.li,{children:[e.jsx(t.code,{children:"GET /v1/workspace/knowledge"})," — list sources"]}),`
162`,e.jsxs(t.li,{children:[e.jsx(t.code,{children:"POST /v1/workspace/knowledge/upload"})," — multipart upload"]}),`
163`,e.jsxs(t.li,{children:[e.jsx(t.code,{children:"POST /v1/workspace/knowledge"})," — inline-text source"]}),`
164`,e.jsxs(t.li,{children:[e.jsx(t.code,{children:"DELETE /v1/workspace/knowledge/{id}"})," — archive"]}),`
165`,e.jsxs(t.li,{children:[e.jsx(t.code,{children:"PATCH /v1/workspace/assistants/{id}"}),` with
166`,e.jsx(t.code,{children:'knowledge_source_ids: ["uuid1", "uuid2"]'}),` — attach (replaces
167the full set)`]}),`
168`]}),`
169`,e.jsxs(t.p,{children:["See the ",e.jsx(t.a,{href:"/docs/api-reference",children:"API reference"}),` on your running
170gateway for the full schema.`]}),`
171`,e.jsx(t.h2,{id:"next",children:"Next"}),`
172`,e.jsxs(t.ul,{children:[`
173`,e.jsxs(t.li,{children:[e.jsx(t.a,{href:"/docs/cloud/workspace/for-admins",children:"For admins"}),` — the rest of
174the admin surface.`]}),`
175`,e.jsxs(t.li,{children:[e.jsx(t.a,{href:"/docs/cloud/workspace/for-employees",children:"For employees"}),` — what
176the citation chips look like to your team.`]}),`
177`]})]})}function c(s={}){const{wrapper:t}=s.components||{};return t?e.jsx(t,{...s,children:e.jsx(n,{...s})}):n(s)}export{c as default,r as extractedReferences,a as frontmatter,o as structuredData,h as toc};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.