| 1 | -- Sessions, memory, routines and the workspace's agent policy |
| 2 | -- (docs/WORKSPACE.md, "Sessions", "Memory", "Routines", "Budgets"). |
| 3 | |
| 4 | -- One row per session: a bounded piece of work an agent took on. Talking |
| 5 | -- to an agent is a reply (agent_replies); real work is a session, with its |
| 6 | -- own context, transcript, cap and live card. Sessions form trees: a |
| 7 | -- session starts others for its subagents or for colleagues it brings in, |
| 8 | -- and the whole tree is paid by the agent at its root (payer_agent_id). |
| 9 | CREATE TABLE agent_sessions ( |
| 10 | id TEXT PRIMARY KEY, |
| 11 | workspace_id TEXT NOT NULL, |
| 12 | agent_id TEXT NOT NULL, |
| 13 | -- The subagent running it, by name, for kind `subagent`. |
| 14 | subagent TEXT, |
| 15 | -- chat, routine, helper or subagent. |
| 16 | kind TEXT NOT NULL, |
| 17 | parent_id TEXT, |
| 18 | root_id TEXT NOT NULL, |
| 19 | payer_agent_id TEXT NOT NULL, |
| 20 | title TEXT NOT NULL, |
| 21 | goal TEXT NOT NULL, |
| 22 | -- queued, working, waiting, needs_approval, done, failed or stopped. |
| 23 | status TEXT NOT NULL, |
| 24 | status_note TEXT, |
| 25 | summary TEXT, |
| 26 | -- Where it was asked and where it reports, and who asked with what access |
| 27 | -- (the asker's access caps everything it reads and does). |
| 28 | workspace TEXT NOT NULL, |
| 29 | channel_id TEXT NOT NULL, |
| 30 | channel_kind TEXT NOT NULL, |
| 31 | channel_name TEXT, |
| 32 | -- The conversation's thread the request was in (null: top level). |
| 33 | thread_root TEXT, |
| 34 | message_id TEXT, |
| 35 | card_message_id TEXT, |
| 36 | asked_by TEXT, |
| 37 | asked_by_username TEXT, |
| 38 | asker TEXT, |
| 39 | routine_id TEXT, |
| 40 | -- The agents that handed this work along, oldest first (hop limit, no ping-pong). |
| 41 | chain TEXT NOT NULL DEFAULT '[]', |
| 42 | hops INTEGER NOT NULL DEFAULT 0, |
| 43 | -- The model's working context: a bounded list of turns, compacted as it |
| 44 | -- grows. The full record is agent_session_events. |
| 45 | context TEXT NOT NULL DEFAULT '[]', |
| 46 | -- What arrived while it worked (steering, helpers' results), read at its next step. |
| 47 | inbox TEXT NOT NULL DEFAULT '[]', |
| 48 | steps INTEGER NOT NULL DEFAULT 0, |
| 49 | tool_calls INTEGER NOT NULL DEFAULT 0, |
| 50 | input_tokens INTEGER NOT NULL DEFAULT 0, |
| 51 | output_tokens INTEGER NOT NULL DEFAULT 0, |
| 52 | cost_micros INTEGER NOT NULL DEFAULT 0, |
| 53 | charged_micros INTEGER NOT NULL DEFAULT 0, |
| 54 | cap_micros INTEGER, |
| 55 | model TEXT, |
| 56 | outputs TEXT NOT NULL DEFAULT '[]', |
| 57 | -- When its current step started: a step that never finished is picked up again. |
| 58 | step_started_at TEXT, |
| 59 | created_at TEXT NOT NULL, |
| 60 | updated_at TEXT NOT NULL, |
| 61 | finished_at TEXT |
| 62 | ); |
| 63 | |
| 64 | CREATE INDEX agent_sessions_agent ON agent_sessions (agent_id, created_at); |
| 65 | CREATE INDEX agent_sessions_workspace ON agent_sessions (workspace_id, status, created_at); |
| 66 | CREATE INDEX agent_sessions_root ON agent_sessions (root_id); |
| 67 | CREATE INDEX agent_sessions_parent ON agent_sessions (parent_id); |
| 68 | CREATE INDEX agent_sessions_card ON agent_sessions (card_message_id); |
| 69 | CREATE INDEX agent_sessions_payer ON agent_sessions (payer_agent_id, created_at); |
| 70 | |
| 71 | -- A session's transcript, as its page shows it: what it was asked, what |
| 72 | -- it said, every tool it used (arguments cut, never results), steering, |
| 73 | -- updates it posted, sessions it started, and its report. |
| 74 | CREATE TABLE agent_session_events ( |
| 75 | session_id TEXT NOT NULL, |
| 76 | seq INTEGER NOT NULL, |
| 77 | kind TEXT NOT NULL, |
| 78 | by_name TEXT, |
| 79 | body TEXT NOT NULL, |
| 80 | tool TEXT, |
| 81 | outcome TEXT, |
| 82 | created_at TEXT NOT NULL, |
| 83 | PRIMARY KEY (session_id, seq) |
| 84 | ); |
| 85 | |
| 86 | -- What an agent remembers, each fact with its source and a scope that |
| 87 | -- decides where it may be recalled: workspace, a channel, or one person's |
| 88 | -- direct messages (scope_ref: the channel or user id). |
| 89 | CREATE TABLE agent_memories ( |
| 90 | id TEXT PRIMARY KEY, |
| 91 | agent_id TEXT NOT NULL, |
| 92 | workspace_id TEXT NOT NULL, |
| 93 | scope TEXT NOT NULL, |
| 94 | scope_ref TEXT NOT NULL DEFAULT '', |
| 95 | scope_label TEXT, |
| 96 | body TEXT NOT NULL, |
| 97 | source_kind TEXT NOT NULL, |
| 98 | source_ref TEXT, |
| 99 | source_label TEXT, |
| 100 | source_channel_id TEXT, |
| 101 | created_by TEXT NOT NULL, |
| 102 | created_by_kind TEXT NOT NULL, |
| 103 | pinned INTEGER NOT NULL DEFAULT 0, |
| 104 | created_at TEXT NOT NULL, |
| 105 | updated_at TEXT NOT NULL |
| 106 | ); |
| 107 | |
| 108 | CREATE INDEX agent_memories_agent ON agent_memories (agent_id, scope, scope_ref); |
| 109 | |
| 110 | -- Work an agent does on a schedule: each run is a session in the routine's |
| 111 | -- channel, with the access of the person who set it up (sponsor). |
| 112 | CREATE TABLE agent_routines ( |
| 113 | id TEXT PRIMARY KEY, |
| 114 | agent_id TEXT NOT NULL, |
| 115 | workspace_id TEXT NOT NULL, |
| 116 | -- The workspace's slug when it was saved, for posting and billing. |
| 117 | workspace TEXT NOT NULL, |
| 118 | name TEXT NOT NULL, |
| 119 | instructions TEXT NOT NULL, |
| 120 | -- JSON: every (hour, day, weekday, week), minute, hour, weekday. UTC. |
| 121 | -- Null when it runs only on events. |
| 122 | schedule TEXT, |
| 123 | -- JSON lists: what it runs on (pull_ready, checks_failed...), and which |
| 124 | -- repositories those come from (workspace/name; empty: any its sponsor can read). |
| 125 | events TEXT NOT NULL DEFAULT '[]', |
| 126 | repos TEXT NOT NULL DEFAULT '[]', |
| 127 | channel_id TEXT NOT NULL, |
| 128 | channel_name TEXT, |
| 129 | sponsor TEXT NOT NULL, |
| 130 | sponsor_username TEXT, |
| 131 | enabled INTEGER NOT NULL DEFAULT 1, |
| 132 | paused_note TEXT, |
| 133 | next_run_at TEXT, |
| 134 | last_run_at TEXT, |
| 135 | last_session_id TEXT, |
| 136 | runs INTEGER NOT NULL DEFAULT 0, |
| 137 | created_at TEXT NOT NULL, |
| 138 | updated_at TEXT NOT NULL |
| 139 | ); |
| 140 | |
| 141 | CREATE INDEX agent_routines_agent ON agent_routines (agent_id); |
| 142 | CREATE INDEX agent_routines_due ON agent_routines (enabled, next_run_at); |
| 143 | CREATE INDEX agent_routines_workspace ON agent_routines (workspace_id, enabled); |
| 144 | |
| 145 | -- What each routine ran on, so one thing that happened runs it once. |
| 146 | CREATE TABLE agent_routine_runs ( |
| 147 | routine_id TEXT NOT NULL, |
| 148 | -- The event's kind and what it was about: pull_ready:rep_1:12. |
| 149 | run_key TEXT NOT NULL, |
| 150 | session_id TEXT, |
| 151 | created_at TEXT NOT NULL, |
| 152 | PRIMARY KEY (routine_id, run_key) |
| 153 | ); |
| 154 | CREATE INDEX agent_routine_runs_recent ON agent_routine_runs (routine_id, created_at); |
| 155 | |
| 156 | -- The workspace's say over all its agents together. |
| 157 | CREATE TABLE agent_policies ( |
| 158 | workspace_id TEXT PRIMARY KEY, |
| 159 | monthly_micros INTEGER, |
| 160 | default_agent_monthly_micros INTEGER, |
| 161 | default_session_micros INTEGER NOT NULL DEFAULT 2000000, |
| 162 | updated_by TEXT, |
| 163 | updated_at TEXT NOT NULL |
| 164 | ); |
| 165 | |
| 166 | -- Every agent's spend together, by workspace and period (YYYY-MM, YYYY-MM-DD), |
| 167 | -- for the workspace's agent budget; and which alerts went out this month. |
| 168 | CREATE TABLE workspace_agent_spend ( |
| 169 | workspace_id TEXT NOT NULL, |
| 170 | period TEXT NOT NULL, |
| 171 | micros INTEGER NOT NULL DEFAULT 0, |
| 172 | alerted INTEGER NOT NULL DEFAULT 0, |
| 173 | PRIMARY KEY (workspace_id, period) |
| 174 | ); |
| 175 | |
| 176 | -- Replies say who they were for, where, and how many tools they used, for |
| 177 | -- the spend breakdown and the Activity tab. |
| 178 | ALTER TABLE agent_replies ADD COLUMN asked_by_username TEXT; |
| 179 | ALTER TABLE agent_replies ADD COLUMN channel_name TEXT; |
| 180 | ALTER TABLE agent_replies ADD COLUMN tool_count INTEGER NOT NULL DEFAULT 0; |
| 181 | -- Session steps counted with the agent's spend, beside replies. |
| 182 | ALTER TABLE agent_spend ADD COLUMN sessions INTEGER NOT NULL DEFAULT 0; |
| 183 | |
| 184 | -- Issues an agent drafted in a conversation, as cards with File and |
| 185 | -- Discard: whoever presses File files it as themselves, if they can read |
| 186 | -- the repository. status: draft, filed, discarded. |
| 187 | CREATE TABLE agent_drafts ( |
| 188 | id TEXT PRIMARY KEY, |
| 189 | agent_id TEXT NOT NULL, |
| 190 | workspace_id TEXT NOT NULL, |
| 191 | workspace TEXT NOT NULL, |
| 192 | channel_id TEXT NOT NULL, |
| 193 | message_id TEXT, |
| 194 | session_id TEXT, |
| 195 | repo_id TEXT NOT NULL, |
| 196 | repo TEXT NOT NULL, |
| 197 | title TEXT NOT NULL, |
| 198 | body TEXT NOT NULL, |
| 199 | labels TEXT NOT NULL DEFAULT '[]', |
| 200 | asked_by TEXT, |
| 201 | status TEXT NOT NULL DEFAULT 'draft', |
| 202 | filed_by TEXT, |
| 203 | number INTEGER, |
| 204 | created_at TEXT NOT NULL, |
| 205 | updated_at TEXT NOT NULL |
| 206 | ); |
| 207 | CREATE INDEX agent_drafts_message ON agent_drafts (message_id); |
| 208 | |
| 209 | -- Each agent's required reading: Docs spaces (a JSON list of ids) it |
| 210 | -- checks first whenever it answers or works. |
| 211 | ALTER TABLE agents ADD COLUMN reading TEXT NOT NULL DEFAULT '[]'; |