尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Plano Routing API 实战指南:请求响应协议、按轮次路由与模型亲和
Plano Routing API 实战指南请求响应协议、按轮次路由与模型亲和【免费下载链接】planoPlano is an AI-native proxy server and data plane for agentic apps. Smart LLM routing, observability, agent orchestration, and guardrails so you stay focused on your agents core logic.项目地址: https://gitcode.com/GitHub_Trending/ar/plano本篇技术指南以 Plano 开源仓库中的路由 API 文档为主体完整讲解 Plano 路由 API 的请求/响应协议、routing_preferences配置体系、按请求per-request与按轮次turn-level两种路由策略以及X-Model-Affinity模型亲和机制。读完本文你将掌握如何接入 Plano 的路由决策端点、如何编排候选模型回退逻辑以及如何通过配置与源码级行为让 Agent 循环在成本、质量与缓存效率之间取得平衡。文中所有实现细节均可在仓库源码中验证。一、路由 API 工作方式概览Plano 是一个面向 Agent 应用的 AI 原生代理服务器与数据面。路由 API 是其中智能 LLM 路由能力的对外接口Plano 拦截 LLM 请求基于语义意图与实时成本/延迟数据把请求路由到最优可用模型。核心工作流程如下开发者发送一个标准 OpenAI 兼容请求可附带可选的routing_preferences字段Plano 返回一个有序候选模型列表客户端优先使用列表中的第一个模型遇到 429限流或 5xx服务端错误时依次回退到下一个模型。该 API 同时提供两种形态的端点全代理路径POST /v1/chat/completionsOpenAI Chat、/v1/messagesAnthropic、/v1/responsesOpenAI Responses由 Plano 直接转发上游路由决策端点POST /routing/v1/chat/completions只返回路由决策不转发 LLM 请求供客户端自行发起调用。从 入口分发逻辑 可以看到所有以/routing前缀开头且匹配chat/completions、messages、responses路径的请求都会被分发给routing_decision处理函数见 routing_service.rs与全代理路径共用同一套会话缓存与路由决策逻辑。二、请求格式与routing_preferences请求体是标准的 OpenAI Chat Completion 结构唯一的增量是一个可选字段routing_preferences。该字段在转发上游之前会被剥离上游 provider 永远不会看到它。POST /v1/chat/completions { model: openai/gpt-4o-mini, messages: [ {role: user, content: write a sorting algorithm in Python} ], routing_preferences: [ { name: code generation, description: generating new code snippets, models: [anthropic/claude-sonnet-4-6, openai/gpt-4o, openai/gpt-4o-mini] }, { name: general questions, description: casual conversation and simple queries, models: [openai/gpt-4o-mini] } ] }routing_preferences字段说明字段类型必填说明namestring是路由标识符必须与 LLM 路由器的路由分类route classification一致descriptionstring是自然语言描述路由器据此匹配用户意图modelsstring[]是有序候选池至少需要一项每个模型都必须在配置的model_providers中声明请求内偏好如何被解析与剥离源码实现在 extract_routing_policy 中可以看到这一机制的底层实现函数将原始 JSON 反序列化为serde_json::Value通过remove(routing_preferences)把该字段从对象中移除再尝试将其解析为VecTopLevelRoutingPreference随后用清理后的 JSON 重新序列化出请求体字节交给下游解析器。也就是说解析失败时只会记录warn日志并视作无内联偏好不会拒绝整个请求其他字段如temperature、max_tokens在剥离过程中被完整保留这由单元测试 extract_routing_policy_preserves_other_fields 验证。从 TopLevelRoutingPreference 定义 可以看到除文档表格中的三个必填字段外每个偏好还支持一个可选的selection_policy默认prefer: none用于控制候选池内的选择倾向例如prefer: fastest相关边界行为同样有单元测试覆盖见 routing_service.rs 测试模块。使用注意routing_preferences是可选的。省略时使用配置文件中定义的路由偏好若请求体中提供了该字段则仅对本次请求覆盖配置文件中的偏好model字段仍然必填当没有任何路由匹配时作为回退模型使用。三、响应格式路由决策端点返回如下 JSON{ models: [ anthropic/claude-sonnet-4-6, openai/gpt-4o, openai/gpt-4o-mini ], route: code generation, trace_id: 4bf92f3577b34da6a3ce929d0e0e4736 }字段说明字段类型说明modelsstring[]排序后的模型列表。使用models[0]作为首选遇到 429/5xx 时依次回退到models[1]以此类推routestring | null匹配到的路由名称。未匹配到任何路由时为null此时客户端应使用原始请求中的modeltrace_idstring用于分布式追踪与可观测性的 Trace ID响应结构源码响应由 RoutingDecisionResponse 结构序列化而来。除了文档中列出的三个字段当请求带有模型亲和时还会额外返回两个字段session_id当前请求解析出的会话键显式亲和头或隐式前缀键仅在有会话时出现skip_serializing_ifpinned布尔值表示会话是否已热绑定在某个模型上可视为请为这个 provider 保持缓存热度的信号switched布尔值表示本轮路由预算是否允许了模型切换对应 span 上的plano.switch.decisionallowed。在决策路径上如果没有任何候选模型匹配models会返回哨兵值none且route为null但 HTTP 状态码仍为 200客户端应检查models内容而不是只依赖状态码见 routing_service.rs 的决策结果判定。另外决策端点支持在响应中给出带序回退列表的同时把最终选定的模型排到列表首位routing_service.rs即使路由预算否决了一次切换保留 warm anchor回退列表依然以被锚定的模型打头保证 429/5xx 回退语义始终成立。四、客户端使用模式排名列表回退客户端拿到有序模型列表后采用先选后用、失败回退的消费模式。文档给出的 Python 参考实现如下response plano.routing_decision(request) models response[models] for model in models: try: result call_llm(model, messages) break # success — stop trying except (RateLimitError, ServerError): continue # try next model in the ranked list该模式与models字段的设计目标一致models[0]是质量路由器的首选models[1]起依次是容量与降级备选。注意只有429限流与 5xx服务端错误这类可重试错误才触发回退业务错误如 400 参数错误不应盲目切换到下一个模型。五、平台配置model_providers与routing_preferences路由偏好的全局定义由平台/运维团队放在配置文件中。要求version: v0.4.0及以上routing_preferences中列出的模型必须同时在model_providers中声明这是启动时校验的硬约束见下文版本要求一节。version: v0.4.0 model_providers: - model: anthropic/claude-sonnet-4-6 access_key: $ANTHROPIC_API_KEY - model: openai/gpt-4o access_key: $OPENAI_API_KEY - model: openai/gpt-4o-mini access_key: $OPENAI_API_KEY default: true routing_preferences: - name: code generation description: generating new code snippets or boilerplate models: - anthropic/claude-sonnet-4-6 - openai/gpt-4o - name: general questions description: casual conversation and simple queries models: - openai/gpt-4o-mini - openai/gpt-4o要点model_providers中的access_key支持环境变量引用如$ANTHROPIC_API_KEY避免明文密钥落盘可以通过default: true标记默认模型示例中openai/gpt-4o-mini为默认作为未匹配任何路由时的兜底配置中的routing_preferences与请求体内联偏好结构完全一致都对应 TopLevelRoutingPreference 结构。六、按请求路由per-request默认策略当routing.route_on_user_only为false默认值时采用按请求路由每一个请求都被独立路由包括 Agent 循环中的连续步骤。因此用户的一轮交互一个 turn内可能由多个模型分别服务——例如常规的工具编排迭代交给轻量模型复杂的推理步骤或最终综合交给更强模型。适用场景每步最优模型Best model per step一个 turn 中的每一步都由与该步难度或专长最匹配的模型服务成本效率Cost efficiency简单步骤走小模型只有困难步骤才用贵模型失败升级Escalation on failure表现不佳的模型可以在 turn 的剩余部分被替换掉容量灵活性Capacity flexibility每个请求都可以放到任意有容量的位置没有固定pinning约束。七、按轮次路由turn-levelroute_on_user_only: true当routing.route_on_user_only为true时路由器每个用户 turn 只选择一次模型并把该 Agent 循环的剩余部分固定pin到这个模型上。routing: route_on_user_only: true该开关在配置结构中的定义与默认值可见于 Routing 结构体其序列化解析行为缺省为关、显式 true/false 生效有 对应单元测试 保障。适用场景计划一致性Plan consistency一个模型在整轮循环中延续自己的推理与计划缓存局部性Cache locality循环迭代复用共享的提示前缀缓存不会因切换模型而丢失缓存命中无需状态转换No state translation避免剥离或转换模型特有的产物如带签名的 thinking blocks更简单的参数处理Simpler parameter handling引擎原生参数每个 turn 解析一次而不是每个请求重新映射。何时路由用户轮次判定源码级按轮次路由的关键在于判断本次请求是否是新用户轮次的开始。判定逻辑实现在 is_user_turn只有当最后一条归一化消息的role为user且在剥离 harness 注入的包裹envelope后仍然带有真实文本时才认为这是一个新的用户轮次——即真正的用户文本而不是 Agent 循环中回灌的工具结果。跨客户端 API 的具体表现OpenAI Chat最后一条消息role为userAnthropic最后一段内容是用户文本只有tool_result的轮次会归一化为role: toolResponses最后一项不是function_call_output或custom_tool_call_outputCodex 默认注册自定义工具因此其步骤走后者Bedrock Converse最后一条消息携带用户文本而不仅是toolResult块。几个精细边界均可在 session_router.rs 的判定实现 中找到对应代码新的用户消息总是重新路由包括 Anthropic 在tool_result旁边打包新用户文本的情况空用户消息、或只包含 Claude Code 的system-reminder/user-prompt-submit-hook包裹的消息属于 harness 输出而非真实发言因此循环保持固定strip_injected_envelopes会把这些包裹从文本中剥除剥完后为空即不视为新轮次无说明文字的多媒体附件如粘贴的图片属于用户输入会触发路由has_non_text_content判定。已知限制如果 Agent 框架把工具输出以普通用户散文的形式回灌例如 ReAct 的Observation: ...在线路上与真实用户消息无法区分每一步都会重新路由。要获得 turn 级固定请把工具输出以role: tool或 Anthropictool_result/ Responsesfunction_call_output形式发送。何时跳过路由sticky 复用当请求是进行中的 Agent 循环的延续——最后一条归一化消息不是用户轮次工具结果、assistant 步骤、未解决的tool_use或空的 / 仅包裹的用户消息——路由会被跳过复用先前选定的模型。该请求被固定到当前 turn 记录的模型上。相关入口为 should_reuse_prior_decision 与 reuse_prior_decision。以下情况仍会重新路由复用被拒绝无法再识别先前的决策——会话变冷cache 已过期、系统提示或工具集发生变化、或请求落在不同模型车道上例如 Claude Code 的ANTHROPIC_SMALL_FAST_MODEL调用独立于主循环路由前缀哈希漂移prefix drift存储的绑定前缀与当前请求前缀不一致时说明 provider 缓存已失效视为冷会话处理请求模型车道requested_model与写入绑定的车道不一致别名解析后比较见 alias_is_resolved_before_becoming_the_session_lane 测试。跳过是可观测的span 属性plano.routing.skipped以及brightstaff_router_skips_total计数器会记录跳过事件相关实现见 routing_service.rs 的 skip 记录。八、Model Affinity跨轮次固定整个会话用户轮次判定只覆盖单个查询。若要把整个对话跨多个用户轮次固定在一个模型上需要发送X-Model-Affinity请求头。发送该头时Plano 用其中的值作为显式会话键不发送时Plano 从稳定的提示前缀system tools 第一条用户消息推导隐式会话键——这正是无头重放replay能够工作的原因。关键约定一个会话一个 id而不是一个客户端会话一个 id。会话键只持有一个绑定。如果旁路调用侧边聊天、摘要器、子 Agent与主循环共用同一个 id则后执行的调用会占有绑定lane 与前缀守卫能防止旁路调用被固定到主循环的模型上但主循环自身的 pin 会被驱逐下一次延续会重新路由。正确做法是给旁路调用独立的 id或干脆省略该头让隐式亲和按提示前缀把它们区分开。POST /v1/chat/completions X-Model-Affinity: a1b2c3d4-5678-... { model: openai/gpt-4o-mini, messages: [...] }路由决策端点同样支持模型亲和POST /routing/v1/chat/completions X-Model-Affinity: a1b2c3d4-5678-...固定pinned时的响应{ models: [anthropic/claude-sonnet-4-6], route: code generation, trace_id: ..., session_id: a1b2c3d4-5678-..., pinned: true, switched: false }pinned报告会话在其绑定模型上是热的调用方可以把它当作保持该 provider 缓存热度的信号决策端点与代理走相同的循环处理逻辑因此客户端在工具调用之间轮询该端点时整个 turn 内会得到稳定的答案。请求头常量在 common/consts.rs 中定义为x-model-affinityX-Plano-Cache: off请求头可让单次请求退出隐式亲和绕过粘滞决策路径与 LLM 处理路径共享同一个哨兵语义见 routing_service.rs。配置 TTL 与缓存大小routing: session_ttl_seconds: 600 # default: 10 min session_max_entries: 10000 # upper limit这两个参数分别控制会话绑定的存活时间与内存/Redis 会话缓存的最大条目数。会话缓存支持内存与 Redis 两种后端session_cache.type见 SessionCacheConfig并支持tenant_header做租户级键前缀键形如plano:affinity:{tenant_id}:{session_id}。绑定背后的缓存与预算语义从 session_router 的 route 决策 可以看到决策端点与全代理路径共用同一个route()核心路由器质量维度先选出候选模型随后按会话缓存热度与切换预算决定是采纳候选还是保留 warm anchor。默认姿态是粘住stick只有当候选切换不会让会话总开销超过max_switch_spend_pct相对从不切换基线的百分比上限时才允许付费切换更便宜的切换免费但不减少已累计花费。缓存热度按 provider 的缓存窗口结构推断warmth_window、provider_cache_capability相关边界warm/cold、扩展保留、基线定价于 default 而非 anchor 等均有 session_router.rs 测试 覆盖。九、可观测性路由决策过程全程接入 OpenTelemetry 追踪每次决策对应一个routing_decisionspan携带request_id、HTTP 方法与路径等属性trace_id从请求的traceparent头中提取并回传客户端格式00-{trace_id}-{span_id}-{flags}客户端可用它关联后续 LLM 调用的追踪span 属性覆盖缓存热度plano.cache.warm、plano.cache.idle_ms、切换预算plano.session.overhead_pct、plano.session.switch_spend_in_usd、plano.session.baseline_in_usd、plano.session.switches与累计会话成本plano.session.total_cost_in_usd等见 session_router.rs 的 span 属性设置服务端指标区分已服务决策routing_svc.decision_served与无候选routing_svc.no_candidates弥补纯 HTTP 状态码无法区分的盲区。十、版本要求版本顶层routing_preferences v0.4.0不允许——配置中出现会启动报错v0.4.0支持模型路由所需也就是说要使用routing_preferences无论是配置文件顶层定义还是请求体内联配置文件版本必须声明为v0.4.0或更高更低版本下该字段属于非法配置进程启动即报错。总结Plano 路由 API 以标准 OpenAI 兼容协议为基座通过可选的routing_preferences字段与排名模型列表响应为 Agent 应用提供了一条先选优、失败回退的低成本接入路径route_on_user_only在按请求路由与按轮次路由之间切换前者追求每步最优与容量灵活后者追求计划一致与缓存局部性X-Model-Affinity则把固定粒度从单轮提升到整个会话。这三层能力在源码中相互贯通——请求偏好剥离、轮次判定、粘滞复用、缓存热度推断与切换预算共同构成了 Plano 路由的数据面核心相关实现均可在 crates/brightstaff/src/handlers 与 crates/brightstaff/src/handlers/llm/session_router.rs 中进一步深入研读。【免费下载链接】planoPlano is an AI-native proxy server and data plane for agentic apps. Smart LLM routing, observability, agent orchestration, and guardrails so you stay focused on your agents core logic.项目地址: https://gitcode.com/GitHub_Trending/ar/plano创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

