工具超时或返回空结果时,如何约束 Agent 向用户反馈真实执行状态?
未标记
考查重点:执行证据与状态反馈。返回结构化状态区分失败、未知和合法空结果;回复说明已完成与未完成动作,超时先查真实执行结果再安排重试
本题目录
参考答案
DB-GPTPython
核心回答
先让执行层返回可判断的状态与证据,再让 Agent 解释结果。没有查到数据、查询失败、等待超时和结果无法归档,是四种不同情况。 超时尤其不能被翻译成“数据库已经停止执行”,也不能用上一次查询的数字补成这一次的答案。
DB-GPT 的数据分析入口将 SQL 工具结果与报告产物关联:正常结果提供 artifact_id 和表格预览;失败返回 success: false 与具体 error_code。接入报告产物 sink 后,真实 SQL 尝试还会记录数据库、SQL、耗时和状态,供后续报告检查。这里约束的是执行事实,不靠提示词要求模型“诚实”来代替执行检查。
空结果和失败如何区分
sql_query 在执行前检查是否选择数据源、是否为单条只读查询,对应 SQL_DATASOURCE_REQUIRED 和 SQL_READ_ONLY_REQUIRED。只读检查遍历解析后的 token,拒绝写操作和 SELECT INTO,但不替代数据库权限,也不证明查询口径正确。执行前检查。
执行成功而没有数据行,是合法的零行结果。返回值可能完全为空,也可能包含列头但没有行;两条路径都可以捕获成功产物,后者保留列和 row_count=0。Agent 应说明“按当前数据源和筛选条件未查到记录”,不能直接推导“该活动销售额为零”。缺少记录、聚合返回 NULL 与数值 0 也要根据具体查询区分。
执行异常则返回 SQL_QUERY_FAILED,不能因为结果中存在一段文字或一个产物记录就当成查询成功。capture_sql_execution() 将带错误的 SQL 产物记为 failed;正常零行产物仍是 succeeded。数据库工具的当前返回结构与 MCP 的 isError 不是同一套字段,但两者都说明调用收到响应不等于业务执行成功。产物捕获、MCP 工具错误约定。
等待超时为什么不能说查询已停止
工具默认通过 asyncio.wait_for() 等待最多 30 秒,超时返回 SQL_QUERY_TIMEOUT,设置 cancel_event,反馈为“已请求中断”。上层任务取消也设置该事件、捕获取消记录,并继续抛出取消异常。
真正能否停止,要看连接器:
- 原生 SQLite 路径把超时和事件传给
query_ex(),通过连接上的 progress handler 检查截止时间及取消信号,并调整锁等待时间。若驱动缺少相应接口,代码会记录警告后继续执行,不能承诺所有 SQLite 环境都有硬中断。 - 其他连接器走线程中的
connector.run();此处没有把同样的取消参数传入。取消等待协程不保证线程里的数据库调用已结束,连接器自身的超时能力需要另行确认。
因此可以说“这次工具等待已超时,尚未取得可用结果,已请求中断”,不能说“查询已被数据库终止”。30 秒是默认等待预算,也不是所有连接器的统一数据库截止时间。工具超时分支、SQLite 协作中断。
工具会提示检查执行计划和关联索引,优化查询后再尝试,而非原样反复提交。若要继续自动重试,应先核对原查询是否仍运行、还剩多少总预算,限制次数和并发;这些是接入时应补齐的运行策略,不能写成当前工具已具备完整查询对账与重试系统。
查询完成但产物保存失败怎么办
capture_sql_execution() 的归档异常会转为 ARTIFACT_CAPTURE_FAILED,说明 SQL 尝试完成,但结果快照没有保存,并明确提示不要重跑查询。Agent 既不能把它说成查询未执行,也不能编造一个可以给报告使用的产物 ID。应反馈“查询尝试已完成,结果归档失败,暂时无法提供可追溯结果”,再由系统恢复归档或人工排查。
报告可以继续使用已经核实的成功产物,但应说明缺少的指标与结论。失败产物只能说明尝试发生过,合法空产物只能说明这次查询没有行,超时记录只能说明工具没有在预算内取得结果;三者都不提供可随意替代的业务数字。