一个仓库里多个 Agent

用多个 agent_id 在同一项目目录里隔离不同的 SDK Agent

如果你在同一个项目目录里创建多个本地 SDK Agent,最重要的是:

  • 给每个 agent 一个稳定且不同的 id

例如:

const planner = new Agent({ id: "planner" });
const planner_workspace = new Workspace({ id: "planner-project", path: repo_path });
const planner_session = await planner.sessions.create({ workspace: planner_workspace });

const reviewer = new Agent({ id: "reviewer" });
const reviewer_workspace = new Workspace({ id: "reviewer-project", path: repo_path });
const reviewer_session = await reviewer.sessions.create({ workspace: reviewer_workspace });

两个 Workspace 可以指向同一物理目录。Session 存储按 agent_id 分区,每个 Session 在创建时显式选择 Workspace。如果两个 Agent 需要彼此隔离的命令环境,应分别为 Workspace 创建和传入 Shell 实例。

使用决策模型组织 Group

Group 每轮只选择需要回复的成员,选中的成员并行执行。所有成员结束后,将整轮回复写入共享上下文,再调用决策模型;返回空成员集合时回到空闲。Group 不使用语言模型生成任务指令或阶段计划。

每个 GroupSession 只有一个调度循环。执行期间收到的用户补充立即保存,等本轮所有成员结束后,与整轮回复一起组成下一批 pending_messages。判断期间收到新输入会取消旧判断并重新调用;过期结果即使延迟返回也不能启动成员,其审计状态为 superseded,不会显示为失败。普通消息不打断已开始的成员执行,需要立即中断时使用停止操作。

恢复检查点保存未消费的 pending_message_ids,包括执行期间尚未交接的输入。重启后将这些消息交回同一个循环重新判断。

/** 通过 Federation Jev 选择每轮并行回复的成员。 */
import { Group } from "@downcity/agent";
import { Embassy } from "@downcity/federation";

const embassy = new Embassy({
  federation_url: "http://localhost:3000",
  user_token: process.env.FEDERATION_USER_TOKEN,
});
const group = new Group({
  id: "delivery",
  instruction: "研究方案并完成实现,避免重复已有成果。",
  members: [planner, reviewer],
  model: {
    decision: (input, signal) => embassy.user.ai.decision({
      ...input,
      model: "jev-latest",
    }, signal),
  },
});
const group_session = await group.sessions.create({ workspace: planner_workspace });
await group_session.prompt({ query: "分析当前方案并提出可执行的改进。" });

group.sessions.create({ workspace }) 创建独立的项目群聊。需要固定的 Group 自身会话时,使用 group.sessions.self({ workspace }):其 ID 恒等于 group.id,首次打开时创建,后续打开恢复同一会话。宿主负责提供稳定的 Workspace,恢复时必须使用相同的 Workspace。会话集合默认存储在内存中;跨进程恢复需要配置持久化存储 Provider。

Desktop 的 Chat 列表点击 Group 会打开固定自身会话,使用私有 groups/<group_id>/main Workspace;Work 中的项目群聊独立创建。自身会话标题使用 Group 名称,配置可从聊天页设置菜单打开,未读提示归属 Chat。

成员需要分别配置自己的执行模型与能力描述。决策调用一次提交所有成员的布尔问题,Group 将答案汇总为 member_ids。自定义 dispatch_strategy.decide_dispatch() 同样只返回 { member_ids: [...] },空数组表示本次不再回复。默认调度在用户新消息轮次允许成员回应问候、确认在线、点名和直接提问,并按每位成员的回复概率独立抽样:概率不超过 40% 时不回复,40%–75% 之间按 (回复概率 - 0.4) / 0.35 计算实际回复率,达到 75% 时一定回复。例如回复概率为 60%,实际回复率约为 57%;抽样仍可能选中零位或多位成员。决策答案必须提供 0–1 范围的 probability,它表示所选布尔结论的置信度;value: false 时用 1 - probability 还原回复概率,缺失或无效概率会使本次调度失败。成员回复触发的自动接力保留布尔判定,只在需要补充或继续工作时进行,避免重复确认。执行失败会记录到群聊;停止操作会取消正在进行的决策和成员执行,自动接力仍受轮次上限与重复内容检测约束。

每轮成员收到真实群成员名单、触发来源、最新用户请求和本轮新增消息。执行期间收到的用户补充在下一轮作为当前请求,不会被刚完成的成员回复覆盖。最新用户请求优先于群聊长期目标;问候、在线确认和角色询问只需简短回应,不授权自行创建文档或启动开发。自动接力默认结束,仅对用户已授权且明确未完成的工作、必要交接或成员问题继续;泛泛邀请、计划和等待用户提供需求不触发自我接力。

默认策略将每位成员的模型结论、置信度、回复概率、实际回复率、随机数(仅抽样时)和最终选择保存到调度记录的 decision.member_decisions。可据此区分模型判断与随机抽样导致的未回复。

Desktop 的模型设置展示“决策模型”,创建或编辑 Group 时在“调度模型”中选择 Jev。已有 Group 使用文本模型的配置需要重新选择决策模型。AI 辅助创建团队的草稿仍使用文本模型,与 Group 运行时调度分开。