基于Jansen机构与YOLO v3的机械导盲犬设计与实现

基于Jansen机构与YOLO v3的机械导盲犬设计与实现

简介:这是一份聚焦仿生机械导盲犬研究的文档资料,适合机器人设计、机械仿生与计算机视觉方向的工程师、研究生及竞赛爱好者。资源以Jansen机构为蓝本,系统阐述了行走机构的单电机驱动方案、红外与视觉融合的控制设计,并通过ADAMS软…

📅 2026/9/17 17:58:25
NocoBase 审计日志插件深度解析:基于数据库事件钩子的操作变更追踪

NocoBase 审计日志插件深度解析:基于数据库事件钩子的操作变更追踪

NocoBase 审计日志插件深度解析:基于数据库事件钩子的操作变更追踪 【免费下载链接】nocobase NocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of product…

📅 2026/9/17 17:58:25
BLE 5.1方向定位全解析:从CTE到AoA/AoD,一文讲透

BLE 5.1方向定位全解析:从CTE到AoA/AoD,一文讲透

说到蓝牙协议版本,很多人第一反应是"数字越大越快"。BLE 5.1如果按这个逻辑理解就完全跑偏了——它的速率和BLE 5.0一模一样,2Mbps物理层,没有任何提速。那蓝牙技术联盟花这么大力气推一个"不加速"的版本图什么&#xff…

