跳到主要内容

Envoy

Envoy

一个 envoy 是工作区 Agent 通过别人的线路被触及的方式——Telegram 或 WhatsApp。到达的是一条来自工作区可能没有用户行的人的消息,所以关键问题不是“我如何说这种协议”,而是 Agent 回答时以谁的权限行事 。这就是 policies ,也是为什么 envoy 是源码中的声明而不是宿主配置:答案应该出现在一次 diff 里。

传输本身仍然由宿主提供。保持一个 socket 打开不是按需伸缩(scale-to-zero)的租户能做的事,所以工作区指明传输方式,宿主提供它——凭据、连接或已验证的 webhook 端点以及密封会话都由 Colony 持有。

声明

每个 envoy 一个文件,位于 src/envoys/+<lower_snake_case>.ts ;文件名就是 envoy 键。

// src/envoys/+sales_desk.ts
export default {
	transport: 'telegram',
	audience: 'public',
	policies: ['commercial_shared', 'sales_rep'],
	groupMessages: 'disabled',
	delegation: 'enabled',
	task: 'Answer questions about quotes and accounts for this customer.'
} satisfies Envoy;
字段含义
transport触及它的线路( telegram 或 whatsapp )。传输方式决定了地址如何规范化与比较。
audience谁可以触及它:`public`(任何能发消息的人)或 `authenticated`(已验证地址属于他们的成员)。这是可达性而非对话形态——后者由 `groupMessages` 回答。
policies该 envoy 可做的全部——绑定到生成的策略名,因此 envoy 不能指向不存在的策略。它是一个数组,安全仅因为编译器拒绝在同一集合上无条件授权与收窄授权并存。
taskEnvoy 的常驻指令,叠加在工作区的 `src/+agents.md` 之上。
groupMessages群消息如何触发一轮:`disabled`、`mention_or_reply` 或 `all`。不触发回合的消息仍会记录在聊天副本中,可用 `read_messages` 读取。
delegation必填。`enabled` 允许该 envoy 派生子任务;`disabled` 彻底拒绝委派,适合必须独自行动的窄入口 envoy。

配对与发送者注册是两件事

配对只把一个 envoy 连接到它用于回复的账号——WhatsApp 号码通过扫描二维码,Telegram 机器人通过 BotFather 令牌,并不会注册给它发消息的人。对于 `authenticated` 受众,每个发送者只有在首次联系 envoy 时才证明该地址归自己所有。

  1. 未知发送者直接私聊,或在群聊中明确提及 envoy。
  2. Envoy 只向该发送者私聊回复一个一次性注册链接,15 分钟后过期;链接绝不会发到群里。
  3. 链接打开该租户内置的注册页面,并要求此人先登录平台。
  4. 明确确认后,系统把规范化的传输地址绑定到该租户身份并显示成功页;此人随后可回到对话重新发送请求。
对链接扫描器与预览安全
打开注册或工作区邀请 URL 只会检查状态。GET 永不消费凭证,因此 Outlook Safe Links、安全扫描器和消息预览都无法提前用掉它;只有已认证的确认 POST 才会改变状态。

回合运行中到达的消息

普通的已寻址消息会进入同一对话队列,并在下一次工具循环前加入模型上下文。群聊中的 ambient 消息保留在频道副本中,永不打断回合;每次模型调用都会附带未读数量的尾部提示,助手可按需用 `read_messages` 读取。助手在工具调用前写入简短文字更新,并随写随发,让发送者跟进工作;最终答复作为一条消息送达。较旧上下文离开提示窗口后,Agent 仍可搜索完整的已存储对话记录,包括排队中的后续消息。

聊天副本

每一条入站消息和每一条回复都会按顺序保存在每个聊天唯一的副本中,双向、媒体在到达时即落盘。已寻址消息同时进入工作队列;其余消息留在副本中,由 `read_messages` 按需读取,每次模型调用都会附带未读数量的尾部提示。副本是频道所显示内容的拷贝:服务商上报的编辑会在副本中收敛,已答复的对话记录永不改写;每次读取都会报告该频道的历史下限——本主机最早看到该聊天的时间,因为更早的消息无法从服务商取回。

Agent 以谁的权限行事

Envoy 可能是群聊,所以背后没有可以继承权限的单独个人。每个声明的 envoy 都获得自己的 Agent 主体 ——恰好持有它声明的 policies ,此外一无所有——并且每条入站消息在 Norbius 循环开始前都以该主体重新进入工作区。公开 envoy 的线程路由到管理员收件箱,不进任何成员收件箱;策略没有任何授权的 envoy 什么也做不了,与任何其他客户端一样,相同的写入契约与审批门都适用。

工作台、文档与委派

每个 envoy 都只有 一个共享工作台 ,只保存委派 Agent 会话。入站文本和文档绝不进入工作台:每个对话都拥有自己的转录、bolt_envoy_messages 副本与排空认领,以及记录在其中的附件绑定。读取文档时,必须同时解析对象键与会话绑定,才会返回字节。共享工作台可以安全提供 subagent ,因为其中没有发送者上传的内容。

把 delegation 设为 'disabled' 后,该 envoy 完全不会派生子 Agent——正是窄入口表面应有的形态。

一次突发消息就是一个回合
Envoy 对话落入租户数据库—— envoy_name 行上的键; bolt_envoy_messages 它携带的会话 id 把外部聊天绑定到对应会话。入口只做准入与缓冲,不调用模型;一个带租约的排空任务按顺序取得整批消息,持久保存完整发送者归属,只运行一个回合,并随写随发助手的进展,在回合结束时送达最终答复。
  • Norbius ——每条 envoy 消息都会经过的循环
  • 策略 ——envoy 的主体可以看到和更改什么
  • 工作区源码 ——envoy 角色在布局中的位置