agent-orchestrator-mcp-server 0.7.3 → 0.7.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-orchestrator-mcp-server",
3
- "version": "0.7.3",
3
+ "version": "0.7.9",
4
4
  "description": "Local implementation of agent-orchestrator MCP server",
5
5
  "main": "build/index.js",
6
6
  "type": "module",
@@ -29,7 +29,7 @@
29
29
  "stage-publish": "npm version"
30
30
  },
31
31
  "dependencies": {
32
- "@modelcontextprotocol/sdk": "^1.26.0",
32
+ "@modelcontextprotocol/sdk": "^1.29.0",
33
33
  "zod": "^3.24.1"
34
34
  },
35
35
  "devDependencies": {
@@ -241,8 +241,8 @@ export function createIntegrationMockOrchestratorClient(initialMockData) {
241
241
  if (!session) {
242
242
  throw new Error(`API Error (404): Session not found`);
243
243
  }
244
- if (session.status !== 'needs_input') {
245
- throw new Error(`API Error (422): Session must be in needs_input state to sleep`);
244
+ if (session.status !== 'needs_input' && session.status !== 'running') {
245
+ throw new Error(`API Error (422): Session must be in needs_input or running state to sleep (current: ${session.status})`);
246
246
  }
247
247
  session.status = 'waiting';
248
248
  session.updated_at = new Date().toISOString();
@@ -633,7 +633,7 @@ export function createIntegrationMockOrchestratorClient(initialMockData) {
633
633
  return {
634
634
  id: 1,
635
635
  name: data.name,
636
- trigger_type: data.trigger_type,
636
+ trigger_type: data.trigger_type || 'schedule',
637
637
  status: data.status || 'enabled',
638
638
  agent_root_name: data.agent_root_name,
639
639
  prompt_template: data.prompt_template,
@@ -642,7 +642,7 @@ export function createIntegrationMockOrchestratorClient(initialMockData) {
642
642
  mcp_servers: data.mcp_servers || [],
643
643
  configuration: data.configuration || {},
644
644
  schedule_description: null,
645
- last_session_id: null,
645
+ last_session_id: data.last_session_id ?? null,
646
646
  last_triggered_at: null,
647
647
  last_polled_at: null,
648
648
  sessions_created_count: 0,
@@ -500,7 +500,12 @@ const SELF_SESSION_TOOL_DESCRIPTION = `Perform a self-management action on a ses
500
500
  **Use cases:**
501
501
  - Update session notes to record progress or context
502
502
  - Set a meaningful session title
503
- - Archive the session when work is complete`;
503
+ - Archive the session when work is complete
504
+
505
+ **Archive guidelines:**
506
+ - Only self-archive when explicitly instructed to (e.g., a stop condition says "archive yourself")
507
+ - 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
508
+ - 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\``;
504
509
  export function selfSessionActionSessionTool(_server, clientFactory) {
505
510
  return {
506
511
  name: 'action_session',
@@ -11,6 +11,13 @@ function buildToolDescription() {
11
11
  const utcNow = now.toISOString().replace(/\.\d{3}Z$/, 'Z');
12
12
  return `Schedule this session to be woken up at a specific time. The session will be put to sleep (waiting status) and a one-time trigger will fire at the specified time to resume it with the given prompt. If the session is manually resumed before the scheduled time, the trigger will be silently dropped.
13
13
 
14
+ **IMPORTANT — Use this tool instead of workarounds.** When this tool is available, it is the correct way to schedule a delayed wake-up in an Agent Orchestrator context. Do NOT use these alternatives:
15
+ - **Bash \`sleep\`**: Blocks the process and wastes compute resources for the entire sleep duration. The session remains "running" and cannot be reclaimed.
16
+ - **Claude Code \`ScheduleWakeup\` tool**: Does not integrate with AO's session lifecycle — it won't transition the session to sleeping/waiting state or create an AO trigger, so AO cannot track or manage the wake-up.
17
+ - **Claude Code \`Monitor\` tool**: Same problem — it operates outside AO's session state management.
18
+
19
+ This tool creates a one-time AO wake-up trigger bound to the target session. The AO API atomically transitions the session to sleeping (waiting) state as part of creating the trigger, so AO can reclaim resources and the trigger is guaranteed to resume the correct session at the specified time.
20
+
14
21
  **Current server time:** ${utcNow} (UTC). Use this as your reference point when calculating wake-up times.
15
22
 
16
23
  **Timezone handling:**
@@ -21,16 +28,15 @@ function buildToolDescription() {
21
28
  - If you omit timezone, wake_at is treated as UTC.
22
29
 
23
30
  **Parameters:**
24
- - **session_id**: The session to wake up (must be in needs_input state)
31
+ - **session_id**: The session to wake up. 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.
25
32
  - **wake_at**: ISO 8601 datetime without offset for when to wake up (e.g., "2026-04-15T14:30:00")
26
33
  - **timezone**: IANA timezone for interpreting wake_at (default: "UTC", e.g., "America/New_York")
27
34
  - **prompt**: The prompt to send when waking up the session
28
35
 
29
36
  **What happens:**
30
- 1. Validates the session is in needs_input state
31
- 2. Puts the session to sleep (waiting status)
32
- 3. Creates a one-time schedule trigger that fires at the specified time
33
- 4. The trigger resumes the session with the provided prompt`;
37
+ 1. Creates a one-time schedule trigger bound to this session that fires at the specified time.
38
+ 2. As a side effect of creating the trigger, the AO API transitions the session to sleeping (waiting) status — immediately if currently \`needs_input\`, or after the current turn ends if currently \`running\`.
39
+ 3. At the scheduled time, the trigger resumes the session with the provided prompt.`;
34
40
  }
35
41
  export function wakeMeUpLaterTool(_server, clientFactory) {
36
42
  return {
@@ -41,7 +47,7 @@ export function wakeMeUpLaterTool(_server, clientFactory) {
41
47
  properties: {
42
48
  session_id: {
43
49
  oneOf: [{ type: 'string' }, { type: 'number' }],
44
- description: 'Session ID (numeric) or slug (string). Must be in needs_input state.',
50
+ description: 'Session ID (numeric) or slug (string). Accepts sessions in needs_input or running state — from a running session, the sleep takes effect after the current turn ends.',
45
51
  },
46
52
  wake_at: {
47
53
  type: 'string',
@@ -76,30 +82,49 @@ export function wakeMeUpLaterTool(_server, clientFactory) {
76
82
  };
77
83
  }
78
84
  const session = await client.getSession(session_id);
79
- if (session.status !== 'needs_input') {
85
+ // Reject states the Rails API can't auto-sleep from. `needs_input`
86
+ // immediate sleep; `running` → deferred sleep via pending_sleep metadata;
87
+ // `waiting` → already dormant, trigger fires normally. Anything else
88
+ // (failed, archived) would silently no-op the auto-sleep and leave the
89
+ // caller with a trigger targeting a session that can't be woken.
90
+ const WAKEABLE_STATUSES = ['needs_input', 'running', 'waiting'];
91
+ if (!WAKEABLE_STATUSES.includes(session.status)) {
80
92
  return {
81
93
  content: [
82
94
  {
83
95
  type: 'text',
84
- text: `Error: Session must be in "needs_input" state to sleep (current: "${session.status}"). Only idle sessions can be scheduled for a delayed wake-up.`,
96
+ text: `Error: Session ${session.id} is in "${session.status}" state and cannot be scheduled for wake-up. Only sessions in ${WAKEABLE_STATUSES.join(', ')} can be woken up.`,
85
97
  },
86
98
  ],
87
99
  isError: true,
88
100
  };
89
101
  }
90
- const sleepingSession = await client.sleepSession(session_id);
102
+ // The Rails Trigger model requires agent_root_name, but for per-session
103
+ // wake-up triggers (reuse_session + last_session_id + one-time schedule)
104
+ // the value is never used to spawn a session — the target session is
105
+ // always reused. Prefer the canonical metadata value. The agent_type
106
+ // fallback is a best-effort for pre-migration sessions without an
107
+ // agent_root_key; if agent_type isn't a registered agent root, the
108
+ // createTrigger call will fail loudly with a 422 rather than proceed
109
+ // with a bad value — which is what we want.
110
+ const agentRootName = session.metadata?.agent_root_key || session.agent_type;
91
111
  let trigger;
92
112
  try {
93
113
  trigger = await client.createTrigger({
94
- name: `Wake session #${sleepingSession.id} at ${wake_at}`,
95
- trigger_type: 'schedule',
96
- agent_root_name: session.agent_type,
114
+ name: `Wake session #${session.id} at ${wake_at}`,
115
+ agent_root_name: agentRootName,
97
116
  prompt_template: prompt,
98
117
  reuse_session: true,
99
- configuration: {
100
- scheduled_at: wake_at,
101
- timezone,
102
- },
118
+ last_session_id: session.id,
119
+ trigger_conditions_attributes: [
120
+ {
121
+ condition_type: 'schedule',
122
+ configuration: {
123
+ scheduled_at: wake_at,
124
+ timezone,
125
+ },
126
+ },
127
+ ],
103
128
  });
104
129
  }
105
130
  catch (triggerError) {
@@ -107,28 +132,23 @@ export function wakeMeUpLaterTool(_server, clientFactory) {
107
132
  content: [
108
133
  {
109
134
  type: 'text',
110
- text: `Error: Session ${sleepingSession.id} was put to sleep (waiting status) but trigger creation failed: ${triggerError instanceof Error ? triggerError.message : 'Unknown error'}. The session is now in "waiting" state and needs manual intervention (use action_session with "restart" or "follow_up" to recover).`,
135
+ text: `Error: Trigger creation failed: ${triggerError instanceof Error ? triggerError.message : 'Unknown error'}. The session is still in its original state no changes were made.`,
111
136
  },
112
137
  ],
113
138
  isError: true,
114
139
  };
115
140
  }
116
- await client.updateSession(session_id, {
117
- custom_metadata: {
118
- ...session.custom_metadata,
119
- wake_trigger_id: trigger.id,
120
- },
121
- });
122
141
  const lines = [
123
- '## Session Scheduled for Wake-Up',
142
+ '## Wake-Up Scheduled Successfully',
124
143
  '',
125
- `- **Session ID:** ${sleepingSession.id}`,
126
- `- **Session Status:** ${sleepingSession.status}`,
144
+ `- **Session ID:** ${session.id}`,
127
145
  `- **Wake At:** ${wake_at} (${timezone})`,
128
146
  `- **Trigger ID:** ${trigger.id}`,
129
147
  `- **Trigger Name:** ${trigger.name}`,
130
148
  '',
131
- 'The session is now sleeping. It will be automatically resumed at the scheduled time with the provided prompt.',
149
+ '**You must end your conversation turn now.** The session will be automatically transitioned to waiting (immediately if currently needs_input; after the current turn ends if currently running) and resumed at the scheduled time with the provided prompt.',
150
+ '',
151
+ '⚠️ **Warning:** If you do not end your conversation turn, the session may still be running when the scheduled wake-up fires. A wake-up cannot be delivered to a session that is not in a wakeable (sleeping/waiting) state — it will be silently dropped, and you will never receive it.',
132
152
  ];
133
153
  return { content: [{ type: 'text', text: lines.join('\n') }] };
134
154
  }
package/shared/types.d.ts CHANGED
@@ -251,9 +251,13 @@ export interface TriggerChannelsResponse {
251
251
  num_members: number;
252
252
  }>;
253
253
  }
254
+ export interface TriggerConditionAttributes {
255
+ condition_type: 'slack' | 'schedule' | 'ao_event';
256
+ configuration: Record<string, unknown>;
257
+ }
254
258
  export interface CreateTriggerRequest {
255
259
  name: string;
256
- trigger_type: TriggerType;
260
+ trigger_type?: TriggerType;
257
261
  agent_root_name: string;
258
262
  prompt_template: string;
259
263
  status?: TriggerStatus;
@@ -261,6 +265,8 @@ export interface CreateTriggerRequest {
261
265
  reuse_session?: boolean;
262
266
  mcp_servers?: string[];
263
267
  configuration?: Record<string, unknown>;
268
+ last_session_id?: number;
269
+ trigger_conditions_attributes?: TriggerConditionAttributes[];
264
270
  }
265
271
  export interface UpdateTriggerRequest {
266
272
  name?: string;