treg 工具解析机制全解析:URL 主机匹配 + 最长前缀如何决定 API 路由
【免费下载链接】tregOpenRouter for agent tools. Join community here: https://discord.gg/6mQYYfFMAn项目地址: https://gitcode.com/GitHub_Trending/treg/treg
如果你正在使用 treg 这个"AI Agent 的工具网关",一定好奇:当你只输入一个 API 地址,treg 是怎么知道该用哪个团队的凭据、该转发到哪个上游服务的?答案就在它的目标解析机制里——先按 URL 主机(host)圈定候选工具,再用最长 base_url 前缀(longest prefix)从中选出唯一赢家。这套机制藏在 resolve.py 中,是 treg 被称为"agent 工具的 OpenRouter"的核心原因。
为什么需要"工具解析"?
treg 的定位是让 AI Agent 不持有任何厂商密钥就能安全调用各家 API:Agent 只管发出请求,treg 在转发途中注入凭据、审计、计费。
关键问题在于:Agent 只会说"我要访问https://api.stripe.com/v1/charges",它不知道 treg 内部的工具名。于是 treg 需要一种零词汇量的解析方式——你写的就是原生 API 地址,路由由地址本身决定。
两种请求形态:URL 透传 vs 命名调用
进入/call/的请求(路由定义见 call.py)共有两种形态:
| 形态 | 长什么样 | 解析方式 |
|---|---|---|
| URL 透传(Agent 原生) | /call/https://api.intercom.io/me | 主机 + 最长前缀匹配 |
| 命名(CLI/遗留) | /call/my-tool/<path> | 直接按工具名精确查找 |
本文的主角是第一种。它的完整流水线只有一句话:解析 → 授权 → 扣费 → 忠实转发,其中"解析"阶段就产出了ResolvedTarget(工具, 上游URL)这个结果。
三步解析:主机圈定 → 前缀筛选 → 最长者胜
以下逻辑对应 resolve.py 中的_resolve_call函数:
第一步:提取主机并命中索引
把透传 URL 解析出 netloc(主机名,统一转小写),然后按带索引的Tool.host字段查询——这是 models.py 中专门设计的一列,注释写着"netloc of base_url — indexed for URL-passthrough resolution"。所有查询都限定在调用者自己的 org内,两个团队即使注册了相同主机也不会互相干扰。
第二步:路径分段边界上的前缀匹配
每个候选工具都有自己的base_url。匹配规则不是朴素的字符串前缀,而是要求落在路径分段边界上:
- ✅
.../v2匹配.../v2本身,或.../v2/... - ❌
.../v2绝不匹配.../v20/...
这一条看似苛刻的规则防止了一个真实事故:把 v2 的凭据错误注入到未注册的兄弟路径/v20上。
第三步:最长前缀胜出
多个工具可能同时命中同一主机(比如团队同时连接了同一供应商的多个 API 子域)。此时比较去掉尾部斜杠后的base_url长度,最长者获胜:
base_url = https://api.example.com/v1 (13 字符路径) ← 胜出 base_url = https://api.example.com (更短) 请求 = https://api.example.com/v1/users比较前会先做rstrip("/")归一化,所以.../v1和.../v1/算等长——这不是"悄悄分出胜负",而是会被如实判定为一次真正的冲突(409)。
平局怎么破?409 错误与注册表优先
当最长前缀出现平局,treg 的处理非常克制(resolve.py):
- 注册表连接优先:如果平局中只有一个工具绑定的是"注册表 OAuth 凭据"(provider-backed),直接选它。因为这种连接往往是用户刚刚授权、正在使用的"活连接",而手动注册的旧工具很可能拿着过期密钥——对永远不打工具名的 Agent 调用方来说,409 是纯粹的打断。
- 仍是平局 → 409:返回
target_ambiguous,错误信息列出所有冲突的工具名,并明确指示"改用无歧义的/call/<name>/<path>形式"。
对应的行为测试见 test_passthrough.py:test_longest_prefix_wins验证最长前缀胜出,test_ambiguous_host_409验证真正的平局返回 409。
权限过滤:先用 ACL 缩小候选集,再比长短
一个容易被忽略的顺序细节:权限过滤发生在最长前缀比较之前(proxy-model.md 中的 "ACL-filtered candidates" 一节)。
同主机所有工具 → 用 ACL(项目范围 + 工具白名单)过滤 → 剩下的人里才比前缀为什么顺序重要?一个你根本看不见的同主机工具,不应当让你收到 409——它不配参与你视野内的竞争。同时这个过滤只缩小候选集,永远不放大:任何解析结果之后仍会经过完整的访问策略闸门。
由此还能区分两种失败:
- 403:主机上有匹配工具,但全被 ACL 过滤掉了 → "你有工具但没权限,找管理员开"
- 404:这个主机压根没有注册工具 → "no registered tool for upstream ..."
403 的措辞只点出你输入的主机名,绝不泄露被隐藏的工具内部名字。
小结:一张图看懂路由决策
/call/https://api.x.com/v1/users │ ├─ 1. host = api.x.com ──命中索引──> 本 org 内同主机工具 │ ├─ 2. ACL 过滤(看不见的不许参赛) │ ├─ 3. 路径分段边界前缀匹配 │ 无匹配 → 403(被 ACL 挡)/ 404(不存在) │ ├─ 4. 最长 base_url 者胜(去尾斜杠后比长度) │ 平局 → 注册表连接优先,否则 409 │ └─ 5. 产出 ResolvedTarget → 授权 → 计费 → 忠实转发这套"主机 + 最长前缀"的设计,本质是把 DNS 的"最长标签匹配"思想搬到了凭据路由上:既让 Agent 零学习成本地直接喊出原生 API 地址,又保证每一次注入都有唯一、可解释、可审计的依据。
延伸阅读:完整的代理与转发契约见 proxy-model.md,凭据注入与忠实转发的规则也写在其中。
【免费下载链接】tregOpenRouter for agent tools. Join community here: https://discord.gg/6mQYYfFMAn项目地址: https://gitcode.com/GitHub_Trending/treg/treg
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考