📅 2026/9/17 17:58:25
MORE NEWS

更多资讯

📰

STM32教程制作复盘:从寄存器到实战项目的完整学习路径

一年多前,我给自己定了一个看起来有点“劝退”的目标:做一套完整的STM32教程,从入门到能独立做项目,预计周期是一年。当时身边不少人觉得这个周期太长了,理由也很朴素——市面上讲STM32的视频、文章多如牛毛&#xff0…

📰

Unkey Dashboard API SDK:Speakeasy 驱动的 OpenAPI 代码生成型 TypeScript SDK 与 ESM 构建实践

Unkey Dashboard API SDK:Speakeasy 驱动的 OpenAPI 代码生成型 TypeScript SDK 与 ESM 构建实践 【免费下载链接】unkey The Developer Platform for Modern APIs 项目地址: https://gitcode.com/GitHub_Trending/un/unkey 导读 web/internal/api 是 Unkey…

📰

wagmi 中 `Actions.wallet.deposit` 实战指南:带预填充字段的 Tempo 钱包充值流程

wagmi 中 Actions.wallet.deposit 实战指南:带预填充字段的 Tempo 钱包充值流程 【免费下载链接】wagmi Reactive primitives for Ethereum apps 项目地址: https://gitcode.com/GitHub_Trending/wa/wagmi wallet.deposit 是 wagmi Tempo 系列动作中负责“打…

📰

Perfetto 原生堆内存分析(Heapprofd)完全指南:从采样原理到火焰图与 SQL 分析

Perfetto 原生堆内存分析(Heapprofd)完全指南:从采样原理到火焰图与 SQL 分析 【免费下载链接】perfetto Production-grade client-side tracing, profiling, and analysis for complex software systems. 项目地址: https://gitcode.com/G…

📰

OpenProject 通知与邮件提醒完整配置指南:账号设置中的 Notification and email

OpenProject 通知与邮件提醒完整配置指南:账号设置中的 Notification and email 【免费下载链接】openproject OpenProject is the leading open source project management software for product, project and portfolio management. A powerful Jira alternative …

📰

FPGA上的Linux触摸屏驱动:从硬件到校准的完整链路

第一次在FPGA板卡上接7寸触摸屏,我花了一个下午找到的是一根弯折的FPC排线,而不是改设备树。后来我才明白,触摸驱动这件事从来不是"加载一个内核模块"这么简单,它是完整的一条链路:屏幕模组上的触摸控制芯片…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