@chaitin-ai/agent-compose-runtime-sdk

中文文档
0.14.0发布于 2026/11/06LGPL-3.0-onlyTypeScriptESM + CJS构建来源已验证近 30 天下载 4868

Node.js SDK for scripts running inside an agent-compose guest runtime.

原始使用文档
文档目录17 节
  1. Installation
  2. Quick Start
  3. Runtime Paths
  4. API
  5. runtime.exec(command, args?, options?)
  6. runtime.shell(script, options?)
  7. runtime.agent(prompt, options?)
  8. runtime.workflow(script, options?) and runtime.workflowFile…
  9. runtime.llm(prompt, options?)
  10. runtime.env.get(name)
  11. runtime.env.require(name)
  12. runtime.env.all()
  13. runtime.log(message, payload?)
  14. runtime.report.writeMarkdown(name, content, options?)
  15. runtime.ssh.prepareConfig(options)
  16. OctoBus capabilities in custom scripts
  17. Errors

@chaitin-ai/agent-compose-runtime-sdk

Node.js SDK for scripts running inside an agent-compose guest runtime.

The package provides both named exports and a default runtime object:

const { runtime } = require("@chaitin-ai/agent-compose-runtime-sdk");
import runtime, { exec, shell, agent, llm, workflowFile, ssh } from "@chaitin-ai/agent-compose-runtime-sdk";

Installation

Install from the public npm registry:

npm install @chaitin-ai/agent-compose-runtime-sdk

Guest images can also install the SDK from an offline tarball:

npm install --offline /opt/agent-compose/npm/agent-compose-runtime-sdk.tgz

Quick Start

const { runtime } = require("@chaitin-ai/agent-compose-runtime-sdk");

async function main() {
  const result = await runtime.shell("echo hello");
  runtime.log("command completed", { success: result.success });
}

main().catch((error) => {
  console.error(error);
  process.exit(1);
});

Runtime Paths

runtime.paths exposes runtime paths resolved from environment variables:

FieldEnvironment variableDefault
workspaceWORKSPACE/workspace
stateRootSTATE_ROOT/data/state
runtimeRootRUNTIME_ROOT/data/runtime
homeHOME/root

workspace, stateRoot, and runtimeRoot also accept the legacy aliases AGENT_COMPOSE_WORKSPACE, AGENT_COMPOSE_STATE_ROOT, and AGENT_COMPOSE_RUNTIME_ROOT when the primary variable is unset. home has no alias.

API

runtime.exec(command, args?, options?)

Runs a command directly without shell expansion.

const result = await runtime.exec("node", ["-e", "console.log(process.cwd())"]);

Options:

OptionDescription
cwdWorking directory. Defaults to runtime.paths.workspace.
envKey-value pairs appended to the child process environment.
timeoutMsTerminates the command after this number of milliseconds.
maxOutputBytesMaximum captured bytes for stdout, stderr, and combined output. Defaults to 1 MiB.
rejectOnFailureThrows CommandError when the process exits with a non-zero status code.
streamOutputStreams child process stdout and stderr to the current process. Defaults to true.
forwardOutputDeprecated. Use streamOutput instead.

Return value:

{
  stdout: string;
  stderr: string;
  output: string;
  exitCode: number;
  success: boolean;
  stdoutTruncated: boolean;
  stderrTruncated: boolean;
  outputTruncated: boolean;
}

By default, runtime.exec() streams command logs so agent-compose can display live output while the script is still running. Pass { streamOutput: false } for quiet execution.

runtime.shell(script, options?)

Runs a shell script through bash -lc.

const result = await runtime.shell("echo shell:$AGENT_COMPOSE_TEST_VALUE", {
  env: { AGENT_COMPOSE_TEST_VALUE: "works" },
});

Options and return values are the same as runtime.exec(). Use runtime.shell() when you need variable expansion, pipes, redirects, or compound commands.

runtime.agent(prompt, options?)

Calls the agent bridge in the agent-compose runtime.

const result = await runtime.agent("Inspect the workspace and summarize the project.");

Pass outputSchema when you need structured JSON. A Zod schema is recommended: the SDK converts it to JSON Schema for the runtime agent bridge and validates the parsed json value with the same Zod schema.

import { z } from "zod";

const RiskSummary = z.object({
  summary: z.string(),
  risk: z.enum(["low", "high"]),
});

const result = await runtime.agent("Inspect the workspace and return risk.", {
  provider: "codex",
  outputSchema: RiskSummary,
});

console.log(result.json.summary);

When a Zod schema is passed, the type of result.json is inferred from the schema:

import { z } from "zod";

