Agent 构造参数
详细说明 Workspace env、WorkspaceTools 以及本地 Agent 的 id、instruction、model、tools 和 plugins 参数
Agent 构造参数
本地 Agent 的构造方式:
const workspace = new Workspace({
path,
shell,
env,
});
new Agent({
id,
workspace,
model,
instruction,
tools,
plugins,
Session,
})id
agent 的稳定标识。
它会影响 SDK session 落盘路径:
<project_root>/.downcity/agents/<agent_id>/...推荐:
- 稳定
- 可 URL 编码
- 不要随便改
因为它直接决定了 session 落盘目录分区。
workspace
当前 Agent 可以访问的项目资源与安全边界。Workspace 统一持有项目根目录、文件与搜索工具,以及可选 Shell:
const workspace = new Workspace({
path: "/path/to/project",
shell,
});关键点:
- macOS、Linux 和 Windows 使用同一个
Workspace path会在 Workspace 构造时解析为真实绝对目录- 文件和搜索工具固定限制在 Workspace 内
- Shell 与文件工具使用同一个项目根目录
- 一个 Workspace 实例只绑定一个 Agent
- 多个 Agent 可以指向同一目录,但必须分别创建 Workspace
agent.dispose()会同时释放它独占的 Workspace
如果 path 不存在、不是目录或为空,Workspace 会立即拒绝构造。
instruction
调用方传入的本地 SDK Agent 静态基础指令。
new Agent({
id: "repo-helper",
workspace: new Workspace({ path: "/path/to/project" }),
instruction: [
"你是一个简洁的代码助手。",
"解释代码时优先给出明确文件引用。",
],
});关键点:
instruction是静态的,应该保持缓存友好- SDK 不会对它做动态变量渲染
- SDK 不读取项目 prompt 配置文件
- 如果省略
instruction,SDK 会使用包内最小 core instruction 作为 fallback
宿主需要额外基础指令时,应通过 instruction 显式传入。
model
Agent 持有的默认 AgentModel 实例。AgentModel 可以是 AI SDK LanguageModel 或 City CityModel,不需要调用方提前转换。
new Agent({
id: "repo-helper",
workspace: new Workspace({ path: "/path/to/project" }),
model: openai.responses("gpt-5"),
});关键点:
- SDK 不负责选择、保存或恢复模型 ID,只持有
AgentModel实例 CityModel自身实现LanguageModelV3,Agent 直接调用- Session 没有自己的模型时回退使用 Agent 模型
- 本地 Session 可通过
session.set({ model })覆盖 Agent 模型 - 有效模型解析顺序固定为 Session 模型、Agent 模型
Workspace 的 env
Env 描述当前 Workspace 的项目执行环境,由 Workspace 持有:
const workspace = new Workspace({
path: "/path/to/project",
env: {
OPENAI_API_KEY: process.env.OPENAI_API_KEY ?? "",
},
});关键点:
- SDK 先读取项目
.env,再用 Workspace 构造参数env覆盖同名值 - Env 属于 Workspace,不属于 Agent
- 如果宿主需要合并多层 env,应先在外部合并,再把最终结果传给
env - 这些值会成为 Workspace 的运行时 env,但不会自动回写系统环境变量
运行时更新 env
构造 Workspace 之后,可以在运行期增量更新或整体替换 configured env:
workspace.set_env({ FOO: "1" });
workspace.get_env(); // => { FOO: "1" }
workspace.patch_env({ BAR: "2" }); // 增量合并
workspace.patch_env({ FOO: null }); // null 表示删除
workspace.set_env({ ONLY: "ok" }); // 整体覆盖关键点:
get_env()返回浅拷贝快照patch_env()中null/undefined表示删除该 keyset_env()整体覆盖当前 Workspace envagent.set_instruction()只影响之后新建的 Session,不会回溯修改当前内存中的已有 Session- Session 恢复时若没有
instruction.md,会从 Agent 当前 instruction 和 plugin 重新生成 system;已有 Session 可用session.syncshot()手动刷新,并用session.snapshot()持久化 - Workspace env 与 plugin 修改会在已有 Session 的下一个 Session step 检查点提交
- 正在进行的 provider 请求及其工具调用继续使用当前 step 已生效的 env
- 如果当前 Session turn 没有后续 step,排队中的修改会在下一个 Session turn 开始时提交
- 配置真正生效时,Session timeline 会写入 completed action message
- 运行时变更只活在内存,不会回写项目
.env或系统环境变量
tools
Agent 最终持有的额外自定义工具集合。
关键点:
- Workspace 提供文件、搜索和可选 Shell 组成的 WorkspaceTools
- PluginRegistry 提供
plugin_read和plugin_call AgentOptions.tools提供调用方自定义工具ask_question等可选工具需要调用方从@downcity/agent/tools导入并显式传入- Agent 统一注册这些工具并由 Session 共享
- 任意来源的工具重名会直接报错,不会静默覆盖
这很适合“多个 session 共用一套默认工具能力”的场景。
Workspace 的 shell
详细配置参见 Shell 与沙箱。
可选的内建 shell 能力。
import { Agent, Workspace } from "@downcity/agent";
import { Shell } from "@downcity/shell";
import { MacOsSeatbeltSandbox } from "@downcity/sandbox-macos";
const agent = new Agent({
id: "repo-helper",
workspace: new Workspace({
path: "/path/to/project",
shell: new Shell({ sandbox: new MacOsSeatbeltSandbox() }),
}),
});关键点:
- Shell 不是 plugin
- Shell 只挂载
shell_exec和shell_session - Workspace 自身挂载
grep、find、read、write和edit,没有 Shell 时仍可使用 - session 与 turn 上下文由 Agent 内部自动接线
- 审批归属具体 Session,使用
session.interactions()、session.respond(...)和session.set({ security }) - 文件和搜索工具固定限制在 Agent 项目根目录内,不提供 unrestricted 模式
plugins
这里接收的是已经实例化好的 BasePlugin 对象。
例如:
import { Agent, Workspace } from "@downcity/agent";
import { SkillPlugin } from "@downcity/plugins/skill";
const agent = new Agent({
id: "repo-helper",
workspace: new Workspace({ path: "/path/to/project" }),
tools: {},
plugins: [new SkillPlugin()],
});联网能力是显式选择的,并且必须提供 provider,请参阅 Web Plugin 文档。
SDK 会为当前 Agent 创建独立的 plugin registry。
关键点:
- 应该传
new SkillPlugin()这类实例,而不是原始 plugin 定义对象 - 它不会默认注册全部内建 plugin
- 它不会复用全局 runtime 的 plugin manager
- 同名 plugin 被重复注册时会直接报错
agent.plugins与PluginContext.plugins会使用这份 registry- 按 Agent 的实际需要实例化对应 plugin,并将这些实例显式传入
plugins
Session
本地 session 的高级自定义类。
当你希望替换本地 session 实现,或者在 Session 层注入自定义 Composer 时使用它。Agent 只负责用这个类创建和恢复 session,不理解 Composer 的具体策略。
import {
Agent,
Workspace,
DefaultSessionComposer,
Session,
type SessionOptions,
type SessionComposeInput,
} from "@downcity/agent";
class CustomSessionComposer extends DefaultSessionComposer {
override async compose(input: SessionComposeInput) {
const step = await super.compose(input);
return {
...step,
system: [
...step.system,
{ role: "system" as const, content: "始终简洁回答。" },
],
};
}
}
class CustomSession extends Session {
constructor(options: SessionOptions) {
super({
...options,
composer: new CustomSessionComposer(),
});
}
}
const agent = new Agent({
id: "repo-helper",
workspace: new Workspace({ path: "/path/to/project" }),
session_class: CustomSession,
});关键点:
- 传入的是 class,不是已经创建好的 session 实例
- 这样
Agent可以按不同session_id创建多个 session - Composer 自定义留在自定义 Session 类内部
- Composer 只读取 Session 快照并组装 system、history、tools 或压缩计划,不直接持久化消息
RemoteAgent不支持本地 Session 类,因为它只是远程 runtime 的访问器
Session Composer 的可定制范围
统一的 SessionComposer 取代了旧的 System、History、Context 和 Compaction 四类 Composer。自定义 Session 只需要提供一个 Composer:
| 方法 | 用途 |
|---|---|
compose(input) | 返回当前模型 Step 使用的 system、messages 和 tools |
compact(input) | 根据只读 Message 快照返回 SessionCompactionPlan,无需压缩时返回 null |
should_compact(error) | 判断模型错误是否需要在持久化压缩后重试 |
compose(input) 可以:
- 增删或重排 system messages
- 筛选、转换或注入本轮模型 messages
- 调整当前 Step 可见的 tools
Composer 不消费 Prompt Queue,不控制 Turn,也不写 Message、Metadata、Mutation 或 JSONL。User Message 会在调用 Composer 前由 Session 持久化,所以自定义 Composer 不需要把当前 query 再追加到 history。
压缩也分为策略和提交两个阶段:Composer 只返回计划,Session 在 Assistant 草稿完成后提交 Segment。这样自定义策略不会绕过 Session 的消息一致性和恢复机制。