docs: 清理过期文档,新增认证 Token 刷新设计文档
This commit is contained in:
@@ -1,188 +0,0 @@
|
||||
# Agent 模块审查报告
|
||||
|
||||
**日期**: 2026-03-07
|
||||
**范围**: `backend/src/core/agent`
|
||||
**状态**: 待修复
|
||||
|
||||
---
|
||||
|
||||
## 🔴 HIGH - 阻塞性问题
|
||||
|
||||
### 1. 同步 LLM 调用阻塞异步事件循环
|
||||
|
||||
**文件**: `infrastructure/crewai/runtime.py:126`
|
||||
|
||||
**问题**:
|
||||
```python
|
||||
response = run_completion(...) # 同步调用
|
||||
```
|
||||
|
||||
`run_completion` 使用 `litellm.completion()` 是同步的,但 `RunService.run()` 是异步方法。这会阻塞整个事件循环,在高并发下严重影响性能。
|
||||
|
||||
**建议**: 使用 `litellm.acompletion()` 或 `asyncio.to_thread()`。
|
||||
|
||||
**影响范围**:
|
||||
- `infrastructure/litellm/client.py` - 需要添加异步版本
|
||||
- `infrastructure/crewai/runtime.py` - `_run_stage()` 需要改为异步
|
||||
|
||||
---
|
||||
|
||||
## 🟡 MEDIUM - 需要修复
|
||||
|
||||
### 2. 缺少输入长度验证
|
||||
|
||||
**文件**: `application/run_service.py:63`
|
||||
|
||||
**问题**:
|
||||
```python
|
||||
async def run(self, *, session_id: str, user_input: str) -> dict[str, object]:
|
||||
```
|
||||
|
||||
`user_input` 没有长度限制,恶意用户可发送超大输入消耗 tokens 和资源。
|
||||
|
||||
**建议**: 添加最大长度验证(如 10000 字符)。
|
||||
|
||||
```python
|
||||
MAX_USER_INPUT_LENGTH = 10000
|
||||
|
||||
if len(user_input) > MAX_USER_INPUT_LENGTH:
|
||||
raise ValueError(f"user_input exceeds maximum length of {MAX_USER_INPUT_LENGTH}")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. LLM 调用无超时控制
|
||||
|
||||
**文件**: `infrastructure/crewai/runtime.py:126`
|
||||
|
||||
**问题**: `run_completion` 没有设置超时,如果 LLM API 挂起,请求会无限期阻塞。
|
||||
|
||||
**建议**: 添加 `timeout` 参数。
|
||||
|
||||
```python
|
||||
def run_completion(
|
||||
*,
|
||||
model: str,
|
||||
api_key: str,
|
||||
messages: list[dict[str, Any]],
|
||||
temperature: float | None = None,
|
||||
max_tokens: int | None = None,
|
||||
timeout: float | None = None, # 新增
|
||||
) -> Any:
|
||||
kwargs["timeout"] = timeout
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. 硬编码工具结果
|
||||
|
||||
**文件**: `application/resume_service.py:52`
|
||||
|
||||
**问题**:
|
||||
```python
|
||||
content='{"status":"ok"}',
|
||||
```
|
||||
|
||||
工具执行结果被硬编码为 `{"status":"ok"}`,看起来是占位符代码,实际工具执行结果未被使用。
|
||||
|
||||
**建议**: 实现真正的工具执行逻辑,或明确标注为待实现。
|
||||
|
||||
---
|
||||
|
||||
### 5. 缓存写入异常静默失败
|
||||
|
||||
**文件**: `infrastructure/persistence/user_context_cache.py:95-96`
|
||||
|
||||
**问题**:
|
||||
```python
|
||||
async def set(self, *, session_id: UUID, context: UserAgentContext) -> None:
|
||||
...
|
||||
except Exception:
|
||||
return None
|
||||
```
|
||||
|
||||
`set()` 方法失败时静默返回 `None`,调用方无法知道缓存是否成功,可能导致缓存失效问题难以排查。
|
||||
|
||||
**建议**: 记录日志或抛出异常。
|
||||
|
||||
```python
|
||||
except Exception as exc:
|
||||
logger.warning("Failed to cache user context", session_id=str(session_id), error=str(exc))
|
||||
return None
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🟢 LOW - 建议改进
|
||||
|
||||
### 6. Redis Stream 响应格式校验缺失
|
||||
|
||||
**文件**: `infrastructure/events/redis_stream.py:62`
|
||||
|
||||
**问题**:
|
||||
```python
|
||||
_, entries = response[0]
|
||||
```
|
||||
|
||||
假设 response 格式正确,异常格式会导致 `IndexError`。
|
||||
|
||||
**建议**: 添加防御性检查。
|
||||
|
||||
---
|
||||
|
||||
### 7. 路径限制不支持子目录
|
||||
|
||||
**文件**: `infrastructure/crewai/loader.py:47`
|
||||
|
||||
**问题**:
|
||||
```python
|
||||
if resolved.parent != base_dir:
|
||||
```
|
||||
|
||||
只允许文件直接在 `base_dir` 下,未来扩展子目录模板可能受限。
|
||||
|
||||
**建议**: 改为检查路径是否在 `base_dir` 下(允许子目录)。
|
||||
|
||||
---
|
||||
|
||||
### 8. 异常信息丢失
|
||||
|
||||
**文件**: `infrastructure/queue/tasks.py:112`
|
||||
|
||||
**问题**:
|
||||
```python
|
||||
except Exception: # noqa: BLE001
|
||||
error_id = "agent_runtime_failed"
|
||||
logger.exception(...)
|
||||
```
|
||||
|
||||
捕获所有异常但只用 `error_id` 标识,丢失了具体异常类型,排查困难。
|
||||
|
||||
**建议**: 在日志中记录异常类型。
|
||||
|
||||
---
|
||||
|
||||
## ✅ 良好实践
|
||||
|
||||
以下设计值得肯定:
|
||||
|
||||
- **DDD 分层清晰**: domain / application / infrastructure 职责分明
|
||||
- **Repository 不做 commit**: 由 Service 控制事务边界
|
||||
- **并发控制**: 使用 `FOR UPDATE` 锁防止并发问题
|
||||
- **敏感字段脱敏**: `agui/bridge.py` 实现了 `_redact_sensitive()`
|
||||
- **路径穿越防护**: `loader.py` 使用 `_resolve_allowed_path()`
|
||||
- **协议抽象**: 使用 Protocol 进行依赖解耦
|
||||
|
||||
---
|
||||
|
||||
## 修复优先级建议
|
||||
|
||||
| 优先级 | 问题 | 预计工时 |
|
||||
|--------|------|----------|
|
||||
| P0 | 同步 LLM 调用阻塞 | 2h |
|
||||
| P1 | 输入长度验证 | 0.5h |
|
||||
| P1 | LLM 超时控制 | 1h |
|
||||
| P2 | 硬编码工具结果 | 待定 |
|
||||
| P2 | 缓存异常处理 | 0.5h |
|
||||
| P3 | 其他 LOW 问题 | 1h |
|
||||
@@ -1,323 +0,0 @@
|
||||
# Agent 模块审查报告 - 工具架构
|
||||
|
||||
**日期**: 2026-03-08
|
||||
**范围**: `backend/src/core/agent`
|
||||
**状态**: 待评估
|
||||
|
||||
---
|
||||
|
||||
## 🟡 MEDIUM - 工具架构问题
|
||||
|
||||
### 1. 未使用 CrewAI 工具模块,工具硬编码
|
||||
|
||||
**文件**:
|
||||
- `application/run_service.py:406` - `_execute_backend_tool()`
|
||||
- `infrastructure/crewai/runtime.py` - 三阶段流程
|
||||
|
||||
**问题**:
|
||||
|
||||
当前 agent 只使用了 CrewAI 的 **agent/task 配置模板**(YAML),但**没有使用 CrewAI 的工具系统**:
|
||||
|
||||
```
|
||||
已用到:
|
||||
├── agents.yaml (agent 角色定义)
|
||||
└── tasks.yaml (task 定义)
|
||||
|
||||
未用到:
|
||||
├── @tool 装饰器
|
||||
├── BaseTool 类
|
||||
└── Tools 工具注册表
|
||||
```
|
||||
|
||||
**当前实现**:
|
||||
```python
|
||||
# run_service.py:406
|
||||
async def _execute_backend_tool(self, *, tool_name, tool_args, ...):
|
||||
if tool_name != "create_calendar_event": # 硬编码判断
|
||||
raise ValueError(f"unsupported backend tool: {tool_name}")
|
||||
# 手动执行工具...
|
||||
```
|
||||
|
||||
**影响**:
|
||||
1. 每新增一个工具需要修改 `_execute_backend_tool()` 代码
|
||||
2. 无法利用 CrewAI 的工具选择、执行结果处理等能力
|
||||
3. 与 CrewAI 集成度低,无法发挥框架优势
|
||||
4. 无法将工具描述等prompt信息自动注入agent中
|
||||
|
||||
---
|
||||
|
||||
## 🟡 MEDIUM - 工具结果存储问题
|
||||
|
||||
### 2. 工具结果存储到对象存储的功能未启用
|
||||
|
||||
**文件**:
|
||||
- `application/session_state_persistence.py:52` - `persist_tool_result_payload()`
|
||||
- `models/agent_chat_message.py` - messages 表
|
||||
|
||||
**问题**:
|
||||
|
||||
已定义 `persist_tool_result_payload()` 函数,可将工具结果上传到对象存储(MinIO/Supabase Storage),但**该函数未被调用**。
|
||||
|
||||
当前实现:
|
||||
- 工具结果直接存在数据库 `messages.content` 字段
|
||||
- `metadata_json` 中定义了 `storage_bucket`, `storage_path` 等字段,但都是 `None`
|
||||
|
||||
```python
|
||||
# message_metadata.py:17-27
|
||||
class MessageMetadataToolResult(BaseModel):
|
||||
storage_bucket: str | None = None # 当前未使用
|
||||
storage_path: str | None = None # 当前未使用
|
||||
payload_sha256: str | None = None # 当前未使用
|
||||
```
|
||||
|
||||
**影响**:
|
||||
1. 工具结果(尤其是 UI 组件等大数据)存在数据库,增加 DB 负担
|
||||
2. 已定义的存储接口未被使用,代码冗余
|
||||
3. 无法利用对象存储的 CDN 加速和带宽优势
|
||||
|
||||
---
|
||||
|
||||
## 🟡 MEDIUM - 工具输出格式问题
|
||||
|
||||
### 3. 工具输出不是 UI Schema,前端无法直接渲染
|
||||
|
||||
**文件**:
|
||||
- `application/run_service.py:456-479` - `_execute_backend_tool()`
|
||||
|
||||
**问题**:
|
||||
|
||||
当前 `create_calendar_event` 工具返回的是**非结构化文本**,不是前端可渲染的 UI Schema:
|
||||
|
||||
```python
|
||||
# run_service.py:456-479
|
||||
event_id = str(schedule_item.id)
|
||||
ui_card = {
|
||||
"type": "calendar_card.v1",
|
||||
"version": "v1",
|
||||
"data": {...}
|
||||
"actions": [...]
|
||||
}
|
||||
# ui_card 构建了但没有作为 tool result 返回
|
||||
return {"status": "ok", "event_id": event_id} # 只返回了简单结构
|
||||
```
|
||||
|
||||
**当前输出**:
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"event_id": "xxx"
|
||||
}
|
||||
```
|
||||
|
||||
**期望输出**(UI Schema):
|
||||
```json
|
||||
{
|
||||
"type": "calendar_card.v1",
|
||||
"version": "v1",
|
||||
"data": {
|
||||
"id": "xxx",
|
||||
"title": "会议",
|
||||
"startAt": "2026-03-08T15:00:00Z",
|
||||
...
|
||||
},
|
||||
"actions": [
|
||||
{"type": "link", "label": "查看详情", "target": "/calendar/events/xxx"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**影响**:
|
||||
1. 前端无法直接渲染丰富的 UI 组件
|
||||
2. 需要前端手动解析文本再渲染,增加前端工作量
|
||||
3. 无法利用 AG-UI 协议的 `ui_schema` 能力
|
||||
|
||||
---
|
||||
|
||||
## 🟡 MEDIUM - 阶段配置问题
|
||||
|
||||
### 4. 三阶段流程参数硬编码,无法为每个阶段配置不同策略
|
||||
|
||||
**文件**:
|
||||
- `infrastructure/crewai/runtime.py:190-277` - `CrewAIRuntime.execute()`
|
||||
|
||||
**问题**:
|
||||
|
||||
当前三阶段流程(intent → execution → organization)是硬编码在 `run_agent_task()` 中的,无法为每个阶段配置不同的参数,如每个阶段可以使用的工具:
|
||||
|
||||
```python
|
||||
# runtime.py:203-277
|
||||
# intent 阶段
|
||||
intent_text, intent_usage = _run_stage(
|
||||
litellm_model=litellm_model,
|
||||
api_key=...,
|
||||
llm_config=self._llm_config, # 同一套配置
|
||||
stage="intent",
|
||||
...
|
||||
)
|
||||
|
||||
# execution 阶段(如果有)
|
||||
execution_text, execution_usage = _run_stage(
|
||||
litellm_model=litellm_model,
|
||||
api_key=...,
|
||||
llm_config=self._llm_config, # 同一套配置
|
||||
stage="execution",
|
||||
...
|
||||
)
|
||||
|
||||
# organization 阶段
|
||||
organization_text, organization_usage = _run_stage(
|
||||
litellm_model=litellm_model,
|
||||
api_key=...,
|
||||
llm_config=self._llm_config, # 同一套配置
|
||||
stage="organization",
|
||||
...
|
||||
)
|
||||
```
|
||||
|
||||
**当前限制**:
|
||||
1. 无法为 intent 阶段设置只读 LLM(不允许工具调用)
|
||||
|
||||
|
||||
**影响**:
|
||||
1. 无法精细控制每个阶段的 LLM 行为
|
||||
2. 意图识别阶段可能误触发工具调用
|
||||
3. 增加不必要的 LLM 调用成本
|
||||
4. 降低了架构的灵活性
|
||||
|
||||
---
|
||||
|
||||
## 🔴 HIGH - Agent Loop 断裂问题
|
||||
|
||||
### 5. 工具审批后未继续 Agent Loop
|
||||
|
||||
**文件**:
|
||||
- `application/resume_service.py:121-158`
|
||||
|
||||
**问题**:
|
||||
|
||||
前端审批工具调用后,后端返回 tool result,但**没有继续执行 agent loop**,直接标记 session 为 COMPLETED 结束。
|
||||
|
||||
当前流程:
|
||||
```python
|
||||
# resume_service.py:121-127
|
||||
snapshot = self._state_persistence.build_completed_snapshot()
|
||||
await session_repository.update_runtime_state(
|
||||
chat_session=chat_session,
|
||||
status=AgentChatSessionStatus.COMPLETED, # 直接完成
|
||||
state_snapshot=snapshot,
|
||||
...
|
||||
)
|
||||
```
|
||||
|
||||
缺失的流程:
|
||||
```
|
||||
1. 接收 tool result
|
||||
2. 将 tool result 作为 message 存入上下文
|
||||
3. 再次调用 LLM(带 tool result)
|
||||
4. 生成最终回复
|
||||
5. 标记为 COMPLETED
|
||||
```
|
||||
|
||||
**影响**:
|
||||
1. 用户审批工具后,agent 不会继续生成回复
|
||||
2. 整个 agent loop 在工具审批后断裂
|
||||
3. 用户体验不完整
|
||||
|
||||
---
|
||||
|
||||
## 🔴 HIGH - 对话历史和用户上下文架构错误
|
||||
|
||||
### 6. 对话历史由前端维护,违反后端架构设计
|
||||
|
||||
**文件**:
|
||||
- `application/run_service.py:89-124`
|
||||
- `domain/agui_input.py`
|
||||
|
||||
**问题**:
|
||||
|
||||
当前架构中,**对话历史完全由前端维护并传递**:
|
||||
|
||||
```
|
||||
前端 → GET /runs/{thread_id}/history → 后端返回历史 messages
|
||||
前端 → POST /runs/{thread_id}/run → 前端把 history 放入 run_input.messages 传给后端
|
||||
后端 → 只读取 run_input 中的最新 user_input,不读取数据库历史
|
||||
```
|
||||
|
||||
代码证据 (`run_service.py:89-124`):
|
||||
```python
|
||||
async def run(self, *, run_input: RunAgentInput):
|
||||
user_input = extract_latest_user_text(run_input) # 只取最新用户消息
|
||||
|
||||
runtime_result = await asyncio.to_thread(
|
||||
runtime.execute,
|
||||
user_input=user_input, # 只传最新输入
|
||||
system_prompt=system_prompt,
|
||||
)
|
||||
```
|
||||
|
||||
**影响**:
|
||||
1. **高危安全风险**:前端可以篡改对话历史,伪造上下文
|
||||
2. **架构违反**:用户上下文和对话历史都应该由后端维护
|
||||
3. **数据不一致**:前端可能遗漏或错误处理历史消息
|
||||
4. **无法支持多端同步**:不同前端设备看到的历史可能不同
|
||||
5. **Token 浪费**:每次请求都要传递完整历史,增加请求体积
|
||||
6. 原来的计划文档写清楚了,后端通过redis来缓存对话历史,并结合数据库读取的回退策略
|
||||
|
||||
---
|
||||
|
||||
## 🟡 MEDIUM - 多模态输入支持问题
|
||||
|
||||
### 7. 不支持图片等多模态输入
|
||||
|
||||
**文件**:
|
||||
- `domain/agui_input.py:64-86` - `extract_latest_user_text()`
|
||||
- `infrastructure/crewai/runtime.py:121-136` - `_run_stage()`
|
||||
- `infrastructure/litellm/client.py`
|
||||
|
||||
**问题**:
|
||||
|
||||
当前架构**只支持纯文本输入**,图片等多模态内容被丢弃:
|
||||
|
||||
代码证据 (`agui_input.py:64-86`):
|
||||
```python
|
||||
def extract_latest_user_text(run_input: RunAgentInput) -> str:
|
||||
if isinstance(content, list):
|
||||
for item in content:
|
||||
if getattr(item, "type", None) != "text":
|
||||
continue # ❌ 跳过非 text 类型(图片被丢弃)
|
||||
```
|
||||
|
||||
代码证据 (`runtime.py:125`):
|
||||
```python
|
||||
messages.append({"role": "user", "content": user_content}) # 只传 str
|
||||
```
|
||||
|
||||
**影响**:
|
||||
1. 用户无法发送图片进行多模态交互
|
||||
2. 浪费多模态 LLM 能力
|
||||
3. 无法实现"上传图片让 AI 分析"等场景
|
||||
|
||||
---
|
||||
|
||||
## 🟡 MEDIUM - 缺失语音识别 (ASR) 功能
|
||||
|
||||
### 8. 未实现 fun-asr-realtime 语音识别 API 相关路由
|
||||
|
||||
**文件**:
|
||||
- 无(功能缺失)
|
||||
|
||||
**问题**:
|
||||
|
||||
后端**未实现语音识别功能**,无法处理前端传入的音频数据:
|
||||
|
||||
当前状态:
|
||||
- `dashscope` 只用于 LLM(qwen3.5-flash 等)
|
||||
- 没有任何 fun-asr、ASR、audio、transcribe 相关代码
|
||||
- v1 路由中无语音/音频相关 API
|
||||
|
||||
**影响**:
|
||||
1. 用户无法发送语音消息
|
||||
2. 无法实现实时语音对话场景
|
||||
3. 需要前端自行完成 ASR,增大前端负担
|
||||
|
||||
---
|
||||
@@ -1,118 +0,0 @@
|
||||
# Bug - 后端工具事件与前端中断稳定性
|
||||
|
||||
**日期**: 2026-03-08
|
||||
**范围**: `backend/src/core/agent`
|
||||
|
||||
## 状态
|
||||
|
||||
- [x] Bug 1 已修复: 后端工具调用事件未转发
|
||||
- [x] Bug 2 已修复: history 未过滤负 seq 内部消息
|
||||
- [ ] Bug 3 调查中: live 前端工具中断不稳定
|
||||
|
||||
---
|
||||
|
||||
## Bug 1 - 后端工具调用不转发事件给前端(已修复)
|
||||
|
||||
### 修复
|
||||
|
||||
- `run_service.py` 现在会消费 runtime 的 `tool_calls`(`target=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_id` 为 `None`。
|
||||
|
||||
### 已采集证据
|
||||
|
||||
- 输入文本已明确要求调用工具。
|
||||
- 前端工具描述已注入到 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 文档要求 `BaseTool` 的 `args_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 校验失败而提前终止。
|
||||
Reference in New Issue
Block a user