const RiskSummary = z.object({
  summary: z.string(),
  risk: z.enum(["low", "high"]),
});

const result = await runtime.agent("Inspect the workspace and return risk.", {
  provider: "claude",
  outputSchema: RiskSummary,
});

if (result.json) {
  console.log(result.json.risk);
}

You can also pass a plain JSON Schema object and declare the return type with a generic:

type RiskSummary = {
  summary: string;
  risk: "low" | "high";
};

const result = await runtime.agent<RiskSummary>("Inspect the workspace and return risk.", {
  outputSchema: {
    type: "object",
    additionalProperties: false,
    properties: {
      summary: { type: "string" },
      risk: { type: "string", enum: ["low", "high"] },
    },
    required: ["summary", "risk"],
  },
});

Options:

OptionDescription
providerAgent provider. One of codex, claude, opencode, pi, or dsh. Defaults to codex.
stateRootAgent state root directory. Defaults to runtime.paths.stateRoot.
workspaceWorkspace path. Defaults to runtime.paths.workspace.
homeHome directory. Defaults to runtime.paths.home.
timeoutMsTerminates the agent bridge after this number of milliseconds.
outputSchemaZod schema or JSON Schema object. When set, the returned json field is parsed from finalText. Codex and Claude support this; OpenCode, Pi, and DSH currently throw an unsupported error when schema-based output is unavailable.

Return value:

{
  provider: string;
  threadId: string;
  stopReason: string;
  finalText: string;
  json: unknown | null;
  transcript: string;
  stderr: string;
}

finalText always preserves the raw text returned by the agent bridge. When outputSchema is set, finalText must be a JSON string. The SDK runs JSON.parse(finalText) and stores the result in json. If outputSchema is a Zod schema, the SDK also validates the parsed result with that schema. Without outputSchema, json is null.

Error behavior:

ScenarioBehavior
outputSchema is not a plain JSON objectruntime.agent() throws before calling the runtime.
A Zod schema cannot be converted to JSON Schemaruntime.agent() throws before calling the runtime.
The provider does not support schema-based outputThe runtime throws a provider-specific error. Codex and Claude support schema-based output; the OpenCode, Pi, and DSH runners report unsupported output.
The provider returns finalText that is not valid JSONruntime.agent() throws a parse error.
The provider returns JSON that does not satisfy the Zod schemaruntime.agent() throws a validation error.

runtime.workflow(script, options?) and runtime.workflowFile(path, options?)

Runs a dynamic workflow through the guest runtime CLI. workflow() accepts source text and manages a temporary script file; workflowFile() passes the caller-owned file directly.

const result = await runtime.workflowFile("workflows/inspect.js", {
  args: { area: "api" },
  provider: "codex",
  concurrency: 4,
  onUpdate(event) {
    if (event.type === "phase") {
      console.error(`phase: ${event.title}`)
    }
  },
})

console.log(result.result)

Options include args, provider, model, concurrency, tokenBudget, runId, resumeRunId, stateRoot, workspace, home, timeoutMs, and onUpdate. Events are decoded incrementally from stderr, so onUpdate runs while the workflow is active. Non-event stderr is returned in result.stderr.

Failed or aborted workflow payloads throw RuntimeWorkflowError; its outcome field retains the run ID, agents, events, and stderr. Invalid CLI protocol throws RuntimeWorkflowProtocolError. SDK timeout throws RuntimeWorkflowTimeoutError and retains partial events and stderr.

runtime.llm(prompt, options?)

Calls the agent-compose LLM service. The daemon selects the HTTP protocol via LLM_API_PROTOCOL (responses by default, or chat_completions for OpenAI-compatible Chat Completions backends). With outputSchema, chat_completions uses prompt guidance and response_format: json_object, not Responses API strict JSON Schema.

const result = await runtime.llm("Summarize the workspace risk.", {
  model: "gpt-5.4",
});

console.log(result.text);

runtime.llm() supports the same outputSchema mechanism as runtime.agent(). A Zod schema is recommended: the SDK converts it to JSON Schema for the LLM service and validates the parsed json value with the same Zod schema.

import { z } from "zod";

const RiskSummary = z.object({
  summary: z.string(),
  risk: z.enum(["low", "high"]),
});

const result = await runtime.llm("Inspect the workspace and return risk.", {
  model: "gpt-5.4",
  outputSchema: RiskSummary,
});

console.log(result.json.risk);

You can also pass a plain JSON Schema object and declare the return type with a generic:

type RiskSummary = {
  summary: string;
  risk: "low" | "high";
};

