Agent SDK
在 Node 应用中嵌入 Downcity Agent 运行时
Agent SDK
@downcity/agent 用于在同一进程中创建 Agent、管理 Session 并执行模型调用。完整 API 参考在 Agent SDK 文档。
import { Agent, Workspace } from "@downcity/agent";
import { Shell } from "@downcity/shell";
import { MacOsSeatbeltSandbox } from "@downcity/sandbox-macos";
const workspace = new Workspace({
path: process.cwd(),
shell: new Shell({ sandbox: new MacOsSeatbeltSandbox() }),
env: { API_KEY: process.env.API_KEY ?? "" },
});
const agent = new Agent({
id: "repo-helper",
workspace,
model,
tools: { search: search_tool },
plugins: [plugin],
});
const session = await agent.sessions.create();
const turn = await session.prompt({ query: "检查当前项目" });
const result = await turn.finished;
await agent.dispose();Workspace 是统一资源容器,同时提供 AgentStore、WorkspaceTools、Env 与可选 Shell。Session 历史和元数据默认保存在同一个项目的 .downcity 目录中,也可以被 Workspace 的文件工具正常读取和编辑;创建 Agent 时不需要单独配置 Store。
每个 Workspace 实例只绑定一个 Agent,并由 agent.dispose() 一并释放。多个 Agent 可以操作同一物理目录,但需要分别创建 Workspace 实例。
Agent 在构造时启动 plugin 生命周期与后台任务;需要明确等待就绪时使用 await agent.ready(),关闭时使用 await agent.dispose()。HTTP 与 RPC 由独立包 @downcity/server 的 AgentHTTP 与 AgentRPC 提供。
流式消息
subscribe() 返回统一的实时 Session Mutation:
const unsubscribe = session.subscribe((mutation) => {
if (mutation.variant === "delta" && mutation.type === "text") {
process.stdout.write(mutation.delta);
}
});Tool 生命周期使用 type: "tool",用户参与使用 type: "interaction"。pending Interaction 携带完整请求,关联 Tool 同时进入 waiting-user;响应通过独立 Session 命令提交:
同一 Assistant step 内的 Part 顺序始终与模型流一致。即使 Tool 已提前进入执行准备,它也会等待对应的 Tool Part 出现在流中,不会越过尚未写入的前置文本。等待按 tool_call_id 相互隔离,多个 Tool 仍可并发执行;客户端应按 Mutation 与历史快照中的顺序直接渲染,无需自行重排。
const unsubscribe = session.subscribe((mutation) => {
if (
mutation.variant === "part" &&
mutation.type === "interaction" &&
mutation.part.status === "pending"
) {
render_interaction(mutation.part);
}
});
async function decide_approval(interaction_id: string, decision: "approved" | "denied") {
await session.respond({
interaction_id,
response: { kind: "approval", decision },
});
}历史快照使用 session.messages()。它返回当前 Active 页;存在更早的不可变 Segment 时,会同时返回 next_before_sequence 游标。连接断开后重新读取快照并建立新的订阅。
需要渲染平铺活动时间线的宿主可以直接使用 SDK 投影,不需要依赖 .downcity 的物理文件名:
import { to_session_message_timeline_events } from "@downcity/agent";
const page = await session.messages();
const timeline = page.items.flatMap(to_session_message_timeline_events);Session JSONL、日志和调度任务统一通过 Workspace FileSystem 完成根目录限制、原子写入与跨进程文件事务。应用应通过 Agent 和 Session API 访问结构化状态,而不是直接读取物理存储布局。
继续阅读: