news 2026/10/9 1:46:45

firstmate 的 agy(Antigravity CLI)适配器:从信任预注册到监督式 spawn 的完整验证实录

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
firstmate 的 agy(Antigravity CLI)适配器:从信任预注册到监督式 spawn 的完整验证实录

【免费下载链接】firstmate

Talk to one agent. Ship with a crew.

项目地址:https://gitcode.com/gh_mirrors/fi/firstmate
点击查看免费下载

本指南以 docs/verification/agy.md 这份验证记录为骨架,围绕 firstmate 项目中 agy(Antigravity CLI)crewmate/scout 适配器的检测、启动、信任对话框处理、忙碌状态判定、中断与退出、后端存活探活以及监督式任务全流程展开。读完本文,你将掌握 agy 为何"只有进程名可检测"、--prompt-interactive启动形态的完整命令构成、trustedWorkspaces预注册的安全语义与原子写入方式,以及agy_wait_for_going就绪闸门如何把"对话框已应答 + 忙碌签名"作为 spawn 成功的双重证据——这些知识可以直接迁移到任何需要在无人值守 TUI 后端上托管外部 CLI 的编排系统设计中。

1. 文档定位:一份"经验事实"而非"操作手册"

docs/verification/agy.md在 firstmate 仓库中扮演特殊角色:它记录的不是该适配器的操作事实本体(那由.agents/skills/harness-adapters/SKILL.md及其 references/harness/agy.md 知识树持有),而是这些事实是如何被建立、以及哪些仍未得到证明的验证档案。因此本文同样以"验证了什么、怎么验证的、边界在哪"为叙事主线,而不是一份安装教程。

验证对象的基本盘如下表:

字段值
版本agy 1.2.0;发送确认时序在agy 1.2.1(2026-09-12)上重测
验证时间2026-09-10
二进制/home/andpod/.local/bin/agy,ELF 64 位 Go 编译的单一可执行文件
平台Linux x64(Arch,内核 7.2.3)
后端Herdr,在隔离的非default实验室会话中(fm-lab-firstmate-agy-ad-*,经 bin/fm-herdr-lab.sh 创建);全程未触碰default会话与 captain fleet 状态

所有命令都在可丢弃的 firstmate 任务工作树或命名 Herdr 实验室会话内运行,不涉及任何 fleet 状态。

2. 检测:仅靠祖先进程名,无身份标记

agy 与 claude、codex 等"有环境变量标记"的适配器不同,它不发布任何身份标记。实测证据链如下:

  • agy --version输出1.2.0。
  • 一个活跃 TUI 的/proc/<pid>/environ中没有任何AGY_*或ANTIGRAVITY_*变量。
  • 环境里确实有AGENT=1与CLAUDECODE=1,但两者都继承自启动环境——AGENT不是 agy 身份,而CLAUDECODE会让检测器误判成 claude,所以都不能被提升为标记。
  • Herdr 的pane process-info报告该 pane 的前台进程为name=agy、argv=["agy", ...];ps -o comm=同样输出agy。

因此 bin/fm-harness.sh 采用锚定进程名agy单独匹配(代码注释明确:"Anchored, never*agy*, so unrelated commands cannot be misread as this harness"),并在启动边界清掉CLAUDECODE、PI_CODING_AGENT、GROK_AGENT、FM_PI_HARNESS四个外来标记——理由与 cursor 适配器相同:agy 不清理继承的CLAUDECODE,若不主动清除,bin/fm-harness.sh会把 agy worker 误读成其启动者(claude)。锚定的必要性同样体现在 bin/fm-agent-process-lib.sh:agy与 muse、omp 一样是裸词进程名,通配agy*会误吞无关命令。

tests/fm-agy-harness.test.sh 用三组用例钉死这三件事:

  • test_agy_ancestry_detects_the_native_command_name——锚定匹配生效;
  • test_agy_ancestry_rejects_unrelated_mentions——含agy片段的无关名字被拒绝;
  • test_agy_claims_no_inherited_launcher_marker——被 spawn 清除后,继承的CLAUDECODE永远无法压过一个真实的agy祖先。

