@desplega.ai/agent-swarm 1.2.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +20 -1
- package/.dockerignore +3 -0
- package/.env.docker.example +22 -1
- package/.env.example +17 -0
- package/.github/workflows/docker-publish.yml +92 -0
- package/CONTRIBUTING.md +270 -0
- package/DEPLOYMENT.md +391 -0
- package/Dockerfile.worker +29 -1
- package/FAQ.md +19 -0
- package/LICENSE +21 -0
- package/MCP.md +249 -0
- package/README.md +105 -185
- package/assets/agent-swarm-logo-orange.png +0 -0
- package/assets/agent-swarm-logo.png +0 -0
- package/assets/agent-swarm.png +0 -0
- package/deploy/docker-push.ts +30 -0
- package/docker-compose.example.yml +137 -0
- package/docker-entrypoint.sh +223 -7
- package/package.json +13 -4
- package/{cc-plugin → plugin}/.claude-plugin/plugin.json +1 -1
- package/plugin/README.md +1 -0
- package/plugin/agents/.gitkeep +0 -0
- package/plugin/agents/codebase-analyzer.md +143 -0
- package/plugin/agents/codebase-locator.md +122 -0
- package/plugin/agents/codebase-pattern-finder.md +227 -0
- package/plugin/agents/web-search-researcher.md +109 -0
- package/plugin/commands/create-plan.md +415 -0
- package/plugin/commands/implement-plan.md +89 -0
- package/plugin/commands/research.md +200 -0
- package/plugin/commands/start-leader.md +101 -0
- package/plugin/commands/start-worker.md +56 -0
- package/plugin/commands/swarm-chat.md +78 -0
- package/plugin/commands/todos.md +66 -0
- package/plugin/commands/work-on-task.md +44 -0
- package/plugin/skills/.gitkeep +0 -0
- package/scripts/generate-mcp-docs.ts +415 -0
- package/slack-manifest.json +69 -0
- package/src/be/db.ts +1431 -25
- package/src/cli.tsx +135 -11
- package/src/commands/lead.ts +13 -0
- package/src/commands/runner.ts +255 -0
- package/src/commands/setup.tsx +5 -5
- package/src/commands/worker.ts +8 -220
- package/src/hooks/hook.ts +108 -14
- package/src/http.ts +361 -5
- package/src/prompts/base-prompt.ts +131 -0
- package/src/server.ts +56 -0
- package/src/slack/app.ts +73 -0
- package/src/slack/commands.ts +88 -0
- package/src/slack/handlers.ts +281 -0
- package/src/slack/index.ts +3 -0
- package/src/slack/responses.ts +175 -0
- package/src/slack/router.ts +170 -0
- package/src/slack/types.ts +20 -0
- package/src/slack/watcher.ts +119 -0
- package/src/tools/create-channel.ts +80 -0
- package/src/tools/get-tasks.ts +54 -21
- package/src/tools/join-swarm.ts +28 -4
- package/src/tools/list-channels.ts +37 -0
- package/src/tools/list-services.ts +110 -0
- package/src/tools/poll-task.ts +47 -3
- package/src/tools/post-message.ts +87 -0
- package/src/tools/read-messages.ts +192 -0
- package/src/tools/register-service.ts +118 -0
- package/src/tools/send-task.ts +80 -7
- package/src/tools/store-progress.ts +9 -3
- package/src/tools/task-action.ts +211 -0
- package/src/tools/unregister-service.ts +110 -0
- package/src/tools/update-profile.ts +105 -0
- package/src/tools/update-service-status.ts +118 -0
- package/src/types.ts +110 -3
- package/src/utils/pretty-print.ts +224 -0
- package/thoughts/shared/plans/.gitkeep +0 -0
- package/thoughts/shared/plans/2025-12-18-inverse-teleport.md +1142 -0
- package/thoughts/shared/plans/2025-12-18-slack-integration.md +1195 -0
- package/thoughts/shared/plans/2025-12-19-agent-log-streaming.md +732 -0
- package/thoughts/shared/plans/2025-12-19-role-based-swarm-plugin.md +361 -0
- package/thoughts/shared/plans/2025-12-20-mobile-responsive-ui.md +501 -0
- package/thoughts/shared/plans/2025-12-20-startup-team-swarm.md +560 -0
- package/thoughts/shared/research/.gitkeep +0 -0
- package/thoughts/shared/research/2025-12-18-slack-integration.md +442 -0
- package/thoughts/shared/research/2025-12-19-agent-log-streaming.md +339 -0
- package/thoughts/shared/research/2025-12-19-agent-secrets-cli-research.md +390 -0
- package/thoughts/shared/research/2025-12-21-gemini-cli-integration.md +376 -0
- package/thoughts/shared/research/2025-12-22-setup-experience-improvements.md +264 -0
- package/tsconfig.json +3 -1
- package/ui/bun.lock +692 -0
- package/ui/index.html +22 -0
- package/ui/package.json +32 -0
- package/ui/pnpm-lock.yaml +3034 -0
- package/ui/postcss.config.js +6 -0
- package/ui/public/logo.png +0 -0
- package/ui/src/App.tsx +43 -0
- package/ui/src/components/ActivityFeed.tsx +415 -0
- package/ui/src/components/AgentDetailPanel.tsx +534 -0
- package/ui/src/components/AgentsPanel.tsx +549 -0
- package/ui/src/components/ChatPanel.tsx +1820 -0
- package/ui/src/components/ConfigModal.tsx +232 -0
- package/ui/src/components/Dashboard.tsx +534 -0
- package/ui/src/components/Header.tsx +168 -0
- package/ui/src/components/ServicesPanel.tsx +612 -0
- package/ui/src/components/StatsBar.tsx +288 -0
- package/ui/src/components/StatusBadge.tsx +124 -0
- package/ui/src/components/TaskDetailPanel.tsx +807 -0
- package/ui/src/components/TasksPanel.tsx +575 -0
- package/ui/src/hooks/queries.ts +170 -0
- package/ui/src/index.css +235 -0
- package/ui/src/lib/api.ts +161 -0
- package/ui/src/lib/config.ts +35 -0
- package/ui/src/lib/theme.ts +214 -0
- package/ui/src/lib/utils.ts +48 -0
- package/ui/src/main.tsx +32 -0
- package/ui/src/types/api.ts +164 -0
- package/ui/src/vite-env.d.ts +1 -0
- package/ui/tailwind.config.js +35 -0
- package/ui/tsconfig.json +31 -0
- package/ui/vite.config.ts +22 -0
- package/cc-plugin/README.md +0 -49
- package/cc-plugin/commands/setup-leader.md +0 -73
- package/cc-plugin/commands/start-worker.md +0 -64
- package/docker-compose.worker.yml +0 -35
- package/example-req-meta.json +0 -24
- /package/{cc-plugin → plugin}/hooks/hooks.json +0 -0
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
---
|
|
2
|
+
date: 2025-12-18T21:25:00-08:00
|
|
3
|
+
researcher: Claude-Main
|
|
4
|
+
git_commit: e0ba9a0d441dfc498a6a974854f3a38415e899ca
|
|
5
|
+
branch: main
|
|
6
|
+
repository: ai-toolbox/cc-orch-mcp
|
|
7
|
+
topic: "Slack Multi-Agent Bot Integration - Codebase Analysis"
|
|
8
|
+
tags: [research, codebase, slack, agent-swarm, http-api, database]
|
|
9
|
+
status: complete
|
|
10
|
+
last_updated: 2025-12-18
|
|
11
|
+
last_updated_by: Claude-Main
|
|
12
|
+
last_updated_note: "Added design decisions based on user feedback"
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Research: Slack Multi-Agent Bot Integration - Codebase Analysis
|
|
16
|
+
|
|
17
|
+
**Date**: 2025-12-18T21:25:00-08:00
|
|
18
|
+
**Researcher**: Claude-Main
|
|
19
|
+
**Git Commit**: e0ba9a0d441dfc498a6a974854f3a38415e899ca
|
|
20
|
+
**Branch**: main
|
|
21
|
+
**Repository**: desplega-ai/ai-toolbox (cc-orch-mcp subdirectory)
|
|
22
|
+
|
|
23
|
+
## Research Question
|
|
24
|
+
|
|
25
|
+
Document the existing Agent Swarm MCP codebase architecture to understand how Slack Multi-Agent Bot support can be implemented in the HTTP API. Focus on:
|
|
26
|
+
- HTTP API structure and routing patterns
|
|
27
|
+
- Database schema and potential token storage
|
|
28
|
+
- Agent swarm coordination patterns
|
|
29
|
+
- Types and interfaces
|
|
30
|
+
|
|
31
|
+
## Summary
|
|
32
|
+
|
|
33
|
+
The Agent Swarm MCP is a multi-agent coordination system built with Bun and the MCP SDK. It provides:
|
|
34
|
+
|
|
35
|
+
1. **HTTP Server** (`src/http.ts`) - Raw Node.js HTTP server with REST API + MCP transport
|
|
36
|
+
2. **SQLite Database** (`src/be/db.ts`) - Three tables: `agents`, `agent_tasks`, `agent_log`
|
|
37
|
+
3. **MCP Tools** (`src/tools/*.ts`) - 8 tools for agent coordination via MCP protocol
|
|
38
|
+
4. **CLI Commands** (`src/commands/*.ts`) - Worker and lead agent runners that spawn Claude CLI
|
|
39
|
+
|
|
40
|
+
**No existing Slack code exists** in the codebase. The Slack manifest has been saved to `slack-manifest.json`.
|
|
41
|
+
|
|
42
|
+
## Detailed Findings
|
|
43
|
+
|
|
44
|
+
### 1. HTTP API Architecture
|
|
45
|
+
|
|
46
|
+
**File**: `src/http.ts:1-423`
|
|
47
|
+
|
|
48
|
+
The HTTP server is a raw Node.js `createServer` implementation (not Express or Bun.serve).
|
|
49
|
+
|
|
50
|
+
#### Server Configuration
|
|
51
|
+
```typescript
|
|
52
|
+
const port = parseInt(process.env.PORT || process.argv[2] || "3013", 10);
|
|
53
|
+
const apiKey = process.env.API_KEY || "";
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
#### Authentication Pattern (`http.ts:96-106`)
|
|
57
|
+
All requests (except `/health`) are authenticated via Bearer token:
|
|
58
|
+
```typescript
|
|
59
|
+
if (apiKey) {
|
|
60
|
+
const authHeader = req.headers.authorization;
|
|
61
|
+
const providedKey = authHeader?.startsWith("Bearer ") ? authHeader.slice(7) : null;
|
|
62
|
+
if (providedKey !== apiKey) {
|
|
63
|
+
res.writeHead(401, { "Content-Type": "application/json" });
|
|
64
|
+
res.end(JSON.stringify({ error: "Unauthorized" }));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
#### CORS Handling (`http.ts:45-50`)
|
|
71
|
+
```typescript
|
|
72
|
+
function setCorsHeaders(res: ServerResponse) {
|
|
73
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
74
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, OPTIONS");
|
|
75
|
+
res.setHeader("Access-Control-Allow-Headers", "*");
|
|
76
|
+
res.setHeader("Access-Control-Expose-Headers", "*");
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
#### Existing Endpoints
|
|
81
|
+
|
|
82
|
+
| Method | Path | Purpose | File Location |
|
|
83
|
+
|--------|------|---------|---------------|
|
|
84
|
+
| GET | `/health` | Health check with version | `http.ts:81-94` |
|
|
85
|
+
| GET | `/me` | Get current agent info | `http.ts:108-126` |
|
|
86
|
+
| POST | `/ping` | Update agent last-seen | `http.ts:128-162` |
|
|
87
|
+
| POST | `/close` | Mark agent offline | `http.ts:164-192` |
|
|
88
|
+
| GET | `/api/agents` | List all agents | `http.ts:201-213` |
|
|
89
|
+
| GET | `/api/agents/:id` | Get single agent | `http.ts:215-235` |
|
|
90
|
+
| GET | `/api/tasks` | List tasks with filters | `http.ts:237-255` |
|
|
91
|
+
| GET | `/api/tasks/:id` | Get task with logs | `http.ts:257-277` |
|
|
92
|
+
| GET | `/api/logs` | List recent logs | `http.ts:279-293` |
|
|
93
|
+
| GET | `/api/stats` | Dashboard stats | `http.ts:295-319` |
|
|
94
|
+
| POST/GET/DELETE | `/mcp` | MCP transport | `http.ts:321-384` |
|
|
95
|
+
|
|
96
|
+
#### URL Parsing Pattern (`http.ts:52-62`)
|
|
97
|
+
```typescript
|
|
98
|
+
function parseQueryParams(url: string): URLSearchParams {
|
|
99
|
+
const queryIndex = url.indexOf("?");
|
|
100
|
+
if (queryIndex === -1) return new URLSearchParams();
|
|
101
|
+
return new URLSearchParams(url.slice(queryIndex + 1));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function getPathSegments(url: string): string[] {
|
|
105
|
+
const pathEnd = url.indexOf("?");
|
|
106
|
+
const path = pathEnd === -1 ? url : url.slice(0, pathEnd);
|
|
107
|
+
return path.split("/").filter(Boolean);
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 2. Database Schema
|
|
112
|
+
|
|
113
|
+
**File**: `src/be/db.ts:1-535`
|
|
114
|
+
|
|
115
|
+
Uses `bun:sqlite` with WAL mode and foreign keys enabled.
|
|
116
|
+
|
|
117
|
+
#### Tables
|
|
118
|
+
|
|
119
|
+
**agents** (`db.ts:24-31`)
|
|
120
|
+
```sql
|
|
121
|
+
CREATE TABLE IF NOT EXISTS agents (
|
|
122
|
+
id TEXT PRIMARY KEY,
|
|
123
|
+
name TEXT NOT NULL,
|
|
124
|
+
isLead INTEGER NOT NULL DEFAULT 0,
|
|
125
|
+
status TEXT NOT NULL CHECK(status IN ('idle', 'busy', 'offline')),
|
|
126
|
+
createdAt TEXT NOT NULL,
|
|
127
|
+
lastUpdatedAt TEXT NOT NULL
|
|
128
|
+
);
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**agent_tasks** (`db.ts:33-46`)
|
|
132
|
+
```sql
|
|
133
|
+
CREATE TABLE IF NOT EXISTS agent_tasks (
|
|
134
|
+
id TEXT PRIMARY KEY,
|
|
135
|
+
agentId TEXT NOT NULL,
|
|
136
|
+
task TEXT NOT NULL,
|
|
137
|
+
status TEXT NOT NULL CHECK(status IN ('pending', 'in_progress', 'completed', 'failed')),
|
|
138
|
+
createdAt TEXT NOT NULL,
|
|
139
|
+
lastUpdatedAt TEXT NOT NULL,
|
|
140
|
+
finishedAt TEXT,
|
|
141
|
+
failureReason TEXT,
|
|
142
|
+
output TEXT,
|
|
143
|
+
progress TEXT,
|
|
144
|
+
FOREIGN KEY (agentId) REFERENCES agents(id) ON DELETE CASCADE
|
|
145
|
+
);
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**agent_log** (`db.ts:50-59`)
|
|
149
|
+
```sql
|
|
150
|
+
CREATE TABLE IF NOT EXISTS agent_log (
|
|
151
|
+
id TEXT PRIMARY KEY,
|
|
152
|
+
eventType TEXT NOT NULL,
|
|
153
|
+
agentId TEXT,
|
|
154
|
+
taskId TEXT,
|
|
155
|
+
oldValue TEXT,
|
|
156
|
+
newValue TEXT,
|
|
157
|
+
metadata TEXT,
|
|
158
|
+
createdAt TEXT NOT NULL
|
|
159
|
+
);
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
#### Database Initialization (`db.ts:14-68`)
|
|
163
|
+
```typescript
|
|
164
|
+
export function initDb(dbPath = "./agent-swarm-db.sqlite"): Database {
|
|
165
|
+
if (db) return db;
|
|
166
|
+
db = new Database(dbPath, { create: true });
|
|
167
|
+
db.run("PRAGMA journal_mode = WAL;");
|
|
168
|
+
db.run("PRAGMA foreign_keys = ON;");
|
|
169
|
+
// ... table creation
|
|
170
|
+
return db;
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
#### Key Database Functions
|
|
175
|
+
|
|
176
|
+
| Function | Purpose | Location |
|
|
177
|
+
|----------|---------|----------|
|
|
178
|
+
| `createAgent()` | Insert new agent | `db.ts:126-136` |
|
|
179
|
+
| `getAgentById()` | Fetch agent by ID | `db.ts:138-141` |
|
|
180
|
+
| `getAllAgents()` | List all agents | `db.ts:143-145` |
|
|
181
|
+
| `updateAgentStatus()` | Update agent status | `db.ts:147-161` |
|
|
182
|
+
| `createTask()` | Create new task | `db.ts:249-257` |
|
|
183
|
+
| `getPendingTaskForAgent()` | Get oldest pending task | `db.ts:259-266` |
|
|
184
|
+
| `startTask()` | Mark task in_progress | `db.ts:268-288` |
|
|
185
|
+
| `completeTask()` | Mark task completed | `db.ts:337-360` |
|
|
186
|
+
| `failTask()` | Mark task failed | `db.ts:362-379` |
|
|
187
|
+
| `createLogEntry()` | Create audit log entry | `db.ts:485-507` |
|
|
188
|
+
|
|
189
|
+
### 3. Types and Interfaces
|
|
190
|
+
|
|
191
|
+
**File**: `src/types.ts:1-67`
|
|
192
|
+
|
|
193
|
+
Uses Zod v4 for schema validation and type inference.
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
// Agent statuses
|
|
197
|
+
export type AgentStatus = "idle" | "busy" | "offline";
|
|
198
|
+
|
|
199
|
+
// Task statuses
|
|
200
|
+
export type AgentTaskStatus = "pending" | "in_progress" | "completed" | "failed";
|
|
201
|
+
|
|
202
|
+
// Log event types
|
|
203
|
+
export type AgentLogEventType =
|
|
204
|
+
| "agent_joined"
|
|
205
|
+
| "agent_status_change"
|
|
206
|
+
| "agent_left"
|
|
207
|
+
| "task_created"
|
|
208
|
+
| "task_status_change"
|
|
209
|
+
| "task_progress";
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### 4. MCP Server and Tools
|
|
213
|
+
|
|
214
|
+
**File**: `src/server.ts:1-41`
|
|
215
|
+
|
|
216
|
+
Creates an MCP server with 8 registered tools:
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
export function createServer() {
|
|
220
|
+
initDb();
|
|
221
|
+
const server = new McpServer({ name, version, description }, {
|
|
222
|
+
capabilities: { logging: {} }
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
registerJoinSwarmTool(server); // Join the swarm
|
|
226
|
+
registerPollTaskTool(server); // Long-poll for tasks
|
|
227
|
+
registerGetSwarmTool(server); // List agents
|
|
228
|
+
registerGetTasksTool(server); // List tasks
|
|
229
|
+
registerSendTaskTool(server); // Assign task to agent
|
|
230
|
+
registerGetTaskDetailsTool(server); // Get task details
|
|
231
|
+
registerStoreProgressTool(server); // Update task progress
|
|
232
|
+
registerMyAgentInfoTool(server); // Get own agent info
|
|
233
|
+
|
|
234
|
+
return server;
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
#### Tool Registration Pattern (`src/tools/utils.ts`)
|
|
239
|
+
|
|
240
|
+
All tools use `createToolRegistrar` which extracts:
|
|
241
|
+
- `X-Agent-ID` header for agent identification
|
|
242
|
+
- Session ID from MCP transport metadata
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
export function createToolRegistrar(server: McpServer) {
|
|
246
|
+
return function registerTool<TInput, TOutput>(
|
|
247
|
+
name: string,
|
|
248
|
+
options: ToolOptions<TInput, TOutput>,
|
|
249
|
+
callback: ToolCallback<TInput, TOutput>
|
|
250
|
+
) {
|
|
251
|
+
server.tool(name, options, async (args, meta) => {
|
|
252
|
+
const requestInfo = extractRequestInfo(meta);
|
|
253
|
+
return callback(args, requestInfo, meta);
|
|
254
|
+
});
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### 5. CLI Runner Architecture
|
|
260
|
+
|
|
261
|
+
**File**: `src/commands/runner.ts:1-263`
|
|
262
|
+
|
|
263
|
+
The runner spawns Claude CLI processes with specific prompts:
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
const CMD = [
|
|
267
|
+
"claude",
|
|
268
|
+
"--verbose",
|
|
269
|
+
"--output-format", "stream-json",
|
|
270
|
+
"--dangerously-skip-permissions",
|
|
271
|
+
"--allow-dangerously-skip-permissions",
|
|
272
|
+
"--permission-mode", "bypassPermissions",
|
|
273
|
+
"-p", opts.prompt,
|
|
274
|
+
];
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
**Lead Agent** (`src/commands/lead.ts`)
|
|
278
|
+
- Default prompt: `/setup-leader Setup the agent swarm and begin coordinating workers!`
|
|
279
|
+
- Environment: `LEAD_YOLO`, `LEAD_LOG_DIR`, `LEAD_SYSTEM_PROMPT`
|
|
280
|
+
|
|
281
|
+
**Worker Agent** (`src/commands/worker.ts`)
|
|
282
|
+
- Default prompt: `/start-worker Start or continue the tasks your leader assigned you!`
|
|
283
|
+
- Environment: `WORKER_YOLO`, `WORKER_LOG_DIR`, `WORKER_SYSTEM_PROMPT`
|
|
284
|
+
|
|
285
|
+
### 6. Frontend UI
|
|
286
|
+
|
|
287
|
+
**Directory**: `ui/src/`
|
|
288
|
+
|
|
289
|
+
A React dashboard with these components:
|
|
290
|
+
- `Dashboard.tsx` - Main layout
|
|
291
|
+
- `AgentsPanel.tsx` - Agent list
|
|
292
|
+
- `TasksPanel.tsx` - Task list
|
|
293
|
+
- `AgentDetailPanel.tsx` - Single agent view
|
|
294
|
+
- `TaskDetailPanel.tsx` - Single task view
|
|
295
|
+
- `ActivityFeed.tsx` - Log stream
|
|
296
|
+
- `StatsBar.tsx` - Summary stats
|
|
297
|
+
- `ConfigModal.tsx` - Settings
|
|
298
|
+
|
|
299
|
+
Uses:
|
|
300
|
+
- React 19
|
|
301
|
+
- TanStack Query for data fetching
|
|
302
|
+
- Emotion for styling
|
|
303
|
+
|
|
304
|
+
### 7. Slack Manifest
|
|
305
|
+
|
|
306
|
+
**File**: `slack-manifest.json`
|
|
307
|
+
|
|
308
|
+
Key configuration:
|
|
309
|
+
- **Bot Name**: `agent-swarm`
|
|
310
|
+
- **Socket Mode**: Enabled (`socket_mode_enabled: true`)
|
|
311
|
+
- **Always Online**: `true`
|
|
312
|
+
|
|
313
|
+
**Scopes**:
|
|
314
|
+
- `chat:write`, `chat:write.customize`, `chat:write.public` - Send messages with custom personas
|
|
315
|
+
- `app_mentions:read` - Detect @mentions
|
|
316
|
+
- `channels:history`, `groups:history`, `im:history`, `mpim:history` - Read message history
|
|
317
|
+
- `channels:read`, `groups:read`, `im:read`, `mpim:read` - Read channel info
|
|
318
|
+
- `im:write`, `mpim:write` - Send DMs
|
|
319
|
+
- `users:read` - Get user info
|
|
320
|
+
- `commands` - Slash commands
|
|
321
|
+
|
|
322
|
+
**Events**:
|
|
323
|
+
- `app_mention` - When bot is @mentioned
|
|
324
|
+
- `message.channels` - Public channel messages
|
|
325
|
+
- `message.groups` - Private channel messages
|
|
326
|
+
- `message.im` - Direct messages
|
|
327
|
+
- `message.mpim` - Group DMs
|
|
328
|
+
|
|
329
|
+
**Slash Command**: `/agent-swarm-status` - Check status of available agents
|
|
330
|
+
|
|
331
|
+
## Architecture Documentation
|
|
332
|
+
|
|
333
|
+
### Request Flow
|
|
334
|
+
|
|
335
|
+
1. HTTP request arrives at `http.ts` server
|
|
336
|
+
2. CORS headers set, OPTIONS handled
|
|
337
|
+
3. API key validated from Bearer token
|
|
338
|
+
4. Route matched by path segments
|
|
339
|
+
5. For `/mcp`: MCP transport handles tool calls
|
|
340
|
+
6. Tools extract `X-Agent-ID` header and interact with SQLite DB
|
|
341
|
+
7. Response returned as JSON
|
|
342
|
+
|
|
343
|
+
### Agent Coordination Pattern
|
|
344
|
+
|
|
345
|
+
1. **Lead** joins swarm with `join-swarm` tool (isLead=true)
|
|
346
|
+
2. **Workers** join swarm with `join-swarm` tool (isLead=false)
|
|
347
|
+
3. Lead uses `send-task` to assign work to idle workers
|
|
348
|
+
4. Workers use `poll-task` (long-polling) to receive assignments
|
|
349
|
+
5. Workers use `store-progress` to report progress/completion
|
|
350
|
+
6. All agents can use `get-swarm` and `get-tasks` for visibility
|
|
351
|
+
|
|
352
|
+
## Code References
|
|
353
|
+
|
|
354
|
+
- `src/http.ts:1-423` - HTTP server implementation
|
|
355
|
+
- `src/be/db.ts:1-535` - Database layer
|
|
356
|
+
- `src/types.ts:1-67` - Type definitions
|
|
357
|
+
- `src/server.ts:1-41` - MCP server setup
|
|
358
|
+
- `src/tools/join-swarm.ts:1-114` - Agent registration
|
|
359
|
+
- `src/tools/send-task.ts:1-100` - Task assignment
|
|
360
|
+
- `src/tools/poll-task.ts:1-143` - Task polling
|
|
361
|
+
- `src/tools/store-progress.ts:1-129` - Progress updates
|
|
362
|
+
- `src/commands/runner.ts:1-263` - Claude CLI runner
|
|
363
|
+
- `slack-manifest.json` - Slack app manifest
|
|
364
|
+
|
|
365
|
+
## Integration Points for Slack
|
|
366
|
+
|
|
367
|
+
Based on this analysis, Slack integration would touch:
|
|
368
|
+
|
|
369
|
+
1. **New Database Table** - For storing workspace OAuth tokens:
|
|
370
|
+
```sql
|
|
371
|
+
CREATE TABLE slack_installations (
|
|
372
|
+
team_id TEXT PRIMARY KEY,
|
|
373
|
+
bot_token TEXT NOT NULL,
|
|
374
|
+
app_token TEXT,
|
|
375
|
+
...
|
|
376
|
+
);
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
2. **New HTTP Endpoints** in `src/http.ts`:
|
|
380
|
+
- `POST /slack/events` - Slack event subscriptions
|
|
381
|
+
- `POST /slack/commands` - Slash command handler
|
|
382
|
+
- `POST /slack/interactions` - Interactive components
|
|
383
|
+
- `GET /oauth/slack/callback` - OAuth callback
|
|
384
|
+
|
|
385
|
+
3. **New Module** (suggested: `src/slack/`):
|
|
386
|
+
- `bolt.ts` - Slack Bolt app initialization
|
|
387
|
+
- `handlers.ts` - Event/command handlers
|
|
388
|
+
- `personas.ts` - Agent persona definitions
|
|
389
|
+
- `router.ts` - Message routing logic
|
|
390
|
+
|
|
391
|
+
4. **Environment Variables**:
|
|
392
|
+
- Single workspace: `SLACK_BOT_TOKEN`, `SLACK_APP_TOKEN`
|
|
393
|
+
- Multi-workspace: `SLACK_CLIENT_ID`, `SLACK_CLIENT_SECRET`, `SLACK_SIGNING_SECRET`
|
|
394
|
+
|
|
395
|
+
## Design Decisions
|
|
396
|
+
|
|
397
|
+
### 1. Connection Mode
|
|
398
|
+
**Decision**: Socket Mode
|
|
399
|
+
|
|
400
|
+
Use Slack's socket mode with `SLACK_APP_TOKEN` for real-time event delivery without exposing public endpoints.
|
|
401
|
+
|
|
402
|
+
### 2. Persona-to-Agent Mapping
|
|
403
|
+
**Decision**: Match by name or ID using `swarm#<id>` syntax
|
|
404
|
+
|
|
405
|
+
- Agent personas correspond directly to swarm agents
|
|
406
|
+
- Can address by agent name or explicit ID: `swarm#<uuid>`
|
|
407
|
+
|
|
408
|
+
### 3. Task Creation from Slack
|
|
409
|
+
**Decision**: Direct task creation with task type field
|
|
410
|
+
|
|
411
|
+
- Slack messages create tasks directly (no lead agent intermediary)
|
|
412
|
+
- Add a `source` or `type` field to `agent_tasks` to distinguish Slack-created tasks
|
|
413
|
+
- Allows future expansion to other sources (Discord, API, etc.)
|
|
414
|
+
|
|
415
|
+
### 4. Message Routing Logic
|
|
416
|
+
**Decision**: Regex-based partial matching with multi-agent support
|
|
417
|
+
|
|
418
|
+
Rules:
|
|
419
|
+
- **Partial name matching**: Match at least one word of agent name (>3 chars to avoid connectors like "the", "and")
|
|
420
|
+
- **Multi-mention support**: A single message can mention multiple agents → create separate tasks for each
|
|
421
|
+
- **Root bot mention**: `@Desplegillo` (the bot's real @) routes to the lead agent
|
|
422
|
+
- **Broadcast**: `swarm#all` sends to all agents in the swarm
|
|
423
|
+
|
|
424
|
+
Example routing:
|
|
425
|
+
```
|
|
426
|
+
"Hey Alpha, can you..." → routes to agent named "Alpha"
|
|
427
|
+
"@Desplegillo help" → routes to lead agent
|
|
428
|
+
"swarm#all status check" → broadcasts to all agents
|
|
429
|
+
"Alpha and Beta, review this" → creates 2 tasks (one for Alpha, one for Beta)
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### 5. Multi-Workspace Support
|
|
433
|
+
**Decision**: Single workspace first, design for expansion
|
|
434
|
+
|
|
435
|
+
- Initial implementation: Single workspace using static env vars
|
|
436
|
+
- Store tokens in DB even for single workspace (cleaner architecture)
|
|
437
|
+
- Leave `team_id` as primary key to support multi-workspace later
|
|
438
|
+
- Document OAuth flow for future multi-workspace implementation
|
|
439
|
+
|
|
440
|
+
## Open Questions
|
|
441
|
+
|
|
442
|
+
None remaining - ready for implementation planning.
|