Knowledge base
Satia Docs (knowledge_docs + knowledge_folders) is the company's centralized Knowledge Base and Single Source of Truth (SSOT). It stores operational manuals, company policies, agent playbooks, chronological dockets/histories (book + entry), and standalone enterprise files (file with automatic AI Vision analysis).
1. Hierarchical Folder Architecture (knowledge_folders)
Satia organizes documents into a multi-level folder tree powered by PostgreSQL materialized path triggers.
1.1 Schema of knowledge_folders
| Column | Type | Required | Rules & Usage |
|---|---|---|---|
id | uuid | Auto | Primary Key (folder_id referenced by knowledge_docs.folder_id). |
parent_id | uuid | Optional | Parent folder UUID (NULL for root-level folders). Cascade Warning: parent_id has ON DELETE CASCADE; deleting a parent folder deletes all its subfolders. |
name | text | Yes | Display name (slashes / are automatically sanitized to - by DB triggers). |
description | text | Recommended | Semantic Routing Context: Explains what documents belong inside this folder. Injected directly into <knowledge_folders_directory> so agents route documents accurately. |
path | text | Read-Only | Materialized Path: Auto-calculated and cascaded by DB triggers (trg_sync_knowledge_folder_path & trg_cascade_knowledge_folder_path), e.g., '/Operaciones/Políticas/2026'. Never write path manually. |
depth | integer | Read-Only | Auto-calculated nesting level (0 = root, 1 = subfolder, etc.). Never write depth manually. |
sort_order | integer | Optional | UI display priority (0 default). Siblings sort by sort_order ASC, name ASC. |
icon | text | Optional | Icon identifier (e.g., 'folder', 'book', 'briefcase', 'shield', 'file-text'). |
color | text | Optional | HEX color code (e.g., '#10b981', '#2F4F4F', '#00CFB5'). |
[!NOTE] Data Loss Protection for Documents: While deleting a folder cascades to its child subfolders, documents inside a deleted folder are never deleted — their
folder_idis automatically set toNULL(ON DELETE SET NULL), preserving them safely at the root of Satia Docs.
1.2 How <knowledge_folders_directory> Works & Exploring Subfolders
To prevent context window bloat, <knowledge_folders_directory> in the system prompt lists only root-level folders (parent_id IS NULL), along with their path, semantic description, and direct subfolder count ((N subfolders)).
- Explore direct subfolders of a root folder:
SELECT id, name, description, path, depth, sort_order FROM knowledge_folders WHERE parent_id = '<root_folder_uuid>' ORDER BY sort_order ASC, name ASC; - Query all documents across an entire folder branch (including all nested subfolders) via
path:SELECT d.id, d.title, d.doc_type, f.path, d.updated_at FROM knowledge_docs d JOIN knowledge_folders f ON d.folder_id = f.id WHERE f.path LIKE '/Operaciones/%' OR f.id = '<root_folder_uuid>' ORDER BY d.updated_at DESC; - Query unfiled documents at the root level:
SELECT id, title, doc_type, updated_at FROM knowledge_docs WHERE folder_id IS NULL AND parent_id IS NULL ORDER BY updated_at DESC;
1.3 Mandatory UI Markdown Link Format in Chat Responses
Whenever you create, cite, or recommend a Satia Doc or Knowledge Folder to the user in chat, always format it as a clickable relative Markdown link so the user can open it directly in the Satia UI:
- Document Link:
[Document Title](/knowledge/<doc_id>) - Folder Link:
[Folder Name](/knowledge?folder=<folder_id>)
2. Document Archetypes in knowledge_docs & metadata Contracts
2.1 Schema of knowledge_docs
| Column | Type | Required | Description |
|---|---|---|---|
id | uuid | Auto | Unique document ID. |
folder_id | uuid | Optional | FK -> knowledge_folders.id (NULL = root / unfiled). |
title | text | Yes | Document, book, entry, or file title. |
content | text | Conditional | Markdown body (Warning: The column name is content, there is NO description column on knowledge_docs). NULL when doc_type = 'file'. |
doc_type | text | Yes | 'document', 'book', 'entry', or 'file'. |
parent_id | uuid | Conditional | Required only when doc_type = 'entry' (points to the parent 'book' UUID in knowledge_docs.id). |
metadata | jsonb | Optional | Stores metadata.file (for doc_type = 'file') or metadata.media (attachments array on 'document' / 'book'). |
2.2 The 4 Document Archetypes (doc_type)
doc_type | Purpose | Rules & Runtime Behavior |
|---|---|---|
'document' | Standard Markdown articles, SOPs, FAQs, pricing policies, and reports. | Written in Markdown inside content. Always edit existing documents using database__inspect_text + database__patch_text. |
'book' | Chronological container / docket (e.g., Clinical History, Legal Case File, Project Log, Equipment Maintenance Log). | content holds the permanent header/summary of the docket. NEVER overwrite content with database__update to log new events; instead, insert child 'entry' rows. |
'entry' | Individual chronological note/update inside a 'book'. | Requires parent_id = '<book_uuid>'. Append-only via database__insert(table_name="knowledge_docs", data={"doc_type": "entry", "parent_id": "<book_uuid>", "title": "...", "content": "..."}). |
'file' | Standalone file asset (PDF manual, brochure, image, audio, video) uploaded to the satia-docs bucket. | content is NULL. All file properties and automatic AI semantic extraction live inside metadata.file. |
2.3 doc_type = 'book' + 'entry' Runtime Concatenation
Whenever a 'book' document is read (either injected via agent_docs, queried via consult_entity_manual, or read via satia_docs__read), Satia automatically fetches all child rows (WHERE parent_id = '<book_id>' AND doc_type = 'entry' ORDER BY created_at ASC) and assembles them as:
=== EXPEDIENTE PRINCIPAL ===
<content of the parent 'book'>
=== HISTORIAL DE ACTUACIONES ===
- [2026-10-01] Consulta Inicial: Paciente ingresa por...
- [2026-10-15] Control Quincenal: Evolución favorable...
2.4 metadata.file (Standalone Files) vs. metadata.media (Document Attachments)
-
Standalone File Assets (
doc_type = 'file'->metadata.file):- Uploaded by users in the UI (up to 20 MB) into the
satia-docsbucket. Upon upload, Satia automatically runs AI multimodal indexing to analyze the file (extracting text, tables, SKUs, prices, or visual descriptions) and saves it inmetadata.file.ai_description. - Structure of
metadata:{ "file": { "url": "https://.../storage/v1/object/public/satia-docs/<space_id>/guid_catalogo.pdf", "filename": "catalogo.pdf", "mime_type": "application/pdf", "type": "document", "size": 2451000, "ai_description": "Catálogo mayorista 2026 con tabla de precios, referencias SKU y dimensiones..." } } - How to Query Standalone Files in SQL: Never expect text in
contentwhendoc_type = 'file'. Querymetadata->'file'->>'ai_description'andmetadata->'file'->>'url':SELECT id, title, metadata->'file'->>'filename' AS filename, metadata->'file'->>'url' AS url, metadata->'file'->>'ai_description' AS ai_description FROM knowledge_docs WHERE doc_type = 'file' AND (title ILIKE '%catalogo%' OR metadata->'file'->>'ai_description' ILIKE '%catalogo%');
- Uploaded by users in the UI (up to 20 MB) into the
-
Attached Media Inside Written Documents (
doc_type = 'document' | 'book'->metadata.media):- A written Markdown document can also have attached reference files stored in
metadata.media:{ "media": [ { "id": "media_1", "url": "https://.../satia-docs/<space_id>/diagrama.png", "type": "image", "filename": "diagrama.png", "description": "Diagrama de instalación paso a paso" } ] }
- A written Markdown document can also have attached reference files stored in
3. Ontological Boundary: knowledge Column vs. media Column on Business Tables
When designing or querying business tables (e.g., clientes, productos, pedidos), always respect the architectural boundary between media and knowledge columns:
| Dimension | media Column (Row-Local Attachment) | knowledge Column (Enterprise SSOT Link) |
|---|---|---|
| Use Case | Transactional evidence specific to one row (e.g., payment receipt/voucher, photo of damaged item, customer avatar, signed delivery slip). | Reusable Single Source of Truth (SSOT) asset or structured dossier (e.g., product technical datasheet PDF, official warranty policy, patient clinical 'book'). |
| Physical Storage | JSONB object or array of objects ([{"url": "...", "name": "...", "type": "image", "caption": "..."}]) stored directly inside the row's column (satia-media bucket). | Stores a single UUID string referencing knowledge_docs.id. |
| Folder Hierarchy | None (satia-media flat bucket). | Organized inside knowledge_folders. Column config supports {"default_folder_id": "<folder_uuid>", "allowed_doc_types": ["document", "book", "file"]}. |
| AI Indexing | On-demand only (via preview_media / media__preview_file). | Pre-analyzed automatically on upload (metadata.file.ai_description) or structured in Markdown/Books. |
4. How Transactional Agents Consume & Manage Knowledge
4.1 Global Agent Playbooks (agent_docs) — Always Loaded in System Prompt
- When to use: Company-wide rules, FAQs, tone guidelines, sales playbooks, or master price lists that the agent must know in every conversation.
- How to link: Insert a row into
agent_docs(agent_id,knowledge_doc_id— neverdoc_id):database__insert( table_name="agent_docs", data={"agent_id": "<agent_uuid>", "knowledge_doc_id": "<knowledge_doc_uuid>"} ) - Runtime behavior (
config_loader.py):- If the linked doc is
'document', its Markdowncontent(plus any[ARCHIVOS ADJUNTOS DISPONIBLES]frommetadata.media) is injected directly into<agent_docs>. - If the linked doc is
'book', the parent content and all chronological'entry'rows are concatenated and injected. - If the linked doc is
'file', an### ARCHIVO ADJUNTO: <title>block is injected with the clean storage reference so the agent can send it immediately viasend_media(url="...").
- If the linked doc is
4.2 Per-Record Manuals (knowledge Column on Catalogs) — Loaded On-Demand
- When to use: Specific datasheets, assembly guides, or legal contracts tied to individual catalog items (where preloading 100 manuals would overflow the prompt).
- Runtime behavior (
entity_knowledge.py):- In
<data_context>, records with a populatedknowledgecolumn display📎 [Attached Manual](ID Manual: <uuid>). - When a customer asks about that specific item, the transactional agent calls
consult_entity_manual(name="...", record_id="...", doc_id="..."), which resolves the linkedknowledge_docsrow (whether'document','book'with entries, or'file'withai_descriptionandfile_url) in a single turn.
- In
4.3 Dynamic Knowledge Creation by Transactional Agents (satia_docs Store Tool)
By default, transactional agents only read knowledge. If a transactional agent needs to create, read, or patch Satia Docs during a conversation (e.g., a medical assistant appending a new 'entry' to a patient's clinical 'book', or an internal assistant drafting SOPs), install the satia_docs Store Tool via store__install_tool:
- Exposes 3 tools to the transactional agent (
common_libs/skills/store/knowledge_manager.py):satia_docs__create(title, content, doc_type="document"|"book"|"entry", parent_id?)satia_docs__read(document_id)(returns the doc pluschild_entriesifdoc_type == 'book')satia_docs__patch_text(document_id, replacements=[{"target_text": "...", "replacement_text": "..."}])
5. Media & File Search, AI Vision Preview, and Dispatch Tools
5.1 Sati (Planner / Workspace Administrator) Media Tools (common_libs/skills/media_search.py)
media__search_files(query?, contact_name?, date_from?, date_to?, media_type?, source='all'|'conversations'|'docs', limit=10):- Searches across both chat attachments (
messages.media_storage_pathinsatia-media) and Satia Docs files (knowledge_docs.metadatainsatia-docs). - Returns candidate files with
bucket("satia-media"or"satia-docs"),storage_path,filename,media_type,context, andcontact_name.
- Searches across both chat attachments (
media__preview_file(storage_path, bucket, url?):- Downloads a stored file (up to 20 MB) from
satia-mediaorsatia-docsand uses multimodal AI analysis to inspect and transcribe/describe its exact contents (amounts, dates, names, visual details). - Rule: Always preview candidate files from
media__search_filesbefore sending if the filename is ambiguous. Never call preview tools on files the user just attached in the current chat turn (those are already visible in your multimodal context).
- Downloads a stored file (up to 20 MB) from
media__send_file(storage_path, bucket, url?, caption?):- Generates a signed URL and dispatches the file directly to the user in the active conversation.
5.2 Transactional Agent Media Tools (common_libs/skills/entity_knowledge.py)
send_media(url?, doc_id?, media_ids?, caption?): Dispatches media either by directurl/ storage path (from an ERP row'smediacolumn or adoc_type = 'file'doc) or bydoc_id+media_ids(frommetadata.media).preview_media(url?, storage_path?): Inspects stored system files via AI Vision. (Never call on inbound user images).
6. Mandatory Surgical Editing Protocol (database__inspect_text + database__patch_text)
- NEVER use
database__updateto overwrite the entirecontentcolumn of an existingknowledge_docsrecord when making edits, additions, or corrections — doing so wastes output tokens and risks truncating long manuals. - Always use the 2-step surgical workflow:
- Inspect lines or search pattern:
database__inspect_text( table_name="knowledge_docs", record_id="<doc_uuid>", column_name="content", search_pattern="garantía", context_lines=5 ) - Patch exact text fragments:
database__patch_text( table_name="knowledge_docs", record_id="<doc_uuid>", column_name="content", replacements=[ { "target_text": "La garantía cubre 12 meses.", "replacement_text": "La garantía cubre 24 meses en piezas y mano de obra." } ] )
- Inspect lines or search pattern: