Skip to content

Commit 2e45e8e

Browse files
committed
feat(sdk): add cloud runtime preflight
1 parent cb06bc2 commit 2e45e8e

5 files changed

Lines changed: 104 additions & 4 deletions

File tree

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ JavaScript and TypeScript SDK for AgentDispatch. Use it to call the MCP server f
88
## What it does
99

1010
- Wraps the provider-neutral AgentDispatch MCP tools.
11-
- Provides typed requests for `spawn_cloud_agent`, `dispatch_task`, polling, logs, results, and cancellation.
11+
- Provides typed requests for `check_cloud_agent_runtime`, `spawn_cloud_agent`, `dispatch_task`, polling, logs, results, and cancellation.
1212
- Preserves provider-neutral inputs so future adapters do not require SDK API churn.
1313
- Returns cloud-agent metadata for A2A, MCP, AG-UI, or HTTP interaction after spawn.
1414

@@ -28,6 +28,14 @@ const client = await AgentDispatchStdioClient.connect({
2828
args: ["agentdispatch-mcp", "--config", "/absolute/path/agentdispatch.config.json"]
2929
});
3030

31+
const readiness = await client.checkCloudAgentRuntime({
32+
runtime: "research-agent",
33+
live: true
34+
});
35+
if (!readiness.ok) {
36+
throw new Error(`Cloud agent runtime is not ready: ${JSON.stringify(readiness.checks)}`);
37+
}
38+
3139
const task = await client.spawnCloudAgent({
3240
instruction: "Run a long-running repo analysis task.",
3341
protocol: "a2a",

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@agent-dispatch/sdk",
3-
"version": "0.1.4",
3+
"version": "0.1.5",
44
"description": "TypeScript SDK for AgentDispatch.",
55
"type": "module",
66
"license": "Apache-2.0",

src/index.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,40 @@ export interface CloudAgentA2AResult {
123123
metadata?: Record<string, unknown>;
124124
}
125125

126+
export interface CloudAgentRuntimeCheckRequest {
127+
runtime?: string;
128+
provider?: string;
129+
accountProfile?: string;
130+
account_profile?: string;
131+
live?: boolean;
132+
runtimeArn?: string;
133+
runtime_arn?: string;
134+
target?: {
135+
mode?: string;
136+
protocol?: string;
137+
details?: Record<string, unknown>;
138+
};
139+
}
140+
141+
export interface CloudAgentRuntimeCheck {
142+
name: string;
143+
status: "pass" | "warn" | "fail";
144+
message: string;
145+
}
146+
147+
export interface CloudAgentRuntimeCheckResult {
148+
ok: boolean;
149+
runtime?: string;
150+
provider?: string;
151+
accountProfile?: string;
152+
account_profile?: string;
153+
backend?: string;
154+
adapter?: string;
155+
targetMode?: string;
156+
target_mode?: string;
157+
checks: CloudAgentRuntimeCheck[];
158+
}
159+
126160
export type CloudAgentA2ATransport =
127161
| ((request: CloudAgentA2AHttpRequest) => Promise<unknown>)
128162
| { send(request: CloudAgentA2AHttpRequest): Promise<unknown> };
@@ -195,6 +229,18 @@ export class AgentDispatchMcpClient {
195229
});
196230
}
197231

232+
async checkCloudAgentRuntime(request: CloudAgentRuntimeCheckRequest = {}): Promise<CloudAgentRuntimeCheckResult> {
233+
return this.call<CloudAgentRuntimeCheckResult>("check_cloud_agent_runtime", {
234+
runtime: request.runtime,
235+
provider: request.provider,
236+
account_profile: request.accountProfile ?? request.account_profile,
237+
live: request.live,
238+
runtimeArn: request.runtimeArn,
239+
runtime_arn: request.runtime_arn,
240+
target: request.target
241+
});
242+
}
243+
198244
async getTaskStatus(taskId: string): Promise<TaskRecord> {
199245
return this.call<TaskRecord>("get_task_status", { task_id: taskId });
200246
}