3. 启动形态:位置参数 +--prompt-interactive自动提交

验证中使用的完整启动命令:

$ agy --prompt-interactive "Reply with exactly AGY_LIVE_PROBE_OK and nothing else" --model gemini-3.8-flash-low --effort low --dangerously-skip-permissions

观察到的行为:brief 自动提交(无需额外回车),回合运行,回复渲染到 pane 中;同一目录第二次启动以同样方式应答新 prompt,证明该形态可重复而非首次运行巧合。页脚渲染Gemini 3.8 Flash · low,证明--model与--effort两个旗标被同时接受。

bin/fm-spawn.sh 的launch_template将其固化为可展开模板(agy 分支):

env -u CLAUDECODE -u PI_CODING_AGENT -u GROK_AGENT -u FM_PI_HARNESS \ __AGYBIN__ --prompt-interactive "$(__OPINPUT__ encode launch-brief < __BRIEF__)" \ __MODELFLAG____EFFORTFLAG__--dangerously-skip-permissions

几个细节值得展开:

  • brief 随启动命令携带:--prompt-interactive "<brief>"启动监督式交互会话并自动提交,因此 agy不需要像 claude 那样额外的投递闸门(bin/fm-spawn.sh 第 4276 行注释明言:"agy carries its brief on the launch command, so it needs no delivery gate")。
  • --dangerously-skip-permissions自动批准所有工具调用,是无人值守 crewmate 的必要条件。
  • 占位符展开:__AGYBIN__解析为经过校验的 agy 可执行文件绝对路径(resolve_pi_executable agy,找不到时直接报错"install Antigravity CLI or select a different verified harness");__MODELFLAG__/__EFFORTFLAG__按模型与力度生成旗标。
  • 任务种类限制:agy 与 muse、gemini、devin 一样仅验证为 crewmate/scout 适配器,--secondmate直接被拒(bin/fm-spawn.sh 第 2357 行);docs/supervision-protocols/下也没有 agy 的 wake 协议。

测试 tests/fm-agy-harness.test.sh 的test_agy_launch_carries_the_brief_with_model_effort_and_autonomy逐项断言:启动命令钉死解析后的绝对二进制路径、携带--prompt-interactive、--model 'gemini-3.8-flash-low'、--effort 'low'、--dangerously-skip-permissions,且清理了继承的CLAUDECODE,所有占位符都被替换。test_agy_effort_xhigh_is_recorded_but_omitted则验证:请求xhigh时元数据仍记录该意图,但启动命令中不出现--effort(agy 1.2.0 只接受low|medium|high)。

4. 模型与力度:agy models远程目录校验

agy models的输出形态:

$ agy models Fetching available models... gemini-3.8-flash-high Gemini 3.8 Flash (High) gemini-3.8-flash-medium Gemini 3.8 Flash (Medium) gemini-3.8-flash-low Gemini 3.8 Flash (Low) ...

要点:

  • agy --help将--effort文档化为low|medium|high,--model为会话模型。
  • 模型 id 是裸 id(gemini-3.8-flash-high),绝无 provider 前缀;此前配置中无后缀的gemini-3.8-flash不在列表中,只有带-high/-medium/-low后缀的变体。
  • 该列表是远程拉取(输出首行Fetching available models...),依赖网络与已登录账号。

bin/fm-spawn.sh 的agy_model_validate据此实现三层策略:

  1. 列表可达且请求 id 不在其中 → 拒绝 spawn:error: agy model '<model>' is not listed by 'agy models'; choose a listed id or omit --model。这使过期的 id(如已下线的裸gemini-3.8-flash)在创建任何 pane 之前大声失败,而不是卡死一个 worker pane。
  2. 列表不可达(非 124 退出码)→ 放行但打 notice:listing is unreachable (exit N); launching with --model '<model>' unvalidated——不可达的列表"什么也没证明",因此不阻塞。
  3. 列表超时(退出码 124)→ 同样放行并 notice:探测运行在 bin/fm-timeout-lib.sh 的共享硬时限下(默认 15 秒,环境变量FM_AGY_MODELS_TIMEOUT可调;非正数或非数值会被钳回 15,因为"非正的时限不算时限"),stdin 分离运行——卡死的拉取或登录提示被切断后落到未校验启动,绝不让 spawn 在 pane 尚未存在时被阻塞。

