Files
social-app/docs/bugs/2026-03-08-backend-tool-no-events.md
T

5.4 KiB
Raw Blame History

Bug - 后端工具事件与前端中断稳定性

日期: 2026-03-08 范围: backend/src/core/agent

状态

  • Bug 1 已修复: 后端工具调用事件未转发
  • Bug 2 已修复: history 未过滤负 seq 内部消息
  • Bug 3 调查中: live 前端工具中断不稳定

Bug 1 - 后端工具调用不转发事件给前端(已修复)

修复

  • run_service.py 现在会消费 runtime 的 tool_callstarget=backend)并发出:
    • TOOL_CALL_START
    • TOOL_CALL_ARGS
    • TOOL_CALL_END
    • TOOL_CALL_RESULT
  • 同时落库 role=TOOL 消息,metadata 使用 tool_result

验证

  • backend/tests/unit/core/agent/test_run_resume_service.py::test_run_service_executes_backend_calendar_tool_and_emits_result

Bug 2 - seq 设计缺陷与 history 暴露内部消息(已修复)

修复

  • SessionRepository.next_message_seq() 支持 mode:
    • public: 仅基于正序号递增
    • internal: 基于负序号递减
  • v1/agent/repository.py history 查询增加 seq > 0 过滤。

验证

  • backend/tests/unit/v1/agent/test_repository.py::test_get_history_day_filters_out_negative_seq_messages

Bug 3 - live 前端工具中断不稳定(调查中)

现象

  • test_agent_live_front_tool_interrupt_resume_continue 偶发或持续失败。
  • 失败点: pending_tool_call_idNone

已采集证据

  • 输入文本已明确要求调用工具。
  • 前端工具描述已注入到 prompt,且 execution 阶段可见工具列表。
  • 部分失败样本中,模型在 execution 输出里给出“需要审批”的文字/结构化说明,但没有真正触发工具调用事件。
  • 常见 execution_data 形态:
    • tool_used/tool_name
    • approval_status/approval_required
    • target_route/target
    • 但无真实 tool call 事件。

当前判断

  • 问题不在“工具未注入”。
  • 主要是模型在 execution 阶段把“应调用工具”退化为“文本说明审批状态”,导致 runtime 无法拿到 pending call。

已做改进(非硬编码兜底)

  • 提示词集中化到 core/agent/prompt/runtime_stage_prompts.py
  • execution prompt 增加规则: 工具可满足请求时必须通过 runtime 工具接口调用,不可伪造工具结果文本。
  • pending 提取逻辑增强以兼容 approval_required/target 变体结构。
  • DynamicRoutingTool._run 改为接受 **kwargs,兼容 CrewAI 直接参数调用(之前仅收 payload,会导致 unexpected keyword argument)。
  • execution 阶段关闭 output_pydantic 强约束,避免 structured output 过早收敛影响 ReAct 工具动作循环。

最新验证(2026-03-08 晚)

  • 前端中断 live 用例仍失败:
    • AGENT_LIVE_E2E=1 uv run pytest backend/tests/e2e/test_agent_live_flow.py::test_agent_live_front_tool_interrupt_resume_continue -v -rs
    • 结果:pending_tool_call_id = null
    • assistant 文本会声称“已触发审批/待确认”,但 runtime 仍未捕获真实 tool call。
  • 后端工具 live 用例本次环境未能执行到断言:
    • AGENT_LIVE_E2E=1 uv run pytest backend/tests/e2e/test_agent_live_flow.py::test_agent_live_image_calendar_tool_persistence -v -rs
    • Tool result storage unavailable 已定位并修复(测试初始化顺序问题,不是 Docker Storage 服务故障)
    • 当前新失败为业务断言:未创建 schedule_items
  • 非 live 证据:
    • uv run pytest backend/tests/unit/core/agent/test_crewai_runtime_tools.py -q PASS(验证 front tool kwargs 可进入 runtime
    • uv run pytest backend/tests/unit/core/agent/test_run_resume_service.py -q PASS(后端工具链路单测通过)

后续建议

  1. 为 live 失败样本继续沉淀 execution 原始输出分型统计。
  2. 评估在 execution stage 增加 CrewAI guardrail: 若 NEEDS_EXECUTION 且零 tool call,则判为无效输出并重试。
  3. 若仍不稳定,考虑升级模型或为关键路径启用更强结构化调用策略。
  4. 补充可观测性:在 execution 阶段记录“注入工具名列表 + Crew 原始 action 文本片段(脱敏)”,用于区分“未注入”与“注入后未 act”。

额外排查结论(CrewAI tools 与 Storage

A) CrewAI tools 机制对齐结论

  • 官方 tools 文档要求 BaseToolargs_schema_run 参数语义一致,示例为 _run(self, argument: str)
  • CrewAI 执行器在 ReAct 模式下依赖 Action / Action Input 文本被 parser 解析后才会真正执行工具。
  • 我们此前 _run(self, payload: dict) 与实际运行时 kwargs 形态存在不匹配风险,已改为 _run(self, **kwargs) 兼容调用。
  • execution 阶段若过度强调“直接输出严格 JSON”,会与 ReAct 工具动作循环冲突,已在 prompt 中补充明确的 Action / Action Input 约束。

B) Tool result storage unavailable 根因

  • 根因不是 Supabase Docker Storage 宕机;docker compose ps 显示 supabase-storage healthy。
  • 真实原因是 live 测试在 supabase_service.initialize() 之前调用 create_tool_result_storage(),导致 admin client 尚未初始化而返回 None
  • 已修复测试顺序:先初始化 Supabase,再创建 storage。

C) 现阶段阻塞

  • 后端图片场景还暴露出 AG-UI multimodal 输入兼容问题:type=image 不符合当前 RunAgentInput(期望 binary)。
  • 已修复为 binary 输入并在 agui_input 增加 binary 解析兼容;用例不再因 payload 校验失败而提前终止。