agent-orchestrator-mcp-server 0.7.16 → 0.8.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/README.md CHANGED
@@ -25,7 +25,7 @@ MCP server for PulseMCP's agent-orchestrator: a Claude Code + MCP-powered agent-
25
25
  | -------------------------- | ------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
26
26
  | `quick_search_sessions` | sessions | read | Quick title-based search/list sessions with optional ID lookup, title query, and status filter |
27
27
  | `get_session` | sessions | read | Get detailed session info with optional logs, transcripts, and transcript format (text/json) |
28
- | `get_configs` | sessions | read | Fetch all static configuration (MCP servers, agent roots, stop conditions) |
28
+ | `get_configs` | sessions | read | Fetch all static configuration (MCP servers, agent roots, goals) |
29
29
  | `get_transcript_archive` | sessions | read | Get download URL and metadata for the transcript archive zip file |
30
30
  | `start_session` | sessions | write | Create and start a new agent session |
31
31
  | `action_session` | sessions | write | Perform actions: follow_up, pause, restart, archive, unarchive, change_mcp_servers, change_model, fork, refresh, refresh_all, update_notes, update_title, toggle_favorite, bulk_archive |
@@ -40,12 +40,12 @@ MCP server for PulseMCP's agent-orchestrator: a Claude Code + MCP-powered agent-
40
40
 
41
41
  ### Resources
42
42
 
43
- | Resource | Description |
44
- | ---------------------------------------------- | ----------------------------------------------- |
45
- | `agent-orchestrator://config` | Server configuration and status (for debugging) |
46
- | `agent-orchestrator://configs/mcp-servers` | List of available MCP servers for sessions |
47
- | `agent-orchestrator://configs/agent-roots` | Preconfigured repository settings with defaults |
48
- | `agent-orchestrator://configs/stop-conditions` | Session completion criteria definitions |
43
+ | Resource | Description |
44
+ | ------------------------------------------ | ----------------------------------------------- |
45
+ | `agent-orchestrator://config` | Server configuration and status (for debugging) |
46
+ | `agent-orchestrator://configs/mcp-servers` | List of available MCP servers for sessions |
47
+ | `agent-orchestrator://configs/agent-roots` | Preconfigured repository settings with defaults |
48
+ | `agent-orchestrator://configs/goals` | Session completion criteria definitions |
49
49
 
50
50
  ### Tool Groups
51
51
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-orchestrator-mcp-server",
3
- "version": "0.7.16",
3
+ "version": "0.8.0",
4
4
  "description": "Local implementation of agent-orchestrator MCP server",
5
5
  "main": "build/index.js",
6
6
  "type": "module",
