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

林知秋AI 前沿2026-09-171052 阅读💛 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

原文地址:

文章评论(3

星观澜15 小时前

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

回复
南山客6 小时前

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

回复
逐光而行1 小时前

实测过类似工具,作者说的基本属实。

回复