const result = await runtime.llm<RiskSummary>("Inspect the workspace and return risk.", {
  outputSchema: {
    type: "object",
    additionalProperties: false,
    properties: {
      summary: { type: "string" },
      risk: { type: "string", enum: ["low", "high"] },
    },
    required: ["summary", "risk"],
  },
});

Options:

OptionDescription
modelLLM model name. When omitted, agent-compose uses the server-side configuration.
baseUrlagent-compose service URL. Defaults to BASE_URL, then HTTP_URL, then AGENT_COMPOSE_BASE_URL, then AGENT_COMPOSE_HTTP_URL, then http://127.0.0.1:7410.
timeoutMsTerminates the LLM service request after this number of milliseconds.
outputSchemaZod schema or JSON Schema object. When set, the returned json field is parsed from text.

Return value:

{
  text: string;
  model: string;
  responseId: string;
  finishReason: string;
  json: unknown | null;
}

text always preserves the raw text returned by the LLM service. When outputSchema is set, text must be a JSON string. The SDK runs JSON.parse(text) and stores the result in json. If outputSchema is a Zod schema, the SDK also validates the parsed result with that schema. Without outputSchema, json is null.

runtime.env.get(name)

Reads an environment variable. Returns undefined when the variable is not set.

const value = runtime.env.get("WORKSPACE");

runtime.env.require(name)

Reads a required environment variable. Throws when the variable is missing or an empty string.

const token = runtime.env.require("API_TOKEN");

runtime.env.all()

Returns all defined environment variables as a plain object.

const environment = runtime.env.all();

runtime.log(message, payload?)

Writes one structured runtime log line to stdout.

runtime.log("step completed", { step: "build", ok: true });

Output JSON shape:

{
  type: "agent-compose.runtime.log";
  message: string;
  payload: unknown;
  createdAt: string;
}

runtime.report.writeMarkdown(name, content, options?)

Writes a Markdown report file and returns the created file path.

const reportPath = await runtime.report.writeMarkdown("summary.md", "# Summary\n\nDone.");

Options:

OptionDescription
dirOutput directory. Defaults to runtime.paths.workspace.

File names are normalized with path.basename(), so callers should pass a file name rather than a nested path.

runtime.ssh.prepareConfig(options)

Writes SSH client configuration for reaching a host and returns the resolved paths. It creates the SSH directory, optionally writes a private key, and maintains a marked block in ~/.ssh/config that points at a known_hosts file.

const sshConfig = await runtime.ssh.prepareConfig({
  hostAlias: "sandbox",
  hostName: "10.0.0.5",
  user: "root",
  privateKey: process.env.SANDBOX_SSH_KEY,
});

const command = runtime.ssh.command(sshConfig);

Options:

OptionDescription
hostAliasRequired Host alias written to ~/.ssh/config.
hostNameRequired host name or address.
userSSH user. Defaults to root.
portSSH port. Defaults to 22.
proxyJumpOptional ProxyJump target.
privateKeyPrivate key contents to write. The value must contain PRIVATE KEY; escaped \n sequences are normalized.
privateKeyNameFile name for the written key under ~/.ssh. Defaults to id_rsa.
homeHome directory used to resolve ~/.ssh. Defaults to runtime.paths.home.
blockNameMarker name for the managed config block. Defaults to agent-compose-runtime-sdk.
strictHostKeyCheckingOne of accept-new, yes, or no. Defaults to accept-new.

Return value:

{
  hostAlias: string;
  hostName: string;
  user: string;
  port: string;
  proxyJump?: string;
  privateKeyPath?: string;
  configPath: string;
  knownHostsPath: string;
  blockName: string;
  strictHostKeyChecking: "accept-new" | "yes" | "no";
}

The returned config can be turned into shell commands with runtime.ssh.command(config) (ssh …), runtime.ssh.scpCommand(config) (scp …), and runtime.ssh.options(config) (the shared -F, UserKnownHostsFile, and StrictHostKeyChecking flags).

OctoBus capabilities in custom scripts

runtime.capabilities lets an existing script or Codex-compatible runner use the sandbox's declared OctoBus capabilities without an application-side relay. It reads the daemon-generated RUNTIME_ROOT/mpi/capabilities.json snapshot and uses the guest image's grpcurl executable through CAP_GRPC_TARGET.

import { runtime } from "@chaitin-ai/agent-compose-runtime-sdk";

const tools = await runtime.capabilities.list();
// Select an explicitly intended tool; identical methods on different
// instances/capsets have different IDs.
const selected = tools.find((tool) => tool.id === requestedToolID);
if (!selected) throw new Error("Requested tool is unavailable");
const definition = await runtime.capabilities.describe(selected.id);
// definition.method/request/response contain reflected Protobuf text.
const result = await runtime.capabilities.call(selected.id, params, {
  timeoutMs: 30_000,
  maxOutputBytes: 256 * 1024,
  signal: abortController.signal,
});

