Skip to content

Data model

Status: Current | Last reviewed: 2026-09-01

The conceptual shape of TrueServe's data. For the concrete table list, read tables.md.

Top-level entities

tenants ─┐
         ├── users
         ├── agents ────── agent_versions  (1 draft + N published)
         │       └── surface_configs
         ├── workflow_configs ── workflow_versions
         │       └── trigger_rules
         ├── integrations (encrypted credentials)
         ├── tools (optionally referencing integrations)
         └── conversations
                 ├── conversation_messages
                 └── conversation_recordings

The agent / agent_version split

The most important pattern in this schema. Read this carefully.

agents carries identity:

Column Purpose
id Primary key
name Human label
description Human description
surface_config_id Which surface to render in
tenant_id Owner

agent_versions carries runtime config:

Column Purpose
agent_id Foreign key
version 0 = draft, 1+ = published
is_current_published At most one per agent
config JSONB. The pipeline graph, prompts, tools, etc.
created_by, published_at, notes, weight Audit + A/B traffic split

Note: name and description live only on agents. Adding them to agent_versions is a recurring mistake. The orchestrator never reads them — it reads agent_versions.config exclusively, via resolve_agent_version().

agent_configs was a view that joined the two during the migration. It was dropped in init-script 104. If you find a reference to it, the reference is stale.

For the SQL functions that operate on this model (resolve_agent_version, publish_agent_version, create_new_agent_draft, update_agent_draft, resolve_agent_version_weighted), see sql-functions.md.

The TypeScript types for the JSONB blob live in apps/ai-manager/lib/pipeline-types.ts.

The same pattern, applied to workflows

workflow_configs (identity) + workflow_versions (config JSONB) mirrors the agent split exactly. Workflows are addressed by the numeric workflow_configs.id; workflow_versions keys on (workflow_id, version_number) where workflow_id is an integer FK to workflow_configs.id (renamed from base_workflow_id in the 2026-06-20 squash). The old text-slug column (legacy_slug) from the migration-130 cutover was dropped in that squash. See rename-map.md.

Surfaces

A surface is the UI an end user sees. The agent points at a surface_configs row that controls layout, branding, theme, and embedded widgets.

The same agent can appear in multiple surfaces by being referenced from different surface configs — common when the same brain runs on the web, in Salesforce, and on phone.

Integrations and tools

integrations rows hold tenant-scoped credentials for third-party services (Genesys org, OpenAI key, Salesforce org). The credential blob is encrypted with AES-256-GCM keyed off MASTER_ENCRYPTION_KEY. See secret-storage.md.

tools rows expose actions to agents. A tool may reference an integration row for credentials, or carry its own auth. The tool catalog also feeds workflow nodes (a tool node in async-agent invokes an MCP tool through agent-host).

Conversations

conversations is the long-form record of a session — voice, chat, or async. It carries the agent it was bound to, the surface it ran in, the user (where authenticated), tenant, timestamps, and metadata.

Per-message detail lives in conversation_messages; transcript rows also carry lifecycle lineage fields (message_key, session_seq, variant, revision) so streaming interim/final/enhanced updates replay in order without duplicate variants. Audio recordings live in conversation_recordings, which references object storage (the recordings-role bucket, STORAGE_BUCKET_RECORDINGS). conversation_search_documents holds one indexed row per conversation for global and per-agent history search. When archiving is enabled, transcript/event/recording detail can move to an object-storage archive bundle while search metadata stays hot.

Tenants and isolation

Multi-tenancy is enforced via row-level security on every tenant-scoped table. The tenants.slug column drives URL paths, catalog directories, and integration namespacing — and is consequently locked while a tenant owns dependent rows. See multi-tenancy.md.

Catalogs (A2UI)

a2ui_catalogs rows describe published component bundles built from TypeScript source. The bundle artifact lives in object storage; the row points at it. catalog-builder writes; multimodal-service reads. Source is archived alongside the build so it survives volume wipes.

Knowledge graph

knowledge_* tables hold ingestion checkpoints, assertions, and event logs. The actual graph lives in Neo4j; the Postgres tables are the durable source for replay and reconciliation.

See also