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

ColumnTypeRequiredRules & Usage
iduuidAutoPrimary Key (folder_id referenced by knowledge_docs.folder_id).
parent_iduuidOptionalParent folder UUID (NULL for root-level folders). Cascade Warning: parent_id has ON DELETE CASCADE; deleting a parent folder deletes all its subfolders.
nametextYesDisplay name (slashes / are automatically sanitized to - by DB triggers).
descriptiontextRecommendedSemantic Routing Context: Explains what documents belong inside this folder. Injected directly into <knowledge_folders_directory> so agents route documents accurately.
pathtextRead-OnlyMaterialized 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.
depthintegerRead-OnlyAuto-calculated nesting level (0 = root, 1 = subfolder, etc.). Never write depth manually.
sort_orderintegerOptionalUI display priority (0 default). Siblings sort by sort_order ASC, name ASC.
icontextOptionalIcon identifier (e.g., 'folder', 'book', 'briefcase', 'shield', 'file-text').
colortextOptionalHEX 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_id is automatically set to NULL (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

ColumnTypeRequiredDescription
iduuidAutoUnique document ID.
folder_iduuidOptionalFK -> knowledge_folders.id (NULL = root / unfiled).
titletextYesDocument, book, entry, or file title.
contenttextConditionalMarkdown body (Warning: The column name is content, there is NO description column on knowledge_docs). NULL when doc_type = 'file'.
doc_typetextYes'document', 'book', 'entry', or 'file'.
parent_iduuidConditionalRequired only when doc_type = 'entry' (points to the parent 'book' UUID in knowledge_docs.id).
metadatajsonbOptionalStores metadata.file (for doc_type = 'file') or metadata.media (attachments array on 'document' / 'book').

2.2 The 4 Document Archetypes (doc_type)

doc_typePurposeRules & 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)

  1. Standalone File Assets (doc_type = 'file' -> metadata.file):

    • Uploaded by users in the UI (up to 20 MB) into the satia-docs bucket. Upon upload, Satia automatically runs AI multimodal indexing to analyze the file (extracting text, tables, SKUs, prices, or visual descriptions) and saves it in metadata.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 content when doc_type = 'file'. Query metadata->'file'->>'ai_description' and metadata->'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%');
      
  2. 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"
          }
        ]
      }
      

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:

Dimensionmedia Column (Row-Local Attachment)knowledge Column (Enterprise SSOT Link)
Use CaseTransactional 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 StorageJSONB 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 HierarchyNone (satia-media flat bucket).Organized inside knowledge_folders. Column config supports {"default_folder_id": "<folder_uuid>", "allowed_doc_types": ["document", "book", "file"]}.
AI IndexingOn-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 — never doc_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 Markdown content (plus any [ARCHIVOS ADJUNTOS DISPONIBLES] from metadata.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 via send_media(url="...").

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 populated knowledge column 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 linked knowledge_docs row (whether 'document', 'book' with entries, or 'file' with ai_description and file_url) in a single turn.

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 plus child_entries if doc_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)

  1. 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_path in satia-media) and Satia Docs files (knowledge_docs.metadata in satia-docs).
    • Returns candidate files with bucket ("satia-media" or "satia-docs"), storage_path, filename, media_type, context, and contact_name.
  2. media__preview_file(storage_path, bucket, url?):
    • Downloads a stored file (up to 20 MB) from satia-media or satia-docs and 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_files before 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).
  3. 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 direct url / storage path (from an ERP row's media column or a doc_type = 'file' doc) or by doc_id + media_ids (from metadata.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__update to overwrite the entire content column of an existing knowledge_docs record when making edits, additions, or corrections — doing so wastes output tokens and risks truncating long manuals.
  • Always use the 2-step surgical workflow:
    1. 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
      )
      
    2. 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."
              }
          ]
      )