@ agent- 组成/ sdk
类型脚本 SDK 代理编程用于:
- 作者工作流程 在孤立的沙盒内运行代理环
- 使用或定义运行时间 驱动编码代理(Claude Code, Codex, Amp, OpenCode, Cursor, Droid,...) 作为代理循环
- 登记、援引、观察和注销 hTTP API 上的工作流程(
AgentComposeClient(中文(简体) ) - 管理工厂、秘密、 API 密钥和快照 方案
等级:a 团队 拥有一个或多个 工厂每个工厂都拥有工作流程模板、秘密、运行和驱动器。 工作流量为每个版本 (factory, name, version)每个团队都有 default 工厂,和每个电话 需要 factorySlug 归去来.
安装
npm install @agent-compose/sdk zod # zod ^4 is a peer dependency
AgentComposeClient 运行在20号节点或邦。 连接工作流程
登记bundleWorkflow, (中文(简体) ), agentc register)需要Bun(英语:Bun).
正在编写工作流程
工作流程是一组独立的步骤的输入链:
defineWorkflow({ id, input, output }).step(defineStep(...)).build()。 。 。 .
每个步骤都是一个持久的重放检查点:引擎记录每个
步骤的验证输出,所以在最后一个步骤之后重试或恢复拾取
完成步骤,而不是重新运行整个工作流程.
// my-workflow.ts
import { defineWorkflow, defineStep, agent, claudeRuntime } from "@agent-compose/sdk";
import { z } from "zod";
import PROMPT from "./prompt.md" with { type: "text" };
const Input = z.object({ repo: z.string() });
const Output = z.object({ ok: z.boolean(), summary: z.string().optional() });
const review = defineStep({
name: "review",
input: Input,
output: Output,
run: async (ctx) => {
const result = await agent({
sandbox: ctx.sandbox!, // the run's own VM
runtime: claudeRuntime,
prompt: `${PROMPT}\n\nRepository: ${ctx.input.repo}`,
tools: ["Bash", "Read", "Edit", "Write", "Grep", "Glob"],
budget: { turnsPerIteration: 40, maxIterations: 8 },
});
await ctx.setMetadata({ summary: result.lastStatus?.summary });
return { ok: result.lastStatus?.exit_signal ?? false, summary: result.lastStatus?.summary };
},
});
export default defineWorkflow({
id: "my-workflow",
input: Input,
output: Output,
// Optional: outbound network rules the runner sandbox enforces. Both
// providers enforce the host list and inject the headers; only Vercel
// also enforces per-host method/path rules. `$VAR` placeholders resolve
// from the workflow's secrets at dispatch, and the value never enters
// the sandbox.
networkPolicy: {
allow: {
"*": [],
"api.anthropic.com": [{ transform: [{ headers: { "x-api-key": "$ANTHROPIC_API_KEY" } }] }],
},
},
})
.step(review)
.build();
建造者在编译时的链检查,每个步骤 input
与上一个步骤相匹配的策略 output,以及 .build() 核实
最后的步骤 output 与工作流程中的 Zod 实例相同
已声明 output。 。 。 . networkPolicy, (中文(简体) ), placeholders, (中文(简体) ), snapshots, (中文(简体) ),
resources 而其他定义字段成为元数据捆绑器
登记时接听.
运行形式( E)defineWorkflow({ run(ctx, sandbox) { … } }))已经
删除 : defineWorkflow 当它看到一个 run 键。 步骤形式是
唯一的形状, 和贫困只在那里工作.
一步能怎样 ctx
每个步骤 run(ctx) 收到一个 StepContext数字 :
interface StepContext<TInput> {
input: TInput; // validated against the step's `input` schema
stepName: string;
run: { id: string };
sandbox?: SandboxProvider; // the run's VM: pass to `agent({ sandbox: ctx.sandbox })`
abortSignal: AbortSignal; // fires when the run is canceled
requestContext: RequestContext; // tenant identity, for processors
agentEvents: AgentEventSink; // `agent({ events: ctx.agentEvents })`
setMetadata(data: Record<string, unknown>): Promise<void>;
step<T>(name: string, fn: () => Promise<T>): Promise<T>; // durable named sub-step
pause<T>(req: PauseRequest<T>): Promise<T>; // wait for a human, durably
sleep(durationMs: number): Promise<void>;
waitForEvent<T>(req: WaitForEventRequest<T>): Promise<T>;
requestDecision(req: DecisionRequest): Promise<{ decision: string }>;
invokeChild(name, input?, opts?): Promise<RunStatus>; // run another workflow
}
ctx.step("phase-name", () => …) 覆盖一个相 在内部 步骤
运行时间表 。 它会记下结果( 暂停- 恢复返回)
而不是重新运行)和发音 workflow_substep_started 编号 :
workflow_substep_completed 编号 : workflow_substep_failed 生命周期
持续时间。 用于设置、外部 API 调用或
任何您想要在运行页面中可见的内容 .
这个 agent 循环
agent({
sandbox, // ctx.sandbox, the run's VM
runtime, // claudeRuntime, codexRuntime, …, or your own via defineRuntime
prompt, // raw markdown; a `--- frontmatter ---` block is stripped
tools?, // model tool allowlist (defaults inside agentLoop; [] disables tools)
budget?, // { turnsPerIteration, maxIterations }; omitted: no turn cap, up to 3 iterations
workingDir?, // every shell command runs here (default: the run's dir on the drive)
responseSchema?, // zod; when set, the loop demands a `<response>` block on exit
mode?, // "auto" (default) or "hitl" (a human can steer it mid-run)
events?, // lifecycle sink, e.g. ctx.agentEvents
onAgentEvent?, // per-message hook
onIteration?, // per-iteration hook with the parsed `<status>` block
processors?, // pre/post pipeline around the loop
})
// → AgentLoopResult { agentId, label, sessionId, lastStatus, iterations, response? }
模型释放出被标记的 XML 块(<status>, (中文(简体) ), <response>循环
解说. lastStatus 是最后一个 <status> 块 : { summary, completed, blockers, exit_signal }。见 sdk/src/agent/protocol-suffix.md 联 合 国
每个提示都附有指令.
运行时间
运行时间将代理器的执行模式(通常是编码CLI)包起来,所以
agent 可以开车 SDK飞船是内置的,你只需要定制的
对于一个供养者,它不覆盖.
内建运行时间
每一个都作为 现成的默认和 create… 需要配置的工厂 :
| 默认 | 工厂 | 驱动器 |
|---|---|---|
claudeRuntime | createClaudeRuntime | 克劳德通过克劳德特工SDK, 从跑道过程 |
claudeCodeRuntime | createClaudeCodeRuntime | 克劳德代码 CLI |
codexRuntime | createCodexRuntime | 代码 CLI |
ampRuntime | createAmpRuntime | 倾角 |
opencodeRuntime | createOpencodeRuntime | 打开代码 |
cursorRuntime | createCursorRuntime | 光标 cursor-agent 国 际 |
droidRuntime | createDroidRuntime | 工厂 droid 国 际 |
createVercelRuntime | 通过Vercel AI SDK的模型 |
openAIDesktopRuntime 不在软件包根中: 它拉入 sharp 页:1
截图,其原生绑定不能交叉编译. 从这里导入
它的子路径,当你想要它的时候:
import openAIDesktopRuntime from "@agent-compose/sdk/runtimes/openai-desktop";
自定义运行时间
import { defineRuntime, type AgentMessage } from "@agent-compose/sdk";
export default defineRuntime({
create: (sandbox, opts) => ({
// Return a ModelExecutionContract; see sdk/src/types/runtime.ts
async *sendMessage({ prompt, sessionId, signal }): AsyncGenerator<AgentMessage> {
// Run the model against `sandbox` and yield AgentMessage chunks the loop parses.
},
}),
});
AgentRuntime 实值 { create(sandbox, RuntimeOptions) → ModelExecutionContract }。 。 。 .
有一个 没有 provider 字段 上面:运行时间与
作者时间的工作流程( 您将其传递给 agent),未被该
服务器.
登记工作流程
这个 agentc 一步内将CLI捆绑并注册:
agentc register my-workflow.ts -n my-workflow
盖子下面,打电话 bundleWorkflow(workflowPath),该组合
来源为 Bun.build,检查默认导出是
defineWorkflow(...) 工作流程,并返回源头并显示
服务器对照源散列进行验证。 然后它贴到
/api/v1/factories/<slug>/templates从自己的建筑注册
管道(在Bun下):
import { AgentComposeClient, bundleWorkflow } from "@agent-compose/sdk";
const client = new AgentComposeClient({
baseUrl: "https://your-server.example.com", // default: AGENT_COMPOSE_URL, else https://api.agentcompose.ai
apiKey: process.env.AGENT_COMPOSE_API_KEY!, // default: AGENT_COMPOSE_API_KEY
});
const bundled = await bundleWorkflow("./my-workflow.ts");
await client.register({
name: "my-workflow",
source: bundled.source,
manifest: bundled.manifest, // required
workflowPlan: bundled.workflowPlan,
schedule: "*/30 * * * *", // optional cron (UTC)
factorySlug: "default", // optional, defaults to "default"
// pass bundled.networkPolicy, placeholders, snapshots, resources, … to keep
// what the workflow declares
});
register() 需求 manage 在呼叫器的钥匙.
引用工作流程
两个花香:
// Fire-and-forget: returns the run id at once.
const { id } = await client.invoke("my-workflow", {
repo: "owner/repo",
});
// Block until the run settles (default 30 min timeout, 1 s poll).
const status = await client.invokeAndWait("my-workflow", { repo: "owner/repo" }, {
timeoutMs: 5 * 60_000,
pollIntervalMs: 2000,
});
console.log(status.status); // "success" | "failed" | "abandoned" | "canceled"
console.log(status.output); // the workflow's return value
output 是最后一个步骤的返回值,相对于
工作流程已宣布 output 计划. setMetadata() 写给 a
单独 metadata 字段,用于侧道事实(一个 PR URL,一个计划 URL)
这不属于结构化的返回.
invoke 财务报告和审定财务报表 invokeAndWait 带 { factorySlug, snapshots, networkPolicy, placeholders, size, parentRunId, idempotencyKey } 作为
第三辩相. 援引 snapshots 按字段合并字段
注册的默认值. factorySlug 默认为 "default"。 。 。 .
自动父/子跟踪
SDK读取 process.env.RUN_ID (由跑道沙盒设置)
并把它编成 parentRunId 打开 invoke() 打电话 工作流量
风扇到其他工作流程 在仪表板上取出一棵母子树
免费的。 过 parentRunId: null 选择退出.
取消运行
await client.cancelRun(runId);
同上:取消已经结束的运行返回当前状态
没有扔。 服务器标记运行 canceled,发出a
run_canceled 并杀死它的沙盒.
流动现场活动
streamRunLogs 返回 RunEvent在实时,
超过SSE。 过 lastEventId (最高 seq 您已处理)
重新连接后恢复.
for await (const ev of client.streamRunLogs(runId, { lastEventId: 0 })) {
console.log(ev.event, ev.seq);
if (ev.event === "run_complete" || ev.event === "run_failed" || ev.event === "run_canceled") {
break;
}
}
AbortSignal 工作时间:通过 { signal } 打电话 controller.abort()
关闭从呼叫方的溪流.
工厂
工厂是团队内部的容器。 每一个都有自己的工作流程
模板,秘密,运行和驱动,API密钥可以限制在一个.
新项目不需要考虑: default 存在于每个
团队和SDK在 factorySlug 省略.
// CRUD on factories
await client.createFactory({ slug: "ci-bots", name: "CI Bots", description: "…" });
const factories = await client.listFactories();
const f = await client.getFactory("ci-bots");
await client.updateFactory("ci-bots", { name: "Continuous-Integration Bots" });
await client.deleteFactory("ci-bots");
// Templates: across factories, or scoped to one
const all = await client.listTemplates();
const scoped = await client.listTemplates({ factorySlug: "ci-bots" });
// Register, invoke and secret calls all accept factorySlug
await client.invoke("scrape", { url: "…" }, { factorySlug: "ci-bots" });
await client.setSecret("scrape", "GH_TOKEN", "ghp_…", { factorySlug: "ci-bots" });
CLI 等价: agentc factory list | create | use | delete | show, (中文(简体) ),
加号 --factory <slug> 在大多数其它命令上.
秘诀
秘密值存在于 GCP 秘密管理器中, 并且只写: 只写 API
返回元数据(键、时间戳)。 跑步会看到工厂的秘密
它的工作流程本身, 工作流程的胜利在冲突。 一个秘密
工作流程 networkPolicy 参考文献 $VAR 被中介: 平台
添加到网络层和沙盒内置的匹配请求中
只有占位符,或者什么都没有。 任何其它秘密 是一个平地入地
跑跑跑跑跑跑跑跑跑跑跑跑跑跑跑跑跑跑跑跑跑跑跑跑跑跑跑跑跑.
// Per-workflow
await client.setSecret("my-workflow", "ANTHROPIC_API_KEY", process.env.ANTHROPIC_API_KEY!);
const list = await client.listSecrets("my-workflow"); // [{ key, createdAt, updatedAt }]
await client.deleteSecret("my-workflow", "STALE_KEY");
// Factory-wide (every workflow in the factory inherits them)
await client.setFactorySecret("SLACK_WEBHOOK_URL", "https://hooks.slack.com/…", { factorySlug: "ci-bots" });
工厂的秘密需要 manage 范围。 改变工作流程的秘密
需求 invoke 加上写入该工作流程.
API 密钥
薄荷和按程序列出密钥( 呼叫者的关键需求) admin) (中文(简体) ). 一个新的
返回密钥 一次在与其元数据相同的回复中:
ac_… 一次值.
const created = await client.createApiKey({
name: "ci-dispatcher",
scopes: ["read", "invoke"], // omitted = ["read"]
expiresAt: new Date(Date.now() + 30 * 86_400_000).toISOString(), // 30 days
// factorySlug: "ci-bots" // optional: limit the key to one factory
});
console.log(created.key); // "ac_…", the only time you will see it
const page = await client.listApiKeys();
范围: read, (中文(简体) ), invoke (发送运行), manage (经营工厂:
模板、秘密、重置)和 admin (成员,角色,钥匙). 键可以
只有薄荷瞄准镜 持有者有。 等效CLI :
agentc keys create <name> --scopes read,invoke --expires-in 30d。 。 。 .
使用量
const usage = await client.getUsage(
new Date(Date.now() - 30 * 86_400_000),
new Date(),
);
// usage.data: [{ eventType, unit, total, tags }]
等效CLI : agentc usage。 。 。 .
快照(反放友好沙盒)
一个工作流程可以捕捉它的跑步沙盒,作为成功的快照
(单位:千美元)snapshots: { saveLatest: true }),位于Vercel或E2B上. 其他运行启动
带它 snapshots.bootFrom 装入同一制备的 VM( 安装设备, repo)
克隆)而不是重复设置.
// Capture per-invocation:
await client.invoke("my-workflow", input, { snapshots: { saveLatest: true } });
// Boot from a captured snapshot (take the id from `agentc snapshot list`
// or the dashboard):
await client.invoke("my-workflow", input, {
snapshots: { bootFrom: { snapshotId: "snap_…" } },
});
// Set a default in the definition:
defineWorkflow({ id, input, output, snapshots: { saveLatest: true } }).step(…).build();
// Keep every step's snapshot (not just the latest):
defineWorkflow({ id, input, output, snapshots: { saveLatest: true, retainSteps: true } }).step(…).build();
// Browse and clean up:
const page = await client.listSnapshotsPage({ workflow: "my-workflow", limit: 50 });
const snaps = page.data;
await client.deleteRunSnapshot(snaps[0].runId, snaps[0].snapshotId);
CLI 等价: agentc snapshot list, (中文(简体) ), agentc snapshot show <run-id>, (中文(简体) ),
agentc snapshot delete <run-id> [snapshot-id]。 。 。 .
按字段合并字段
这个 snapshots 对象在 invoke() 实值 合并 使用注册模板 snapshots 配置: 您可以覆盖 bootFrom 一个人不输 saveLatest或者换个角度.
认证
SDK发送了 Bearer API 密钥 (ac_…) (中文(简体) ). 仪表板上的薄荷一:标志
在,打开空间的设置, 全权证书 —— API 密钥。一个新的密钥得到
read 默认; 勾选 invoke 发送运行, manage 注册
工作流程或设置秘密,以及 admin 仅用于薄荷键或管理成员.
const client = new AgentComposeClient({
baseUrl: process.env.AGENT_COMPOSE_URL,
apiKey: process.env.AGENT_COMPOSE_API_KEY,
});
两个选项都回落到那些 Env vars (和 URL 到
https://api.agentcompose.ai),这样 new AgentComposeClient() 在一个
运行沙盒。 仪表板本身使用会话饼干;SDK用于
程序及服务器对服务器的呼叫器.
公共出口:快速参考
| 导出 | 什麽 |
|---|---|
defineWorkflow | 已键入的步工作流程构建器 : defineWorkflow({ id, input, output }).step(...).build() |
defineStep | 宣布一个输入的工作流程步骤({ name, input, output, run }(中文(简体) ) |
defineRuntime | 将代理执行提供者包装为 AgentRuntime |
defineSandboxEnvironment | 宣布一个工作流程,其目的是为他人绘制一个快照以启动 |
agent 编号 : agentLoop | 在工作流程中嵌入代理循环 |
runWorkflow | 运行流程中工作流程的本地引擎( 测试带) |
bundleWorkflow | 捆绑和验证登记工作流程(Bun) |
claudeRuntime, (中文(简体) ), codexRuntime,以及他们的 create… 工厂 | 内建运行时间(上表) |
AgentComposeClient | HTTP 客户端: 注册、 引用、 取消、 流、 工厂、 快照、 秘密、 API 密钥、 使用、 对话、 会话、 项目 |
AgentComposeError | 由每个非-2xx HTTP 响应抛出 |
parseAgentStatus 编号 : parseAgentResponse 编号 : AgentStatusSchema 编号 : AgentMessageSchema | 协议解析器 |
parseSseStream | 通用 SSE 解码器(由 streamRunLogs(中文(简体) ) |
createSandbox 编号 : reconnectSandbox 编号 : killAllSandboxes 编号 : killSandboxById 编号 : getSandboxQuotas 编号 : listOwnedSandboxes 编号 : deleteSandboxSnapshot | 提供沙盒的助手(Vercel和E2B) |
出口类型包括: Workflow, (中文(简体) ), Step, (中文(简体) ), StepContext, (中文(简体) ), WorkflowBuilder, (中文(简体) ),
WorkflowHooks, (中文(简体) ), AgentBudget, (中文(简体) ), AgentRuntime, (中文(简体) ), RuntimeOptions, (中文(简体) ),
ModelExecutionContract, (中文(简体) ), McpServerConfig, (中文(简体) ), AgentMessage 联合国
变体),, AgentStatus, (中文(简体) ), RunStatus, (中文(简体) ), RegisterResult, (中文(简体) ), RunEvent, (中文(简体) ),
FactoryRow, (中文(简体) ), SnapshotListEntry, (中文(简体) ), ApiKey, (中文(简体) ), ApiKeyCreated, (中文(简体) ),
UsageRollupRow, (中文(简体) ), UsageResponse, (中文(简体) ), CancelRunResponse, (中文(简体) ), AgentLoopResult, (中文(简体) ),
AgentOpts, (中文(简体) ), SandboxProvider, (中文(简体) ), DesktopSandboxProvider, (中文(简体) ),
SandboxNetworkPolicy, (中文(简体) ), SandboxCreateOpts, (中文(简体) ), OwnedSandbox 财务报告和审定财务报表
BundledWorkflow。 。 。 .
确切签名请遵循您的 IDE 定义
@agent-compose/sdk数字 : sdk/src/index.ts 是公众的表面,和
文件会从带满字串中再导出.
错误
每个非-2xx HTTP 响应抛出 AgentComposeError它携带 status
(单位:千美元) message 取自服务器的 { error: string } 身体何时
显示( 包含 HTTP 状态文本), 外加 code 财务报告和审定财务报表 capability 一个
拒绝批准和 retryAfterMs 当服务器发送时 Retry-After数字 :
import { AgentComposeError } from "@agent-compose/sdk";
try {
await client.invoke("missing-workflow");
} catch (err) {
if (err instanceof AgentComposeError && err.status === 404) {
// template not registered
}
}
invokeAndWait 掷出 AgentComposeError(504, …) 超时.