@@ -13,7 +13,7 @@ export interface RawAgentRoot {
13
13
  default_branch?: string;
14
14
  subdirectory?: string;
15
15
  custom?: boolean;
16
- default_stop_condition?: string;
16
+ default_goal?: string;
17
17
  default?: boolean;
18
18
  default_mcp_servers?: string[];
19
19
  default_skills?: string[];
@@ -52,7 +52,7 @@ export interface IAgentOrchestratorClient {
52
52
  unarchiveSession(id: string | number): Promise<Session>;
53
53
  followUp(id: string | number, prompt: string, options?: {
54
54
  force_immediate?: boolean;
55
- stop_condition?: string;
55
+ goal?: string;
56
56
  }): Promise<SessionActionResponse>;
57
57
  pauseSession(id: string | number): Promise<SessionActionResponse>;
58
58
  sleepSession(id: string | number): Promise<Session>;
@@ -98,11 +98,11 @@ export interface IAgentOrchestratorClient {
98
98
  getEnqueuedMessage(sessionId: string | number, messageId: number): Promise<EnqueuedMessage>;
99
99
  createEnqueuedMessage(sessionId: string | number, data: {
100
100
  content: string;
101
- stop_condition?: string;
101
+ goal?: string;
102
102
  }): Promise<EnqueuedMessage>;
103
103
  updateEnqueuedMessage(sessionId: string | number, messageId: number, data: {
104
104
  content?: string;
105
- stop_condition?: string;
105
+ goal?: string;
106
106
  }): Promise<EnqueuedMessage>;
107
107
  deleteEnqueuedMessage(sessionId: string | number, messageId: number): Promise<void>;
108
108
  reorderEnqueuedMessage(sessionId: string | number, messageId: number, position: number): Promise<EnqueuedMessage>;
@@ -179,7 +179,7 @@ export declare class AgentOrchestratorClient implements IAgentOrchestratorClient
179
179
  unarchiveSession(id: string | number): Promise<Session>;
180
180
  followUp(id: string | number, prompt: string, options?: {
181
181
  force_immediate?: boolean;
182
- stop_condition?: string;
182
+ goal?: string;
183
183
  }): Promise<SessionActionResponse>;
184
184
  pauseSession(id: string | number): Promise<SessionActionResponse>;
185
185
  sleepSession(id: string | number): Promise<Session>;
@@ -225,11 +225,11 @@ export declare class AgentOrchestratorClient implements IAgentOrchestratorClient
225
225
  getEnqueuedMessage(sessionId: string | number, messageId: number): Promise<EnqueuedMessage>;
226
226
  createEnqueuedMessage(sessionId: string | number, data: {
227
227
  content: string;
228
- stop_condition?: string;
228
+ goal?: string;
229
229
  }): Promise<EnqueuedMessage>;
230
230
  updateEnqueuedMessage(sessionId: string | number, messageId: number, data: {
231
231
  content?: string;
232
- stop_condition?: string;
232
+ goal?: string;
233
233
  }): Promise<EnqueuedMessage>;
234
234
  deleteEnqueuedMessage(sessionId: string | number, messageId: number): Promise<void>;
235
235
  reorderEnqueuedMessage(sessionId: string | number, messageId: number, position: number): Promise<EnqueuedMessage>;
@@ -20,7 +20,7 @@ export function createIntegrationMockOrchestratorClient(initialMockData) {
20
20
  branch: 'main',
21
21
  subdirectory: null,
22
22
  execution_provider: 'local_filesystem',
23
- stop_condition: null,
23
+ goal: null,
24
24
  mcp_servers: ['github-development'],
25
25
  config: {},
26
26
  metadata: { clone_path: 'repo-main-123' },
@@ -144,7 +144,7 @@ export function createIntegrationMockOrchestratorClient(initialMockData) {
144
144
  branch: data.branch || 'main',
145
145
  subdirectory: data.subdirectory || null,
146
146
  execution_provider: data.execution_provider || 'local_filesystem',
147
- stop_condition: data.stop_condition || null,
147
+ goal: data.goal || null,
148
148
  mcp_servers: data.mcp_servers || [],
149
149
  config: data.config || {},
150
150
  metadata: {},
@@ -168,8 +168,8 @@ export function createIntegrationMockOrchestratorClient(initialMockData) {
168
168
  session.title = data.title;
169
169
  if (data.slug !== undefined)
170
170
  session.slug = data.slug;
171
- if (data.stop_condition !== undefined)
172
- session.stop_condition = data.stop_condition;
171
+ if (data.goal !== undefined)
172
+ session.goal = data.goal;
173
173
  if (data.mcp_servers !== undefined)
174
174
  session.mcp_servers = data.mcp_servers;
175
175
  if (data.custom_metadata !== undefined)
@@ -447,7 +447,7 @@ export function createIntegrationMockOrchestratorClient(initialMockData) {
447
447
  default_skills: ['discovery-classify', 'discovery-validate'],
448
448
  },
449
449
  ],
450
- stop_conditions: [
450
+ goals: [
451
451
  {
452
452
  id: 'pr_merged',
453
453
  name: 'PR Merged',
@@ -546,7 +546,7 @@ export function createIntegrationMockOrchestratorClient(initialMockData) {
546
546
  id: messageId,
547
547
  session_id: 1,
548
548
  content: 'Test message',
549
- stop_condition: null,
549
+ goal: null,
550
550
  position: 1,
551
551
  status: 'pending',
552
552
  created_at: new Date().toISOString(),
@@ -558,7 +558,7 @@ export function createIntegrationMockOrchestratorClient(initialMockData) {
558
558
  id: 1,
559
559
  session_id: Number(sessionId),
560
560
  content: data.content,
561
- stop_condition: data.stop_condition || null,
561
+ goal: data.goal || null,
562
562
  position: 1,
563
563
  status: 'pending',
564
564
  created_at: new Date().toISOString(),
@@ -570,7 +570,7 @@ export function createIntegrationMockOrchestratorClient(initialMockData) {
570
570
  id: messageId,
571
571
  session_id: 1,
572
572
  content: data.content || 'Updated message',
573
- stop_condition: data.stop_condition || null,
573
+ goal: data.goal || null,
574
574
  position: 1,
575
575
  status: 'pending',
576
576
  created_at: new Date().toISOString(),
@@ -585,7 +585,7 @@ export function createIntegrationMockOrchestratorClient(initialMockData) {
585
585
  id: messageId,
586
586
  session_id: 1,
587
587
  content: 'Test message',
588
- stop_condition: null,
588
+ goal: null,
589
589
  position,
590
590
  status: 'pending',
591
591
  created_at: new Date().toISOString(),
@@ -614,7 +614,7 @@ export function createIntegrationMockOrchestratorClient(initialMockData) {
614
614
  status: 'enabled',
615
615
  agent_root_name: 'mcp-servers',
616
616
  prompt_template: 'Test prompt',
617
- stop_condition: null,
617
+ goal: null,
618
618
  reuse_session: false,
619
619
  mcp_servers: [],
620
620
  conditions: [
@@ -650,7 +650,7 @@ export function createIntegrationMockOrchestratorClient(initialMockData) {
650
650
  status: data.status || 'enabled',
651
651
  agent_root_name: data.agent_root_name,
652
652
  prompt_template: data.prompt_template,
653
- stop_condition: data.stop_condition || null,
653
+ goal: data.goal || null,
654
654
  reuse_session: data.reuse_session || false,
655
655
  mcp_servers: data.mcp_servers || [],
656
656
  conditions,
@@ -676,7 +676,7 @@ export function createIntegrationMockOrchestratorClient(initialMockData) {
676
676
  status: data.status || 'enabled',
677
677
  agent_root_name: data.agent_root_name || 'mcp-servers',
678
678
  prompt_template: data.prompt_template || 'Test prompt',
679
- stop_condition: data.stop_condition || null,
679
+ goal: data.goal || null,
680
680
  reuse_session: data.reuse_session || false,
681
681
  mcp_servers: data.mcp_servers || [],
682
682
  conditions,
@@ -697,7 +697,7 @@ export function createIntegrationMockOrchestratorClient(initialMockData) {
697
697
  status: 'disabled',
698
698
  agent_root_name: 'mcp-servers',
699
699
  prompt_template: 'Test prompt',
700
- stop_condition: null,
700
+ goal: null,
701
701
  reuse_session: false,
702
702
  mcp_servers: [],
703
703
  conditions: [],
@@ -16,7 +16,7 @@ export function mapAgentRoot(raw) {
16
16
  git_root: raw.url,
17
17
  default_branch: raw.default_branch,
18
18
  default_subdirectory: raw.subdirectory,
19
- default_stop_condition: raw.default_stop_condition,
19
+ default_goal: raw.default_goal,
20
20
  default_mcp_servers: raw.default_mcp_servers,
21
21
  default_skills: raw.default_skills,
22
22
  default_model: raw.default_model,
@@ -208,7 +208,7 @@ export class AgentOrchestratorClient {
208
208
  return this.request('POST', `/sessions/${id}/follow_up`, {
209
209
  prompt,
210
210
  ...(options?.force_immediate && { force_immediate: true }),
211
- ...(options?.stop_condition && { stop_condition: options.stop_condition }),
211
+ ...(options?.goal && { goal: options.goal }),
212
212
  });
213
213
  }
214
214
  async pauseSession(id) {
@@ -282,7 +282,7 @@ export class AgentOrchestratorClient {
282
282
  return {
283
283
  mcp_servers: raw.mcp_servers,
284
284
  agent_roots: raw.agent_roots.map(mapAgentRoot),
285
- stop_conditions: raw.stop_conditions,
285
+ goals: raw.goals,
286
286
  };
287
287
  }
288
288
  // Notifications
@@ -26,12 +26,12 @@ export function createRegisterResources(clientFactory) {
26
26
  {
27
27
  uri: 'agent-orchestrator://configs/agent-roots',
28
28
  name: 'Agent Roots',
29
- description: 'Preconfigured repository settings with default branch, MCP servers, and stop conditions.',
29
+ description: 'Preconfigured repository settings with default branch, MCP servers, and goals.',
30
30
  mimeType: 'application/json',
31
31
  },
32
32
  {
33
- uri: 'agent-orchestrator://configs/stop-conditions',
34
- name: 'Stop Conditions',
33
+ uri: 'agent-orchestrator://configs/goals',
34
+ name: 'Goals',
35
35
  description: 'Available session completion criteria for use with start_session.',
36
36
  mimeType: 'application/json',
37
37
  },
@@ -121,15 +121,15 @@ export function createRegisterResources(clientFactory) {
121
121
  ],
122
122
  };
123
123
  }
124
- if (uri === 'agent-orchestrator://configs/stop-conditions') {
124
+ if (uri === 'agent-orchestrator://configs/goals') {
125
125
  return {
126
126
  contents: [
127
127
  {
128
128
  uri,
129
129
  mimeType: 'application/json',
130
130
  text: JSON.stringify({
131
- stop_conditions: configs.stop_conditions,
132
- _usage: 'Use the "id" field when specifying stop_condition in start_session',
131
+ goals: configs.goals,
132
+ _usage: 'Use the "id" field when specifying goal in start_session',
133
133
  }, null, 2),
134
134
  },
135
135
  ],
@@ -43,7 +43,7 @@ export const ActionSessionSchema = z.object({
43
43
  const TOOL_DESCRIPTION = `Perform an action on an agent session.
44
44
 
45
45
  **Actions:**
46
- - **follow_up**: Send a follow-up prompt to a session (requires "prompt"; optional "force_immediate" to interrupt a running session). Without "force_immediate", uses smart routing: sends immediately if idle, auto-queues if running. Alternative: use manage_enqueued_messages "send_now" for one-step immediate delivery with stop_condition support.
46
+ - **follow_up**: Send a follow-up prompt to a session (requires "prompt"; optional "force_immediate" to interrupt a running session). Without "force_immediate", uses smart routing: sends immediately if idle, auto-queues if running. Alternative: use manage_enqueued_messages "send_now" for one-step immediate delivery with goal support.
47
47
  - **pause**: Pause a running session, transitioning it to idle "needs_input" status
48
48
  - **restart**: Restart an idle or failed session without providing new input
49
49
  - **archive**: Archive a session (marks as completed)
@@ -527,7 +527,7 @@ const SELF_SESSION_TOOL_DESCRIPTION = `Perform a self-management action on a ses
527
527
  - Archive the session when work is complete
528
528
 
529
529
  **Archive guidelines:**
530
- - Only self-archive when explicitly instructed to (e.g., a stop condition says "archive yourself")
530
+ - Only self-archive when explicitly instructed to (e.g., a goal says "archive yourself")
531
531
  - Subagents that report results back to a parent agent via a tool call may self-archive, since no human needs to read the session output directly
532
532
  - Do NOT self-archive if a human user needs to read your output. Sessions in \`needs_input\` appear on the user's homepage — archiving removes them before the user can see your work. If your work product is a message the user should read, let the session stay in \`needs_input\``;
533
533
  export function selfSessionActionSessionTool(_server, clientFactory) {
@@ -9,14 +9,14 @@ export declare const ActionTriggerSchema: z.ZodObject<{
9
9
  agent_root_name: z.ZodOptional<z.ZodString>;
10
10
  prompt_template: z.ZodOptional<z.ZodString>;
11
11
  status: z.ZodOptional<z.ZodEnum<["enabled", "disabled"]>>;
12
- stop_condition: z.ZodOptional<z.ZodString>;
12
+ goal: z.ZodOptional<z.ZodString>;
13
13
  reuse_session: z.ZodOptional<z.ZodBoolean>;
14
14
  mcp_servers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
15
15
  configuration: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
16
16
  }, "strip", z.ZodTypeAny, {
17
17
  action: "create" | "update" | "delete" | "toggle";
18
18
  status?: "enabled" | "disabled" | undefined;
19
- stop_condition?: string | undefined;
19
+ goal?: string | undefined;
20
20
  mcp_servers?: string[] | undefined;
21
21
  trigger_type?: "slack" | "schedule" | undefined;
22
22
  id?: number | undefined;
@@ -28,7 +28,7 @@ export declare const ActionTriggerSchema: z.ZodObject<{
28
28
  }, {
29
29
  action: "create" | "update" | "delete" | "toggle";
30
30
  status?: "enabled" | "disabled" | undefined;
31
- stop_condition?: string | undefined;
31
+ goal?: string | undefined;
32
32
  mcp_servers?: string[] | undefined;
33
33
  trigger_type?: "slack" | "schedule" | undefined;
34
34
  id?: number | undefined;
@@ -75,7 +75,7 @@ export declare function actionTriggerTool(_server: Server, clientFactory: () =>
75
75
  enum: string[];
76
76
  description: string;
77
77
  };
78
- stop_condition: {
78
+ goal: {
79
79
  type: string;
80
80
  description: string;
81
81
  };
@@ -9,7 +9,7 @@ export const ActionTriggerSchema = z.object({
9
9
  agent_root_name: z.string().optional(),
10
10
  prompt_template: z.string().optional(),
11
11
  status: z.enum(['enabled', 'disabled']).optional(),
12
- stop_condition: z.string().optional(),
12
+ goal: z.string().optional(),
13
13
  reuse_session: z.boolean().optional(),
14
14
  mcp_servers: z.array(z.string()).optional(),
15
15
  configuration: z.record(z.unknown()).optional(),
@@ -49,7 +49,7 @@ export function actionTriggerTool(_server, clientFactory) {
49
49
  agent_root_name: { type: 'string', description: 'Agent root name. Required for create.' },
50
50
  prompt_template: { type: 'string', description: 'Prompt template. Required for create.' },
51
51
  status: { type: 'string', enum: ['enabled', 'disabled'], description: 'Trigger status.' },
52
- stop_condition: { type: 'string', description: 'Stop condition for triggered sessions.' },
52
+ goal: { type: 'string', description: 'Goal for triggered sessions.' },
53
53
  reuse_session: { type: 'boolean', description: 'Whether to reuse existing sessions.' },
54
54
  mcp_servers: {
55
55
  type: 'array',
@@ -103,7 +103,7 @@ export function actionTriggerTool(_server, clientFactory) {
103
103
  agent_root_name: validated.agent_root_name,
104
104
  prompt_template: validated.prompt_template,
105
105
  status: validated.status,
106
- stop_condition: validated.stop_condition,
106
+ goal: validated.goal,
107
107
  reuse_session: validated.reuse_session,
108
108
  mcp_servers: validated.mcp_servers,
109
109
  configuration: validated.configuration,
@@ -136,7 +136,7 @@ export function actionTriggerTool(_server, clientFactory) {
136
136
  agent_root_name: validated.agent_root_name,
137
137
  prompt_template: validated.prompt_template,
138
138
  status: validated.status,
139
- stop_condition: validated.stop_condition,
139
+ goal: validated.goal,
140
140
  reuse_session: validated.reuse_session,
141
141
  mcp_servers: validated.mcp_servers,
142
142
  configuration: validated.configuration,
@@ -11,8 +11,8 @@ const TOOL_DESCRIPTION = `Fetches all static configuration data in a single call
11
11
 
12
12
  Returns:
13
13
  - **MCP servers**: Available servers for use with start_session (name, title, description)
14
- - **Agent roots**: Preconfigured repository settings with defaults (git_root, branch, mcp_servers, skills, stop_condition)
15
- - **Stop conditions**: Available session completion criteria (id, name, description)
14
+ - **Agent roots**: Preconfigured repository settings with defaults (git_root, branch, mcp_servers, skills, goal)
15
+ - **Goals**: Available session completion criteria (id, name, description)
16
16
 
17
17
  **Use this tool** to get all configuration options before calling start_session.
18
18
 
@@ -101,19 +101,19 @@ function formatResponse(configs, fromCache) {
101
101
  formatAgentRoot(lines, root);
102
102
  }
103
103
  }
104
- // Stop Conditions section
104
+ // Goals section
105
105
  lines.push('---');
106
106
  lines.push('');
107
- lines.push('## Stop Conditions');
107
+ lines.push('## Goals');
108
108
  lines.push('');
109
- if (configs.stop_conditions.length === 0) {
110
- lines.push('*No stop conditions defined.*');
109
+ if (configs.goals.length === 0) {
110
+ lines.push('*No goals defined.*');
111
111
  }
112
112
  else {
113
- lines.push(`Found ${configs.stop_conditions.length} stop condition${configs.stop_conditions.length === 1 ? '' : 's'}:`);
113
+ lines.push(`Found ${configs.goals.length} goal${configs.goals.length === 1 ? '' : 's'}:`);
114
114
  lines.push('');
115
- for (const condition of configs.stop_conditions) {
116
- formatStopCondition(lines, condition);
115
+ for (const goal of configs.goals) {
116
+ formatGoal(lines, goal);
117
117
  }
118
118
  }
119
119
  // Usage hints
@@ -125,7 +125,7 @@ function formatResponse(configs, fromCache) {
125
125
  lines.push('- Use `git_root` from **Agent Roots** to start sessions with preconfigured defaults');
126
126
  lines.push('- If an **Agent Root** has a `default_subdirectory`, pass it as `subdirectory` in `start_session` — do not set `subdirectory` to arbitrary internal paths');
127
127
  lines.push("- Pass `default_skills` from **Agent Roots** in the `skills` parameter of `start_session` — sessions won't have skills loaded unless you explicitly pass them");
128
- lines.push('- Use `id` values from **Stop Conditions** in `start_session` `stop_condition` parameter');
128
+ lines.push('- Use `id` values from **Goals** in `start_session` `goal` parameter');
129
129
  if (fromCache) {
130
130
  lines.push('');
131
131
  lines.push('*(Returned from cache. Use `force_refresh: true` to fetch fresh data.)*');
@@ -154,8 +154,8 @@ function formatAgentRoot(lines, root) {
154
154
  if (root.default_mcp_servers && root.default_mcp_servers.length > 0) {
155
155
  lines.push(`- **Default MCP Servers:** ${root.default_mcp_servers.map((s) => `\`${s}\``).join(', ')}`);
156
156
  }
157
- if (root.default_stop_condition) {
158
- lines.push(`- **Default Stop Condition:** \`${root.default_stop_condition}\``);
157
+ if (root.default_goal) {
158
+ lines.push(`- **Default Goal:** \`${root.default_goal}\``);
159
159
  }
160
160
  if (root.default_skills && root.default_skills.length > 0) {
161
161
  lines.push(`- **Default Skills:** ${root.default_skills.map((s) => `\`${s}\``).join(', ')}`);
@@ -165,9 +165,9 @@ function formatAgentRoot(lines, root) {
165
165
  }
166
166
  lines.push('');
167
167
  }
168
- function formatStopCondition(lines, condition) {
169
- lines.push(`### ${condition.name}`);
170
- lines.push(`- **ID:** \`${condition.id}\``);
171
- lines.push(`- **Description:** ${condition.description}`);
168
+ function formatGoal(lines, goal) {
169
+ lines.push(`### ${goal.name}`);
170
+ lines.push(`- **ID:** \`${goal.id}\``);
171
+ lines.push(`- **Description:** ${goal.description}`);
172
172
  lines.push('');
173
173
  }
@@ -69,8 +69,8 @@ function formatSessionDetails(session, includeTranscript) {
69
69
  lines.push('');
70
70
  lines.push('### Execution');
71
71
  lines.push(`- **Execution Provider:** ${session.execution_provider}`);
72
- if (session.stop_condition)
73
- lines.push(`- **Stop Condition:** ${session.stop_condition}`);
72
+ if (session.goal)
73
+ lines.push(`- **Goal:** ${session.goal}`);
74
74
  if (session.mcp_servers && session.mcp_servers.length > 0) {
75
75
  lines.push(`- **MCP Servers:** ${session.mcp_servers.join(', ')}`);
76
76
  }
@@ -6,7 +6,7 @@ export declare const ManageEnqueuedMessagesSchema: z.ZodObject<{
6
6
  action: z.ZodEnum<["list", "get", "create", "update", "delete", "reorder", "interrupt", "send_now"]>;
7
7
  message_id: z.ZodOptional<z.ZodNumber>;
8
8
  content: z.ZodOptional<z.ZodString>;
9
- stop_condition: z.ZodOptional<z.ZodString>;
9
+ goal: z.ZodOptional<z.ZodString>;
10
10
  position: z.ZodOptional<z.ZodNumber>;
11
11
  page: z.ZodOptional<z.ZodNumber>;
12
12
  per_page: z.ZodOptional<z.ZodNumber>;
@@ -15,7 +15,7 @@ export declare const ManageEnqueuedMessagesSchema: z.ZodObject<{
15
15
  action: "list" | "get" | "create" | "update" | "delete" | "reorder" | "interrupt" | "send_now";
16
16
  per_page?: number | undefined;
17
17
  page?: number | undefined;
18
- stop_condition?: string | undefined;
18
+ goal?: string | undefined;
19
19
  content?: string | undefined;
20
20
  message_id?: number | undefined;
21
21
  position?: number | undefined;
@@ -24,7 +24,7 @@ export declare const ManageEnqueuedMessagesSchema: z.ZodObject<{
24
24
  action: "list" | "get" | "create" | "update" | "delete" | "reorder" | "interrupt" | "send_now";
25
25
  per_page?: number | undefined;
26
26
  page?: number | undefined;
27
- stop_condition?: string | undefined;
27
+ goal?: string | undefined;
28
28
  content?: string | undefined;
29
29
  message_id?: number | undefined;
30
30
  position?: number | undefined;
@@ -54,7 +54,7 @@ export declare function manageEnqueuedMessagesTool(_server: Server, clientFactor
54
54
  type: string;
55
55
  description: string;
56
56
  };
57
- stop_condition: {
57
+ goal: {
58
58
  type: string;
59
59
  description: string;
60
60
  };
@@ -14,7 +14,7 @@ export const ManageEnqueuedMessagesSchema = z.object({
14
14
  action: z.enum(ACTION_ENUM),
15
15
  message_id: z.number().optional(),
16
16
  content: z.string().optional(),
17
- stop_condition: z.string().optional(),
17
+ goal: z.string().optional(),
18
18
  position: z.number().min(1).optional(),
19
19
  page: z.number().min(1).optional(),
20
20
  per_page: z.number().min(1).max(100).optional(),
@@ -32,7 +32,7 @@ Use "send_now" when you need the agent to act on something urgently. Use "create
32
32
  - **create**: Add a new message to the end of the queue for later delivery (requires "content"). The message waits until the session becomes idle.
33
33
  - **list**: List all enqueued messages for a session (supports pagination with "page" and "per_page")
34
34
  - **get**: Get a specific enqueued message by ID (requires "message_id")
35
- - **update**: Update an existing queued message's content or stop condition (requires "message_id")
35
+ - **update**: Update an existing queued message's content or goal (requires "message_id")
36
36
  - **delete**: Remove a message from the queue (requires "message_id")
37
37
  - **reorder**: Change a message's position in the queue (requires "message_id" and "position")
38
38
  - **interrupt**: Pause the session and send an existing queued message immediately (requires "message_id"). Prefer "send_now" for new messages — "interrupt" is for promoting an already-queued message.`;
@@ -60,9 +60,9 @@ export function manageEnqueuedMessagesTool(_server, clientFactory) {
60
60
  type: 'string',
61
61
  description: 'Message content. Required for create and send_now. Optional for update.',
62
62
  },
63
- stop_condition: {
63
+ goal: {
64
64
  type: 'string',
65
- description: 'Stop condition for this message. Optional for create, send_now, and update.',
65
+ description: 'Goal for this message. Optional for create, send_now, and update.',
66
66
  },
67
67
  position: {
68
68
  type: 'number',
@@ -83,7 +83,7 @@ export function manageEnqueuedMessagesTool(_server, clientFactory) {
83
83
  try {
84
84
  const validated = ManageEnqueuedMessagesSchema.parse(args);
85
85
  const client = clientFactory();
86
- const { session_id, action, message_id, content, stop_condition, position, page, per_page, } = validated;
86
+ const { session_id, action, message_id, content, goal, position, page, per_page } = validated;
87
87
  let result;
88
88
  switch (action) {
89
89
  case 'list': {
@@ -100,8 +100,8 @@ export function manageEnqueuedMessagesTool(_server, clientFactory) {
100
100
  lines.push(`### Position ${msg.position} (ID: ${msg.id})`);
101
101
  lines.push(`- **Status:** ${msg.status}`);
102
102
  lines.push(`- **Content:** ${msg.content.substring(0, 200)}${msg.content.length > 200 ? '...' : ''}`);
103
- if (msg.stop_condition)
104
- lines.push(`- **Stop Condition:** ${msg.stop_condition}`);
103
+ if (msg.goal)
104
+ lines.push(`- **Goal:** ${msg.goal}`);
105
105
  lines.push('');
106
106
  });
107
107
  result = lines.join('\n');
@@ -125,7 +125,7 @@ export function manageEnqueuedMessagesTool(_server, clientFactory) {
125
125
  `- **Position:** ${msg.position}`,
126
126
  `- **Status:** ${msg.status}`,
127
127
  `- **Content:** ${msg.content}`,
128
- msg.stop_condition ? `- **Stop Condition:** ${msg.stop_condition}` : '',
128
+ msg.goal ? `- **Goal:** ${msg.goal}` : '',
129
129
  `- **Created:** ${msg.created_at}`,
130
130
  ]
131
131
  .filter(Boolean)
@@ -143,7 +143,7 @@ export function manageEnqueuedMessagesTool(_server, clientFactory) {
143
143
  }
144
144
  const msg = await client.createEnqueuedMessage(session_id, {
145
145
  content,
146
- stop_condition: stop_condition || undefined,
146
+ goal: goal || undefined,
147
147
  });
148
148
  result = [
149
149
  '## Message Queued',
@@ -171,7 +171,7 @@ export function manageEnqueuedMessagesTool(_server, clientFactory) {
171
171
  }
172
172
  const msg = await client.updateEnqueuedMessage(session_id, message_id, {
173
173
  content: content || undefined,
174
- stop_condition: stop_condition || undefined,
174
+ goal: goal || undefined,
175
175
  });
176
176
  result = [
177
177
  '## Message Updated',
@@ -263,7 +263,7 @@ export function manageEnqueuedMessagesTool(_server, clientFactory) {
263
263
  }
264
264
  const response = await client.followUp(session_id, content, {
265
265
  force_immediate: true,
266
- stop_condition: stop_condition || undefined,
266
+ goal: goal || undefined,
267
267
  });
268
268
  result = [
269
269
  '## Message Sent Immediately',
@@ -92,8 +92,8 @@ export function searchTriggersTool(_server, clientFactory) {
92
92
  `- **Reuse Session:** ${t.reuse_session ? 'Yes' : 'No'}`,
93
93
  `- **MCP Servers:** ${t.mcp_servers && t.mcp_servers.length > 0 ? t.mcp_servers.join(', ') : '(none)'}`,
94
94
  ];
95
- if (t.stop_condition)
96
- lines.push(`- **Stop Condition:** ${t.stop_condition}`);
95
+ if (t.goal)
96
+ lines.push(`- **Goal:** ${t.goal}`);
97
97
  lines.push(`- **Sessions Created:** ${t.sessions_created_count}`);
98
98
  if (t.last_triggered_at)
99
99
  lines.push(`- **Last Triggered:** ${t.last_triggered_at}`);
@@ -7,7 +7,7 @@ export declare const StartSessionSchema: z.ZodObject<{
7
7
  agent_root: z.ZodOptional<z.ZodString>;
8
8
  title: z.ZodOptional<z.ZodString>;
9
9
  slug: z.ZodOptional<z.ZodString>;
10
- stop_condition: z.ZodOptional<z.ZodString>;
10
+ goal: z.ZodOptional<z.ZodString>;
11
11
  execution_provider: z.ZodOptional<z.ZodEnum<["local_filesystem", "remote_sandbox"]>>;
12
12
  mcp_servers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
13
13
  skills: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
@@ -22,7 +22,7 @@ export declare const StartSessionSchema: z.ZodObject<{
22
22
  prompt?: string | undefined;
23
23
  title?: string | undefined;
24
24
  slug?: string | undefined;
25
- stop_condition?: string | undefined;
25
+ goal?: string | undefined;
26
26
  execution_provider?: "local_filesystem" | "remote_sandbox" | undefined;
27
27
  mcp_servers?: string[] | undefined;
28
28
  agent_root?: string | undefined;
@@ -36,7 +36,7 @@ export declare const StartSessionSchema: z.ZodObject<{
36
36
  prompt?: string | undefined;
37
37
  title?: string | undefined;
38
38
  slug?: string | undefined;
39
- stop_condition?: string | undefined;
39
+ goal?: string | undefined;
40
40
  execution_provider?: "local_filesystem" | "remote_sandbox" | undefined;
41
41
  mcp_servers?: string[] | undefined;
42
42
  agent_root?: string | undefined;
@@ -70,9 +70,9 @@ export declare function startSessionTool(_server: Server, clientFactory: () => I
70
70
  type: string;
71
71
  description: "URL-friendly identifier for the session. Must be unique.";
72
72
  };
73
- stop_condition: {
73
+ goal: {
74
74
  type: string;
75
- description: "Stop condition ID from get_configs (e.g. \"pr_merged\"). The description is automatically resolved and passed to the agent as context.";
75
+ description: "Goal ID from get_configs (e.g. \"pr_merged\"). The description is automatically resolved and passed to the agent as context.";
76
76
  };
77
77
  execution_provider: {
78
78
  type: string;
@@ -11,7 +11,7 @@ const PARAM_DESCRIPTIONS = {
11
11
  '(e.g. "Fix login redirect loop on mobile Safari", "Add dark mode toggle to settings page"). ' +
12
12
  'Only omit if you truly have zero context about the session purpose, which should be extremely rare.',
13
13
  slug: 'URL-friendly identifier for the session. Must be unique.',
14
- stop_condition: 'Stop condition ID from get_configs (e.g. "pr_merged"). The description is automatically resolved and passed to the agent as context.',
14
+ goal: 'Goal ID from get_configs (e.g. "pr_merged"). The description is automatically resolved and passed to the agent as context.',
15
15
  execution_provider: 'Execution environment. Options: "local_filesystem" (runs locally), "remote_sandbox" (runs in isolated sandbox). Default: "local_filesystem"',
16
16
  mcp_servers: 'List of MCP server names to enable for this session. Example: ["github-development", "slack"]',
17
17
  skills: 'List of skill names to enable for this session. Always include the agent root\'s default_skills from get_configs as the starting point — omitting skills means the session gets none. Add extras as needed; removing a default should be rare and intentional. Example: ["discovery-classify", "publish-and-pr"]',
@@ -30,7 +30,7 @@ export const StartSessionSchema = z.object({
30
30
  agent_root: z.string().optional().describe(PARAM_DESCRIPTIONS.agent_root),
31
31
  title: z.string().optional().describe(PARAM_DESCRIPTIONS.title),
32
32
  slug: z.string().optional().describe(PARAM_DESCRIPTIONS.slug),
33
- stop_condition: z.string().optional().describe(PARAM_DESCRIPTIONS.stop_condition),
33
+ goal: z.string().optional().describe(PARAM_DESCRIPTIONS.goal),
34
34
  execution_provider: z
35
35
  .enum(['local_filesystem', 'remote_sandbox'])
36
36
  .optional()
@@ -44,7 +44,7 @@ export const StartSessionSchema = z.object({
44
44
  });
45
45
  const TOOL_DESCRIPTION = `Start a new agent session in the Agent Orchestrator.
46
46
 
47
- **IMPORTANT:** Before starting a session, call get_configs to discover available agent roots, MCP servers, stop conditions, and their defaults.
47
+ **IMPORTANT:** Before starting a session, call get_configs to discover available agent roots, MCP servers, goals, and their defaults.
48
48
 
49
49
  **Returns:** The created session with its ID, status, and configuration.
50
50
 
@@ -54,7 +54,7 @@ const TOOL_DESCRIPTION = `Start a new agent session in the Agent Orchestrator.
54
54
 
55
55
  **Agent Roots:** Use \`agent_root\` to specify which preconfigured agent root to use. The API resolves git_root, branch, subdirectory, default_model, and other defaults from the agent root configuration.
56
56
 
57
- **Defaults from Agent Roots:** The agent root defines \`default_mcp_servers\`, \`default_skills\`, and optionally a \`default_stop_condition\`. Omitting \`mcp_servers\` or \`skills\` means the session gets NONE — there is no automatic fallback to defaults.
57
+ **Defaults from Agent Roots:** The agent root defines \`default_mcp_servers\`, \`default_skills\`, and optionally a \`default_goal\`. Omitting \`mcp_servers\` or \`skills\` means the session gets NONE — there is no automatic fallback to defaults.
58
58
 
59
59
  - **MCP servers:** Start with \`default_mcp_servers\`. Drop servers the task doesn't need (least-privilege). Add extras when the task requires tools beyond the defaults. When \`ALLOWED_AGENT_ROOTS\` is active, you cannot add servers beyond the defaults.
60
60
  - **Skills:** Start with \`default_skills\`. You can freely add skills beyond the defaults. Removing a default skill should be rare and intentional — only when you have a specific reason, like replacing a skill with a more capable variant that covers the same ground. Skills are lightweight text files with no blast radius, so keeping all defaults costs nothing.
@@ -91,9 +91,9 @@ export function startSessionTool(_server, clientFactory) {
91
91
  type: 'string',
92
92
  description: PARAM_DESCRIPTIONS.slug,
93
93
  },
94
- stop_condition: {
94
+ goal: {
95
95
  type: 'string',
96
- description: PARAM_DESCRIPTIONS.stop_condition,
96
+ description: PARAM_DESCRIPTIONS.goal,
97
97
  },
98
98
  execution_provider: {
99
99
  type: 'string',
@@ -151,18 +151,18 @@ export function startSessionTool(_server, clientFactory) {
151
151
  };
152
152
  }
153
153
  }
154
- // Resolve stop_condition ID to its description so the agent receives
154
+ // Resolve goal ID to its description so the agent receives
155
155
  // meaningful context about when to stop, not just an opaque identifier.
156
156
  let createArgs = validatedArgs;
157
- if (validatedArgs.stop_condition) {
157
+ if (validatedArgs.goal) {
158
158
  let configs = getConfigsCache();
159
159
  if (!configs) {
160
160
  configs = await client.getConfigs();
161
161
  setConfigsCache(configs);
162
162
  }
163
- const match = configs.stop_conditions.find((sc) => sc.id === validatedArgs.stop_condition);
163
+ const match = configs.goals.find((sc) => sc.id === validatedArgs.goal);
164
164
  if (match) {
165
- createArgs = { ...validatedArgs, stop_condition: match.description };
165
+ createArgs = { ...validatedArgs, goal: match.description };
166
166
  }
167
167
  }
168
168
  const session = await client.createSession(createArgs);
@@ -4,18 +4,18 @@ import type { IAgentOrchestratorClient } from '../orchestrator-client/orchestrat
4
4
  export declare const WakeMeUpWhenSessionChangesStateSchema: z.ZodObject<{
5
5
  session_id: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
6
6
  watched_session_id: z.ZodNumber;
7
- event_name: z.ZodEnum<["session_needs_input", "session_failed"]>;
7
+ event_name: z.ZodEnum<["session_needs_input", "session_failed", "session_archived"]>;
8
8
  prompt: z.ZodString;
9
9
  }, "strip", z.ZodTypeAny, {
10
10
  prompt: string;
11
11
  session_id: string | number;
12
12
  watched_session_id: number;
13
- event_name: "session_needs_input" | "session_failed";
13
+ event_name: "session_needs_input" | "session_failed" | "session_archived";
14
14
  }, {
15
15
  prompt: string;
16
16
  session_id: string | number;
17
17
  watched_session_id: number;
18
- event_name: "session_needs_input" | "session_failed";
18
+ event_name: "session_needs_input" | "session_failed" | "session_archived";
19
19
  }>;
20
20
  export declare function wakeMeUpWhenSessionChangesStateTool(_server: Server, clientFactory: () => IAgentOrchestratorClient): {
21
21
  name: string;
@@ -35,7 +35,7 @@ export declare function wakeMeUpWhenSessionChangesStateTool(_server: Server, cli
35
35
  };
36
36
  event_name: {
37
37
  type: string;
38
- enum: ("session_needs_input" | "session_failed")[];
38
+ enum: ("session_needs_input" | "session_failed" | "session_archived")[];
39
39
  description: string;
40
40
  };
41
41
  prompt: {
@@ -1,45 +1,53 @@
1
1
  import { z } from 'zod';
2
2
  import { parseAllowedAgentRoots } from '../allowed-agent-roots.js';
3
- const AO_EVENT_NAMES = ['session_needs_input', 'session_failed'];
3
+ const AO_EVENT_NAMES = ['session_needs_input', 'session_failed', 'session_archived'];
4
4
  export const WakeMeUpWhenSessionChangesStateSchema = z.object({
5
5
  session_id: z.union([z.string(), z.number()]),
6
6
  watched_session_id: z.number().int().positive(),
7
7
  event_name: z.enum(AO_EVENT_NAMES),
8
8
  prompt: z.string(),
9
9
  });
10
- const TOOL_DESCRIPTION = `Schedule this session to be woken up when another session transitions to \`needs_input\` or \`failed\`. The requester session is put to sleep (waiting status) and a one-time trigger fires when the watched session enters the matching state. If the requester is manually resumed before the watched session transitions, the trigger is silently consumed and won't re-fire.
10
+ const TOOL_DESCRIPTION = `Schedule this session to be woken up when another session transitions to \`needs_input\`, \`failed\`, or \`archived\`. The requester session is put to sleep (waiting status) and a one-time trigger fires when the watched session enters the matching state. If the requester is manually resumed before the watched session transitions, the trigger is silently consumed and won't re-fire.
11
11
 
12
- This is the **state-based analog of \`wake_me_up_later\`**. Use \`wake_me_up_later\` when you know *when* to wake up (a clock time). Use this tool when you know *what event* to wake up on but not when it will happen — e.g., a subagent session you spawned will eventually need input or might fail, and you want to be the first to handle it without polling.
12
+ This is the **state-based analog of \`wake_me_up_later\`**. Use \`wake_me_up_later\` when you know *when* to wake up (a clock time). Use this tool when you know *what event* to wake up on but not when it will happen — e.g., a subagent session you spawned will eventually finish (self-archive), pause for input, or crash, and you want to be the first to handle it without polling.
13
+
14
+ **Triple-wake pattern (typical use).** When you spawn a downstream session and want to wake up on whatever outcome it produces, you'll TYPICALLY want to schedule THREE state-change triggers — one for each terminal/idle event — so you wake on whichever happens first:
15
+ - \`session_archived\` — the watched session self-archived on success (common for closed-loop tasks like "open a PR and self-archive when CI is green"). A downstream session that self-archives goes \`running\` → \`archived\` directly, skipping \`needs_input\`, so a trigger on \`session_needs_input\` alone would NEVER fire for these tasks.
16
+ - \`session_needs_input\` — the watched session paused for user input or finished a turn awaiting follow-up.
17
+ - \`session_failed\` — the watched session crashed.
18
+
19
+ Pair these three triggers with ONE \`wake_me_up_later\` deadline backstop so a hung watched session can't keep you sleeping forever. The first trigger to fire wins; the others are silently consumed when the requester resumes. **Picking only ONE of the three is a footgun** — if you only schedule \`session_needs_input\` and the downstream session self-archives directly, the only thing that wakes you is the deadline (long, wasteful). Schedule all three unless you have a specific reason to wake only on one outcome.
13
20
 
14
21
  **IMPORTANT — Use this tool instead of polling.** When this tool is available, it is the correct way to wait on another session's state. Do NOT use these alternatives:
15
22
  - **Repeated \`get_session\` calls in a poll loop**: wastes compute, racks up tool-call overhead, and either polls too often (waste) or too rarely (latency). The trigger fires immediately on transition with no polling latency.
16
- - **\`wake_me_up_later\` with a guessed duration**: time-based wake-ups are wrong here — you don't know when the watched session will transition, and a guess is either too short (you wake up early and have to re-sleep) or too long (the watched session has been sitting in \`needs_input\` while you sleep).
23
+ - **\`wake_me_up_later\` with a guessed duration**: time-based wake-ups are wrong as the *primary* signal here — you don't know when the watched session will transition, and a guess is either too short (you wake up early and have to re-sleep) or too long (the watched session has been sitting in \`needs_input\` / archived while you sleep). Use \`wake_me_up_later\` only as a deadline backstop alongside the state-change triggers.
17
24
 
18
25
  **The watched session can be ANY session**, not just one the requester spawned. You can watch a peer session, a session a different agent created, or even a session run by a different user — as long as the requester knows the watched session's id.
19
26
 
20
- **One-shot semantics.** The trigger auto-disables after firing. If the watched session transitions, the requester wakes up exactly once, then the trigger is gone. To wake on the next transition too, schedule another trigger from the woken-up turn.
27
+ **One-shot semantics.** Each trigger auto-disables after firing. If the watched session transitions, the requester wakes up exactly once and only the first-firing trigger's prompt is delivered; any companion triggers (the other two state events plus the deadline backstop) are silently consumed and gone. To wake on a future transition too, schedule another trigger from the woken-up turn.
21
28
 
22
- **Important — fires on transitions, not on current state.** The trigger fires when the watched session *moves into* the target state, not when it is *already in* it. If the watched session is already \`needs_input\` when you create the trigger, the trigger waits for the next transition out and back in (which only happens if someone resumes the watched session). For \`session_failed\` on a session that is already \`failed\`, the trigger never fires \`failed\` is terminal. This tool rejects those terminal/no-fire-possible cases up front (already-failed watched session, archived watched session, self-watch). For non-terminal "already in target state" cases, the call succeeds but is a no-op until the watched session is resumed.
29
+ **Important — fires on transitions, not on current state.** The trigger fires when the watched session *moves into* the target state, not when it is *already in* it. \`failed\` and \`archived\` are both terminal under typical flow — a session that is already \`failed\` will not transition to \`failed\` again, and a session that is already \`archived\` will not transition to \`archived\` again unless someone unarchives it and re-archives it (rare and surprising). \`needs_input\` is non-terminal: if the watched session is already \`needs_input\` when you create the trigger, it waits for the next transition out and back in. This tool rejects up front any case where the trigger could never fire — already-failed and already-archived watched sessions (terminal states), plus the self-watch case (requester == watched) so the requester doesn't sleep on a trigger that can never fire.
23
30
 
24
- **Deadline backstop pattern.** If you need to wake on the watched session's transition *or* after a max wait time (whichever comes first), create a second \`wake_me_up_later\` trigger alongside this one. First trigger to fire wins; the AO firing path resumes the requester once and the other trigger is silently dropped.
31
+ **Deadline backstop pattern.** Always pair the state-change triggers with one \`wake_me_up_later\` trigger so the requester eventually wakes even if the watched session hangs. First trigger to fire wins; the AO firing path resumes the requester once and the others are silently dropped.
25
32
 
26
33
  **Parameters:**
27
34
  - **session_id**: The session to wake up (the requester). Works from either \`needs_input\` or \`running\` state — if you call this tool from within your own currently-running session, the sleep transition is recorded and takes effect after the current turn ends.
28
35
  - **watched_session_id**: The session to watch. Must be a positive integer. The Rails API rejects unknown ids with a clear 422.
29
36
  - **event_name**: Which transition to wake on:
30
- - \`session_needs_input\`: watched session moves to \`needs_input\` (typically: it finished a turn and is waiting for the user, OR it asked a clarifying question)
31
- - \`session_failed\`: watched session moves to \`failed\` (a hard error — the session crashed or was killed)
37
+ - \`session_needs_input\`: watched session moves to \`needs_input\` (typically: it finished a turn, or it asked a clarifying question).
38
+ - \`session_failed\`: watched session moves to \`failed\` (a hard error — the session crashed or was killed).
39
+ - \`session_archived\`: watched session moves to \`archived\` (typically: it self-archived after completing closed-loop work, OR a user manually archived it).
32
40
 
33
- Pick the one that matches what you're actually waiting for. If you want to wake on either, create two triggers (one per event) — the first to fire wins, and the other is silently dropped on the requester's resume.
34
- - **prompt**: The prompt to send when waking up the session. Include enough context that the woken-up turn knows what to do (e.g., "session #N you were watching just transitioned — check its output and decide next steps").
41
+ When in doubt, schedule all three (see the triple-wake pattern above) — the first to fire wins.
42
+ - **prompt**: The prompt to send when waking up the session. Include enough context that the woken-up turn knows what to do (e.g., "session #N you were watching just transitioned — check its output and decide next steps"). If you scheduled multiple triggers (the typical case), each trigger's prompt should make clear which event fired so the woken-up turn knows the outcome without re-checking.
35
43
 
36
44
  **What happens:**
37
45
  1. Creates a one-time \`ao_event\` trigger bound to the requester (\`reuse_session: true\`, \`last_session_id: session_id\`) with a single condition scoped to \`watched_session_id\` and \`event_name\`.
38
46
  2. As a side effect of creating the trigger, the AO API transitions the requester to sleeping (waiting) status — immediately if currently \`needs_input\`, or after the current turn ends if currently \`running\`.
39
47
  3. When the watched session transitions to the matching state, the trigger fires and resumes the requester with the provided prompt. The trigger then auto-deletes (one-shot).
40
- 4. If the requester is manually resumed first, the pending trigger is consumed (won't fire). If the watched session is archived without ever transitioning, the trigger is cleaned up.
48
+ 4. If the requester is manually resumed first, the pending trigger is consumed (won't fire). If the watched session is archived without ever transitioning to the matching state (e.g., you only scheduled \`session_needs_input\` and it went straight to \`archived\`), the trigger is cleaned up — and you'll only wake when your deadline backstop fires.
41
49
 
42
- **You must end your conversation turn after calling this tool** so the auto-sleep can take effect. If your turn keeps running, the requester will not be in a wakeable state when the watched session transitions, and the wake-up will be silently dropped.`;
50
+ **You must end your conversation turn after calling this tool** so the auto-sleep can take effect. If your turn keeps running, the requester will not be in a wakeable state when the watched session transitions, and the wake-up will be silently dropped. When scheduling multiple triggers (the typical triple-wake + deadline pattern), call this tool repeatedly within the same turn — the auto-sleep is idempotent and only takes effect once the turn ends.`;
43
51
  export function wakeMeUpWhenSessionChangesStateTool(_server, clientFactory) {
44
52
  return {
45
53
  name: 'wake_me_up_when_session_changes_state',
@@ -58,7 +66,7 @@ export function wakeMeUpWhenSessionChangesStateTool(_server, clientFactory) {
58
66
  event_name: {
59
67
  type: 'string',
60
68
  enum: [...AO_EVENT_NAMES],
61
- description: 'Which transition to wake on: "session_needs_input" (watched session is waiting for input) or "session_failed" (watched session crashed).',
69
+ description: 'Which transition to wake on: "session_needs_input" (watched session is waiting for input), "session_failed" (watched session crashed), or "session_archived" (watched session self-archived or was archived by a user). Typically schedule all three (plus a wake_me_up_later deadline backstop) for a downstream session you spawned — see the triple-wake pattern in the tool description.',
62
70
  },
63
71
  prompt: {
64
72
  type: 'string',
@@ -170,6 +178,17 @@ export function wakeMeUpWhenSessionChangesStateTool(_server, clientFactory) {
170
178
  isError: true,
171
179
  };
172
180
  }
181
+ if (event_name === 'session_archived' && watchedSession.status === 'archived') {
182
+ return {
183
+ content: [
184
+ {
185
+ type: 'text',
186
+ text: `Error: Watched session ${watched_session_id} is already in "archived" state. The trigger fires on transitions only — a session that is already archived will not transition to archived again (barring an unarchive + re-archive, which is rare), so the requester would sleep forever. Pass an active session id, or inspect the archived session directly.`,
187
+ },
188
+ ],
189
+ isError: true,
190
+ };
191
+ }
173
192
  if (watchedSession.status === 'archived') {
174
193
  return {
175
194
  content: [
package/shared/types.d.ts CHANGED
@@ -21,7 +21,7 @@ export interface Session {
21
21
  branch: string | null;
22
22
  subdirectory: string | null;
23
23
  execution_provider: string;
24
- stop_condition: string | null;
24
+ goal: string | null;
25
25
  mcp_servers: string[];
26
26
  catalog_skills?: string[];
27
27
  catalog_plugins?: string[];
@@ -114,12 +114,12 @@ export interface AgentRootInfo {
114
114
  git_root: string;
115
115
  default_branch?: string;
116
116
  default_subdirectory?: string;
117
- default_stop_condition?: string;
117
+ default_goal?: string;
118
118
  default_mcp_servers?: string[];
119
119
  default_skills?: string[];
120
120
  default_model?: string;
121
121
  }
122
- export interface StopConditionInfo {
122
+ export interface GoalInfo {
123
123
  id: string;
124
124
  name: string;
125
125
  description: string;
@@ -127,7 +127,7 @@ export interface StopConditionInfo {
127
127
  export interface ConfigsResponse {
128
128
  mcp_servers: MCPServerInfo[];
129
129
  agent_roots: AgentRootInfo[];
130
- stop_conditions: StopConditionInfo[];
130
+ goals: GoalInfo[];
131
131
  }
132
132
  export interface SendPushNotificationResponse {
133
133
  success: boolean;
@@ -142,7 +142,7 @@ export interface CreateSessionRequest {
142
142
  subdirectory?: string;
143
143
  title?: string;
144
144
  slug?: string;
145
- stop_condition?: string;
145
+ goal?: string;
146
146
  execution_provider?: string;
147
147
  mcp_servers?: string[];
148
148
  skills?: string[];
@@ -155,7 +155,7 @@ export interface CreateSessionRequest {
155
155
  export interface UpdateSessionRequest {
156
156
  title?: string;
157
157
  slug?: string;
158
- stop_condition?: string;
158
+ goal?: string;
159
159
  mcp_servers?: string[];
160
160
  custom_metadata?: Record<string, unknown>;
161
161
  }
@@ -198,7 +198,7 @@ export interface EnqueuedMessage {
198
198
  id: number;
199
199
  session_id: number;
200
200
  content: string;
201
- stop_condition: string | null;
201
+ goal: string | null;
202
202
  position: number;
203
203
  status: EnqueuedMessageStatus;
204
204
  created_at: string;
@@ -232,7 +232,7 @@ export interface Trigger {
232
232
  status: TriggerStatus;
233
233
  agent_root_name: string;
234
234
  prompt_template: string;
235
- stop_condition: string | null;
235
+ goal: string | null;
236
236
  reuse_session: boolean;
237
237
  enqueue_messages?: boolean;
238
238
  resuscitate_archived?: boolean;
@@ -269,7 +269,7 @@ export interface CreateTriggerRequest {
269
269
  agent_root_name: string;
270
270
  prompt_template: string;
271
271
  status?: TriggerStatus;
272
- stop_condition?: string;
272
+ goal?: string;
273
273
  reuse_session?: boolean;
274
274
  mcp_servers?: string[];
275
275
  last_session_id?: number;
@@ -282,7 +282,7 @@ export interface UpdateTriggerRequest {
282
282
  agent_root_name?: string;
283
283
  prompt_template?: string;
284
284
  status?: TriggerStatus;
285
- stop_condition?: string;
285
+ goal?: string;
286
286
  reuse_session?: boolean;
287
287
  mcp_servers?: string[];
288
288
  trigger_conditions_attributes?: TriggerConditionAttributes[];