print模式是另一条验证凭证路径的手段:agy -p "Reply with exactly: AGY_PRINT_PROBE_OK" --model gemini-3.8-flash-low在约 8 秒内以退出码 0 返回完全一致的回复,证明无 pane 情况下凭证链路可用。

5. 信任对话框:预先注册为主,忙碌回合闸门兜底

5.1 现象与根因

在全新工作树中的首次启动会弹出文件夹信任对话框:

Accessing workspace: /home/andpod/.treehouse/firstmate-7bab20/1/firstmate/agy-probe-tmp Do you trust the contents of this project? Antigravity CLI requires permission to read, edit, and execute files here. > Yes, I trust this folder No, exit

agy --help(1.2.0)没有列出任何信任旗标或预注册命令,但 agy 会认领启动前写入~/.gemini/antigravity-cli/settings.json中trustedWorkspaces数组的条目。验证过程在一次性HOME(持有~/.gemini副本,真实设置文件从未被写入)下完成:

  • 手工把文件夹追加进数组后,--prompt-interactive启动直接进入回合并渲染回复,无对话框;
  • 同一方式启动未注册的兄弟文件夹,则停在对话框上。

两个关键语义:

  • agy 比较的是 pane 的逻辑工作目录而非解析路径:只注册真实路径而 cwd 是符号链接时,仍会停在对话框上。因此 bin/fm-agy-trust.sh 在两者不同时同时记录逻辑路径与其解析形式。
  • 注册失败只是 stderr 警告而非拒绝:因为 agy 的对话框预选了安全答案("Yes, I trust this folder"),且下方闸门可以代答它。这与 claude 的对话框(未预选、阻塞一切)形成鲜明对照,后者注册失败会直接拒绝 spawn。

5.2 安全语义:结构性作用域测试

bin/fm-agy-trust.sh 的注释开宗明义:"THE SCOPE TEST IS THE SAFETY PROPERTY"。它复刻了 bin/fm-claude-trust.sh 的形状,对<worktree>施加严格的结构约束:

  • 必须是链接的 git worktree——拥有自己的 git dir、与<project>共享 common dir,且顶层恰好等于解析后的参数;
  • 主检出(primary checkout)、无关仓库的 worktree、worktree 的子目录、普通目录、主目录一律以非零退出拒绝,绝不警告后跳过;
  • 只写启动用户自己的 store,store 必须是本 uid 拥有的常规文件;
  • 保留 store 中所有无关键与条目,替换是原子的。

实现细节:refuse()统一打印error: refusing to pre-register agy trust: <原因>并以 1 退出;依次校验 worktree 可访问、非主目录、处于 git 仓库内、是 worktree 根、git dir 与 common dir 可解析且不同(不同才证明是隔离 worktree 而非主检出)、与项目共享 common dir;随后用内嵌 Node 脚本做读-改-写 + 指纹校验 + 回读:先 SHA-256 指纹原文件,写入临时文件(0600、wx独占创建),rename 前再次指纹对比(防止 agy 自己重写了文件),rename 后回读确认条目在列;若发现 store 被并发移动,最多重试一次后拒绝覆盖。整个注册过程最多 3 次尝试,全部失败则报错退出。

5.3 为什么不能只靠预注册:实测的边界行为

验证记录了若干令人警醒的实测观察:

  • 两次受监督的 Herdr 运行在 treehouse worktree 中完成了文件写入回合,而观测时对话框仍未应答(worker 文件与done:状态行都在向 pane 发送 Enter 之前就已落盘)。
  • 在不受信任的/tmp目录中的隔离运行从未在 Enter 之前到达工作区:回合改在 agy 自己的 scratch 目录里做探索性工具调用,只有排队的 prompt 在应答后才运行。
  • 有一次运行搁置数分钟未应答,最终应答后把文件写进了 agy 的 scratch 目录而不是工作区。
  • 差异背后的机制未被建立:路径、后端、延迟在多次运行中都有变化,但未能隔离出单一原因。

