agent-relay 3.2.1 → 3.2.2

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.
Files changed (54) hide show
  1. package/bin/agent-relay-broker-darwin-arm64 +0 -0
  2. package/bin/agent-relay-broker-darwin-x64 +0 -0
  3. package/bin/agent-relay-broker-linux-arm64 +0 -0
  4. package/bin/agent-relay-broker-linux-x64 +0 -0
  5. package/dist/index.cjs +108 -36
  6. package/dist/src/cli/commands/core.d.ts +1 -0
  7. package/dist/src/cli/commands/core.d.ts.map +1 -1
  8. package/dist/src/cli/commands/core.js +18 -0
  9. package/dist/src/cli/commands/core.js.map +1 -1
  10. package/dist/src/cli/lib/broker-lifecycle.d.ts.map +1 -1
  11. package/dist/src/cli/lib/broker-lifecycle.js +16 -13
  12. package/dist/src/cli/lib/broker-lifecycle.js.map +1 -1
  13. package/package.json +8 -8
  14. package/packages/acp-bridge/package.json +2 -2
  15. package/packages/config/package.json +1 -1
  16. package/packages/hooks/package.json +4 -4
  17. package/packages/memory/package.json +2 -2
  18. package/packages/openclaw/README.md +2 -2
  19. package/packages/openclaw/dist/identity/files.js +2 -2
  20. package/packages/openclaw/dist/identity/files.js.map +1 -1
  21. package/packages/openclaw/dist/setup.js +2 -2
  22. package/packages/openclaw/package.json +2 -2
  23. package/packages/openclaw/skill/SKILL.md +8 -8
  24. package/packages/openclaw/src/identity/files.ts +2 -2
  25. package/packages/openclaw/src/setup.ts +2 -2
  26. package/packages/openclaw/templates/SOUL.md.template +2 -2
  27. package/packages/policy/package.json +2 -2
  28. package/packages/sdk/dist/examples/example.js +1 -1
  29. package/packages/sdk/dist/examples/example.js.map +1 -1
  30. package/packages/sdk/dist/relay-adapter.js +4 -4
  31. package/packages/sdk/dist/relay-adapter.js.map +1 -1
  32. package/packages/sdk/dist/workflows/builder.d.ts +18 -3
  33. package/packages/sdk/dist/workflows/builder.d.ts.map +1 -1
  34. package/packages/sdk/dist/workflows/builder.js +24 -12
  35. package/packages/sdk/dist/workflows/builder.js.map +1 -1
  36. package/packages/sdk/dist/workflows/runner.d.ts +2 -0
  37. package/packages/sdk/dist/workflows/runner.d.ts.map +1 -1
  38. package/packages/sdk/dist/workflows/runner.js +103 -24
  39. package/packages/sdk/dist/workflows/runner.js.map +1 -1
  40. package/packages/sdk/dist/workflows/validator.js +1 -1
  41. package/packages/sdk/dist/workflows/validator.js.map +1 -1
  42. package/packages/sdk/package.json +2 -2
  43. package/packages/sdk/src/examples/example.ts +1 -1
  44. package/packages/sdk/src/relay-adapter.ts +4 -4
  45. package/packages/sdk/src/workflows/builder.ts +38 -11
  46. package/packages/sdk/src/workflows/runner.ts +108 -32
  47. package/packages/sdk/src/workflows/validator.ts +1 -1
  48. package/packages/sdk-py/pyproject.toml +1 -1
  49. package/packages/telemetry/package.json +1 -1
  50. package/packages/trajectory/package.json +2 -2
  51. package/packages/user-directory/package.json +2 -2
  52. package/packages/utils/package.json +2 -2
  53. package/relay-snippets/agent-relay-protocol.md +4 -4
  54. package/relay-snippets/agent-relay-snippet.md +9 -9
@@ -87,7 +87,7 @@ export function validateWorkflow(config) {
87
87
  }
88
88
  // Check 4: non-interactive agent that references relay messaging tools in task
