返回 CodeWhale
3209-workrooms.md
根目录 / docs / rfcs / 3209-workrooms.md
1 # RFC: CodeWhale Workrooms — Chat-native Threaded Agent Work
2
3 **Issue:** #3209
4 **Status:** Future RFC — Phase 1 shipped (protocol types + link parser in
5 `crates/protocol/src/workroom.rs`); Phase 2 (store, app-server endpoints,
6 `resolve_workroom_link` tool, TUI inbox) not started
7 **Date:** 2026-06-17 (status refreshed 2026-07-15)
8 **Target:** post-v0.9.0; the release label is a maintainer decision, not part
9 of this design
10
11 This document is design scaffolding. As of v0.9.0 the tree carries the
12 shared protocol types and link parser only; runtime endpoints, mobile UI
13 integration, persistent state, and model-visible tools remain follow-up work.
14
15 ## 1. Problem
16
17 CodeWhale agent work currently lives in transient TUI sessions, local Runtime API
18 threads, Fleet runs, and chat-bridge message loops — each with its own lifecycle,
19 state representation, and context boundary. There is no first-class abstraction
20 that:
21
22 - lets a user start work on one surface (TUI) and resume it on another (mobile)
23 - gives a stable, shareable link to a thread of agent work
24 - attaches GitHub issues/PRs/commits as context without copying transcripts
25 - records which agent/model produced each event for multi-agent workflows
26 - provides a unified inbox of mentions, approvals, failures, and completions
27
28 ## 2. Proposed Abstraction: `Workroom`
29
30 A `Workroom` is a durable, addressable container for a threaded conversation
31 involving one or more agents, models, and human participants. It maps onto
32 the existing Runtime API thread infrastructure and extends it with:
33
34 ### 2.1 Core Types
35
36 ```rust
37 /// Unique identifier for a workroom, stable across restarts.
38 pub struct WorkroomId(pub String); // e.g. "wr_abc123def456"
39
40 /// A workroom aggregates threads, members, and metadata.
41 pub struct Workroom {
42 pub id: WorkroomId,
43 pub title: String,
44 pub workspace: Option<String>, // repo root or project path
45 pub repo_identity: Option<RepoRef>, // GitHub repo identity (owner/name)
46 pub owner: String, // local user or identity handle
47 pub created_at: DateTime<Utc>,
48 pub updated_at: DateTime<Utc>,
49 pub visibility: WorkroomVisibility,
50 }
51
52 pub enum WorkroomVisibility {
53 Private,
54 Shared { allowed_tokens: Vec<String> },
55 }
56
57 /// A thread within a workroom — can be a channel, DM, or linked external ref.
58 pub struct WorkroomThread {
59 pub id: String,
60 pub workroom_id: WorkroomId,
61 pub title: String,
62 pub kind: WorkroomThreadKind,
63 pub external_ref: Option<ExternalThreadRef>,
64 pub created_at: DateTime<Utc>,
65 }
66
67 pub enum WorkroomThreadKind {
68 Channel,
69 DirectMessage,
70 AgentTask, // spawned by an agent for sub-work
71 ApprovalQueue, // pending human approvals
72 ReceiptLog, // completed agent receipts
73 }
74
75 /// An external reference that can be attached to a workroom thread.
76 pub enum ExternalThreadRef {
77 GitHubIssue {
78 owner: String,
79 repo: String,
80 number: u64,
81 },
82 GitHubPullRequest {
83 owner: String,
84 repo: String,
85 number: u64,
86 },
87 GitHubCommit {
88 owner: String,
89 repo: String,
90 sha: String,
91 },
92 GitHubCheck {
93 owner: String,
94 repo: String,
95 check_run_id: u64,
96 },
97 }
98
99 /// An event within a workroom thread, attributed to an agent/model.
100 pub struct WorkroomEvent {
101 pub id: String,
102 pub thread_id: String,
103 pub workroom_id: WorkroomId,
104 pub timestamp: DateTime<Utc>,
105 pub kind: WorkroomEventKind,
106 pub agent: Option<AgentAttribution>,
107 }
108
109 pub enum WorkroomEventKind {
110 Message { content: String },
111 Mention { mentioned_user: String },
112 ToolCall { tool_name: String, summary: String },
113 ToolResult { tool_name: String, success: bool },
114 ApprovalRequest { tool_name: String },
115 ArtifactLinked { path: String, kind: String },
116 Receipt { summary: String },
117 Failure { error: String },
118 NeedsHuman { reason: String },
119 Resumed,
120 }
121
122 pub struct AgentAttribution {
123 pub provider: String, // e.g. "deepseek"
124 pub model: String, // e.g. "deepseek-v4-pro"
125 pub agent_id: String, // sub-agent or fleet worker id
126 }
127
128 /// A link that can be pasted into any surface and resolved back to a workroom.
129 pub struct WorkroomLink {
130 pub workroom_id: WorkroomId,
131 pub thread_id: Option<String>,
132 pub event_id: Option<String>,
133 }
134 ```
135
136 ### 2.2 Link Format
137
138 ```
139 codewhale://workroom/wr_abc123def456
140 codewhale://workroom/wr_abc123def456/thread/thr_xyz
141 codewhale://workroom/wr_abc123def456/event/evt_789
142 ```
143
144 ### 2.3 Mapping to Existing Infrastructure
145
146 | Workroom concept | Existing mapping |
147 |---|---|
148 | `Workroom` | New abstraction; future persisted state alongside Runtime API threads |
149 | `WorkroomThread` | Maps to a `ThreadId` in the Runtime API |
150 | `WorkroomEvent` | Wraps existing thread/fleet events with agent attribution |
151 | `WorkroomLink` | New URL scheme resolvable by the Runtime API |
152 | `ExternalThreadRef` | New; metadata-only, no secret/token storage |
153 | `AgentAttribution` | Extracted from sub-agent metadata and fleet worker identity |
154
155 ## 3. Planned Runtime API Endpoints
156
157 ### 3.1 `GET /workrooms`
158
159 List all workrooms visible to the authenticated caller.
160
161 Response:
162 ```json
163 {
164 "workrooms": [
165 {
166 "id": "wr_abc123",
167 "title": "PR #3231 — DeepInfra support",
168 "updated_at": "2026-06-15T12:00:00Z",
169 "active_threads": 3
170 }
171 ]
172 }
173 ```
174
175 ### 3.2 `GET /workroom/:id/threads`
176
177 List active threads within a workroom.
178
179 ### 3.3 `GET /workroom/resolve?link=codewhale://workroom/wr_abc/thread/thr_x`
180
181 Resolve a workroom link to scoped context (thread metadata, recent events)
182 without replaying the full transcript.
183
184 ### 3.4 Planned tool: `resolve_workroom_link`
185
186 A model-visible tool that takes a `codewhale://workroom/...` URL and returns
187 the scoped context (thread title, recent event summaries, external refs). This
188 should not be registered until the backing runtime resolution behavior exists.
189
190 ## 4. Security Model
191
192 - **Local-first by default.** Persisted workroom state should live under the
193 CodeWhale home directory alongside existing state. No cloud service is
194 assumed.
195 - **Runtime API auth required.** Planned workroom endpoints must use the same
196 `Authorization: Bearer <token>` protection as other runtime surfaces.
197 - **No secrets in links.** Workroom links contain only opaque IDs, never API
198 keys or tokens. Resolution requires local Runtime API access.
199 - **No secrets in events.** Event payloads must not contain API keys, auth
200 tokens, or plaintext credentials. The `ArtifactLinked` event kind references
201 paths, not contents.
202 - **Share semantics.** `WorkroomVisibility::Shared` lists allowed bearer tokens,
203 not usernames. The operator controls which tokens can access a workroom.
204 - **No public links.** There is no unauthenticated read path for workrooms.
205
206 ## 5. Integration Points
207
208 ### 5.1 Mobile Control Page
209
210 The mobile page at `/mobile` already lists active threads. Replace its
211 ad-hoc thread listing with the `/workrooms` projection so it renders the
212 same inbox that the TUI and chat bridges see.
213
214 ### 5.2 Chat Bridges (Telegram, Feishu)
215
216 Chat bridges currently maintain their own message loops. Each bridge should
217 publish bridge-originated messages as `WorkroomEvent::Message` into a
218 designated workroom thread, and consume `WorkroomEvent::Mention` events
219 as bridge notifications.
220
221 ### 5.3 TUI
222
223 The TUI should surface workroom inbox events (mentions, approvals) in the
224 sidebar, and allow pasting `codewhale://` links into the composer for
225 context resolution.
226
227 ## 6. Implementation Plan
228
229 ### Phase 1: Foundation (this PR)
230 - [x] RFC design doc
231 - [x] `WorkroomId`, `Workroom`, `WorkroomThread`, `WorkroomEvent`, `WorkroomLink` types
232 - [x] `ExternalThreadRef` (GitHub refs as workroom context)
233 - [x] `AgentAttribution` (multi-agent/model event attribution)
234 - [x] Security model documentation
235 - [x] Architecture docs
236
237 ### Phase 2: Integration (follow-up)
238 - [ ] Persistent workroom state store
239 - [ ] Runtime API endpoints: `GET /workrooms`, `GET /workroom/:id/threads`
240 - [ ] `resolve_workroom_link` tool for link resolution
241 - [ ] Mobile page consumes workroom projection
242 - [ ] Chat bridges publish/consume workroom events
243 - [ ] TUI inbox sidebar
244 - [ ] Workroom link paste resolution in composer
245
246 ## 7. Non-goals for Phase 1
247
248 - No hosted public CodeWhale cloud service
249 - No default-on Slack/Discord/Feishu/Telegram/GitHub App integration
250 - No arbitrary public share links without explicit auth story
251 - No model-specific workroom format
252 - No migration of existing threads (new workrooms only)
253
253 lines MARKDOWN