正是这些观察决定了 spawn不依赖预注册单独生效,而是再加一道闸门。

5.4 就绪闸门:agy_wait_for_working

bin/fm-spawn.sh 在预注册之后运行后启动就绪闸门(rovo/kimi 的"先启动后确认"形态),核心逻辑(约第 4290–4324 行):

  • 常量AGY_TRUST_DIALOG='Do you trust the contents of this project?'精确匹配对话框文本;
  • 轮询 pane 捕获(默认FM_AGY_READY_POLLS=60次、间隔FM_AGY_POLL_INTERVAL=0.5秒):
    • 若看到对话框且尚未应答 → 发送单个 Enter(利用预选的"Yes, I trust this folder"),标记AGY_TRUST_ANSWERED=1;
    • 否则若路径已预注册或对话框已应答 → 用fm_busy_classify判定忙碌(Herdr 原生working或钉住的esc to cancel状态行),忙碌即视为就绪并返回 0;
  • 顺序严格:由于 Herdr 的原生working判定已知可与未应答对话框共存,忙碌只有在"worktree 已预注册"或"对话框已看到并应答"时才计为就绪;未注册路径上持续轮询对话框,而非接受过早的忙碌判定。
  • 若窗口内无法确认 brief 已运行(应答过的对话框始终不转忙碌、预信任 pane 始终不转忙碌、未注册 pane 始终不显示对话框),则 spawn 失败:向任务状态写入failed:,并关闭 endpoint(rovo_endpoint_cleanup),确保没有孤儿 worker 存活在任务控制之外。

tests/fm-agy-harness.test.sh 用一个"读 spawn 刚写好的 store 来做对话框决策"的假 pane 覆盖了全部四条路径:预信任启动无对话框、对话框照常渲染且恰好应答一次、未注册路径上的过早忙碌判定继续等对话框、以及两条失败并关闭路径。

6. 忙碌状态:钉住的状态行是唯一信号,缺失即 unknown

回合中途,pane 同时渲染状态行与 spinner 行:

⣯ Generating... └ Tip: When reviewing a file edit, press f to see the full diff. ... esc to cancel Gemini 3.8 Flash · low

回合完成后的空闲 composer:

> ────────────────────────────────────────────────────────────────────────────── ? for shortcuts Gemini 3.8 Flash · low

bin/fm-busy-lib.sh 的fm_busy_agy_tail_busy与投递守卫只匹配esc to cancel这个 token:

  • TUI 在整个回合期间把该状态行钉在 pane 底部;空闲行则替换为? for shortcuts。
  • Generating...这个 spinner 词刻意不作为信号:它是自由浮动的输出行,普通 worker 输出(如Generating report...)若被当作信号,会把空闲 worker 误判为忙碌、或"确认"一个根本没落地的提交。
  • 现场观察中没有任何忙碌阶段缺少状态行:每个捕获到的回合中帧都带有它。
  • token 缺失时fm_busy_classify报告unknown agy-regex——长回合可能把标记滚出捕获尾部。
  • 签名硬编码、无环境变量覆盖,因此杂散变量永远无法改变 worker 状态分类。
  • 旁证:Herdr 自己的注册表全程一致——agent get在回合中报告agent_status=working、之后idle,因此在 Herdr 上原生判定即可携带忙碌,无需新代码。

测试 tests/fm-agy-harness.test.sh 中test_agy_busy_tail_needs_the_pinned_status_row、test_agy_busy_signatures_are_harness_scoped、test_agy_classify_reports_unknown_when_the_marker_scrolls_out分别钉死:只有钉住的状态行才算忙碌、签名按 harness 隔离、滚出捕获尾时报告 unknown。

7. 中断与退出:单次 Escape 取消,/quit退出

  • 回合中经herdr pane send-keys发送单个Escape即可取消回合,打印如下行,composer 回到空闲、无文本再污染:
⎿ Interrupted · What should Antigravity CLI do instead?
  • 发送/quit加 Enter 退出进程;pane 在exec启动方式下关闭,Herdr 报告 pane 消失。

