Skip to content

Database schema

Sadie is Postgres-only. The full, authoritative schema is packages/db/src/schema.ts: roughly 1.6k lines of Drizzle table definitions with typed JSONB columns via .$type<T>(). This page groups the tables by domain and calls out notable shapes; for column-level detail, read the file.

TableNotes
usersBetter-Auth-compatible (id, email, emailVerified, name, image) plus Sadie fields (displayName, avatarColor, role). One row per deployment. This is a single-user product.
sessionsCookie sessions. Indexed on token.
accountsBetter-Auth account rows; reserved for future SSO.
verificationsBetter-Auth verification tokens. Unused today.
TableNotes
conversationssadieEmotion column carries one of seven emotions; set per-message and persisted on the conversation.
messagesstatus is `streaming
chat_context_attachmentsRemovable context chips: kind is `discourse
TableNotes
studio_workspacesA user can have many workspaces. colorToken picks the Clay accent.
documentsTiptap + Yjs. ydocState is base64-encoded binary Yjs update. wikiEntryId set when the draft is filed into Memory.
commentsText-anchored via anchorFrom/anchorTo integer offsets.
studio_collaborator_grantsLocal-only collaborator grants; no email send yet.
TableNotes
sourcesLibrary of everything Sadie reads. kind covers notes, docs, past posts, articles, RSS, newsletters, Notion, Obsidian, Readwise, uploads. weighting is optional: `personal_library
source_weightingsAudit trail when weighting changes.
TableNotes
feedsPer-user tracked handle (x_account, rss, newsletter).
feed_itemsPer-user items. Retained for backward compat with code that queries by feed id.
global_feed_itemsDeduplicated across users, keyed by (source, externalId). One X API call per handle, fanned out to all subscribers.
user_feed_item_linksJoin table from user feeds to global_feed_items.
feed_theme_countsRolling theme aggregates for feed-to-wiki promotion.
TableNotes
wiki_entrieskind is `person
wiki_patch_eventsProvenance trail. Before/after hashes, trigger kind, source ID. Idempotent by (wikiEntryId, afterHash).
wiki_link_candidatesCandidate cross-links awaiting review before becoming durable graph edges.
knowledge_nodesGraph nodes. kind is `wiki
knowledge_edgesrelation is `mentions
TableNotes
soul_stateTyped items: `audience
voice_portrait8-dimension voice model with exemplars, systemPrompt, rewriteAdjustments per dimension.
soul_narrativeSix prose sections: work_context, personal_context, top_of_mind, three tiers of brief_history_*.
preference_candidatesObserved preferences before promotion to Soul. Three kind-families: legacy generic, substance, voice.
rewrite_eventsCaptured when the user edits Sadie’s output. dimensionDeltas array feeds voice adjustments.
TableNotes
briefsEditorial syntheses. anchorWikiIds and sourceFeedItemIds track provenance. status is `draft
TableNotes
discourse_opportunitiesToday cards. Carry whyNow, whyYou, whoTalking (DiscourseVoice[]), angles (DiscourseAngle[] with confidence, engagementScore, topCritique), rank, accent. status is `active
TableNotes
policiesDeterministic guardrails. kind is `regex
policy_violationsAudit trail per match.
TableNotes
agent_versionsImmutable config snapshots. config JSONB holds prompts, weights, policies, catalog. parentVersionId forms the lineage. status is `committed
compile_runsAudit log for every background job. kind covers onboarding, incremental, lint, discourse_refresh, soul_promotion, soul_decay, agent_evolution.
compile_cursorsPer-user watermarks for incremental processing.
lint_findingsWiki health-check surface. kind enumerates orphan, stale, weak provenance, contradiction, missing page, low linkage, soul contradiction, soul decayed.
TableNotes
sadie_settingsJSONB payload with persona defaults, cadences, AI provider preference, encrypted userApiKeys, engagement weights, XP weights, currentAgentVersionId.
onboarding_statestep tracks progress through the 8-step flow. data JSONB accumulates calibration, rewrite drills, scenario checks, and learned writing weights.
TableNotes
activityEverything the user does in the app, keyed by (kind, subjectKind, subjectId). Feeds the agent evolution XP calculation and the Memory activity timeline.

Many columns use .$type<T>() to brand their JSONB with a TypeScript type. Compile-time only; Postgres still stores real JSONB and can index into it. Notable types:

  • SadieSettingsPayload. Everything in sadie_settings.payload.
  • AgentConfig. Prompts + weights + policies + catalog per version.
  • VoiceDimension[] / VoiceExemplar[]. Voice portrait contents.
  • NarrativeSection[]. Soul narrative.
  • OnboardingData. Calibration + distillation state.
  • DiscourseAngle[] / DiscourseVoice[]. Today card shapes.

See packages/db/src/schema.ts for every branded type. Drizzle returns these as typed values; the database stores them as plain JSONB.