一个 SDK 管多家模型:harness-sdk 的路由、聚合与故障转移这样配才不翻车
一个 SDK 管多家模型harness-sdk 的路由、聚合与故障转移这样配才不翻车【免费下载链接】harness-sdkBuild an agent harness and control it end-to-end. Open-source SDK for production AI agents in Python TypeScript - any model, any cloud.项目地址: https://gitcode.com/GitHub_Trending/sdkpython13/harness-sdk生产环境里的 Agent 从来不是只调一个模型那么简单主模型偶尔限流、区域故障、供应商维护或者某类任务根本不该浪费旗舰模型的 token。把这些都塞进业务代码路由逻辑会迅速腐烂成一团 if-else。harness-sdkStrands Agents Harness SDK给出的答案是三层解耦统一接入层把provider/model字符串归一成同一个 Model 接口路由层用可插拔策略决定每次调用走哪个候选故障转移层在调用失败时按策略自动切换并重置重试预算。本文基于仓库源码逐层拆解这套机制并给出直接可抄的配置与容易踩的边角。统一模型接入一行字符串切换全云厂商harness 的核心入口create_harness()接受一个provider/name字符串、裸 Bedrock 模型 id或现成的Model实例。模型解析逻辑集中在 strands_harness/models.py内部维护了一张_PROVIDERS表为每个供应商注册了构建函数、推荐的 reasoning 档位、思考级别、是否支持原生 web search 与缓存_PROVIDERS { bedrock: Provider(_bedrock, high, _ANTHROPIC_LEVELS, web_searchFalse, cachingTrue), bedrock-mantle: Provider(_bedrock_mantle, high, _OPENAI_LEVELS, web_searchTrue, cachingTrue), anthropic: Provider(_anthropic, high, _ANTHROPIC_LEVELS, web_searchTrue, cachingTrue), openai: Provider(_openai, high, _OPENAI_LEVELS, web_searchTrue, cachingTrue), google: Provider(_gemini, high, _GOOGLE_LEVELS, web_searchTrue, cachingTrue), ollama: Provider(_ollama, None, (), web_searchFalse, cachingFalse), litellm: Provider(_litellm, None, (), web_searchFalse, cachingTrue), }这意味着业务代码只写模型名不写供应商 SDKfrom strands_harness import create_harness create_harness(modelanthropic/claude-opus-5) # 直连 Anthropic create_harness(modelopenai/gpt-5.6-sol) # OpenAI create_harness(modelgoogle/gemini-3.5-flash) # Google create_harness(modelbedrock/global.anthropic.claude-opus-5) # 默认Bedrock 上的 Opus 5 create_harness(modelbedrock-mantle/openai.gpt-5.6-sol) # Bedrock 的 OpenAI 兼容端点换后端时改一个字符串即可Agent 的其余代码原封不动。更关键的是 reasoning effort 的归一化你只设置一次efforthigh_effort()会把档位映射到各家 API 的字段——Claude 走thinking预算、OpenAI 走reasoning: {effort}、Gemini 走thinking_level、Qwen/xAI 系走reasoning_effort。一个供应商不支持的档位会在构造期直接抛错而不是请求打到云端才报 400。默认值定义在 strands_harness/defaults.pyDEFAULT_MODEL bedrock/global.anthropic.claude-opus-5所有默认项都可在create_harness()里覆盖。基于候选池的路由声明式候选 可插拔策略聚合多家模型的核心构件是ModelRouter实现位于 strands-py/src/strands/models/routing/router.py。它的设计原则是router 只编排决策全归 strategyrouter 在首次模型调用前问一次策略选哪个候选调用失败且没有被重试钩子认领时再问一次并携带到目前为止的尝试记录。from strands import Agent from strands.models import ModelRouter, FallbackStrategy from strands.models.openai import OpenAIModel from strands.models.anthropic import AnthropicModel router ModelRouter([ OpenAIModel(model_idgpt-5.6-sol), # 候选 0默认 AnthropicModel(model_idclaude-opus-5), # 候选 1备用 ]) agent Agent(modelrouter)每个候选可以包一层RoutingCandidate附带name、description和 JSON 可序列化的metadata——这就是基于标签的路由元数据来源供后续的智能分类策略读取。候选还可以嵌套一个嵌套的ModelRouter在外部视作一个不透明候选内部不自己做故障转移外层失败就直接换掉整个候选组。默认策略按失败次数排序的声明式故障转移默认的FallbackStrategyfallback_strategy.py逻辑非常克制排除掉上次成功之后已经试过的候选然后在剩余候选中选失败次数最少的平局按声明顺序。所以一次调用没有任何失败记录时就是纯粹的声明顺序 failoverA → B → C某个模型持续失败会沉到健康候选之下而不是每次都先撞一遍一次成功会让本轮已试的排除失效同时清零成功候选的失败计数其他候选保留失败历史——持续宕机的模型不会因为一次碰巧成功就恢复优先级。再加上max_switches参数限制单次调用内切换次数和每个失败轮次每个候选最多用一次的兜底路由永远不会死循环。智能路由用分类器模型选候选想要真正的按请求复杂度路由用ClassifierStrategyclassifier_strategy.py。它把一个额外的模型当作分类器把候选的 name/description/metadata、最新用户请求、父 Agent 指令裁剪到限额后交给分类模型做结构化输出返回候选下标。其默认策略是先排除证据显示无法满足硬需求的候选再在剩余候选中选能满足任务的最小模型并明令禁止按声明顺序推断能力。分类器自身失败超时、异常时降级返回 Nonerouter 落回候选 0不会让路由本身拖垮调用。注意它把候选元数据和请求内容发给分类模型代码注释里明确警告这些数据不能含密钥且证据有字符限额超限直接抛错而不是静默截断。故障转移的实测配置要点结合源码故障转移配置有几个容易翻车的地方1. 必须给候选独立实例。router 构造时_reject_duplicates会拒绝同一个 Model 实例被路由两次包括嵌套 router 里的重复。原因写在注释里策略按候选身份记录健康状态同一个模型放在两个候选后面会有两份失败预算永远降不了级。所以备用模型要OpenAIModel(...)各建一个实例不能复用。2. 有状态模型不能进候选池。_reject_stateful直接抛错带会话状态的模型路由切换会撕裂对话状态这是设计上的红线。3. 候选的上下文窗口要尽量一致。router 模块顶部注释列了已知限制路由只作用于InvokeModelStageagent.model始终是第一个候选主动压缩按它的上下文窗口估算。候选窗口差异过大时压缩不足会让被路由到的模型溢出。结构化输出Agent.structured_output()直接调模型、完全绕过路由——要用路由就不能依赖这个路径。4. 切换会重置重试预算。切换成功时_advance会调用_retry_strategy._reset_retry_state()给新候选一个全新的重试额度避免把旧模型的限流惩罚带过去。同时_on_model_result里event.retry已为真重试策略已认领时 router 不再插一脚两层故障处理不会打架。5. 子 Agent 与模型路由的关系。harness 的子 Agent 机制harness-py/src/strands_harness/agent.py 中的build_default_subagent默认让子任务继承父模型的候选池modelInherit()是 multiagent 规格strands-py/src/strands/multiagent/spec.py的默认轴策略——想把某些子任务固定到便宜模型用Choice轴给模型列一个封闭选项表模型只能从中选不能自由发挥。容易踩的边角工具函数序列化约束与名字碰撞社区对 harness-sdk 的高频吐槽是插件加载失败、工具莫名消失源码揭示了几个根因工具名碰撞是构造期硬失败。_check_name_collisionsagent.py会在构建时把内置工具、你传的tools、插件 vend 的工具、memory 工具全部拉进同一张表查重连-和_视为同一名字。碰撞直接抛ValueError并点名冲突来源修复方式是改你的工具名或通过builtin_tools先关掉内置的。这比静默覆盖掉一个工具要安全得多——后者会让模型拿到一个不存在的工具。MCP 工具按服务器名前缀命名空间。同一 MCP 服务器下的工具暴露为server_tool规避跨服务器重名但服务器名撞上内置名如服务器叫web暴露fetch→web_fetch仍会与内置冲突agent.py注释里明确提示了这条漏网之鱼。programmatic_tool_caller的序列化约束。这是 harness 内置的一个特殊工具tools/programmatic_tool_caller.py让模型写 Python 代码在 Monty 沙箱里串起其他工具。它暴露给代码的工具函数只接受关键字参数名字不是合法 Python 标识符的工具比如 MCP 工具的fetch-url、ns.fetch会生成下划线别名fetch_url、ns_fetch别名冲突时直接不注入并告警。且该工具永不暴露自身或其他实例防止递归。代码里工具结果若是 JSON 文本会被自动解析成 dict/list 方便索引结构化内容优先返回——但任何print()之外的东西都不回传超大中间结果靠这个机制留在沙箱里不进上下文。web_search 的供应商依赖陷阱。_web_search_modeagent.py的逻辑是模型有原生搜索OpenAI、Anthropic、Gemini、bedrock-mantle 的 GPT-5/6 系就开原生Bedrock Converse 等没有显式点名web_search会抛错防止静默失效想用就显式{web_search: exa}走第三方。默认状态下不支持原生搜索的模型只是关闭该工具并打一条 info 日志——这是默认静默降级 显式请求硬失败的典型组合排查搜索工具去哪了先看日志级别。从单模型到候选池的迁移路径把这套机制落地的顺序建议先用create_harness(model...)固定一个主模型验证工具、会话、记忆链路引入ModelRouter包两个候选默认FallbackStrategy先拿到主模型挂掉自动切备用的兜底max_switches设为 1~2 防止故障期间抖动任务复杂度分化明显时换成ClassifierStrategy用RoutingCandidate的description/metadata写好每个候选的适用证据多 Agent 场景下用spec.py的轴策略Fixed/Inherit/Open/Choice把模型选择权收回到开发者手里——Choice是闭集模型只能从你给的选项里挑。这套 SDK 的价值不在于多接几个供应商而在于把路由、故障转移、重试这三件最容易在业务代码里腐烂的事下沉成了声明式配置和可测试的策略对象。接多家模型之前先想清楚你的路由决策到底该由谁做出——是声明顺序是失败计数还是一个独立的分类模型——harness-sdk 把这三种答案都做成了可替换的插槽。【免费下载链接】harness-sdkBuild an agent harness and control it end-to-end. Open-source SDK for production AI agents in Python TypeScript - any model, any cloud.项目地址: https://gitcode.com/GitHub_Trending/sdkpython13/harness-sdk创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

