agno ReliabilityEval 可靠性评估实战基于 TEST_LOG 解读工具调用验证、执行匹配与团队场景【免费下载链接】agnoBuild, run, and manage agent platforms.项目地址: https://gitcode.com/GitHub_Trending/ag/agno本篇技术指南以 agno 仓库中cookbook/09_evals/reliability/目录的测试日志TEST_LOG.md最近一次运行于 2026-07-19使用真实的OPENAI_API_KEY为核心骨架结合其背后的ReliabilityEval源码与单元测试系统讲解 agno 中工具调用可靠性评估Reliability Evaluation的验证逻辑、各示例用例的通过标准、执行匹配execution matching语义以及数据库日志集成时的环境坑。读完本文你将掌握如何用ReliabilityEval校验 Agent 是否正确地调用了预期工具、校验工具参数、处理多余调用、验证多智能体团队的委托链路并学会如何从测试日志快速定位评估失败是评估逻辑错误还是Agent 行为错误。一、测试日志概览一次可靠性的全量回归cookbook/09_evals/reliability/目录下的可靠性评估示例核心目标正如其 README.md 所述validate whether expected tool calls are made correctly——验证预期工具调用是否正确发生。该目录的 TEST_LOG.md 记录了最近一次全量运行的完整结论被测示例文件状态说明数据库日志评估db_logging.pyFAIL环境问题评估逻辑本身通过但数据库连接因端口不匹配失败异步可靠性评估reliability_async.pyPASS使用arun异步执行评估单工具调用single_tool_calls/calculator.pyPASS单次预期工具调用 参数校验多工具调用multiple_tool_calls/calculator.pyPASS多个预期工具 allow_additional_tool_calls子集匹配团队委托team/ai_news.pyPASS团队委托与新闻搜索工具的联合校验交叉引用01_democookbook/01_demo/evalsPASS抽查local_wiki_reports_state_honestlyJudge PASS、Reliability PASS、exit 0这份日志最有价值的一点是它用真实运行数据标注了 agno 2.8.0 引入的执行匹配execution matching语义一次工具调用只有干净执行clean execution才算满足预期被拒绝、执行出错、参数垃圾的调用不再算数。日志开篇即声明expectations are satisfied only by clean tool executions。二、核心概念什么是干净执行Clean Execution要读懂这份测试日志必须先理解ReliabilityEval的判定基线。其实现位于 libs/agno/agno/eval/reliability.py评估的输入是 Agent 或 Team 的响应对象RunOutput/TeamRunOutput从中收集两条证据链执行侧证据RunOutput.tools中的ToolExecution列表——这是工具真正执行的记录消息侧证据messages中的tool_calls请求——仅用于标注失败原因不用于判定通过。一个干净执行需满足tool_call_error不为真None也算干净因为从存储重新加载的成功执行可能带None、且is_paused为假仍挂起等待人工确认的调用不算执行过。为何要改为执行匹配源码注释给出了明确理由旧版请求侧匹配会把被拒绝refused、出错errored或参数错误的调用也算作满足预期导致工具从未真正干活也能让评估通过。2.8.0 之后这类评估会转为失败并在missing_tool_calls中明确标注(requested but refused/errored — execution matching, new in 2.8.0)让 CI 变红时能一眼读出是评估错了还是 Agent 错了。这一语义在单元测试 libs/agno/tests/unit/eval/test_reliability_eval.py 中被系统锁定例如test_refused_call_no_longer_passes因tool_call_limit被拒绝的调用只存在于消息侧旧语义会通过新语义必须 FAILEDtest_errored_execution_no_longer_passes出错执行不再算通过test_retry_that_succeeds_still_passes预期工具先出错、后重试成功仍然通过——一次错误执行不会毒化整个评估test_none_tool_call_error_passestool_call_errorNone存储重载场景视为干净。三、单工具调用与参数校验single_tool_calls/calculator.py日志显示该示例PASS其依据是Both functions passed: expected tool matched as a clean execution and the argument check matched againstToolExecution.tool_args。示例文件 single_tool_calls/calculator.py 包含两个评估函数3.1 factorial单次预期工具调用agent Agent(modelOpenAIChat(idgpt-5.2), tools[CalculatorTools()]) response: RunOutput agent.run(What is 10! (ten factorial)?) evaluation ReliabilityEval( nameTool Call Reliability, agent_responseresponse, expected_tool_calls[factorial], ) result: Optional[ReliabilityResult] evaluation.run(print_resultsTrue) if result: result.assert_passed()日志记录factorial作为一次干净执行被匹配评估通过。注意ReliabilityEval的构造参数语义源码字段见 reliability.py参数类型说明namestr评估名称用于日志与结果表标题agent_response/team_responseRunOutput/TeamRunOutput二选一同时传两者会抛ValueErrorexpected_tool_callsList[str]预期工具名列表名称集合匹配无序、去重语义allow_additional_tool_callsbool默认False严格模式True时允许额外调用子集匹配expected_tool_call_argumentsDict工具参数校验支持单字典或多条 spec 列表dbBaseDb/AsyncBaseDb评估结果落库异步库需用arunfile_path_to_save_resultsstr结果保存到文件支持{name}、{run_id}占位符show_spinnerbool默认True套件运行器等不写控制台的环境应关闭telemetrybool默认True上报最小化遥测3.2 multiply_with_argument_check参数校验evaluation ReliabilityEval( nameTool Call Argument Validation, agent_responseresponse, expected_tool_calls[multiply], expected_tool_call_arguments{multiply: {a: 10, b: 5}}, )日志明确提到参数检查匹配的是ToolExecution.tool_args——已解析的 dict而非消息侧的 JSON 字符串。源码中参数校验还有这些值得注意的细节校验只针对干净执行出错执行上的参数即使匹配也不计数测试test_argument_check_ignores_errored_execution部分匹配语义spec 只检查声明的键实际调用多出的键不影响test_argument_validation_partial_match多条 spec 列表如{add: [{a: 2, b: 2}, {a: 3, b: 3}]}每条 spec 必须至少匹配一次调用test_argument_validation_multiple_specstool_argsNone会被当作{}处理不会崩溃test_argument_validation_none_arguments已在missing_tool_calls中的工具不会重复计入failed_argument_checkstest_missing_tool_not_double_counted_in_arg_checks。四、多工具调用与子集匹配multiple_tool_calls/calculator.py日志显示PASS关键结论extra call correctly classified as additional underallow_additional_tool_callsTrue。示例文件 multiple_tool_calls/calculator.py 同样包含两个函数4.1 multiply_and_exponentiate严格模式下的多工具预期response: RunOutput agent.run(What is 10*5 then to the power of 2? do it step by step) evaluation ReliabilityEval( nameTool Calls Reliability, agent_responseresponse, expected_tool_calls[multiply, exponentiate], )严格模式下expected_tool_calls之外出现的任何执行都会进入failed_tool_calls。这里有个容易被忽略的语义严格模式管的是尝试而非成功——一个意外工具即使执行出错或被执行限制拒绝只要 Agent 尝试过它评估同样失败源码_evaluate注释与测试test_strict_mode_fails_on_errored_additional_call、test_strict_mode_fails_on_refused_additional_call均印证。4.2 subset_matching允许额外调用evaluation ReliabilityEval( nameSubset Tool Calls, agent_responseresponse, expected_tool_calls[multiply], allow_additional_tool_callsTrue, )allow_additional_tool_callsTrue将评估切换为子集匹配只要预期工具都出现多余调用如exponentiate会被归类到additional_tool_calls列表既不影响通过又保留了审计可见性。对应单元测试test_subset_matching_passes_with_extra_calls同时test_subset_matching_still_fails_on_missing证明即使允许额外调用预期工具缺失依然 FAILED。五、团队委托的可靠性team/ai_news.py日志显示PASS并给出了一个非常有价值的运行事实delegate_task_to_membermatched from the leaders executions andsearch_newsfrommember_responses[0].tools。示例文件 team/ai_news.py 构建了一个新闻研究团队team_member Agent( nameNews Searcher, modelOpenAIChat(gpt-5.6-luna), roleSearches the web for the latest news., tools[WebSearchTools(enable_newsTrue)], ) team Team( nameNews Research Team, modelOpenAIChat(gpt-5.6-luna), members[team_member], markdownTrue, show_members_responsesTrue, ) expected_tool_calls [delegate_task_to_member, search_news] response: TeamRunOutput team.run(What is the latest news on AI?) evaluation ReliabilityEval( nameTeam Reliability Evaluation, team_responseresponse, expected_tool_callsexpected_tool_calls, )5.1 成员执行并集member-execution union关键点在于ReliabilityEval传入的是team_responseTeamRunOutput。源码通过_collect_member_evidence递归收集证据把响应自身tools与消息加入证据链再遍历member_responses递归处理每一层成员响应reliability.py。这意味着领导者的委托调用delegate_task_to_member从领导者自身的执行中匹配成员实际执行的工具如search_news从成员的RunOutput.tools中匹配成员本身也可以是团队孙级成员的干净执行同样满足预期单元测试test_nested_team_member_executions_matched用三层嵌套验证了这一点内层领导者的delegate_task_to_member与 0 层领导者一样受严格模式约束要么列进expected_tool_calls要么开allow_additional_tool_calls测试test_nested_team_depth_two_delegations_policed_like_depth_zero。5.2 历史消息隔离团队/多轮场景还有一个关键保护from_history标记为真的消息由add_history_to_context注入的先前轮次消息携带的工具调用请求不参与本次评估——昨天的工具不能导致今天严格模式失败测试test_from_history_requests_ignored、test_from_history_request_does_not_annotate_missing。六、异步评估reliability_async.py日志显示PASS且明确factorialmatched as a clean execution。示例文件 reliability_async.py 展示了与同步run()完全等价的异步路径arun()def factorial(): agent Agent(modelOpenAIChat(idgpt-5.2), tools[CalculatorTools()]) response: RunOutput agent.run(What is 10!?) evaluation ReliabilityEval(agent_responseresponse, expected_tool_calls[factorial]) result: Optional[ReliabilityResult] asyncio.run(evaluation.arun(print_resultsTrue)) if result: result.assert_passed()从源码看run()与arun()的核心评估逻辑完全一致都走self._evaluate(run_id)差异仅在外部 I/O同步run()若传入异步 DBAsyncBaseDb会直接抛ValueError提示改用arun()数据库写入走log_eval_run遥测走log_eval_telemetry异步arun()数据库写入走async_log_eval遥测走async_log_eval_telemetry其余行为spinner、结果打印、文件保存一致。此外run_id每次评估执行都会通过uuid4()重新生成reliability.py测试test_arun_logs_distinct_run_id_per_execution与test_rerun_stores_a_row_and_a_file_per_run确认每次run/arun都会在评估表中落一条独立记录run_id即主键。七、数据库日志集成与本次 FAIL 的根因db_logging.py日志中唯一的 FAIL 属于db_logging.py且明确标注为**环境问题environmental**而非逻辑问题The evaluation itself reports PASSED under execution matching, but the db logging step cannot connect。示例 db_logging.py 的完整流程是db_url postgresqlpsycopg://ai:ailocalhost:5432/ai db PostgresDb(db_urldb_url, eval_tableeval_runs) agent Agent(modelOpenAIChat(idgpt-5.2), tools[CalculatorTools()]) response: RunOutput agent.run(What is 10!?) evaluation ReliabilityEval( dbdb, nameTool Call Reliability, agent_responseresponse, expected_tool_calls[factorial], ) result: Optional[ReliabilityResult] evaluation.run(print_resultsTrue) if result: result.assert_passed()7.1 端口不匹配5432 vs 5532根因非常具体db_logging.py把数据库地址硬编码为localhost:5432而仓库自带的 pgvector 启动脚本 cookbook/scripts/run_pgvector.sh 在启动容器时将宿主机端口5532映射到容器内5432docker run -d \ -e POSTGRES_DBai \ -e POSTGRES_USERai \ -e POSTGRES_PASSWORDai \ -e PGDATA/var/lib/postgresql \ -v pgvolume:/var/lib/postgresql \ -p 5532:5432 \ --name pgvector \ agnohq/pgvector:18也就是说宿主机上 PostgreSQL 实际监听的是5532而示例里的db_url却连向 5432导致数据库日志步骤无法连接。评估逻辑本身factorial作为干净执行被匹配完全通过——这正是阅读测试日志时需要区分逻辑失败与环境失败的典型样例。7.2 修复与复现建议要让该示例端到端跑通只需将db_url中的端口改为与启动脚本一致db_url postgresqlpsycopg://ai:ailocalhost:5532/ai然后依次执行先运行cookbook/scripts/run_pgvector.sh启动容器再运行python cookbook/09_evals/reliability/db_logging.py。评估通过后结果会以EvalType.RELIABILITY类型写入eval_runs表源码 reliability.py 会同时落库评估输入eval_input——expected_tool_calls、allow_additional_tool_calls、expected_tool_call_arguments——以及asdict(result)的完整结果字段。7.3 结果对象与 CI 断言ReliabilityEval每次运行返回ReliabilityResultreliability.py其字段即评估的结构化证据字段含义run_id本次运行的唯一标识eval_statusPASSED或FAILEDpassed_tool_calls干净执行且属于预期的工具每次执行一条记录failed_tool_calls非预期工具严格模式/ 被拒绝的额外请求additional_tool_calls子集匹配模式下允许的额外调用missing_tool_calls预期但无干净执行的工具若曾请求但被拒绝/出错会带执行匹配注解passed_argument_checks/failed_argument_checks参数校验结果assert_passed()的实现是一行assert self.eval_status PASSED——当 CI 变红时断言消息会携带整个结果对象配合执行匹配注解可以直接区分评估配置错了还是Agent 行为错了。run(print_resultsTrue)还会用 rich 渲染一张Reliability Summary表格展示上述全部字段。八、交叉验证与 01_demo/evals 的联动TEST_LOG 最后补充了跨目录抽查结果cookbook/01_demo/evals的可靠性用例通过套件统一运行local_wiki_reports_state_honestly在 2026-07-19 实测为 Judge PASS、Reliability PASS、exit 0。这印证了两点ReliabilityEval已被集成进更大的评估套件suite runner且在这些环境下需要关闭 spinner源码中show_spinner字段的注释即说明Embedders that must not write to the console (e.g. the suite runner) disable it可靠性评估可以与 Judge 评估组合使用——Reliability 验证工具调用是否符合预期Judge 验证最终回答质量形成互补的双层质检。九、如何复现与扩展你的可靠性评估按仓库当前内容完整的验证路径如下准备环境设置OPENAI_API_KEY日志基于gpt-5.2、gpt-5.6-luna实测如需数据库日志先运行 cookbook/scripts/run_pgvector.sh 并按上文修正端口逐一运行示例python cookbook/09_evals/reliability/reliability_async.pypython cookbook/09_evals/reliability/single_tool_calls/calculator.pypython cookbook/09_evals/reliability/multiple_tool_calls/calculator.pypython cookbook/09_evals/reliability/team/ai_news.pypython cookbook/09_evals/reliability/db_logging.py先修正端口对照单元测试全量语义保障在 libs/agno/tests/unit/eval/test_reliability_eval.py无需真实 API Key 即可离线验证各类边界严格/宽松模式、参数部分匹配、团队嵌套、历史消息隔离、被拒绝/出错/挂起调用等按需扩展file_path_to_save_results可将结果持久化为 JSON支持{run_id}占位符db可将结果写入 PostgreSQL/SQLite/InMemory 等存储便于沉淀评估历史。十、小结从一份测试日志读出评估的意图回看这份 TEST_LOG它其实浓缩了ReliabilityEval的设计哲学通过 干净执行被拒绝、出错、参数错误的调用一律不算数2.8.0 执行匹配失败要可归因missing_tool_calls的注解把评估配置问题与Agent 行为问题分开让红色 CI 一眼可读团队场景透明递归收集成员证据嵌套团队、深层委托与 0 层领导者的规则完全一致环境问题与逻辑问题分开记录db_logging.py的 FAIL 属于端口不匹配的环境问题评估逻辑本身通过——这也是把测试日志写成结论 依据 根因这一格式的最大价值值得在自动化评估流水线中沿用。【免费下载链接】agnoBuild, run, and manage agent platforms.项目地址: https://gitcode.com/GitHub_Trending/ag/agno创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考