@desplega.ai/agent-swarm 1.59.0 → 1.59.1

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/openapi.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "openapi": "3.1.0",
3
3
  "info": {
4
4
  "title": "Agent Swarm API",
5
- "version": "1.59.0",
5
+ "version": "1.59.1",
6
6
  "description": "Multi-agent orchestration API for Claude Code, Codex, and Gemini CLI. Enables task distribution, agent communication, and service discovery.\n\nMCP tools are documented separately in [MCP.md](./MCP.md)."
7
7
  },
8
8
  "servers": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@desplega.ai/agent-swarm",
3
- "version": "1.59.0",
3
+ "version": "1.59.1",
4
4
  "description": "Multi-agent orchestration for Claude Code, Codex, Gemini CLI, and other AI coding assistants",
5
5
  "license": "MIT",
6
6
  "author": "desplega.sh <contact@desplega.sh>",
@@ -2170,6 +2170,8 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
2170
2170
 
2171
2171
  // Per-task repo context — set when processing a task with githubRepo
2172
2172
  let currentRepoContext: BasePromptArgs["repoContext"] | undefined;
2173
+ // Slack context for current task (gates Slack instructions in prompt)
2174
+ let currentTaskSlackContext: BasePromptArgs["slackContext"] | undefined;
2173
2175
 
2174
2176
  // Generate base prompt (identity fields injected after profile fetch below)
2175
2177
  const buildSystemPrompt = async () => {
@@ -2185,6 +2187,7 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
2185
2187
  toolsMd: agentToolsMd,
2186
2188
  claudeMd: agentClaudeMd,
2187
2189
  repoContext: currentRepoContext,
2190
+ slackContext: currentTaskSlackContext,
2188
2191
  skillsSummary: agentSkillsSummary,
2189
2192
  mcpServersSummary: agentMcpServersSummary,
2190
2193
  });
@@ -2923,6 +2926,15 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
2923
2926
  // Extract model from task data for per-task model selection
2924
2927
  const taskModel = (trigger.task as { model?: string } | undefined)?.model;
2925
2928
 
2929
+ // Detect Slack context for conditional prompt sections
2930
+ const taskSlackChannelId = (trigger.task as { slackChannelId?: string } | undefined)
2931
+ ?.slackChannelId;
2932
+ const taskSlackThreadTs = (trigger.task as { slackThreadTs?: string } | undefined)
2933
+ ?.slackThreadTs;
2934
+ currentTaskSlackContext = taskSlackChannelId
2935
+ ? { channelId: taskSlackChannelId, threadTs: taskSlackThreadTs }
2936
+ : undefined;
2937
+
2926
2938
  // Handle repo context for tasks with vcsRepo (GitHub/GitLab)
2927
2939
  const taskVcsRepo = (trigger.task as { vcsRepo?: string } | undefined)?.vcsRepo;
2928
2940
  if (taskVcsRepo && apiUrl) {
@@ -44,6 +44,8 @@ export type BasePromptArgs = {
44
44
  review: string[];
45
45
  } | null;
46
46
  };
47
+ /** Slack context from the current task, if present */
48
+ slackContext?: { channelId: string; threadTs?: string };
47
49
  /** Pre-fetched skill summaries for the installed skills section */
48
50
  skillsSummary?: { name: string; description: string }[];
49
51
  /** Pre-fetched MCP server summaries for the installed MCP servers section */