深入Hotdata CLI Rust架构:clap命令树与tokio运行时的高性能设计

深入Hotdata CLI Rust架构:clap命令树与tokio运行时的高性能设计

【免费下载链接】hotdata-cli CLI for Hotdata 项目地址: https://gitcode.com/gh_mirrors/ho/hotdata-cli 点击查看 免费下载 如果你想知道一个命令行工具如何做到"单文件二进制 秒级响应 大结果集不卡顿",Hotdata CLI 值得细读。它是 Hot…

2026/10/11 3:20:32 阅读更多 →
EXE解压全指南:不运行程序,用7-Zip/innoextract/Binwalk提取内部文件

EXE解压全指南:不运行程序,用7-Zip/innoextract/Binwalk提取内部文件

简介:一份面向开发者、逆向工程师及软件分析人员的EXE可执行文件解压工具,基于Universal Extractor(UniExtract)封装,专门用于提取Windows可执行程序内部嵌套的资源与数据,帮助用户绕过安装流程直接访问其中…

2026/10/11 3:20:32 阅读更多 →
grepai调用图提取技术揭秘:tree-sitter AST与正则双模式解析10+种编程语言

grepai调用图提取技术揭秘:tree-sitter AST与正则双模式解析10+种编程语言

grepai调用图提取技术揭秘:tree-sitter AST与正则双模式解析10种编程语言 【免费下载链接】grepai Semantic Search & Call Graphs for AI Agents (100% Local) 项目地址: https://gitcode.com/gh_mirrors/gr/grepai grepai 是一款 100% 本地运行的 AI 时…