test/client.test.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,15 @@ describe("AgentDispatchMcpClient", () => {
117117
const responses: Record<string, unknown> = {
118118
dispatch_task: { taskId: "task_mcp", status: "provisioning", provider: "aws", accountProfile: "dev-aws" },
119119
spawn_cloud_agent: { taskId: "task_spawn", status: "provisioning", provider: "aws", accountProfile: "dev-aws" },
120+
check_cloud_agent_runtime: {
121+
ok: true,
122+
runtime: "research-agent",
123+
provider: "aws",
124+
accountProfile: "dev-aws",
125+
backend: "aws-agentcore",
126+
targetMode: "session",
127+
checks: [{ name: "aws.research-agent.runtime", status: "pass", message: "runtime reachable" }]
128+
},
120129
get_task_status: task,
121130
get_task_logs: { taskId: "task_mcp", cursor: 0, nextCursor: 5, data: "hello" },
122131
get_task_result: { taskId: "task_mcp", status: "succeeded", artifacts: [] },
@@ -144,6 +153,12 @@ describe("AgentDispatchMcpClient", () => {
144153
executionRoleArn: "arn:aws:iam::123456789012:role/agentcore-runtime",
145154
environmentVariables: { AGENT_FRAMEWORK: "openclaw" }
146155
})).resolves.toMatchObject({ taskId: "task_spawn" });
156+
await expect(client.checkCloudAgentRuntime({
157+
runtime: "research-agent",
158+
runtimeArn: "arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/research-agent",
159+
live: true,
160+
target: { mode: "session", protocol: "a2a" }
161+
})).resolves.toMatchObject({ ok: true, backend: "aws-agentcore" });
147162
await expect(client.getTaskStatus("task_mcp")).resolves.toMatchObject({ status: "running" });
148163
await expect(client.getTaskLogs("task_mcp", 0, 128)).resolves.toMatchObject({ data: "hello" });
149164
await expect(client.getTaskResult("task_mcp")).resolves.toMatchObject({ status: "succeeded" });
@@ -154,6 +169,7 @@ describe("AgentDispatchMcpClient", () => {
154169
expect(calls.map((call) => call.toolName)).toEqual([
155170
"dispatch_task",
156171
"spawn_cloud_agent",
172+
"check_cloud_agent_runtime",
157173
"get_task_status",
158174
"get_task_logs",
159175
"get_task_result",
@@ -180,6 +196,12 @@ describe("AgentDispatchMcpClient", () => {
180196
executionRoleArn: "arn:aws:iam::123456789012:role/agentcore-runtime",
181197
environmentVariables: { AGENT_FRAMEWORK: "openclaw" }
182198
});
199+
expect(calls[2].input).toMatchObject({
200+
runtime: "research-agent",
201+
live: true,
202+
runtimeArn: "arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/research-agent",
203+
target: { mode: "session", protocol: "a2a" }
204+
});
183205
});
184206

185207
it("supports transports that return decoded JSON directly", async () => {
@@ -190,6 +212,30 @@ describe("AgentDispatchMcpClient", () => {
190212
await expect(client.listProviders()).resolves.toEqual(["aws", "gcp"]);
191213
});
192214

215+
it("accepts MCP-native runtime check aliases", async () => {
216+
let forwarded: Record<string, unknown> | undefined;
217+
const client = new AgentDispatchMcpClient({
218+
callTool: async (_toolName, input) => {
219+
forwarded = input;
220+
return { ok: true, checks: [] };
221+
}
222+
});
223+
224+
await client.checkCloudAgentRuntime({
225+
provider: "aws",
226+
account_profile: "dev-aws",
227+
runtime_arn: "arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/alias",
228+
target: { mode: "session" }
229+
});
230+
231+
expect(forwarded).toMatchObject({
232+
provider: "aws",
233+
account_profile: "dev-aws",
234+
runtime_arn: "arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/alias",
235+
target: { mode: "session" }
236+
});
237+
});
238+
193239
it("accepts MCP-native spawn aliases for clarification retries", async () => {
194240
let forwarded: Record<string, unknown> | undefined;
195241
const client = new AgentDispatchMcpClient({

0 commit comments

Comments
 (0)