89
89
  if (def.interactive === false &&
90
- (task.includes('mcp__relaycast__dm_send') || task.includes('mcp__relaycast__message_post') || task.includes('mcp__relaycast__inbox_check'))) {
90
+ (task.includes('mcp__relaycast__message_dm_send') || task.includes('mcp__relaycast__message_post') || task.includes('mcp__relaycast__message_inbox_check'))) {
91
91
  issues.push({
92
92
  severity: 'warning',
93
93
  code: 'NONINTERACTIVE_RELAY',
@@ -1 +1 @@
1
- {"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/workflows/validator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/workflows/validator.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/sdk",
3
- "version": "3.2.1",
3
+ "version": "3.2.2",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -81,7 +81,7 @@
81
81
  "typescript": "^5.7.3"
82
82
  },
83
83
  "dependencies": {
84
- "@agent-relay/config": "3.2.1",
84
+ "@agent-relay/config": "3.2.2",
85
85
  "@relaycast/sdk": "^0.4.0",
86
86
  "yaml": "^2.7.0"
87
87
  }
@@ -78,7 +78,7 @@ async function main(): Promise<void> {
78
78
  });
79
79
 
80
80
  console.log(
81
- `[${now()}] workers spawned. send kickoff via Relaycast (MCP mcp__relaycast__dm_send) and watch events here (Ctrl+C to stop).`,
81
+ `[${now()}] workers spawned. send kickoff via Relaycast (MCP mcp__relaycast__message_dm_send) and watch events here (Ctrl+C to stop).`,
82
82
  );
83
83
  await new Promise<void>(() => {
84
84
  // keep process alive while events stream
@@ -33,16 +33,16 @@ const WORKFLOW_BOOTSTRAP_TASK =
33
33
 
34
34
  const WORKFLOW_CONVENTIONS = [
35
35
  'Messaging requirements:',
36
- '- When you receive `Relay message from <sender> ...`, reply using `mcp__relaycast__dm_send(to: "<sender>", text: "...")`.',
36
+ '- When you receive `Relay message from <sender> ...`, reply using `mcp__relaycast__message_dm_send(to: "<sender>", text: "...")`.',
37
37
  '- Send `ACK: ...` when you receive a task.',
38
38
  '- Send `DONE: ...` when the task is complete.',
39
- '- Do not reply only in terminal text; send the response via mcp__relaycast__dm_send.',
40
- '- Use mcp__relaycast__inbox_check() and mcp__relaycast__agent_list() when context is missing.',
39
+ '- Do not reply only in terminal text; send the response via mcp__relaycast__message_dm_send.',
40
+ '- Use mcp__relaycast__message_inbox_check() and mcp__relaycast__agent_list() when context is missing.',
41
41
  ].join('\n');
42
42
 
43
43
  function hasWorkflowConventions(task: string): boolean {
44
44
  const lower = task.toLowerCase();
45
- return lower.includes('mcp__relaycast__dm_send(') || lower.includes('relay_send(') || (lower.includes('ack:') && lower.includes('done:'));
45
+ return lower.includes('mcp__relaycast__message_dm_send(') || lower.includes('relay_send(') || (lower.includes('ack:') && lower.includes('done:'));
46
46
  }
47
47
 
48
48
  function buildSpawnTask(
@@ -4,6 +4,7 @@ import type { AgentRelayOptions } from '../relay.js';
4
4
  import type {
5
5
  AgentCli,
6
6
  AgentDefinition,
7
+ AgentPreset,
7
8
  DryRunReport,
8
9
  ErrorHandlingConfig,
9
10
  IdleNudgeConfig,
@@ -33,9 +34,12 @@ export interface AgentOptions {
33
34
  /** When false, the agent runs as a non-interactive subprocess (no PTY, no relay messaging).
34
35
  * Default: true. */
35
36
  interactive?: boolean;
37
+ /** Agent preset: 'lead' (interactive PTY), 'worker' | 'reviewer' | 'analyst' (non-interactive subprocess). */
38
+ preset?: AgentPreset;
36
39
  }
37
40
 
38
- export interface StepOptions {
41
+ /** Options for agent steps (default). */
42
+ export interface AgentStepOptions {
39
43
  agent: string;
40
44
  task: string;
41
45
  dependsOn?: string[];
@@ -44,6 +48,20 @@ export interface StepOptions {
44
48
  retries?: number;
45
49
  }
46
50
 
51
+ /** Options for deterministic (shell command) steps. */
52
+ export interface DeterministicStepOptions {
53
+ type: 'deterministic';
54
+ command: string;
55
+ dependsOn?: string[];
56
+ /** Fail if command exit code is non-zero. Default: true. */
57
+ failOnError?: boolean;
58
+ /** Capture stdout as step output for downstream steps. Default: true. */
59
+ captureOutput?: boolean;
60
+ timeoutMs?: number;
61
+ }
62
+
63
+ export type StepOptions = AgentStepOptions | DeterministicStepOptions;
64
+
47
65
  export interface ErrorOptions {
48
66
  maxRetries?: number;
49
67
  retryDelayMs?: number;
@@ -146,6 +164,7 @@ export class WorkflowBuilder {
146
164
  if (options.role !== undefined) def.role = options.role;
147
165
  if (options.task !== undefined) def.task = options.task;
148
166
  if (options.channels !== undefined) def.channels = options.channels;
167
+ if (options.preset !== undefined) def.preset = options.preset;
149
168
  if (options.interactive !== undefined) def.interactive = options.interactive;
150
169
 
151
170
  if (
@@ -168,18 +187,25 @@ export class WorkflowBuilder {
168
187
  return this;
169
188
  }
170
189
 
171
- /** Add a workflow step. */
190
+ /** Add a workflow step (agent or deterministic). */
172
191
  step(name: string, options: StepOptions): this {
173
- const step: WorkflowStep = {
174
- name,
175
- agent: options.agent,
176
- task: options.task,
177
- };
192
+ const step: WorkflowStep = { name };
193
+
194
+ if ('type' in options && options.type === 'deterministic') {
195
+ step.type = 'deterministic';
196
+ step.command = options.command;
197
+ if (options.failOnError !== undefined) step.failOnError = options.failOnError;
198
+ if (options.captureOutput !== undefined) step.captureOutput = options.captureOutput;
199
+ } else {
200
+ const agentOpts = options as AgentStepOptions;
201
+ step.agent = agentOpts.agent;
202
+ step.task = agentOpts.task;
203
+ if (agentOpts.verification !== undefined) step.verification = agentOpts.verification;
204
+ if (agentOpts.retries !== undefined) step.retries = agentOpts.retries;
205
+ }
178
206
 
179
207
  if (options.dependsOn !== undefined) step.dependsOn = options.dependsOn;
180
- if (options.verification !== undefined) step.verification = options.verification;
181
208
  if (options.timeoutMs !== undefined) step.timeoutMs = options.timeoutMs;
182
- if (options.retries !== undefined) step.retries = options.retries;
183
209
 
184
210
  this._steps.push(step);
185
211
  return this;
@@ -196,8 +222,9 @@ export class WorkflowBuilder {
196
222
 
197
223
  /** Build and return the RelayYamlConfig object. */
198
224
  toConfig(): RelayYamlConfig {
199
- if (this._agents.length === 0) {
200
- throw new Error('Workflow must have at least one agent');
225
+ const hasAgentSteps = this._steps.some((s) => s.type !== 'deterministic' && s.type !== 'worktree');
226
+ if (hasAgentSteps && this._agents.length === 0) {
227
+ throw new Error('Workflow must have at least one agent when using agent steps');
201
228
  }
202
229
  if (this._steps.length === 0) {
203
230
  throw new Error('Workflow must have at least one step');
@@ -357,6 +357,8 @@ export class WorkflowRunner {
357
357
  private readonly stepSignalParticipants = new Map<string, StepSignalParticipants>();
358
358
  /** Resolved named paths from the top-level `paths` config, keyed by name → absolute directory. */
359
359
  private resolvedPaths = new Map<string, string>();
360
+ /** Tracks agent names currently assigned as reviewers (ref-counted to handle concurrent usage). */
361
+ private readonly activeReviewers = new Map<string, number>();
360
362
 
361
363
  constructor(options: WorkflowRunnerOptions = {}) {
362
364
  this.db = options.db ?? new InMemoryWorkflowDb();
@@ -2326,6 +2328,7 @@ export class WorkflowRunner {
2326
2328
  this.lastActivity.clear();
2327
2329
  this.supervisedRuntimeAgents.clear();
2328
2330
  this.runtimeStepAgents.clear();
2331
+ this.activeReviewers.clear();
2329
2332
 
2330
2333
  this.log('Shutting down broker...');
2331
2334
  await this.relay?.shutdown();
@@ -3164,9 +3167,13 @@ export class WorkflowRunner {
3164
3167
  }
3165
3168
  const specialistDef = WorkflowRunner.resolveAgentDef(rawAgentDef);
3166
3169
  const usesOwnerFlow = specialistDef.interactive !== false;
3167
- const usesAutoHardening = usesOwnerFlow && !this.isExplicitInteractiveWorker(specialistDef);
3170
+ const currentPattern = this.currentConfig?.swarm?.pattern ?? '';
3171
+ const isHubPattern = WorkflowRunner.HUB_PATTERNS.has(currentPattern);
3172
+ const usesAutoHardening = usesOwnerFlow && isHubPattern && !this.isExplicitInteractiveWorker(specialistDef);
3168
3173
  const ownerDef = usesAutoHardening ? this.resolveAutoStepOwner(specialistDef, agentMap) : specialistDef;
3169
- const reviewDef = usesAutoHardening ? this.resolveAutoReviewAgent(ownerDef, agentMap) : undefined;
3174
+ // Reviewer resolution is deferred to just before the review gate runs (see below)
3175
+ // so that activeReviewers is up-to-date for concurrent steps.
3176
+ let reviewDef: ReturnType<typeof this.resolveAutoReviewAgent> | undefined;
3170
3177
  const supervised: SupervisedStep = {
3171
3178
  specialist: specialistDef,
3172
3179
  owner: ownerDef,
@@ -3333,6 +3340,7 @@ export class WorkflowRunner {
3333
3340
  : await this.spawnAndWait(effectiveOwner, resolvedStep, timeoutMs, {
3334
3341
  evidenceStepName: step.name,
3335
3342
  evidenceRole: usesOwnerFlow ? 'owner' : 'specialist',
3343
+ preserveOnIdle: (!isHubPattern || !this.isLeadLikeAgent(effectiveOwner)) ? false : undefined,
3336
3344
  logicalName: effectiveOwner.name,
3337
3345
  onSpawned: explicitInteractiveWorker
3338
3346
  ? ({ agent }) => {
@@ -3436,19 +3444,31 @@ export class WorkflowRunner {
3436
3444
  }
3437
3445
 
3438
3446
  // Every interactive step gets a review pass; pick a dedicated reviewer when available.
3447
+ // Resolve reviewer JIT so activeReviewers reflects concurrent steps that started earlier.
3448
+ if (usesAutoHardening && usesDedicatedOwner && !reviewDef) {
3449
+ reviewDef = this.resolveAutoReviewAgent(ownerDef, agentMap);
3450
+ supervised.reviewer = reviewDef;
3451
+ }
3439
3452
  let combinedOutput = specialistOutput;
3440
3453
  if (usesOwnerFlow && reviewDef) {
3441
- const remainingMs = timeoutMs ? Math.max(0, timeoutMs - ownerElapsed) : undefined;
3442
- const reviewOutput = await this.runStepReviewGate(
3443
- step,
3444
- resolvedTask,
3445
- specialistOutput,
3446
- ownerOutput,
3447
- ownerDef,
3448
- reviewDef,
3449
- remainingMs
3450
- );
3451
- combinedOutput = this.combineStepAndReviewOutput(specialistOutput, reviewOutput);
3454
+ this.activeReviewers.set(reviewDef.name, (this.activeReviewers.get(reviewDef.name) ?? 0) + 1);
3455
+ try {
3456
+ const remainingMs = timeoutMs ? Math.max(0, timeoutMs - ownerElapsed) : undefined;
3457
+ const reviewOutput = await this.runStepReviewGate(
3458
+ step,
3459
+ resolvedTask,
3460
+ specialistOutput,
3461
+ ownerOutput,
3462
+ ownerDef,
3463
+ reviewDef,
3464
+ remainingMs
3465
+ );
3466
+ combinedOutput = this.combineStepAndReviewOutput(specialistOutput, reviewOutput);
3467
+ } finally {
3468
+ const count = (this.activeReviewers.get(reviewDef.name) ?? 1) - 1;
3469
+ if (count <= 0) this.activeReviewers.delete(reviewDef.name);
3470
+ else this.activeReviewers.set(reviewDef.name, count);
3471
+ }
3452
3472
  }
3453
3473
 
3454
3474
  // Mark completed
@@ -3950,12 +3970,17 @@ export class WorkflowRunner {
3950
3970
  if (roleLC.includes('critic')) return 2;
3951
3971
  return isReviewer(def) ? 1 : 0;
3952
3972
  };
3953
- const dedicated = allDefs
3973
+ // Prefer agents not currently assigned as reviewers to avoid double-booking
3974
+ const notBusy = (def: AgentDefinition): boolean => !this.activeReviewers.has(def.name);
3975
+
3976
+ const dedicatedCandidates = allDefs
3954
3977
  .filter((d) => eligible(d) && isReviewer(d))
3955
- .sort((a, b) => reviewerPriority(b) - reviewerPriority(a) || a.name.localeCompare(b.name))[0];
3978
+ .sort((a, b) => reviewerPriority(b) - reviewerPriority(a) || a.name.localeCompare(b.name));
3979
+ const dedicated = dedicatedCandidates.find(notBusy) ?? dedicatedCandidates[0];
3956
3980
  if (dedicated) return dedicated;
3957
3981
 
3958
- const alternate = allDefs.find((d) => eligible(d) && d.interactive !== false);
3982
+ const alternateCandidates = allDefs.filter((d) => eligible(d) && d.interactive !== false);
3983
+ const alternate = alternateCandidates.find(notBusy) ?? alternateCandidates[0];
3959
3984
  if (alternate) return alternate;
3960
3985
 
3961
3986
  // Self-review fallback — log a warning since owner reviewing itself is weak.
@@ -4692,7 +4717,7 @@ export class WorkflowRunner {
4692
4717
  return (
4693
4718
  'You are a non-interactive worker agent. Produce clean, structured output to stdout.\n' +
4694
4719
  'Do NOT use mcp__relaycast__agent_add, add_agent, or any MCP tool to spawn sub-agents.\n' +
4695
- 'Do NOT use mcp__relaycast__dm_send or any Relaycast messaging tools — you have no relay connection.\n\n'
4720
+ 'Do NOT use mcp__relaycast__message_dm_send or any Relaycast messaging tools — you have no relay connection.\n\n'
4696
4721
  );
4697
4722
  case 'reviewer':
4698
4723
  return (
@@ -5302,19 +5327,70 @@ export class WorkflowRunner {
5302
5327
  return agent.waitForExit(timeoutMs);
5303
5328
  }
5304
5329
 
5305
- // Idle = done: race exit against idle. Whichever fires first completes the step.
5306
- const result = await Promise.race([
5307
- agent.waitForExit(timeoutMs).then((r) => ({ kind: 'exit' as const, result: r })),
5308
- agent.waitForIdle(timeoutMs).then((r) => ({ kind: 'idle' as const, result: r })),
5309
- ]);
5310
- if (result.kind === 'idle' && result.result === 'idle') {
5311
- this.log(`[${step.name}] Agent "${agent.name}" went idle — treating as complete`);
5312
- this.postToChannel(`**[${step.name}]** Agent \`${agent.name}\` idle — treating as complete`);
5313
- await agent.release();
5314
- return 'released';
5330
+ // Idle = done: race exit against idle, but only accept idle if verification passes.
5331
+ const idleLoopStart = Date.now();
5332
+ while (true) {
5333
+ const elapsed = Date.now() - idleLoopStart;
5334
+ const remaining = timeoutMs != null ? Math.max(0, timeoutMs - elapsed) : undefined;
5335
+ if (remaining != null && remaining <= 0) {
5336
+ return 'timeout';
5337
+ }
5338
+ const result = await Promise.race([
5339
+ agent.waitForExit(remaining).then((r) => ({ kind: 'exit' as const, result: r })),
5340
+ agent.waitForIdle(remaining).then((r) => ({ kind: 'idle' as const, result: r })),
5341
+ ]);
5342
+ if (result.kind === 'idle' && result.result === 'idle') {
5343
+ // Check verification before treating idle as complete.
5344
+ // Mirror runVerification's double-occurrence guard: if the task text
5345
+ // contains the token (from the prompt instruction), require a second
5346
+ // occurrence from the agent's actual output to avoid false positives.
5347
+ if (step.verification && step.verification.type === 'output_contains') {
5348
+ const token = step.verification.value;
5349
+ const ptyOutput = (this.ptyOutputBuffers.get(agent.name) ?? []).join('');
5350
+ const taskText = step.task ?? '';
5351
+ const taskHasToken = taskText.includes(token);
5352
+ let verificationPassed = true;
5353
+ if (taskHasToken) {
5354
+ const first = ptyOutput.indexOf(token);
5355
+ verificationPassed = first !== -1 && ptyOutput.includes(token, first + token.length);
5356
+ } else {
5357
+ verificationPassed = ptyOutput.includes(token);
5358
+ }
5359
+ if (!verificationPassed) {
5360
+ // The broker fires agent_idle only once per idle transition.
5361
+ // If the agent is still working (will produce output then idle again),
5362
+ // continuing the loop works. But if the agent is permanently idle,
5363
+ // waitForIdle won't resolve again. Wait briefly for new output,
5364
+ // then release and let upstream verification handle the result.
5365
+ this.log(`[${step.name}] Agent "${agent.name}" went idle but verification not yet passed — waiting for more output`);
5366
+ const idleGraceSecs = 15;
5367
+ const graceResult = await Promise.race([
5368
+ agent.waitForExit(idleGraceSecs * 1000).then((r) => ({ kind: 'exit' as const, result: r })),
5369
+ agent.waitForIdle(idleGraceSecs * 1000).then((r) => ({ kind: 'idle' as const, result: r })),
5370
+ ]);
5371
+ if (graceResult.kind === 'idle' && graceResult.result === 'idle') {
5372
+ // Agent went idle again after producing output — re-check verification
5373
+ continue;
5374
+ }
5375
+ if (graceResult.kind === 'exit') {
5376
+ return graceResult.result as 'exited' | 'timeout' | 'released';
5377
+ }
5378
+ // Grace period timed out — agent is permanently idle without verification.
5379
+ // Release and let upstream executeAgentStep handle verification.
5380
+ this.log(`[${step.name}] Agent "${agent.name}" still idle after ${idleGraceSecs}s grace — releasing`);
5381
+ this.postToChannel(`**[${step.name}]** Agent \`${agent.name}\` idle — releasing (verification pending)`);
5382
+ await agent.release();
5383
+ return 'released';
5384
+ }
5385
+ }
5386
+ this.log(`[${step.name}] Agent "${agent.name}" went idle — treating as complete`);
5387
+ this.postToChannel(`**[${step.name}]** Agent \`${agent.name}\` idle — treating as complete`);
5388
+ await agent.release();
5389
+ return 'released';
5390
+ }
5391
+ // Exit won the race, or idle returned 'exited'/'timeout' — pass through.
5392
+ return result.result as 'exited' | 'timeout' | 'released';
5315
5393
  }
5316
- // Exit won the race, or idle returned 'exited'/'timeout' — pass through.
5317
- return result.result as 'exited' | 'timeout' | 'released';
5318
5394
  }
5319
5395
 
5320
5396
  const nudgeAfterMs = nudgeConfig.nudgeAfterMs ?? 120_000;
@@ -5717,7 +5793,7 @@ export class WorkflowRunner {
5717
5793
  'RELAY SETUP — do this FIRST before any other relay tool:\n' +
5718
5794
  `1. Call: register(name="${agentName}")\n` +
5719
5795
  ' This authenticates you in the Relaycast workspace.\n' +
5720
- ' ALL relay tools (mcp__relaycast__dm_send, mcp__relaycast__inbox_check, mcp__relaycast__message_post, etc.) require\n' +
5796
+ ' ALL relay tools (mcp__relaycast__message_dm_send, mcp__relaycast__message_inbox_check, mcp__relaycast__message_post, etc.) require\n' +
5721
5797
  ' registration first — they will fail with "Not registered" otherwise.\n' +
5722
5798
  `2. Your agent name is "${agentName}" — use this exact name when registering.`
5723
5799
  );
@@ -5746,8 +5822,8 @@ export class WorkflowRunner {
5746
5822
  'you should break it down and delegate to helper agents to avoid timeouts.\n\n' +
5747
5823
  'Option 1 — Spawn relay agents (for real parallel coding work):\n' +
5748
5824
  ' - mcp__relaycast__agent_add(name="helper-1", cli="claude", task="Specific subtask description")\n' +
5749
- ' - Coordinate via mcp__relaycast__dm_send(to="helper-1", text="...")\n' +
5750
- ' - Check on them with mcp__relaycast__inbox_check()\n' +
5825
+ ' - Coordinate via mcp__relaycast__message_dm_send(to="helper-1", text="...")\n' +
5826
+ ' - Check on them with mcp__relaycast__message_inbox_check()\n' +
5751
5827
  ' - Clean up when done: mcp__relaycast__agent_remove(name="helper-1")\n\n' +
5752
5828
  subAgentOption +
5753
5829
  'Guidelines:\n' +
@@ -105,7 +105,7 @@ export function validateWorkflow(config: RelayYamlConfig): ValidationIssue[] {
105
105
  // Check 4: non-interactive agent that references relay messaging tools in task
106
106
  if (
107
107
  def.interactive === false &&
108
- (task.includes('mcp__relaycast__dm_send') || task.includes('mcp__relaycast__message_post') || task.includes('mcp__relaycast__inbox_check'))
108
+ (task.includes('mcp__relaycast__message_dm_send') || task.includes('mcp__relaycast__message_post') || task.includes('mcp__relaycast__message_inbox_check'))
109
109
  ) {
110
110
  issues.push({
111
111
  severity: 'warning',
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "agent-relay-sdk"
7
- version = "3.2.1"
7
+ version = "3.2.2"
8
8
  description = "Python SDK for Agent Relay workflows"
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/telemetry",
3
- "version": "3.2.1",
3
+ "version": "3.2.2",
4
4
  "description": "Anonymous telemetry for Agent Relay usage analytics",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/trajectory",
3
- "version": "3.2.1",
3
+ "version": "3.2.2",
4
4
  "description": "Trajectory integration utilities (trail/PDERO) for Relay",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -22,7 +22,7 @@
22
22
  "test:watch": "vitest"
23
23
  },
24
24
  "dependencies": {
25
- "@agent-relay/config": "3.2.1"
25
+ "@agent-relay/config": "3.2.2"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/node": "^22.19.3",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/user-directory",
3
- "version": "3.2.1",
3
+ "version": "3.2.2",
4
4
  "description": "User directory service for agent-relay (per-user credential storage)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -22,7 +22,7 @@
22
22
  "test:watch": "vitest"
23
23
  },
24
24
  "dependencies": {
25
- "@agent-relay/utils": "3.2.1"
25
+ "@agent-relay/utils": "3.2.2"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/node": "^22.19.3",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/utils",
3
- "version": "3.2.1",
3
+ "version": "3.2.2",
4
4
  "description": "Shared utilities for agent-relay: logging, name generation, command resolution, update checking",
5
5
  "type": "module",
6
6
  "main": "dist/cjs/index.js",
@@ -112,7 +112,7 @@
112
112
  "vitest": "^3.2.4"
113
113
  },
114
114
  "dependencies": {
115
- "@agent-relay/config": "3.2.1",
115
+ "@agent-relay/config": "3.2.2",
116
116
  "compare-versions": "^6.1.1"
117
117
  },
118
118
  "publishConfig": {
@@ -4,10 +4,10 @@ Advanced features for session continuity and trajectory tracking.
4
4
 
5
5
  ## Session Continuity
6
6
 
7
- Use `mcp__relaycast__send_dm` with a continuity message to save state for session recovery:
7
+ Use `mcp__relaycast__message_dm_send` with a continuity message to save state for session recovery:
8
8
 
9
9
  ```
10
- mcp__relaycast__send_dm(to: "system", text: "KIND: continuity\nACTION: save\n\nCurrent task: Implementing user authentication\nCompleted: User model, JWT utils\nIn progress: Login endpoint")
10
+ mcp__relaycast__message_dm_send(to: "system", text: "KIND: continuity\nACTION: save\n\nCurrent task: Implementing user authentication\nCompleted: User model, JWT utils\nIn progress: Login endpoint")
11
11
  ```
12
12
 
13
13
  ### When to Save
@@ -51,10 +51,10 @@ trail abandon --reason "Blocked by missing credentials"
51
51
 
52
52
  ## Cross-Project Messaging
53
53
 
54
- In bridge mode, use `project:agent` format with `mcp__relaycast__send_dm`:
54
+ In bridge mode, use `project:agent` format with `mcp__relaycast__message_dm_send`:
55
55
 
56
56
  ```
57
- mcp__relaycast__send_dm(to: "frontend:Designer", text: "Please update the login UI.")
57
+ mcp__relaycast__message_dm_send(to: "frontend:Designer", text: "Please update the login UI.")
58
58
  ```
59
59
 
60
60
  Special targets:
@@ -9,9 +9,9 @@ Tool names use dot-notation: Claude uses `mcp__relaycast__<category>_<action>`,
9
9
 
10
10
  | Tool | Description |
11
11
  | --------------------------------- | ------------------------------------- |
12
- | `dm_send(to, text)` | Send a DM to an agent |
12
+ | `message.dm.send(to, text)` | Send a DM to an agent |
13
13
  | `message_post(channel, text)` | Post a message to a channel |
14
- | `inbox_check()` | Check your inbox for new messages |
14
+ | `message.inbox.check()` | Check your inbox for new messages |
15
15
  | `agent_list()` | List online agents |
16
16
  | `agent_add(name, cli, task)` | Spawn a new worker agent |
17
17
  | `agent_remove(name)` | Release/stop a worker agent |
@@ -21,7 +21,7 @@ Tool names use dot-notation: Claude uses `mcp__relaycast__<category>_<action>`,
21
21
  ### Direct Messages
22
22
 
23
23
  ```
24
- mcp__relaycast__dm_send(to: "Bob", text: "Can you review my code changes?")
24
+ mcp__relaycast__message_dm_send(to: "Bob", text: "Can you review my code changes?")
25
25
  ```
26
26
 
27
27
  ### Channel Messages
@@ -76,11 +76,11 @@ Reply to the channel shown, not the sender.
76
76
  If you were spawned by another agent:
77
77
 
78
78
  1. Your first message is your task from your spawner
79
- 2. Use `mcp__relaycast__dm_send` to reply to your spawner
79
+ 2. Use `mcp__relaycast__message_dm_send` to reply to your spawner
80
80
  3. Report status to your spawner (your lead), not broadcast
81
81
 
82
82
  ```
83
- mcp__relaycast__dm_send(to: "Lead", text: "ACK: Starting on the task.")
83
+ mcp__relaycast__message_dm_send(to: "Lead", text: "ACK: Starting on the task.")
84
84
  ```
85
85
 
86
86
  ## Protocol
@@ -95,8 +95,8 @@ mcp__relaycast__dm_send(to: "Lead", text: "ACK: Starting on the task.")
95
95
 
96
96
  | Context | Correct | Incorrect |
97
97
  | ---------------------- | ----------------------------------------------------------- | ------------------------------------------------------ |
98
- | Local (same project) | `mcp__relaycast__dm_send(to: "Lead", ...)` | `mcp__relaycast__dm_send(to: "project:lead", ...)` |
99
- | Bridge (cross-project) | `mcp__relaycast__dm_send(to: "frontend:Designer", ...)` | N/A |
98
+ | Local (same project) | `mcp__relaycast__message_dm_send(to: "Lead", ...)` | `mcp__relaycast__message_dm_send(to: "project:lead", ...)` |
99
+ | Bridge (cross-project) | `mcp__relaycast__message_dm_send(to: "frontend:Designer", ...)` | N/A |
100
100
 
101
101
  ## Multi-Workspace
102
102
 
@@ -112,6 +112,6 @@ Relay message from Alice [my-team / abc123]: Hello!
112
112
  ## Checking Status
113
113
 
114
114
  ```
115
- mcp__relaycast__agent_list() # List online agents
116
- mcp__relaycast__inbox_check() # Check for unread messages
115
+ mcp__relaycast__agent_list() # List online agents
116
+ mcp__relaycast__message_inbox_check() # Check for unread messages
117
117
  ```