一个Token调3000个接口Treg零词汇量路由背后的最长前缀博弈【免费下载链接】tregOpenRouter for agent tools. Join community here: https://discord.gg/6mQYYfFMAn项目地址: https://gitcode.com/GitHub_Trending/treg/treg把 OpenAI 的模型网关逻辑搬到一个工具网关上会是什么样treg 给出的答案是Agent 只拿一个 base URL 加一个 token就能按需调用 60 供应商的 3000 真实业务端点——从 SEO 关键词到 TikTok 用户画像从邮箱富集到广告库检索全部按调用计费、最低一分钱起。但一个 URL 通吃三千个接口这句话背后藏着一个真正的工程难题当 Agent 在请求里直接写下游供应商的原始 URL 时网关凭什么知道该把哪一把密钥注入进去这就是 treg 所谓的零词汇量路由——调用方不需要记住任何 treg 内部的工具命名不需要tool_name字典只要把真实的上游 URL 原样扔给网关路由就发生在 URL 自身。而支撑它的是一套从主机名筛选、到分段边界前缀匹配、再到 ACL 预过滤和 OAuth 优先级仲裁的多层决策链。这篇文章基于 treg 仓库源码核心实现在 src/treg/application/call/resolve.py与 tests/test_passthrough.py 的测试用例拆解这条决策链的每一环以及它为了可审计付出了什么代价。从主机名筛选到分段边界的决策链URL-passthrough 的调用形态在 docs/context/reference/glossary.md 里有精确定义prefix the real upstream URL with…/call/instead of naming a tool path。也就是说Agent 请求/call/https://api.intercom.io/me网关要自己把api.intercom.io解析成某个注册工具再把me这条路径拼到该工具上。解析的第一步是主机名索引。Tool模型里有一个专门为这个场景建的字段见 src/treg/models.pyhost: str Field(default, indexTrue) # netloc of base_url — indexed for URL-passthrough resolution_resolve_call首先用urlsplit(norm).netloc.lower()取出请求 URL 的主机名然后做一次按 org 隔离的索引查询select(Tool).where(Tool.host host, Tool.org_id org_id)。这一步同时回答了三个问题这个主机有没有人注册过是不是我这个团队注册的是不是还能被这个调用者使用两个团队可以各自注册同一个上游主机而互不干扰这正是多租户隔离在路由层的体现。主机命中之后才轮到路径匹配。关键在下面这段src/treg/application/call/resolve.pydef _prefix_match(base: str) - bool: b base.rstrip(/) return norm b or norm.startswith(b /)注意这不是一个朴素的字符串startswith而是一个分段边界path-segment boundary匹配base_url为.../v2的工具只匹配请求.../v2/anything或恰好.../v2但绝不匹配.../v20/...。为什么这么较真因为如果按裸前缀匹配/v20/会命中v2工具的凭据绑定——等于把 v2 的密钥悄悄注入到了一个它从未注册过的兄弟路径上这是凭证错配不是路由效率问题。仓库在注释里直接点明了这个动机that would inject v2s credential onto an unregistered sibling path。多主机候选都命中后进入最长前缀决胜longest max(len(t.base_url.rstrip(/)) for t in matches)再取所有长度相等的工具。这里有个容易被忽略的细节长度比较前先rstrip(/)目的在注释里写得很清楚——.../v1和.../v1/在语义上是同一个 base如果有一个工具注册时手滑多写了一个斜杠它不应该静默地更长从而悄悄赢下路由它应该被视为平局走平局仲裁逻辑。最长前缀匹配的边界与冲突场景平局仲裁是整条决策链里最有意思的一段。当两个工具的主机相同、规范化后 base_url 长度相同路由就撞上了。仓库给出了两个完全不同性质的冲突场景处理方式也完全不同。场景一手注册工具 vs 注册表自动供给工具。同一个 API 往往先被人手动注册过treg tool add ...通常还绑着一个过期的旧密钥后来用户又通过 OAuth connect 走注册表流程系统自动供给auto-provision了一个新工具。两个都是真实工具谁的 base_url 都不更长。此时如果返回 409被坑的恰恰是 URL-passthrough 的目标用户——那些从来不输入工具名的 Agent。所以 resolve.py 里有一条优先级规则优先选择 provider-backed 工具——即绑定里含有带provider标记的 Secret 的那个。判断逻辑是检查工具绑定指向的 Secret 是否org_id匹配且带provider字段如果恰好只有一个 provider-owned 工具就直接返回它把活着的 OAuth 连接放在可能已经过期的旧手注册前面。场景二真正无法消解的歧义。如果两个工具都不是 provider-owned或者两个都是就只剩 409 一条路——但这条 409 不是干巴巴的错误它把所有调用者可用的冲突工具名列出来并指引调用者改用无歧义的命名形态/call/name/path。测试 tests/test_passthrough.py 钉死了这个契约async def test_ambiguous_host_409(clients: AsyncClient): await _register(clients, g1, https://api.same.com) await _register(clients, g2, https://api.same.com) # identical base - tie r await clients.get(/call/https://api.same.com/echo) assert r.status_code 409 detail r.json()[detail] assert g1 in detail and g2 in detail assert /call/name/path in detail而最长前缀赢的基本盘由 test_longest_prefix_wins 钉死https://api.g2.combroad和https://api.g2.com/v2narrow同时注册时请求/call/https://api.g2.com/v2/echo必须注入 NARROW 密钥断言auth Bearer NARROW。前缀越具体密钥越准确——这是整个零词汇量路由的信任基础调用者写下的路径越深网关越敢断定它想要的是那个更专门的工具。ACL预过滤与OAuth优先级如何影响路由最长前缀匹配本身是纯文本博弈但 treg 在它前面加了一道人员博弈的过滤而且顺序是刻意设计过的。看 src/treg/application/call/resolve.py 的解析逻辑候选集在进入_prefix_match之前先被_tool_usable(caller, t)过滤了一遍。_tool_usable是两道 ACL 的 AND 组合src/treg/domain/governance/access.pydef _tool_usable(caller: Caller, tool: Tool) - bool: return _tool_allowed(caller, tool.name) and _project_allowed(caller, tool)即成员级 per-tool 名单tool_accessNULL 表示全部 项目级 scopeproject_accessNULL 表示整个 org。owner 永远不受限。为什么过滤必须发生在最长前缀决胜之前注释给出的理由非常尖锐一个与调用者同主机、但调用者无权使用的工具must not be able to cause a 409——or win the tiebreak——for someone who cant even see it inlist_tools。换句话说不可见的工具不能参与可见性博弈——否则一个团队里某成员无权使用的工具会污染路由结果甚至让一个本来能解析的请求变成 409。ACL 只收窄候选集从不扩大——不管怎么过滤最终解析出的工具仍然要再过一遍_require_tool_use权限门所以这层预过滤不可能成为越权通道。更精细的是 404 与 403 的区分_resolve_call保留了未过滤的主机命中集如果前缀匹配在过滤后一个都不剩、但在未过滤集里存在——说明工具明明注册了只是不是你的——此时返回 403 而不是 404且错误信息只提调用者输入的主机名绝不泄露被 ACL 隐藏的工具内部名。注释点破这个取舍a 404 here would send an admin hunting for a registration that already exists。OAuth 优先级则出现在另一个层面。一是上面说的平局仲裁里 provider-backed 工具优先二是注册表对上游主机的强约束OAuthProvider.catalog_targets是可执行的策略而非目录数据——一个 catalog YAML 里的host只能从这份 HTTPS 精确批准清单里挑一个profile_for_catalog_host会校验 scheme、netloc、hostname 精确一致杜绝任何 query/fragment/用户名密码注入src/treg/oauth_providers.py。注释直言a catalog edit cannot redirect an injected team or platform credential to an arbitrary host。再加上legacy_base_urls供应商迁移 base_url 后旧主机上的注册工具仍然有效tier 1 优先deny 规则也同时按新旧主机各查一遍——路由优先级与安全策略在主机迁移这件事上达成了同步。零词汇量调用下可审计性的代价路由省掉了词汇表但审计不能省。零词汇量模式的代价恰恰是网关替调用者做了太多决定因此每一层决定都必须留下可追溯的证据。先看请求侧。忠实中继faithful relay是 src/treg/infra/upstream/relay.py 的承诺除了五类东西其他全部原样转发——hop-by-hop 传输头重新推导、x-treg-*控制头与边缘转发头剥离、绑定注入的凭据只覆盖自己的目标位置、共享密钥下的幂等键按 org 重作用域、共享密钥下的 UA 换成 treg 自己的。注意凭据只覆盖自己的目标位置env_injector在注入 query 参数时会把同名的调用者参数替换掉防止调用者把自己的密钥与网关密钥同时传到上游造成混淆。这个只动自己那一格的纪律就是可审计性的第一层上游收到的请求除了凭据位之外就是调用者发出的请求。路由层的审计证据集中在三处。第一解析失败的分类语义409真歧义列出全部冲突工具名、403ACL 排除只提主机、404无注册工具、400畸形 URL。第二调用后的诊断头X-Treg-Served-By直接告诉你这次到底是谁接的单X-Treg-Error: 1让调用方区分treg 没找到工具和供应商返回 404——测试 tests/test_passthrough.py 专门断言了这一点A caller cannot otherwise tell tregs 404 from the vendors own 404——both are a status and some JSON。第三每次 relay 后_audit记录 attemptProvider 身份取 catalog provider 或自有工具的上游主机analytics 里带 outcome/status/timing/cost/call reference但永远不带 params 和 bodiesdocs/context/architecture/proxy-model.md。那么代价到底是什么至少可以数出三笔。第一笔是错误信息的精度零词汇量路由把工具名这个稳定标识藏起来了所以 404/403/409 的每条错误都得更用力地自解释——403 要解释不是你的409 要列出全部候选并把用户导向命名形态。第二笔是平局仲裁的复杂度文本上等长的 base_url 并不等于语义上等权于是引入了 provider-backed 优先、rstrip 规范化、legacy host 兼容这一整套优先级规则——它们都不是路由算法本身而是为少一次 409付出的工程税。第三笔也是最本质的信任转移。零词汇量模式把写对工具名的责任从调用者转嫁给了 URL 自身——调用者写下的 URL 就是全部意图。这意味着 URL 越具体、路径越深路由越安全而网关能做的只是把每条路径都变成可审计的记录把每一次猜都变成明文的served_by。这或许就是零词汇量路由最反直觉的地方它省掉的是调用方的词汇表不是网关自己的决策表。恰恰因为 Agent 不用学任何工具名网关才必须在主机、前缀、边界、ACL、OAuth 归属之间做更多、更精细、也更昂贵的博弈——而这一切博弈的每一回合都被写进了审计日志。一个 Token 调 3000 个接口的浪漫背后是一张以宁可 409 也不猜错密钥为底线的决策网。【免费下载链接】tregOpenRouter for agent tools. Join community here: https://discord.gg/6mQYYfFMAn项目地址: https://gitcode.com/GitHub_Trending/treg/treg创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考