list() returns id, capset, instance, method, request_type and response_type. It rejects missing, malformed, foreign-sandbox or incomplete snapshots. The snapshot is refreshed when the daemon prepares the capability guide; it is not a live directory or a grant. Re-prepare the run, or create a new sandbox, after recovering an unavailable directory.

describe() returns the unary RPC, top-level request/response Protobuf text, and descriptorSetBase64: a standard binary google.protobuf.FileDescriptorSet encoded as Base64, including imported message/enum definitions. Consumers may load it with their own Protobuf library; it is not JSON Schema or a pinned schema approval. Temporary descriptor files are removed on success and failure. call() accepts Protobuf JSON and returns the decoded JSON response; grpcurl performs reflection and standard wire encoding. Well-known messages may use scalar, array or null JSON forms; inputs containing undefined, non-finite numbers or other non-JSON values fail before invocation. Streaming methods are rejected before business invocation. Neither discovery nor SDK validation replaces capproxy/OctoBus authorization or business approval. No read-only classification is inferred from method names.

Options apply per grpcurl operation. describe() makes three reflection operations; call() checks the method and invokes it once. Use signal for a shared end-to-end deadline. Calls are not retried. Request JSON is limited to 256 KiB; output defaults to 256 KiB and may be set up to 1 MiB. Exceeding a limit fails instead of returning truncated JSON. The same output limit applies to the binary descriptor set before Base64 encoding. Upstream diagnostics are not forwarded or attached to errors. The CAP credential uses header environment expansion, and request JSON is sent over stdin, keeping both out of argv.

Existing Codex event output and business routing may be retained. This API does not implement a model/tool loop. Scripts still own their business decisions and projections.

The daemon publishes complete catalog and Markdown snapshots with an atomic rename confined to the sandbox directory. Guest-created symlinks cannot redirect these host writes outside that directory. Origin URLs retain their default port when converted to the grpcurl address.

Errors

When rejectOnFailure is enabled, a non-zero exit from runtime.exec() or runtime.shell() throws CommandError. The error object contains:

FieldDescription
commandExecuted command.
argsArguments passed to the command.
resultCommand result object, with the same shape returned by runtime.exec() or runtime.shell().
const { runtime, CommandError } = require("@chaitin-ai/agent-compose-runtime-sdk");

try {
  await runtime.shell("exit 1", { rejectOnFailure: true });
} catch (error) {
  if (error instanceof CommandError) {
    runtime.log("command failed", { exitCode: error.result.exitCode });
  }
}

版本与发布记录

@chaitin-ai/agent-compose-runtime-sdk 共发布 9 个版本,首次发布于 2026/07/10;过去 12 个月发布了 9 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.14.0latest2026/11/063 天前
0.13.02026/10/2811 天前
0.12.02026/10/1425 天前
0.11.02026/09/082 个月前
0.10.02026/08/132 个月前
0.9.02026/08/073 个月前

关于 @chaitin-ai/agent-compose-runtime-sdk 的常见问题

@chaitin-ai/agent-compose-runtime-sdk 是什么?

Node.js SDK for scripts running inside an agent-compose guest runtime.

如何安装 @chaitin-ai/agent-compose-runtime-sdk?

在项目目录运行 npm install @chaitin-ai/agent-compose-runtime-sdk,或使用 pnpm add / yarn add / bun add。

@chaitin-ai/agent-compose-runtime-sdk 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@chaitin-ai/agent-compose-runtime-sdk 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@chaitin-ai/agent-compose-runtime-sdk 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@chaitin-ai/agent-compose-runtime-sdk 可以商用吗?

@chaitin-ai/agent-compose-runtime-sdk 使用 LGPL-3.0-only 许可。弱 Copyleft:作为库被调用时通常不要求开源你自己的代码,但修改库本身需以 LGPL 开源;前端打包合并后的适用边界存在不同理解。以上为概括,不构成法律意见,请以许可原文为准。

@chaitin-ai/agent-compose-runtime-sdk 的下载量有多少?

根据 npm 官方下载统计,@chaitin-ai/agent-compose-runtime-sdk 在 2026/10/10 – 2026/11/08 这 30 天内被下载 4,868 次,日均约 162 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@chaitin-ai/agent-compose-runtime-sdk 还在维护吗?

最新版本 0.14.0 发布于 2026/11/06(3 天前);至今共发布 9 个版本,其中过去 12 个月发布了 9 个;首次发布于 2026/07/10。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。