Skip to Content
ReferenceData Model

Data Model

RondoFlow stores all state in PostgreSQL via Prisma. This page documents the schema entity by entity: what each model is for, its key fields, and how it relates to the rest. Field names below match the database exactly — the UI wraps many of them in friendlier terms (see Terminology).

The source of truth is packages/server/prisma/schema.prisma. If you change the schema, generate a migration (npm run db:migrate) and update this page to match.

Enums

These shared Prisma enums constrain field values across the model.

EnumValues
UserRoleadmin, editor, viewer
AgentStatusidle, running, waiting_approval, error
PolicyLevelglobal, agent, session
SkillSourcemarketplace, git, custom
DiscussionFormatbrainstorm, review, deliberation
DiscussionStatusdraft, active, concluded
ParticipantRoleparticipant, observer, devil_advocate
MessageRoleuser, assistant, system, tool
StoryStatuspending, in_progress, passed, failed
ResourceTypefile, url, note, variable

StructuredDataset.format is not a Prisma enum — it is stored as a plain String. Its allowed values come from the StructuredFormat TypeScript union in packages/shared/src/structured-format.ts: json-object, json-array, and table. See Structured datasets below.

Authentication

RondoFlow uses Better Auth. Three tables back it: User, Session, and Account, plus a transient Verification table.

User

The account owner. Owns Workspaces and Assistants (Agents).

FieldTypeNotes
idStringUUID primary key
emailStringUnique
emailVerifiedBooleanDefaults to false
nameStringDisplay name
imageString?Avatar URL
roleUserRoleGlobal role; defaults to viewer (fail-closed)
bannedBooleanDefaults to false; true once deactivated (sessions rejected)
banReasonString?Optional reason recorded on deactivation
banExpiresDateTime?Optional ban expiry (null = indefinite)
createdAt / updatedAtDateTimeTimestamps

Relations: sessions, accounts, workspaces (as owner), agents (as owner).

role gates a single shared team workspace — access is by role, not per-user ownership (userId columns are kept for attribution/audit only). The role migration backfills existing users to editor and promotes the oldest account to admin. See Security.

Session

A login session (mapped to the auth_session table — distinct from AgentSession below).

FieldTypeNotes
idStringUUID primary key
userIdStringFK → User, cascades on delete
tokenStringUnique session token
expiresAtDateTimeExpiry
ipAddressString?Client IP
userAgentString?Client user agent
impersonatedByString?Admin user id when the session is an impersonation
createdAt / updatedAtDateTimeTimestamps

Account

A linked credential or OAuth provider account (one per provider per user).

FieldTypeNotes
idStringUUID primary key
userIdStringFK → User, cascades on delete
providerIdStringe.g. github, google, credential
accountIdStringProvider-side account id
accessToken / refreshToken / idTokenString?OAuth tokens
accessTokenExpiresAt / refreshTokenExpiresAtDateTime?Token expiry
scopeString?Granted scopes
passwordString?Hashed password for credential accounts
createdAt / updatedAtDateTimeTimestamps

Unique on [providerId, accountId]. Verification holds short-lived identifier/value pairs used for email verification and similar flows.

Workspace

A Workspace (UI: also “Workspace”) is the top-level container for a canvas, its resources, and its memories.

FieldTypeNotes
idStringUUID primary key
nameStringWorkspace name
contextDocumentString?Shared context injected into runs
planDocumentString?Working plan document
workingDirectoryString?Default working directory for runs
userIdString?FK → User (owner)

Relations: canvasLayouts, resources, memories.

Agent

An Assistant (Agent) — the core actor. Defines a personality (persona), provider, tools, and execution behavior. Owns its skills, policies, memories, sessions, and assignments.

FieldTypeNotes
idStringUUID primary key
nameStringAssistant name
avatarString?Avatar
descriptionString?Short description
personaStringPersonality / system prompt
purposeString?What the assistant is for
scopeString[]Scope tags
allowedToolsString[]Permitted tool names
memoryEnabledBooleanDefaults to false
modelString?Model override
providerStringDefaults to claude-code (also openai, perplexity)
providerConfigJson?Provider-specific settings
statusAgentStatusDefaults to idle
permissionModeStringDefaults to default
loopEnabledBooleanSelf-loop on (defaults false)
loopCriteriaJson?Loop exit conditions
maxIterationsIntDefaults to 10
teamEnabledBooleanDefaults to false
isFavoriteBooleanDefaults to false
isFacilitatorBooleanCan moderate discussions (defaults false)
canvasX / canvasYFloatCard position on the workspace
userIdString?FK → User (owner)