bin/fm-control-lib.sh 对 agy 记录:中断键Escape(一次,无清除键,无 ack 来源)、退出命令/quit(与 codex、pi、omp、gemini、devin 相同)。test_agy_control_mechanics_are_the_verified_ones钉死该控制机制。

8. 后端存活:Herdr 原生识别,tmux 靠进程名

$ herdr agent get w2:p1 --session fm-lab-firstmate-agy-ad-1599574-8823 {"result":{"agent":{"agent":"agy","agent_status":"idle",...,"agent_session":{"agent":"agy","kind":"id","source":"herdr:antigravity_cli",...}}}}
  • Herdr原生跟踪 agy(antigravity-cli集成,检测为agent=agy),因此fm_backend_herdr_pane_agent_state对 agy 的每个已注册状态都返回live,无需任何退出检测加固。
  • tmux 适配器通过 bin/fm-agent-process-lib.sh 的共享名称词汇表,把锚定进程名agy分类为agent——这是 muse/omp 开创的"短裸词名"先例。
  • agy 不在 bin/fm-session-lock-lib.sh 的会话锁名称词汇表中——其他纯 crewmate 适配器同样缺席。

9. Composer:按设计判为 unknown,投递靠忙碌转换

对空闲 pane 的字节级捕获显示:一个无样式的裸>位于两条全宽─规则之间,状态行中是未样式化的? for shortcutscell 与一个暗色(SGR 2)模型 cell。共享分类器在死壳规则下把裸>判为unknown,永远不会是empty。

但投递确认依然成立,因为:

  • Herdr 提交核心以原生idle→working转换为先导,而 agy 会执行这个转换;
  • tmux 路径由投递页脚正则覆盖。

实测时序(agy 1.2.1,2026-09-12 重测)暴露了 agy 的确认循环特性:忙碌页脚渲染较晚——短 steer 约在 Enter 后 1.5 秒,较长真实 brief 约 4–5 秒,而共享预算只有 3 × 0.4 秒。因此 bin/fm-send.sh 给 agy 的键入目标更长的默认提交确认预算:FM_SEND_RETRIES缺省 20 次重试(默认节奏下约 8 秒);显式FM_SEND_RETRIES仍然优先,其余每个 harness 保持共享的 3 次重试缺省。测试钉死:tests/fm-send-agy-confirm.test.sh 锁定提高后的默认值,tests/fm-agy-harness.test.sh 锁定 Herdr 转换路径。这是 cursor 的先例,而非需要在共享代码里打补丁的缺口。

10. 监督式任务全流程:spawn、steer、relaunch、exit

一个简单 scout 通过bin/fm-spawn.sh --harness agy在同一个隔离实验室会话中端到端跑通:

  • spawn:spawned agy-e2e1 harness=agy kind=scout,treehouse 供应的 worktree、--model gemini-3.8-flash-low、--effort low全部记入任务元数据。worker 写入其 worktree 文件,并向其位于 worktree 之外的状态文件追加done: agy e2e turn complete——证明 prompt 处理、工具执行、工作区外文件访问、以及新完成事件四件事同时成立。
  • steer(持久定向):bin/fm-send.sh消息落入任务收件箱,worker 把 steered 行追加到两个文件,收件箱记录移到handled/。
  • relaunch(同副本重启):bin/fm-control.sh relaunch --note在相同的 worktree、模型、力度上原地替换 worker;替换者核验先前两行内容完好并追加relaunched: done。
  • exit:bin/fm-control.sh exit停止 worker,注册表返回agent_not_found,pane 保留为 worktree 中的孤立 shell,所有工作完好。

值得强调的边界声明:没有自动配额故障转移被测试或被声称——上述每次交接都是显式的受监督 relaunch。

11. 仍未证明的事项

验证记录诚实列出了知识边界,本文照录:

  • 未认证失败模式从未被观测到:此宿主上的 agy 以登录态运行,因此任何认证提示都是"大声失败的凭证阻塞器",而不是可处理的对话框。
  • 无斜杠技能调用形式被验证:技能调用保持自然语言形态。
  • --continue与--conversation恢复从未被演练:恢复走的是"从磁盘上的 brief 确定性 relaunch"路线。
  • 没有任何 primary 或 secondmate 行为被构建或测试,也不声称存在。

