fix(agent,loop): 静音路径工具广告面与流式路径统一(P0-12,审计 §4.3)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled

- 原缺陷:流式路径经 loop.toolSchemas(capacity 允许集 + restrict)过滤,而 agent 静音/内部路径
  (RunStep,被 services/automations 等使用)广告 dispatcher **全量** ⇒ 两条路径不一致
- 修法(方案 1):**过滤实现只留一份**(loop.toolSchemas);l.agentStep 调用同一个函数,结果经
  agent.WithToolSurface(ctx, …) 下传,agent 的 buildRequest 原样广告(取不到才回退全量,保持既有回退语义)
  · 按构造相同:同一次函数调用、同一份输入 ⇒ 不存在第二份可漂移的实现
  · 未选「抽共享函数两侧各调一次」:loop 的过滤输入含 loop 私有会话环境 ctx key 与 capacity 判定器,
    agent 侧凑齐等于再造一套 ctx 管线,漂移面更大
- 复核:agent/loop 包测试绿;新增 parity 用例(owner 与 group 两组,静音 == 流式);
  变异(撤掉下传行)→ parity 必红且精确复现「静音=全量 4 个」,已还原
- 附注:全仓仅剩 `services/automations` 的「无 Loop 回退」仍广告全量(没有循环就没有闸可言);
  子代理 ToolWhitelist 是执行期否决、本不参与 schema 过滤(未改)
This commit is contained in:
AskaEth committed 2026-10-04 14:14:05 +08:00
1 parent 20d452a51a
commit 5c28ace70d
5 files changed
+303 -10

No files matched your search

+6 -1
View File
@@ -82,8 +82,13 @@ const (
// 输出侧紧接模型返回裁决(裁决 13.4.1 的「输出侧异步」由流式主路径
// loop.streamStep 承担——agent.RunStep 只服务静音/非流式内部流程,不落在
// 主会话关键路径上,且它的裁决是 StepResult 的一部分)。
//
// 工具面(Tools)不由本方法选择:驱动本步的循环经 WithToolSurface 把过滤好的
// 本步工具面挂在 ctx 上(capacity 允许集 + design/11 §3 环境安全门),本方法
// 只负责原样广告,使静音/非流式路径与流式路径的广告面一致(audit P0-12)。
// 独立使用(ctx 未挂载工具面)时按 dispatcher 全量广告,行为与从前一致。
func (a *Agent) RunStep(ctx context.Context, sessionID string, messages []model.Message) (*StepResult, error) {
req := a.buildRequest(messages)
req := a.buildRequest(ctx, messages)
if a.guards != nil {
gctx, gspan := trace.ChildSpan(ctx, guardrailSpanInput, trace.SpanKindGuardrail)