Relations: skills (via AgentSkill), policies, memories, sessions, participations and moderatedTables (discussions), mcpAssignments (via AgentMcpServer), externalFolders (via AgentExternalFolder).

See Assistants, Loops, and Providers.

Skills

Skill

An installed capability (UI: “Skill”). Catalogs where it came from and where it lives on disk.

FieldTypeNotes
idStringUUID primary key
nameStringUnique
descriptionStringRequired
sourceSkillSourcemarketplace, git, or custom
gitUrlString?Origin when source = git
pathStringOn-disk install path
version / author / category / iconString?Metadata
mcpConfigJson?Optional MCP wiring
installedAtDateTimeInstall timestamp

AgentSkill

Join table assigning a Skill to an Assistant, with ordering and an on/off switch.

FieldTypeNotes
agentIdStringFK → Agent, cascades
skillIdStringFK → Skill, cascades
priorityIntOrdering, defaults 0
enabledBooleanDefaults to true

Composite primary key [agentId, skillId]. See Skills.

Policy (Safety Rule)

A Safety Rule (Policy) constrains what an Assistant may do. Rules can apply globally, per agent, or per session.

FieldTypeNotes
idStringUUID primary key
nameStringRule name
levelPolicyLevelglobal, agent, or session
rulesJsonThe rule payload
agentIdString?FK → Agent (when agent-scoped), cascades
sessionIdString?FK → AgentSession (when session-scoped), cascades

When multiple rules apply, the most restrictive wins. See Safety Rules and Security.

The global per-run budget cap is stored on a single canonical global Policy row (id d0000000-0000-0000-0000-000000000001), not in an env var. See Security.

Sessions & Messages

AgentSession

A Conversation (Session) — one run of an Assistant, or a discussion table run. Mapped to the Session table.

FieldTypeNotes
idStringUUID primary key
agentIdString?FK → Agent (null for table-only runs)
tableIdString?FK → DiscussionTable for discussions
startedAtDateTimeStart time
endedAtDateTime?Null while active

Relations: messages, policies. Indexed on [agentId, startedAt] and [tableId].

Message

A single turn within a Conversation.

FieldTypeNotes
idStringUUID primary key
sessionIdStringFK → AgentSession, cascades
roleMessageRoleuser, assistant, system, tool
contentStringMessage text
toolUseJson?Structured tool call/result
rawEventJson?Raw stream-json event
tokenCountInt?Token count for the turn
timestampDateTimeOrdered by [sessionId, timestamp]

Discussions

DiscussionTable

A multi-agent discussion (UI: “Discussion”), moderated by a Facilitator (Moderator — the moderator Agent).

FieldTypeNotes
idStringUUID primary key
nameStringDiscussion name
topicStringSubject
formatDiscussionFormatbrainstorm, review, deliberation
moderatorIdStringFK → Agent (the Facilitator)
statusDiscussionStatusDefaults to draft
conclusionString?Final summary when concluded
maxRoundsIntDefaults to 5

Relations: participants (via TableParticipant), sessions.

TableParticipant

Join table placing an Assistant at a discussion with a role.

FieldTypeNotes
tableIdStringFK → DiscussionTable, cascades
agentIdStringFK → Agent, cascades
roleParticipantRoleparticipant (default), observer, devil_advocate

Composite primary key [tableId, agentId]. See Discussions.

Memory

A Memory entry persists facts across runs. Scoped to a single Assistant or to a whole Workspace.

FieldTypeNotes
idStringUUID primary key
agentIdString?FK → Agent (agent scope), cascades
workspaceIdString?FK → Workspace (workspace scope), cascades
scopeStringagent (default) or workspace
sourceStringmanual (default), auto, or director
keyStringMemory key
valueStringMemory value
pinnedBooleanAlways-include when set
importanceIntRanking weight, defaults 0

Unique on [agentId, key] and [workspaceId, key] (upserts rely on these). Indexed on [workspaceId, pinned], [agentId, pinned], and [scope, source]. See Memory.

