LangChain Connections 实操:智能体凭据不进代码,四条接入路径把「谁在操作」传给工具

一句话结论
智能体要替人开 issue、搜网页、读私有仓库,凭据管理永远是第一道坎。LangChain 给 Managed Deep Agents 加的 Connections 能力把凭据从 .env 和构建产物里抽出来,存进 LangSmith 工作区,按 slug 在运行时读取——更关键的是「用户级凭据」让每次调用都带着真实操作者身份,工单上落的是本人账号而不是机器人。
要解决的问题
一个 API 密钥硬编码在每次部署里,所有动作都记在服务账号名下。.env 只能回答「智能体被允许做什么」,回答不了「是谁在要求做」。Connections 用一个工作区内的命名凭据对象替代这套做法:工具代码在运行时通过一次 connections.get() 调用按 slug 读取,凭据不在构建里,mda deploy 也不会像打包 .env 那样把它扫进部署密钥。
两轴模型:归属与类型独立选择
一个 connection 有归属方和凭据类型两个独立维度。归属方要么是智能体(凭据属于部署,所有调用者共享),要么是调用者(运行时按人解析)。凭据类型要么是静态密钥,要么是 OAuth 授权——智能体可以持有 OAuth 授权,用户也可以持有密钥,两个维度自由组合。归属在 mda connections create 创建时就固定,connections.get() 只在已存在的凭据里做选择。
路径一:智能体级共享密钥
适合不因人而异的能力:网页搜索、地理编码、行情数据源。以接入 Tavily 网页搜索为例,一条命令创建:
uv run mda connections create tavily-agent --secret-from-env TAVILY_API_KEY
tavily-agent 是你自己起的 slug,代码里读的就是这个名字,不做任何厂商清单校验。密钥值从 TAVILY_API_KEY 环境变量取出后进入 LangSmith 工作区。工具侧只需在普通 LangChain 工具里加一行读取密钥,其余 httpx 调用照旧。要轮换密钥时更新 tavily-agent 存的值,后续请求自动用新密钥,不用改代码或重新部署。
路径二:用户级 OAuth,自带 GitHub 应用
要让智能体代表用户行事、安全地开放更多能力,用用户级 OAuth。GitHub 在连接目录里和另外 22 个服务并列,你只需带 client ID 和 secret,不用写授权页。给自建 GitHub OAuth 应用建连接:
uv run mda connections create github-issues \
--oauth github \
--client-id "$GITHUB_CLIENT_ID" \
--secret-from-env GITHUB_CLIENT_SECRET \
--scope repo
--scope repo 是整体替换目录默认值而不是追加——GitHub 默认的 read:user 开不了 issue,传什么就是完整清单。工具侧关键一行 access_token = await connections.get("github-issues", {"type": "user"}):部署后的智能体遇到新用户自动发起 OAuth 流程,遇老用户直接取缓存 token,token 过期或从未授权过 GitHub 的调用会当场补授权。这套凭据只在 _github 辅助函数里出现一次,search_issues 和 create_issue 两个工具自动继承按人身份,再加第三个 GitHub 工具也零授权代码。收益直接体现在结果上:同一查询、同一部署,不同人看到的私有仓库结果不同;create_issue 建出的 issue 作者栏落的是本人的 handle。

路径三:MCP 服务器免注册接入
有些 MCP 服务器自己注册 OAuth 客户端,这时整个接入就是一个 URL:
uv run mda connections create linear-mcp --mcp <https://mcp.linear.app/mcp>
代码侧用 define_mcp 声明服务器,connection 参数填 connections.get("linear-mcp", {"type": "user"})。没有 client ID、没有 client secret、没有应用注册——服务器广播自己的 OAuth 元数据后客户端替你注册,scope 也从服务器元数据协商出来。对比路径二:GitHub 要你自带应用,这里只要一个服务器 URL,而读取凭据的代码行完全相同;工具本体直接从 MCP 服务器到达,连工具代码都省了。
授权中断:一次暂停,补齐所有缺失授权
调用者要智能体做一件跨服务的事,运行会在第一轮模型调用前暂停,抛出一个中断,列出该调用者尚未授权的所有 connection。补授权后运行从暂停点继续。项目里没有回调路由、没有 token 存储、没有刷新逻辑、没有授权确认页,调用者全程不打开 LangSmith。第二个调用者做同样的事,会从同一个智能体、同一个 slug、同一个工作区条目得到另一个作者署名的 issue——对比智能体级的 Tavily 密钥,那把密钥设计上就对所有人相同。
第四态与上手清单
--authorize 给部署存一份 OAuth 授权,所有调用者以单一共享账号行事——归属×类型模型的第四格,适合要专用团队账号而非逐人身份的场景。上手三步:uv tool install managed-deepagents 后 mda connections catalog 看目录(OAuth 目录内置于二进制,版本决定 --oauth 接受什么);智能体级凭据属于部署,先 scaffold 并部署一次再创建;之后创建、用 connections.get() 读取、重新部署发布读凭据的代码,三步一条线。本地开发同样成立:智能体级从 .env 里的 MDA_DEV_<SLUG> 解析(大写、连字符转下划线),用户级把登录开发者解析为 mda dev 下的真实主体,授权中断本地照样触发。
什么时候选哪条路径
不因人而异的通用能力(搜索、地理编码)选智能体级密钥;要代表用户在 GitHub/Linear 这类有目录支持的服务上操作选用户级 OAuth;目标服务提供 MCP 服务器且自带 OAuth 注册的就一个 URL 搞定;需要团队共享账号行为用 --authorize。判别标准就一条:动作该记在谁名下——记部署名下用智能体级,记个人名下用用户级。
原文信息
- 作者:Victor Moreira(@victordiazmp),LangChain 软件工程师
- 来源:LangChain 官方博客
- 原文发布日期:2026-09-09
原文地址:
看完了,收获满满,期待更多更新。
看标题就点进来了,内容果然没让人失望。
这个观点很中肯,深有同感。
看完了,收获满满,期待更多更新。
作者写得真不错,学到了不少。
收藏了,以后慢慢研究。
讲解得很细致,新手也能看懂。
这个观点很中肯,深有同感。