Agent 构造参数
详细说明 Workspace env、WorkspaceTools 以及本地 Agent 的身份、描述、instruction、model、tools 和 Powers 参数
本地 Agent 的构造方式:
const workspace = new Workspace({
id,
path,
shell,
env,
});
const agent = new Agent({
id,
name,
description,
model,
instruction,
tools,
powers,
Session,
});
// Session 在创建时选择 Workspace。id
agent 的稳定标识。
它会影响用户级 Agent 数据路径:
~/.downcity/agents/<agent_id>/...推荐:
- 稳定
- 可 URL 编码
- 不要随便改
因为它直接决定了 session 落盘目录分区。
name 与 description
name 是 Agent 的用户可见名称;省略或传入空字符串时回退到 id。description 是一句话能力简介,供宿主展示,也供 Group 调度器根据语义选择成员。
const reviewer = new Agent({
id: "reviewer",
name: "代码审查员",
description: "负责审查代码质量、测试覆盖和交付风险",
instruction: "审查时给出具体、可执行的修改建议。",
});id 与 name 会组成每个 Session system prompt 最前面的 Agent 身份块:
# Agent Identity
You are "代码审查员" (agent id: reviewer).两个值总是同时给出:模型用可读名称理解角色,宿主仍可用稳定 id 对账。
description 不会进入普通 AgentSession 的 system 指令,也不替代 instruction:前者描述“这个 Agent 适合做什么”,后者约束“这个 Agent 应该如何工作”。Group 调度只读取成员的 id/name/description,不会读取完整 instruction。
workspace 与会话目录
当前 Agent 可以访问的项目资源与安全边界。Workspace 统一持有项目根目录、文件与搜索工具,以及可选 Shell:
const workspace = new Workspace({
id: "project",
path: "/path/to/project",
shell,
});关键点:
- macOS、Linux 和 Windows 使用同一个
Workspace path会在 Workspace 构造时解析为真实绝对目录- 文件和搜索工具固定限制在 Workspace 内
- Shell 与文件工具使用同一个项目根目录
- Agent 构造时可以传入
workspace作为新建 Session 的默认目录;它不构成绑定 - 会话的当前目录可以在创建后通过
session.set({ workspace })或在get()时指定,随时切换 - 同一个 Agent 可以进入多个 Workspace,每个 Session 拥有独立的当前目录、历史、Shell 和 Power 上下文
- 多个 Agent 可以指向同一目录,但使用各自的
agent.id和数据分区
Workspace 只需要提供稳定的 id、真实项目 path,以及可选的 Shell 和 env。Downcity 内部数据根目录由实现自动解析:
const workspace = new Workspace({
id: "project",
path: "/path/to/project",
shell,
});
// Session 在创建时选择 Workspace。如果 path 不存在、不是目录或为空,Workspace 会立即拒绝构造。
本地实现默认把私有数据写入 ~/.downcity。测试或多实例宿主可以通过 DC_PLATFORM_ROOT 覆盖根目录,该环境变量不属于 Workspace API。
instruction
调用方传入的本地 SDK Agent 静态基础指令。
new Agent({
id: "repo-helper",
instruction: [
"你是一个简洁的代码助手。",
"解释代码时优先给出明确文件引用。",
],
});关键点:
instruction是静态的,应该保持缓存友好- SDK 不会对它做动态变量渲染
- SDK 不读取项目 prompt 配置文件
- 如果省略
instruction,SDK 会使用包内最小 core instruction 作为 fallback
宿主需要额外基础指令时,应通过 instruction 显式传入。
model
Agent 持有的默认 ModelClient 实例。可以使用 Federation 目录返回的 CityModel,也可以使用进程内 Provider Adapter 创建模型。
const model = create_openai_compatible_model({
id: "gpt-5",
upstream_model: "gpt-5",
base_url: "https://api.openai.com/v1",
api_key: process.env.OPENAI_API_KEY!,
});
new Agent({
id: "repo-helper",
model,
});关键点:
- SDK 不负责选择、保存或恢复模型 ID,只持有
ModelClient实例 CityModel自身实现ModelClient,Agent 直接调用stream(call, signal)- Session 没有自己的模型时回退使用 Agent 模型
- 本地 Session 可通过
session.set({ model })覆盖 Agent 模型 - 有效模型解析顺序固定为 Session 模型、Agent 模型
Workspace 的 env
Env 描述当前 Workspace 的项目执行环境,由 Workspace 持有:
const workspace = new Workspace({
id: "project",
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 和 Power 重新生成 system;已有 Session 可用session.syncshot()手动刷新,并用session.snapshot()持久化 - Workspace env 与 Power 修改会在已有 Session 的下一个 Session step 检查点提交
- 正在进行的 provider 请求及其工具调用继续使用当前 step 已生效的 env
- 如果当前 Session turn 没有后续 step,排队中的修改会在下一个 Session turn 开始时提交
- 配置真正生效时,Session timeline 会写入 completed action message
- 运行时变更只活在内存,不会回写项目
.env或系统环境变量
tools
Agent 最终持有的额外自定义工具集合。
关键点:
- Workspace 提供文件、搜索和可选 Shell 组成的 WorkspaceTools
- 宿主为每个 Power 推送一个 AgentTool,工具名即 Power 名
AgentOptions.tools提供调用方自定义工具ask_question等可选工具需要调用方从@downcity/agent/tools导入并显式传入- Agent 统一注册这些工具并由 Session 共享
- 任意来源的工具重名会直接报错,不会静默覆盖
这很适合“多个 session 共用一套默认工具能力”的场景。
Workspace 的 shell
详细配置参见 Shell 与沙箱。
可选的内建 shell 能力。
import { Agent } from "@downcity/agent";
import { Workspace } from "@downcity/city";
import { Shell } from "@downcity/city";
import { MicrosandboxProvider } from "@downcity/sandbox-microsandbox";
const agent = new Agent({ id: "repo-helper" });
const workspace = new Workspace({
id: "project",
path: "/path/to/project",
shell: new Shell({
sandbox_provider: new MicrosandboxProvider(),
}),
runtime_path: "/path/to/downcity-runtime/project",
});关键点:
- Shell 不是 Power
- Shell 只挂载
shell_exec和shell_session - Workspace 自身挂载
grep、find、read、write和edit,没有 Shell 时仍可使用 - session 与 turn 上下文由 Agent 内部自动接线
- 审批归属具体 Session,使用
session.interactions()、session.respond(...)和session.set({ security }) - 文件和搜索工具固定根植于 Agent 项目目录,不提供 host 执行目标
Power 不属于 Agent 构造参数
AgentOptions 不接收 powers。City 登记 CityPowerRegistration 后,自动把全部 Power 提供给全部 Agent:
import { Agent } from "@downcity/agent";
import { City } from "@downcity/city";
import { create_builtin_power_registrations } from "@downcity/powers";
const agent = new Agent({ id: "repo-helper", tools: {} });
const city = new City({
workspaces: [workspace],
powers: create_builtin_power_registrations(),
});
city.agents.add(agent);City 持有 Power 唯一实例、配置投影与生命周期;Agent 只持有身份、模型、指令、Tools 和 Sessions。 联网能力仍需由宿主配置,请参阅 Web Power 文档。
session_composer
只需要调整模型输入或上下文维护方式时,直接传入一个 Composer 实例。它属于 Agent 级特性,描述「这个 Agent 怎么和模型说话」,被该 Agent 的全部 Session 共享。
import { Agent, DefaultSessionComposer } from "@downcity/agent";
const agent = new Agent({
id: "repo-helper",
session_composer: new DefaultSessionComposer(),
});因此 Composer 实现必须无状态:具体 Session 与上下文全部由 compose(input) 参数传入,派生数据写入传入的 derived 存储。不要在实例上缓存任何与 Session 相关的内容。
Session Composer 的定位
Composer 是唯一回答「这一步模型看到什么」的组件。canonical history 与派生存储都由调用方传入,Composer 只读取它们并返回模型输入:
| 方法 | 用途 |
|---|---|
initialize(input) | 在当前 Session 的 session.db 初始化自己的派生 schema;没有派生状态的实现可以是空实现 |
compose(input) | 返回当前模型 Step 使用的 system、messages 和 tools |
advance_context(input) | 在 usage_pressure 或 provider_context_limit 触发下尝试推进派生状态;发生有效推进时返回 true |
compose(input) 可以:
- 增删或重排 system messages
- 筛选、转换或注入本轮模型 messages
- 调整当前 Step 可见的 tools
「压缩」不是独立概念,而是 advance_context() 的一种实现。FullHistorySessionComposer 就是不推进派生状态的现成实现;自定义压缩算法只需继承 DefaultSessionComposer 并覆盖 advance_context()。
Composer 不消费 Prompt Queue,不控制 Turn,也不修改 canonical Message。它只能写命名空间为 composer_<name>_* 的可重建派生表。只有确实要替换 Session 行为时才使用 session_class。