Resources

WorkspaceResource

A Resource attached to a Workspace — a file, URL, note, or variable. See Resources.

FieldTypeNotes
idStringUUID primary key
workspaceIdStringFK → Workspace, cascades
typeResourceTypefile, url, note, variable
nameStringDisplay name
descriptionString?Optional description
filePath / fileSize / mimeTypeString? / Int? / String?For file resources
urlString?For url resources
contentString?For note resources
varKey / varValueString?For variable resources
isSecretBooleanMarks a variable as secret (defaults false)

Indexed on [workspaceId, type].

CanvasLayout

A saved layout of the workspace canvas (cards, edges, viewport).

FieldTypeNotes
idStringUUID primary key
nameStringDefaults to default
workspaceIdStringFK → Workspace, cascades
viewportJsonPan/zoom state
nodesJsonCard positions and data
edgesJsonConnections between cards

See Canvas.

Connections (MCP Servers)

McpServer

A Connection (MCP Server) the Assistants can use.

FieldTypeNotes
idStringUUID primary key
nameStringUnique
descriptionString?Optional
typeStringDefaults to stdio
commandStringExecutable to start the server
argsString[]CLI arguments
envJson?Environment variables

AgentMcpServer

Join table assigning a Connection to an Assistant. Composite primary key [agentId, mcpServerId]; both FKs cascade on delete. See Connections.

External Folders

ExternalFolder

A host directory bind-mounted into the server and exposed to Assistants. See External Folders.

FieldTypeNotes
idStringUUID primary key
nameStringDisplay name
descriptionString?Optional
containerPathStringUnique in-container path (must resolve under EXTERNAL_FOLDERS_CONTAINER_ROOT)
readOnlyBooleanDefaults to false

AgentExternalFolder

Join table mounting a folder for an Assistant, with priority (default 0) and enabled (default true). Composite primary key [agentId, externalFolderId]; both FKs cascade.

Chain Runs

A ChainRun records a workflow execution (a DAG of steps). It owns an append-only event log and per-step results. See Workflows and Orchestration.

ChainRun

FieldTypeNotes
idStringUUID primary key
chainIdStringUnique chain identifier
workspaceIdString?FK reference (workspace)
initialMessageStringThe triggering message
statusStringDefaults to running
totalStepsIntDefaults to 0
completedAtDateTime?Null while running

Relations: steps (ChainStepResult), events (ChainRunEvent).

ChainStepResult

One step in a chain run, including its output and cost.

FieldTypeNotes
idStringUUID primary key
chainRunIdStringFK → ChainRun, cascades
stepIndexIntPosition in the chain
agentIdStringActing assistant
agentNameString?Snapshot of the name
outputStringFinal per-step text (defaults "")
tokensIn / tokensOutIntToken counts (default 0)
costUsdFloatStep cost in USD (defaults 0)
statusStringDefaults to running
startedAt / completedAtDateTime / DateTime?Timestamps

A chain step isn’t always an Assistant turn. The Structurer (Structure) and Save to DB cards run as real non-agent steps inside the ChainExecutor; the Output and Email cards are run-completion sinks rather than execution steps. See Data Nodes for the canvas-side picture and Structured datasets below for the tables they write.

ChainRunEvent

Append-only, ordered transcript of a run: step start, tool use/result, step completion, director decisions, errors, and completion. Streamed text deltas are not stored per-delta — the final per-step output lives on ChainStepResult.output.

FieldTypeNotes
idStringUUID primary key
chainRunIdStringFK → ChainRun, cascades
seqIntOrdering within the run
typeStringEvent type
stepIndexInt?Related step
agentId / agentNameString?Acting assistant
payloadJson?Event data

Indexed on [chainRunId, seq].

Structured datasets

These two tables back the canvas data pipeline: a Structurer (Structure) card turns an Assistant’s prose into a typed dataset, and a Save to DB card persists it here. Datasets are then viewable and CSV-exportable in the Saved Datasets panel, and served by GET /api/datasets and GET /api/datasets/:id (paginated rows). See Data Nodes for the canvas workflow and API for the endpoints.

StructuredDataset

The parent row: one persisted dataset, with its declared schema and provenance.