2026/10/11 3:20:32 阅读更多 →

最新新闻

HJ15 求int型正整数在内存中存储时1的个数

HJ15 求int型正整数在内存中存储时1的个数

import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main {public static void main(String[] args) {Scanner in new Scanner(System.in);int num in.nextInt();int count 0;while(num > 1){if(num % 2 1){count;}num num /…

2026/10/11 4:19:08 阅读更多 →
HarmonyOS 7 AtomicServiceSearch:文搜图输入预上屏提交代次隔离【鸿蒙心迹】

HarmonyOS 7 AtomicServiceSearch:文搜图输入预上屏提交代次隔离【鸿蒙心迹】

同一个搜索框里,用户输入“秋天”,随后补成“秋天的银杏”,肉眼看来不过是多敲几个字。放到真实相册检索,问题并不在搜索按钮本身:输入法可能仍处于预上屏阶段,前一次检索可能尚未返回,用户也可…

2026/10/11 4:19:08 阅读更多 →
HarmonyOS 7 Image Kit:超分连拍参考图时序差分门禁【鸿蒙心迹】

HarmonyOS 7 Image Kit:超分连拍参考图时序差分门禁【鸿蒙心迹】

Demo:BurstStability / BurstReviewPage / FlickerAuditPage 说明:全文使用可人工复算的连拍模拟样本,不包含真实超分推理结果。IDE与手机图片均为演示示意,不是已经完成的 DevEco 编译或真机测量。把一张照片变清晰,和…

2026/10/11 4:19:08 阅读更多 →
Spring Boot 4模块化架构解析:从自动配置到迁移实践

Spring Boot 4模块化架构解析:从自动配置到迁移实践

Spring Boot 4正式版发布后,我第一时间把手头一个维护了两年多的Spring Boot 3项目整体升级了过去。整个迁移和重构过程中,最让我在意的不是启动数字的浮动,而是它把"模块化架构"推进到了框架核心层面。如果你用过Spring Boot&…

2026/10/11 4:19:08 阅读更多 →
智诺方AI|本科毕业论文图表注释,高重复段落定向降重方法

智诺方AI|本科毕业论文图表注释,高重复段落定向降重方法

为什么「图表注释与图例」容易同时踩查重与 AIGC 在本科毕业论文写作场景里,论文「图表注释与图例」常常被低估。图题表注短、信息密,常被忽略,却同样进查重与 AIGC。乱改会导致图文不符。 很多同学只把精力放在正文长段落,忽略了…

2026/10/11 4:19:08 阅读更多 →
Flask酒类购物系统毕业设计:从数据库设计到订单库存核心实现

Flask酒类购物系统毕业设计:从数据库设计到订单库存核心实现

每年毕业设计季,各种“XX购物系统”都是Web方向出现频率最高的题目。而在这些大同小异的商城系统里,酒类购物系统是比较特别的一种:它本质上是一条完整的电商交易链路,但因为商品是酒,所以在商品属性、库存管理、下单流…

2026/10/11 4:18:08 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 5:23:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →