Skip to content
3 min read · 665 words

Database Schema

Nine tables. agents is the root; everything else hangs off it and cascade-deletes with it.

Full ERD

Rendering diagram…

Reading guide by table

Column-level semantics, defaults, and design commentary live on the ORM Models page; the highlights that matter when querying:

TableWritten byGotchas when querying
agentscreate endpointenabled_tools is a CSV string — use LIKE '%tool%' carefully (substring false-positives)
messageschattwo rows per exchange; order by created_at or id
agent_runschatstatus='failed' rows hold the real LLM error in error_message
tasksanalyze + workflowdue_date is free text, not a date — don't ORDER BY it expecting chronology
tool_callseverythingsuccess is the string 'true'/'false'; cost columns are NULL except on workflow LLM stages
documents / document_chunksuploadchunks_count is denormalized; chunk agent_id duplicates the document's for direct filtering
workflow_runsworkflowfinal_output and quality_score need JSON/float parsing; running status can mean crashed-in-flight
workflow_stepsworkfloworder by id asc for chronological trace

Cascade topology

Deleting an Agent removes: messages, runs, tasks, tool calls, documents (→ their chunks), workflow runs (→ their steps). Two important non-cascades:

  1. Chroma vectors survive — no code deletes from the vector collection (Known Issues).
  2. tool_calls.agent_run_id links also cascade via the run, but tool calls belong to the agent first — a tool call never outlives its agent.

Useful queries

sql
-- Failure investigation: last 5 failed automated steps with errors
SELECT tool_name, error_message, created_at
FROM tool_calls WHERE success = 'false'
ORDER BY id DESC LIMIT 5;
 
-- Workflow quality over time
SELECT id, quality_score, status, created_at
FROM workflow_runs WHERE workflow_name = 'multi_agent_email_workflow'
ORDER BY id;
 
-- Spend proxy per tool (workflow stages only — see cost coverage docs)
SELECT tool_name, COUNT(*), SUM(CAST(estimated_cost AS REAL)) AS est_cost
FROM tool_calls WHERE estimated_cost IS NOT NULL
GROUP BY tool_name;
 
-- Verify SQLite↔Chroma linkage for a document
SELECT chunk_index, vector_id FROM document_chunks WHERE document_id = 1 ORDER BY chunk_index;

Indexes

Only the primary keys are indexed (index=True on every id). FK columns (agent_id, etc.) have no explicit indexes — full scans are fine at dev scale; add indexes alongside real load (Design Decisions).