FieldTypeNotes
idStringUUID primary key
workspaceIdString?Plain string correlator (no FK) for the originating workspace
chainRunIdString?Plain string correlator (no FK) for the originating chain run
nodeIdStringThe Save to DB card (node) that wrote the dataset
nameStringDataset name
formatStringOne of json-object, json-array, table (the StructuredFormat union; see Enums)
schemaJsonThe declared column/field schema
rowCountIntNumber of persisted rows (defaults 0)
sourceAgentIdsString[]Assistants whose output fed the dataset
createdAtDateTimeCreated timestamp

Relations: rows (StructuredRow). Indexed on [workspaceId, createdAt] and [chainRunId].

workspaceId and chainRunId are deliberately plain string correlators with no foreign key — the same pattern as ChainStepResult.agentId referencing an Assistant by string. This avoids FK churn when a chain run or workspace is recreated.

StructuredRow

A single row of a dataset, stored separately so rows stay queryable and paginatable.

FieldTypeNotes
idStringUUID primary key
datasetIdStringFK → StructuredDataset, cascades on delete
idxIntRow order within the dataset
dataJsonThe row payload

Indexed on [datasetId, idx].

The Save to DB step enforces write-time caps before persisting: at most 5,000 rows (MAX_DATASET_ROWS) and 2,000,000 bytes (MAX_DATASET_BYTES) of serialized row data. Rows beyond those limits are dropped at write time — these are engine guards in the ChainExecutor, not schema constraints. See Data Nodes.

Cost, Activity & Artifacts

SessionUsage

Token and cost tracking per session/agent/workspace. Fields: sessionId, agentId?, workspaceId?, model?, inputTokens, outputTokens, costUsd. Indexed on [agentId, createdAt], [sessionId], and [workspaceId, createdAt].

ActivityEvent

The activity feed. A lightweight, denormalized event log.

FieldTypeNotes
idStringUUID primary key
userId / workspaceId / agentIdString?Optional context references
typeStringEvent type
titleStringHeadline
detailString?Longer text
metadataJson?Arbitrary extra data

Indexed on [userId, createdAt] and [workspaceId, createdAt]. See Monitoring.

Artifact

A file produced by a session. Fields: sessionId, fileName, filePath, fileSize?, mimeType?. Indexed on [sessionId].

Schedules

ScheduledTask

A cron-scheduled run of a saved workflow or an assistant. See Schedules.

FieldTypeNotes
idStringUUID primary key
nameStringTask name
descriptionStringDefaults to ""
typeStringworkflow or agent
targetIdStringSavedWorkflow.id or Agent.id
messageStringMessage sent on run (defaults "")
scheduleStringCron expression, e.g. 0 9 * * 1-5
timezoneStringDefaults to UTC
enabledBooleanDefaults to true
directorEnabledBooleanStored flag (defaults false); not currently honored — the Scheduler does not invoke the Director for scheduled runs
lastRunAt / nextRunAtDateTime?Scheduling state
lastStatusString?success, error, or running

Indexed on [enabled, nextRunAt]. SavedWorkflow stores reusable workflow definitions: name, description, and a workflow JSON blob.

directorEnabled is plumbed through the API, the database, and the UI type, but the Scheduler engine never reads it — scheduled execution never invokes the Director. Likewise, scheduled agent tasks run with a generic helper prompt rather than the Assistant’s real persona, skills, and model. See Schedules.

PRD & Stories

The PRD pipeline is an experimental backend capability. The data models, the PrdPipelineEngine, and the /api/prds routes exist, but the UI trigger is currently a no-op stub — it is not a ready-to-use feature today. Documented here for completeness of the schema.

PRD is a product requirements document with a title and child stories. Each Story has a prdId (FK → PRD, cascades), a title, acceptanceCriteria, a status (StoryStatus: pending, in_progress, passed, failed, default pending), and a priority (Int, default 0). Story is indexed on [prdId, priority].

Instance Settings

Setting

Global key/value config managed in the UI (credentials, etc.). Values are AES-256-GCM encrypted at rest in the iv:tag:ciphertext form.

FieldTypeNotes
keyStringPrimary key, e.g. ANTHROPIC_API_KEY
valueStringEncrypted ciphertext
createdAt / updatedAtDateTimeTimestamps

Secrets in Setting and any WorkspaceResource with isSecret = true are sensitive. Review Security before exposing the database or backups.

Last updated on