文档 · 03

智能体与长期授权。

CommandAGI 上的智能体可以实时控制真实的机器。权限只有一个来源——由人创建的长期授权——而且每个动作在发生之前就已记录在案。

没有人在回路中——这是设计使然

CommandAGI 为无人值守运行的机器而建。持有授权的智能体可以实时使能(arm)单元、运行程序、发送命令——通过工作台、API 或 MCP——无需对每个动作逐一确认。保障安全的不是有人盯着,而是授权、驱动的边界和记录。

主体

一切行动者都是主体:agent:<name> 或 person:<name>。主体用凭据证明自己的身份——绝不只是报出自己的名字。仅仅声称自己是谁的请求会被拒绝。

  • 主机凭据——cagp_…,由 commandagi grant token --principal agent:<name> 签发一次(添加授权时也会签发)。主机只保存它的 SHA-256。grant token 轮换它;grant forget 删除它。
  • 账户凭据——cagc.<payload>.<signature>,用你账户的密钥(Ed25519)签名,供在云端运行的智能体使用。它写明主体、账户、过期时间,并可选地指定一台主机;只对该账户创建的授权有效。用 grant revoke-credential 吊销。

长期授权

长期授权是一个账户给予某个主体的权限,由人以明确的操作创建。没有任何工具或智能体途径能创建或扩大授权;在每一个改变权限的路由上,智能体的 API 密钥都会被拒绝。

shell
commandagi grant add --principal agent:night-shift \
  --world shop --unit mill-1 --channel gcode \
  --verb open --verb arm --verb run --verb send \
  --for 8h --note "night shift"
commandagi grant list
commandagi grant revoke g-3f9a1c20b7de

一条授权指定一个世界,并可选地指定单元、通道和操作——省略某一项即表示全部。授权可以设置过期(--for 8h、--expires <ISO time>)。授权保存在 ~/.commandagi/grants.json 中,每个动作都会重新读取;也可以在工作台的 设置 → 授权 中创建。格式错误的授权文件不会认可任何授权。

json
{ "grants": [ { "id": "g-3f9a1c20b7de", "principal": "agent:night-shift",
  "grantedBy": "acct:user:u_8f2k", "world": "shop", "units": ["mill-1"],
  "channels": ["gcode"], "verbs": ["open", "arm", "run", "send"],
  "expires": "2026-10-01T06:00:00Z", "note": "night shift" } ] }

同一个命令还能创建另外三种授权:--file PREFIX…(在某个路径下写文件)、--outreach APP… --per-day N(通过已连接的应用发送消息)和 --market VENUE… --symbol S --max-qty N --max-notional N --per-day N(下单)。

授权适用于物理世界。仿真世界不需要授权。

操作、使能与安全停机

一条授权可以给予四种操作:open 打开通道、arm 使能单元、run 运行程序、send 发送命令。

  • 驱动硬件运动的驱动在打开时处于未使能状态。任何在该单元上持有授权的主体都可以使能它。已使能的连接会话空闲五分钟后会自动解除使能。
  • 只接收输入的驱动——shell、Python 内核、作业交接——不需要使能;每次输入都会检查授权。
  • 安全停机始终允许。 stop、disarm 和 close——以及进给保持、暂停、紧急停止、关闭扭矩等安全停机命令——对任何在该单元上持有未过期授权的人、对打开该连接会话的人、以及对账户本人都始终允许。撤销一张挂单也属于安全停机。

每个动作遵循的规则

  • 发送前先记录。 在调用驱动之前,一条备注——主体和动作——会追加到运行的数据流中并落盘。只读项目会拒绝该动作,而不是在没有记录的情况下执行。
  • 确认不等于状态。 一条回复或 ok 绝不意味着已达到所命令的状态。命令会一直处于待定状态,直到机器报告状态。
  • 未知就保持未知。 断开的链路记录为 state: unknown。没有结束记录就终止的数据流显示为 interrupted: state unknown(已中断:状态未知)。
  • 绝不静默重试。 系统从不重试物理命令。智能体可以决定再试一次;这个决定本身会作为一条命令被记录。
  • 边界由驱动负责。 声明的限位、间隔和允许的操作由驱动强制执行,而不是由人。输入流有节奏控制:一次一个动作,间隔至少 30 ms。
  • 仿真与物理绝不混合。 一次运行只属于一个世界,其记录的来源必须与该世界的类型一致。

线程及其智能体

在物理世界中开启一个线程,会把该世界所有单元上的全部操作授予该线程的智能体(threads.agent,默认为 agent:mcp),最长 24 小时,并在线程关闭时撤销。可通过设置 "threads.agentControl": false 关闭此行为。

下一步

通过 MCP 把智能体接入这一切:SDK 与 MCP。