内容提要
FrontierAgent是Apodex开源的agent运行时,针对长程agent失败的两个量化问题:上下文压缩触发过晚导致子agent被端点拒绝,以及压缩后模型重复发送相同搜索。解决方案包括投影下一次请求大小触发压缩,以及通过观察者回滚重复工具调用。文章还涉及任务板、路径授权等细节,强调基于真实失败数据设计机制。
延伸解读
压缩触发时机:投影而非事后
FrontierAgent 将压缩触发从“本轮末尾”改为“投影下一次请求”,因为推理内容回放会让下一轮请求比刚发出的多出约四万 token。校准比例基于真实回报与本地估算的比值,并钳制在 1.0 到 3.0,防止低估。阈值设为窗口的 0.8,经 160 组测试验证,0.65 虽触发更多但无收益,说明余量不是瓶颈,时机才是。
重复检索的回滚机制
压缩后模型常重发相同搜索,平均每次失败试次重发 37 个查询。观察者在工具执行前介入,若发现整批调用与已执行请求重复,则丢弃该助手消息并重跑,不消耗轮次。去重粒度是整批调用,避免误伤查询演进;键排除 num 等参数但保留翻页参数。终结工具被排除,防止报告丢失。
记账时机与活锁防护
回滚预算默认 5,连续 4 次回滚后放行重复,防止活锁。计数器在带工具调用且无重复时清零,预算耗尽后需完整干净轮次才能重新武装。记账在拿到工具结果时进行,而非放行时,因为搜索失败以普通结果返回,上游故障时重发是正确行为,不应被拦截。
路径授权与敏感词匹配
文件访问 fail-closed,允许前缀列表外一律拒绝。敏感文件名按基本名词级匹配,而非路径子串,避免误伤 tokenizer_config.json 等。沙箱目录策略:/inputs 只读、/workspace 读写、/outputs 受控,交互式会话额外批准危险操作,文件改动可撤销。
Q&A
FrontierAgent 是什么?
FrontierAgent 是 Apodex 开源的 agent 运行时,包含终端产品和评测套件,支持 ReAct 和 Agent Team 两种工作流,用 Python 编写,约 13 万行代码,采用 Apache 2.0 许可证。
FrontierAgent 如何解决上下文压缩触发过晚的问题?
FrontierAgent 通过投影下一次请求的大小来触发压缩,而不是仅看当前请求。它记录端点真实回报的 prompt_tokens,并计算一个校准比例(钳制在 1.0 到 3.0),用该比例缩放轮末估算值,取真实值和投影值的较大者与阈值(上下文窗口的 0.8)比较,从而提前触发压缩,避免子 agent 因请求过大被端点拒绝。
FrontierAgent 如何抑制重复搜索?
FrontierAgent 使用一个观察者,在模型发出带工具调用的回复后、工具执行前介入。如果发现某个被追踪的工具调用重复了本轮已执行的请求,就返回干预,丢弃该助手消息并重跑这一轮,且不消耗 max_turns 名额。去重粒度是整批 web_search 调用,并排除 num 等参数,保留 page 等影响结果集的参数。
FrontierAgent 的路径授权策略是怎样的?
FrontierAgent 对文件访问采用 fail-closed 策略,只允许列表中的前缀,其余拒绝。敏感文件名(如 credential、secret)按基本名词级匹配,而非整条路径子串测试,以避免误伤 tokenizer_config.json 等文件。沙箱目录策略为 /inputs 只读、/workspace 读写、/outputs 受控读写,交互式会话对写入、删除等操作有额外批准。
FrontierAgent 的任务板如何保证阶段显示正确?
任务板在每次写操作时记录当前阶段,因为流式观察者可能不在规划循环上,导致操作延迟到执行循环才被排空。通过冻结写入时刻的阶段,确保规划阶段的 add_task 显示为规划阶段。
FrontierAgent 的测试名有什么特点?
测试名是完整的句子,直接描述设计意图,例如 test_the_measured_death_scenario_now_triggers 和 test_repeat_of_an_executed_query_is_rolled_back。有些测试还验证了移除守卫后问题会复现,确保代码的有效性。
FrontierAgent 如何运行?
需要 Python 3.12、uv 和 OpenAI 兼容端点,Docker 可选。克隆仓库后执行 uv sync --python 3.12 --extra dev,复制 .env.example 为 .env 并填写端点,然后运行 uv run frontier-agent --mode react 或 --mode agent_team 启动终端。评测通过子进程 runner 运行,支持断点续跑。
FrontierAgent 的两个失败模式之间有什么关系?
两个失败模式形成一个循环:压缩为了保住上下文而丢弃旧结果,导致模型重发搜索,重发的结果又撑大上下文,逼出下一次压缩。它们本质上是同一问题的两端,需要合起来理解。