@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 +1 -1
- package/package.json +1 -1
- package/src/commands/runner.ts +12 -0
- package/src/prompts/base-prompt.ts +11 -0
- package/src/prompts/session-templates.ts +20 -10
- package/src/tests/prompt-template-session.test.ts +3 -2
- package/src/tests/tool-annotations.test.ts +3 -3
- package/src/tools/tool-config.ts +3 -3
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.
|
|
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
package/src/commands/runner.ts
CHANGED
|
@@ -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
|
|
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(
|
|
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
|
|
182
|
-
expect(CORE_TOOLS.size).toBe(
|
|
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"
|
|
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
|
}
|
package/src/tools/tool-config.ts
CHANGED
|
@@ -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
|
|
82
|
+
// Slack (6)
|
|
83
|
+
"slack-reply",
|
|
84
|
+
"slack-read",
|
|
85
85
|
"slack-upload-file",
|
|
86
86
|
"slack-download-file",
|
|
87
87
|
"slack-list-channels",
|