12. 刷新这份记录:升级后必跑的验证套件

进程名、标记集合、信任对话框文本、忙碌/中断渲染文本全部是厂商控制的表面,spawn 闸门与忙碌回退逐字匹配它们。因此任何 agy 升级后都应运行可移植套件与现场守卫:

bin/fm-test-run.sh tests/fm-agy-harness.test.sh FM_AGY_SIGNALS_LIVE=1 bin/fm-test-run.sh tests/fm-agy-signals-live-e2e.test.sh

第一条是可移植的单元/集成套件(无现场依赖),第二条是开启FM_AGY_SIGNALS_LIVE=1的现场端到端守卫,专门验证真实 agy 二进制下的信号链路(对应 tests/fm-agy-signals-live-e2e.test.sh)。

13. 小结:一份可复用的"无标记 TUI 后端"托管范式

agy 适配器验证记录的价值远超 agy 本身:它示范了一套在"无身份标记、无 hook 表面、有文件夹信任对话框、忙碌页脚渲染延迟"的多重不利条件下托管外部 CLI 的完整方法论——用锚定进程名做检测,用启动前预注册消解交互对话框,用"先启动后确认"的轮询闸门把对话框应答与忙碌签名绑定为就绪证据,用渲染尾部钉住的状态行做忙碌信号且对缺失显式报告 unknown。配合 docs/architecture.md 与 docs/agent-control.md 阅读,可以看清它在 firstmate 整体 agent 编排架构中的位置:agy 是纯 crewmate/scout 适配器之一,与 muse、rovo、devin 同属"按需雇佣、无人值守、可监督可回收"的那一类工人。

【免费下载链接】firstmate

Talk to one agent. Ship with a crew.

项目地址:https://gitcode.com/gh_mirrors/fi/firstmate
点击查看免费下载

相关推荐

上一篇:CodeGeeX代码生成实战:5大常见错误分析与修复指南
下一篇:Coding Coach数据分析:Google Analytics集成与用户行为追踪

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/9 1:46:36

Pi编程智能体实战:概念厘清、skill导入与subagent编排全解析

不整虚的&#xff0c;直接聊点真东西。最近“pi”这个词热度很诡异&#xff0c;你搜出来一堆结果&#xff0c;有讲树莓派的&#xff0c;有讲圆周率的&#xff0c;还有讲控制器的PI参数的。但真正在开发者圈子里炸开锅的&#xff0c;是那个叫 Pi 的 Agent——也就是大家口中的 p…

作者头像 李华
网站建设 2026/10/9 1:46:14

AI Native团队落地手册:从CLAUDE.md到多Agent编排的完整SDLC实践

1. 从“用AI写代码”到“AI Native团队”&#xff1a;差的不是工具&#xff0c;是整套协作骨架很多团队嘴上说着“我们已经 AI Native 了”&#xff0c;实际干的事无非是给每个人开了个 AI 编程助手的账号&#xff0c;然后继续用三年前那套需求评审、排期、联调、提测的流程。结…

作者头像 李华
网站建设 2026/10/9 1:45:44

Agent Memory架构设计与落地:为大模型打造外挂大脑

做过 Agent 的同学&#xff0c;应该都踩过同一个坑&#xff1a;Agent 明明能理解复杂指令&#xff0c;可你让它处理完跟用户的整个对话流程&#xff0c;或者隔几天再回来看它&#xff0c;发现它什么都不记得了。我也在这上面翻过车&#xff0c;最后发现根子不在模型能力上&…

作者头像 李华
网站建设 2026/10/9 1:45:33

LangGraph 实战教程:从 ReAct Agent 到 StateGraph 状态机,构建复杂决策链

在前四篇文章中,我们构建了能够渲染组件、流式解析、多工具并发和实时搜索的 AI 助手。然而,当面对复杂的多步骤任务时,传统的 while 循环开始显露局限性… 你是否遇到过这样的场景: 用户说:“我要去一个北京现在气温在 15 度以上的公园”AI 需要先搜索气温 → 如果不满足再搜…

作者头像 李华