@agent-compose/sdk 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -136
- package/dist/client.d.ts +5 -0
- package/dist/index.js +6 -2
- package/dist/runtimes/openai-desktop.js +6 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
# @agent-compose/sdk
|
|
2
2
|
|
|
3
|
-
TypeScript SDK for
|
|
3
|
+
TypeScript SDK for agent-compose. Use it to:
|
|
4
4
|
|
|
5
5
|
- **Author workflows** that run agentic LLM loops inside isolated sandboxes
|
|
6
6
|
- **Define runtimes** that wrap a coding-CLI tool (Claude Code, OpenAI Desktop, …) into a sandbox-portable agent loop
|
|
7
|
-
- **Register, invoke,
|
|
8
|
-
- **Manage factories, secrets, API keys, and snapshots** programmatically
|
|
9
|
-
|
|
10
|
-
The hierarchy: a **team** owns one or more **factories** (project containers); each factory owns workflow templates, secrets, and runs. Workflows are versioned per `(factory, name, version)`. New code that doesn't care about factories transparently lands in `default` — every team has one.
|
|
7
|
+
- **Register, invoke, and observe** workflows via the HTTP API (`AgentComposeClient`)
|
|
11
8
|
|
|
12
9
|
---
|
|
13
10
|
|
|
@@ -165,10 +162,9 @@ agentc register my-workflow.ts -n my-workflow
|
|
|
165
162
|
```
|
|
166
163
|
|
|
167
164
|
Under the hood that calls `bundleWorkflow(workflowPath)` (resolves imports,
|
|
168
|
-
inlines runtime sources via dynamic-require traversal) and `POST
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
thing via the SDK directly:
|
|
165
|
+
inlines runtime sources via dynamic-require traversal) and `POST /api/v1/templates`
|
|
166
|
+
with the bundled source. If you need to drive registration from your own
|
|
167
|
+
build pipeline, you can do the same thing via the SDK directly:
|
|
172
168
|
|
|
173
169
|
```ts
|
|
174
170
|
import { AgentComposeClient, bundleWorkflow } from "@agent-compose/sdk";
|
|
@@ -180,11 +176,10 @@ const client = new AgentComposeClient(
|
|
|
180
176
|
|
|
181
177
|
const bundled = await bundleWorkflow("./my-workflow.ts");
|
|
182
178
|
await client.register({
|
|
183
|
-
name:
|
|
184
|
-
source:
|
|
185
|
-
runtimes:
|
|
186
|
-
schedule:
|
|
187
|
-
factorySlug: "default", // optional — defaults to "default"
|
|
179
|
+
name: "my-workflow",
|
|
180
|
+
source: bundled.source,
|
|
181
|
+
runtimes: bundled.runtimes, // [{ name, source }] — embedded so the runner has them locally
|
|
182
|
+
schedule: "*/30 * * * *", // optional cron
|
|
188
183
|
// snapshot, saveSnapshot, networkPolicy, placeholders — all optional
|
|
189
184
|
});
|
|
190
185
|
```
|
|
@@ -209,7 +204,7 @@ const status = await client.invokeAndWait("my-workflow", { repo: "owner/repo" },
|
|
|
209
204
|
timeoutMs: 5 * 60_000,
|
|
210
205
|
pollIntervalMs: 2000,
|
|
211
206
|
});
|
|
212
|
-
console.log(status.status); // "success" | "failed" | "abandoned"
|
|
207
|
+
console.log(status.status); // "success" | "failed" | "abandoned"
|
|
213
208
|
console.log(status.output); // workflow's return value
|
|
214
209
|
```
|
|
215
210
|
|
|
@@ -218,10 +213,6 @@ async run() { return … } })` resolves to). `setMetadata()` writes to a
|
|
|
218
213
|
separate `metadata` field — useful for "side-channel" facts (PR url, plan
|
|
219
214
|
url) without polluting the structured return.
|
|
220
215
|
|
|
221
|
-
`invoke` and `invokeAndWait` both accept `{ factorySlug, snapshot,
|
|
222
|
-
saveSnapshot, parentRunId }` as the third argument. `factorySlug` defaults
|
|
223
|
-
to `"default"`.
|
|
224
|
-
|
|
225
216
|
### Auto parent/child tracing
|
|
226
217
|
|
|
227
218
|
The SDK detects `process.env.RUN_ID` (set by the runner sandbox on every
|
|
@@ -230,123 +221,25 @@ dispatch) and automatically threads it as `parentRunId` on subsequent
|
|
|
230
221
|
parent/child tree in the dashboard for free. Pass `parentRunId: null`
|
|
231
222
|
to opt out.
|
|
232
223
|
|
|
233
|
-
### Cancelling a run
|
|
234
|
-
|
|
235
|
-
```ts
|
|
236
|
-
await client.cancelRun(runId);
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
Idempotent — cancelling an already-terminal run returns the current state
|
|
240
|
-
without throwing. The server stamps the run as `canceled`, kills any live
|
|
241
|
-
sandboxes, and emits a `run_canceled` event on the stream.
|
|
242
|
-
|
|
243
|
-
### Streaming live logs
|
|
244
|
-
|
|
245
|
-
`streamRunLogs` returns an async generator of `RunEvent`s in real time,
|
|
246
|
-
re-attaching via SSE under the hood. Pass `lastEventId` (the highest
|
|
247
|
-
`seq` you've already processed) to resume after a reconnect.
|
|
248
|
-
|
|
249
|
-
```ts
|
|
250
|
-
for await (const ev of client.streamRunLogs(runId, { lastEventId: 0 })) {
|
|
251
|
-
console.log(ev.event, ev.seq, ev.data);
|
|
252
|
-
if (ev.event === "run_complete" || ev.event === "run_failed" || ev.event === "run_canceled") {
|
|
253
|
-
break;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
`AbortSignal` works too — pass `{ signal }` and call `controller.abort()`
|
|
259
|
-
to tear the stream down from the caller side.
|
|
260
|
-
|
|
261
|
-
---
|
|
262
|
-
|
|
263
|
-
## Factories
|
|
264
|
-
|
|
265
|
-
Factories are project containers within a team. Each factory has its own
|
|
266
|
-
workflow templates, secrets, runs, and (optionally) scoped API keys. New
|
|
267
|
-
projects don't need to think about them — `default` is auto-created per
|
|
268
|
-
team and is what the SDK falls back to when `factorySlug` is omitted.
|
|
269
|
-
|
|
270
|
-
```ts
|
|
271
|
-
// CRUD on factories
|
|
272
|
-
await client.createFactory({ slug: "ci-bots", name: "CI Bots", description: "…" });
|
|
273
|
-
const factories = await client.listFactories();
|
|
274
|
-
const f = await client.getFactory("ci-bots");
|
|
275
|
-
await client.updateFactory("ci-bots", { name: "Continuous-Integration Bots" });
|
|
276
|
-
await client.deleteFactory("ci-bots");
|
|
277
|
-
|
|
278
|
-
// Templates list — flat across factories, or scoped to one
|
|
279
|
-
const all = await client.listTemplates();
|
|
280
|
-
const scoped = await client.listTemplates({ factorySlug: "ci-bots" });
|
|
281
|
-
|
|
282
|
-
// Register / invoke / secret operations all accept factorySlug
|
|
283
|
-
await client.register({ name: "scrape", source, factorySlug: "ci-bots", … });
|
|
284
|
-
await client.invoke("scrape", { url: "…" }, { factorySlug: "ci-bots" });
|
|
285
|
-
await client.setSecret("scrape", "GH_TOKEN", "ghp_…", { factorySlug: "ci-bots" });
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
CLI equivalents: `agentc factory list | create | get | update | delete`,
|
|
289
|
-
plus `--factory <slug>` on every other command.
|
|
290
|
-
|
|
291
224
|
---
|
|
292
225
|
|
|
293
226
|
## Per-workflow secrets
|
|
294
227
|
|
|
295
|
-
Secrets
|
|
296
|
-
They're injected as env vars into the runner sandbox at dispatch
|
|
297
|
-
never persisted in the VM. Values are write-only — the API only
|
|
298
|
-
metadata (key, timestamps).
|
|
228
|
+
Secrets are stored in GCP Secret Manager, one row per `(team, workflow,
|
|
229
|
+
key)`. They're injected as env vars into the runner sandbox at dispatch
|
|
230
|
+
time, never persisted in the VM. Values are write-only — the API only
|
|
231
|
+
returns metadata (key, timestamps).
|
|
299
232
|
|
|
300
233
|
```ts
|
|
301
234
|
await client.setSecret("my-workflow", "ANTHROPIC_API_KEY", process.env.ANTHROPIC_API_KEY!);
|
|
302
235
|
const list = await client.listSecrets("my-workflow"); // [{ key, createdAt, updatedAt }]
|
|
303
236
|
await client.deleteSecret("my-workflow", "STALE_KEY");
|
|
304
|
-
|
|
305
|
-
// Scope to a non-default factory:
|
|
306
|
-
await client.setSecret("scrape", "GH_TOKEN", "ghp_…", { factorySlug: "ci-bots" });
|
|
307
237
|
```
|
|
308
238
|
|
|
309
239
|
Mutations require `admin` scope.
|
|
310
240
|
|
|
311
241
|
---
|
|
312
242
|
|
|
313
|
-
## API keys
|
|
314
|
-
|
|
315
|
-
Mint and list scoped keys programmatically (requires an `admin`-scoped
|
|
316
|
-
caller key). New keys are returned **once**, in the same response as the
|
|
317
|
-
metadata — copy the `ac_…` value immediately.
|
|
318
|
-
|
|
319
|
-
```ts
|
|
320
|
-
const created = await client.createApiKey({
|
|
321
|
-
name: "ci-dispatcher",
|
|
322
|
-
scopes: ["read", "invoke"],
|
|
323
|
-
expiresAt: new Date(Date.now() + 30 * 86_400_000).toISOString(), // 30 days
|
|
324
|
-
// factorySlug: "ci-bots" // optional — scopes the key to a single factory
|
|
325
|
-
});
|
|
326
|
-
console.log(created.key); // "ac_…" — the only time you'll see this
|
|
327
|
-
|
|
328
|
-
const all = await client.listApiKeys();
|
|
329
|
-
```
|
|
330
|
-
|
|
331
|
-
CLI equivalent: `agentc keys create <name> --scopes read,invoke
|
|
332
|
-
--expires-in 30d`.
|
|
333
|
-
|
|
334
|
-
---
|
|
335
|
-
|
|
336
|
-
## Usage
|
|
337
|
-
|
|
338
|
-
```ts
|
|
339
|
-
const usage = await client.getUsage(
|
|
340
|
-
new Date(Date.now() - 30 * 86_400_000),
|
|
341
|
-
new Date(),
|
|
342
|
-
);
|
|
343
|
-
// usage.rows: [{ day, runs, sandbox_seconds, … }]
|
|
344
|
-
```
|
|
345
|
-
|
|
346
|
-
CLI equivalent: `agentc usage`.
|
|
347
|
-
|
|
348
|
-
---
|
|
349
|
-
|
|
350
243
|
## Snapshots (replay-friendly sandboxes)
|
|
351
244
|
|
|
352
245
|
Long-running workflows can capture the runner sandbox as a Vercel snapshot
|
|
@@ -402,24 +295,17 @@ programmatic / server-to-server callers.
|
|
|
402
295
|
| `defineRuntime` | Wrap an agent execution provider as an `AgentRuntime` |
|
|
403
296
|
| `defineSandboxEnvironment` | Sugar for declaring a workflow whose primary purpose is to build a snapshot for others to boot from |
|
|
404
297
|
| `runAgent` / `agentLoop` | Embed an LLM loop inside a workflow |
|
|
298
|
+
| `claudeRuntime` / `createClaudeRuntime` / `ClaudeRunner` | Built-in Claude Code runtime + factory |
|
|
299
|
+
| `AgentComposeClient` | HTTP client (register, invoke, status, snapshots, secrets) |
|
|
405
300
|
| `runWorkflow` | Local engine for running a workflow in-process (test harness) |
|
|
406
301
|
| `bundleWorkflow` | Resolve + inline a workflow's runtime sources for registration |
|
|
407
|
-
| `claudeRuntime` / `createClaudeRuntime` / `ClaudeRunner` | Built-in Claude Code runtime + factory |
|
|
408
|
-
| `AgentComposeClient` | HTTP client — register, invoke, cancel, stream logs, factories, snapshots, secrets, API keys, usage |
|
|
409
|
-
| `AgentComposeError` | Thrown by every non-2xx HTTP response |
|
|
410
302
|
| `parseAgentStatus` / `parseAgentResponse` / `AgentStatusSchema` / `AgentMessageSchema` | Protocol parsers |
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
`
|
|
416
|
-
`
|
|
417
|
-
variants), `AgentStatus`, `RunStatus`, `RegisterResult`, `RunEvent`,
|
|
418
|
-
`FactoryRow`, `SnapshotListEntry`, `ApiKey`, `ApiKeyCreated`,
|
|
419
|
-
`UsageRollupRow`, `UsageResponse`, `CancelRunResponse`, `AgentLoopResult`,
|
|
420
|
-
`RunAgentOpts`, `SandboxProvider`, `DesktopSandboxProvider`,
|
|
421
|
-
`SandboxNetworkPolicy`, `SandboxCreateOpts`, `OwnedSandbox`,
|
|
422
|
-
`BundledWorkflow`.
|
|
303
|
+
|
|
304
|
+
Type exports: `WorkflowFn`, `WorkflowCtx`, `WorkflowDefinition`, `AgentBudget`,
|
|
305
|
+
`AgentRuntime`, `RuntimeOptions`, `ModelExecutionContract`,
|
|
306
|
+
`AgentMessage` (and its variants), `AgentStatus`, `RunStatus`,
|
|
307
|
+
`RegisterResult`, `RunEvent`, `AgentLoopResult`, `RunAgentOpts`,
|
|
308
|
+
`SandboxProvider`, `SandboxNetworkPolicy`, `BundledWorkflow`.
|
|
423
309
|
|
|
424
310
|
For the canonical signatures, follow your IDE's go-to-definition into
|
|
425
311
|
`@agent-compose/sdk` — `sdk/src/index.ts` is the public surface and the
|
package/dist/client.d.ts
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* register`) or build sources yourself and pass them directly.
|
|
12
12
|
*/
|
|
13
13
|
import type { RunEvent } from "./types/events.js";
|
|
14
|
+
import type { SandboxNetworkPolicy } from "./sandbox.js";
|
|
14
15
|
export interface RegisterResult {
|
|
15
16
|
id: string;
|
|
16
17
|
name: string;
|
|
@@ -136,6 +137,8 @@ export declare class AgentComposeClient {
|
|
|
136
137
|
saveSnapshot?: boolean;
|
|
137
138
|
parentRunId?: string | null;
|
|
138
139
|
factorySlug?: string;
|
|
140
|
+
networkPolicy?: SandboxNetworkPolicy;
|
|
141
|
+
placeholders?: Record<string, string>;
|
|
139
142
|
}): Promise<{
|
|
140
143
|
id: string;
|
|
141
144
|
}>;
|
|
@@ -151,6 +154,8 @@ export declare class AgentComposeClient {
|
|
|
151
154
|
saveSnapshot?: boolean;
|
|
152
155
|
parentRunId?: string | null;
|
|
153
156
|
factorySlug?: string;
|
|
157
|
+
networkPolicy?: SandboxNetworkPolicy;
|
|
158
|
+
placeholders?: Record<string, string>;
|
|
154
159
|
timeoutMs?: number;
|
|
155
160
|
pollIntervalMs?: number;
|
|
156
161
|
}): Promise<RunStatus>;
|
package/dist/index.js
CHANGED
|
@@ -455,7 +455,9 @@ class AgentComposeClient {
|
|
|
455
455
|
input,
|
|
456
456
|
...opts?.snapshot !== undefined ? { snapshot: opts.snapshot } : {},
|
|
457
457
|
...opts?.saveSnapshot !== undefined ? { saveSnapshot: opts.saveSnapshot } : {},
|
|
458
|
-
...parentRunId ? { parentRunId } : {}
|
|
458
|
+
...parentRunId ? { parentRunId } : {},
|
|
459
|
+
...opts?.networkPolicy !== undefined ? { networkPolicy: opts.networkPolicy } : {},
|
|
460
|
+
...opts?.placeholders !== undefined ? { placeholders: opts.placeholders } : {}
|
|
459
461
|
}
|
|
460
462
|
});
|
|
461
463
|
}
|
|
@@ -466,7 +468,9 @@ class AgentComposeClient {
|
|
|
466
468
|
...opts?.snapshot !== undefined ? { snapshot: opts.snapshot } : {},
|
|
467
469
|
...opts?.saveSnapshot !== undefined ? { saveSnapshot: opts.saveSnapshot } : {},
|
|
468
470
|
...opts?.parentRunId !== undefined ? { parentRunId: opts.parentRunId } : {},
|
|
469
|
-
...opts?.factorySlug !== undefined ? { factorySlug: opts.factorySlug } : {}
|
|
471
|
+
...opts?.factorySlug !== undefined ? { factorySlug: opts.factorySlug } : {},
|
|
472
|
+
...opts?.networkPolicy !== undefined ? { networkPolicy: opts.networkPolicy } : {},
|
|
473
|
+
...opts?.placeholders !== undefined ? { placeholders: opts.placeholders } : {}
|
|
470
474
|
});
|
|
471
475
|
const deadline = Date.now() + timeoutMs;
|
|
472
476
|
while (Date.now() < deadline) {
|
|
@@ -455,7 +455,9 @@ class AgentComposeClient {
|
|
|
455
455
|
input,
|
|
456
456
|
...opts?.snapshot !== undefined ? { snapshot: opts.snapshot } : {},
|
|
457
457
|
...opts?.saveSnapshot !== undefined ? { saveSnapshot: opts.saveSnapshot } : {},
|
|
458
|
-
...parentRunId ? { parentRunId } : {}
|
|
458
|
+
...parentRunId ? { parentRunId } : {},
|
|
459
|
+
...opts?.networkPolicy !== undefined ? { networkPolicy: opts.networkPolicy } : {},
|
|
460
|
+
...opts?.placeholders !== undefined ? { placeholders: opts.placeholders } : {}
|
|
459
461
|
}
|
|
460
462
|
});
|
|
461
463
|
}
|
|
@@ -466,7 +468,9 @@ class AgentComposeClient {
|
|
|
466
468
|
...opts?.snapshot !== undefined ? { snapshot: opts.snapshot } : {},
|
|
467
469
|
...opts?.saveSnapshot !== undefined ? { saveSnapshot: opts.saveSnapshot } : {},
|
|
468
470
|
...opts?.parentRunId !== undefined ? { parentRunId: opts.parentRunId } : {},
|
|
469
|
-
...opts?.factorySlug !== undefined ? { factorySlug: opts.factorySlug } : {}
|
|
471
|
+
...opts?.factorySlug !== undefined ? { factorySlug: opts.factorySlug } : {},
|
|
472
|
+
...opts?.networkPolicy !== undefined ? { networkPolicy: opts.networkPolicy } : {},
|
|
473
|
+
...opts?.placeholders !== undefined ? { placeholders: opts.placeholders } : {}
|
|
470
474
|
});
|
|
471
475
|
const deadline = Date.now() + timeoutMs;
|
|
472
476
|
while (Date.now() < deadline) {
|
package/package.json
CHANGED