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

邱宇AI 前沿2026-09-171075 阅读💛 193 收藏

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_issuescreate_issue 两个工具自动继承按人身份,再加第三个 GitHub 工具也零授权代码。收益直接体现在结果上:同一查询、同一部署,不同人看到的私有仓库结果不同;create_issue 建出的 issue 作者栏落的是本人的 handle。

Connections 运行时解析流程

路径三: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-deepagentsmda 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

原文地址:

文章评论(8

龙文博刚刚

看完了,收获满满,期待更多更新。

回复
墨沐雨11 分钟前

看标题就点进来了,内容果然没让人失望。

回复
空向阳34 分钟前

这个观点很中肯,深有同感。

回复
吴超1 分钟前

看完了,收获满满,期待更多更新。

回复
拾贝者9 分钟前

作者写得真不错,学到了不少。

回复
雪影59 分钟前

收藏了,以后慢慢研究。

回复
月归舟46 分钟前

讲解得很细致,新手也能看懂。

回复
暮临风47 分钟前

这个观点很中肯,深有同感。

回复