@@ -60,6 +62,15 @@ export const getBasePrompt = async (args: BasePromptArgs): Promise<string> => {
60
62
  const compositeResult = await resolveTemplateAsync(compositeEventType, vars);
61
63
  let prompt = compositeResult.text;
62
64
 
65
+ // Conditionally inject Slack instructions for workers with Slack-originated tasks
66
+ if (role !== "lead" && args.slackContext) {
67
+ const slackResult = await resolveTemplateAsync("system.agent.worker.slack", {
68
+ slackChannelId: args.slackContext.channelId,
69
+ slackThreadTs: args.slackContext.threadTs ?? "",
70
+ });
71
+ prompt += slackResult.text;
72
+ }
73
+
63
74
  // Inject agent identity (soul + identity + name/description) if available
64
75
  if (args.soulMd || args.identityMd || args.name) {
65
76
  prompt += "\n\n## Your Identity\n\n";
@@ -133,16 +133,6 @@ As a worker agent of the swarm, you are responsible for executing tasks assigned
133
133
  - \`store-progress\`: Save your work progress on tasks (critical!)
134
134
  - \`task-action\`: Manage tasks - claim from pool, release, accept/reject offered tasks
135
135
  - \`read-messages\`: Read messages from the lead or other workers
136
- - \`slack-reply\`: Reply to a Slack thread (use taskId for context — only works when your task has Slack metadata)
137
-
138
- #### Slack Thread Updates
139
-
140
- When your task has Slack metadata (slackChannelId/slackThreadTs), you MUST keep the originating Slack thread informed:
141
- - **On start**: Post a brief update that you've picked up the task
142
- - **On completion**: Post a summary of the result using \`slack-reply\` with your taskId
143
- - **On failure**: Post what went wrong so the requester knows immediately
144
-
145
- This ensures humans who requested work via Slack get timely feedback without having to check the dashboard.
146
136
 
147
137
  #### Completing Tasks
148
138
 
@@ -156,6 +146,26 @@ Always include meaningful output - the lead agent reviews your work.
156
146
  category: "system",
157
147
  });
158
148
 
149
+ registerTemplate({
150
+ eventType: "system.agent.worker.slack",
151
+ header: "",
152
+ defaultBody: `
153
+ #### Slack Thread Updates
154
+
155
+ This task originated from Slack (channel: \`{{slackChannelId}}\`). You MUST keep the originating Slack thread informed:
156
+ - **On start**: Post a brief update that you've picked up the task using \`slack-reply\` with your taskId
157
+ - **On completion**: Post a summary of the result using \`slack-reply\` with your taskId
158
+ - **On failure**: Post what went wrong so the requester knows immediately
159
+
160
+ This ensures humans who requested work via Slack get timely feedback without having to check the dashboard.
161
+ `,
162
+ variables: [
163
+ { name: "slackChannelId", description: "The Slack channel ID for the originating thread" },
164
+ { name: "slackThreadTs", description: "The Slack thread timestamp" },
165
+ ],
166
+ category: "system",
167
+ });
168
+
159
169
  registerTemplate({
160
170
  eventType: "system.agent.filesystem",
161
171
  header: "",
@@ -54,12 +54,13 @@ describe("Session templates — registration", () => {
54
54
  await ensureTemplatesRegistered();
55
55
  });
56
56
 
57
- test("all 12 system templates are registered", () => {
57
+ test("all 13 system templates are registered", () => {
58
58
  const systemTemplates = [
59
59
  "system.agent.role",
60
60
  "system.agent.register",
61
61
  "system.agent.lead",
62
62
  "system.agent.worker",
63
+ "system.agent.worker.slack",
63
64
  "system.agent.filesystem",
64
65
  "system.agent.agent_fs",
65
66
  "system.agent.self_awareness",
@@ -90,7 +91,7 @@ describe("Session templates — registration", () => {
90
91
  test("total of 15 session/system templates registered", () => {
91
92
  const all = getAllTemplateDefinitions();
92
93
  const sessionSystem = all.filter((d) => d.category === "system" || d.category === "session");
93
- expect(sessionSystem.length).toBe(14);
94
+ expect(sessionSystem.length).toBe(15);
94
95
  });
95
96
  });
96
97
 
@@ -178,8 +178,8 @@ describe("Tool Annotations & Classification", () => {
178
178
  expect(overlap).toEqual([]);
179
179
  });
180
180
 
181
- test("CORE_TOOLS contains exactly 15 tools", () => {
182
- expect(CORE_TOOLS.size).toBe(15);
181
+ test("CORE_TOOLS contains exactly 13 tools", () => {
182
+ expect(CORE_TOOLS.size).toBe(13);
183
183
  });
184
184
 
185
185
  test("ALL_TOOLS equals CORE_TOOLS union DEFERRED_TOOLS", () => {
@@ -237,7 +237,7 @@ describe("Tool Annotations & Classification", () => {
237
237
  });
238
238
 
239
239
  test("core tools include essential communication tools", () => {
240
- const commTools = ["read-messages", "post-message", "slack-reply", "slack-read"];
240
+ const commTools = ["read-messages", "post-message"];
241
241
  for (const tool of commTools) {
242
242
  expect(CORE_TOOLS.has(tool)).toBe(true);
243
243
  }
@@ -26,8 +26,6 @@ export const CORE_TOOLS = new Set([
26
26
  // Communication (used every session)
27
27
  "read-messages", // internal swarm chat
28
28
  "post-message", // internal swarm chat
29
- "slack-reply", // respond to Slack threads
30
- "slack-read", // read Slack thread history
31
29
 
32
30
  // Memory (used at session start)
33
31
  "memory-search", // recall relevant context
@@ -81,7 +79,9 @@ export const DEFERRED_TOOLS = new Set([
81
79
  "context-history",
82
80
  "context-diff",
83
81
 
84
- // Slack extras (4)
82
+ // Slack (6)
83
+ "slack-reply",
84
+ "slack-read",
85
85
  "slack-upload-file",
86
86
  "slack-download-file",
87
87
  "slack-list-channels",