Connections:为托管Deep Agents提供托管凭证与调用方身份验证(8分钟阅读)

TLDR AI 工具

摘要

本文介绍了“Connections”——托管Deep Agents的一项功能,它通过提供托管凭证和调用方身份验证来实现安全的智能体操作,支持静态密钥和OAuth授权两种方式。

LangSmith Connections 是一个凭证管理系统,允许智能体使用共享(智能体拥有)或按用户区分(用户拥有)的凭证来执行网页搜索或提交工单等任务。智能体拥有的密钥支持需要共享凭证的场景,而用户拥有的OAuth配置则使智能体能够以用户身份执行操作,从而增强安全性和能力。
查看原文
查看缓存全文

缓存时间: 2026/09/10 14:12

# 连接:托管凭据与基于调用者的身份认证——用于托管式深度智能体 来源:https://www.langchain.com/blog/connections-managed-credentials-and-per-caller-identity-for-managed-deep-agents 每个智能体最终都需要代理他人行事——搜索网络、提交工单、发起代码拉取请求。如今这通常意味着在每次部署中硬编码一个API密钥,且所有操作都显示为服务账户执行。`.env`中的密钥能回答智能体*可以*做什么,却无法回答*是谁*提出的要求。这正是连接要解决的问题。连接是您LangSmith工作区中的一个命名凭据,工具在运行时通过标识符(slug)单次调用即可读取。 ## 两个维度,而非一个 连接包含所有者和凭据类型两个独立维度。**所有者**可以是智能体或调用者。智能体拥有的凭据属于部署本身,所有调用者共享使用;而用户拥有的凭据则在运行时按人员解析。**凭据**可以是静态密钥或OAuth授权:智能体可以持有OAuth授权,用户也可以持有静态密钥。所有权在通过`mda connections create`创建连接时固定,而`connections.get()`仅从已存在的凭据中选择。 ## 智能体拥有的静态密钥 当需要为所有调用者共享单一凭据时,适合使用智能体拥有的静态密钥。这对于不因人而异的能力非常适用:网络搜索、地理编码器、价格数据源等。以下示例将配置一个连接到Tavily(https://www.tavily.com/)的连接,为智能体添加通用网络搜索工具: `uv run mda connections create tavily-agent --secret-from-env TAVILY_API_KEY` 其中`tavily-agent`是标识符(slug)。这是您为连接命名的名称,也是代码中使用的名称,系统不会对照供应商列表进行验证。密钥值从`TAVILY_API_KEY`提取并存储到您的LangSmith工作区中。它不包含在构建产物中,`mda deploy`也不会像处理`.env`那样将其扫入部署密钥。读取该密钥的工具是一个普通的LangChain工具,仅需新增一行代码调用`connections.get`: ```python # tools/search_web.py import httpx from langchain.tools import tool from managed_deepagents import connections @tool(parse_docstring=True) async def search_web(query: str) -> str: """搜索网络。 Args: query: 搜索查询。 """ api_key = await connections.get("tavily-agent", {"type": "agent"}) async with httpx.AsyncClient(timeout=30.0) as client: response = await client.post( "", json={"api_key": api_key, "query": query, "max_results": 5}, ) response.raise_for_status() return response.text ``` 若需轮换密钥,只需更新存储在`tavily-agent`中的静态密钥,后续所有智能体请求将自动使用新密钥。 ## 用户拥有的OAuth(使用您自己的应用) 共享令牌很有用,但允许智能体代理用户行事意味着您可以为智能体安全地提供更多功能。GitHub与其他22项服务一起出现在连接目录中,您只需提供客户端ID和密钥即可——无需授权URL、令牌URL或鉴权方法查询。通过`mda connections catalog`可快速查阅目录连接,但您也可以使用任何支持OAuth的提供商(需提供自己的元数据)。 例如配置连接到自定义GitHub OAuth应用的连接: ```bash uv run mda connections create github-issues \ --oauth github \ --client-id "$GITHUB_CLIENT_ID" \ --secret-from-env GITHUB_CLIENT_SECRET \ --scope repo ``` 此例中`github-issues`是标识符(slug),属于您定义的名称并在代码中使用。`github`是目录服务名称,仅决定哪些端点会被自动填充。`--scope repo`会替换目录默认范围而非追加。GitHub默认范围为`read:user`,无法创建问题,因此您传入的值将成为完整范围列表。 工具通过辅助函数读取令牌,关键代码行如下: ```python access_token = await connections.get("github-issues", {"type": "user"}) ``` 通过单次`connections.get`调用,已部署的智能体可以自动执行OAuth流程:为新用户发起授权,或为已验证用户获取缓存的OAuth令牌。利用此访问令牌,我们可以向GitHub发起任意API调用: ```python # tools/github.py async def _github(method: str, path: str, **kwargs) -> dict: access_token = await connections.get("github-issues", {"type": "user"}) async with httpx.AsyncClient(timeout=30.0) as client: response = await client.request( method, f"{GITHUB_API}{path}", headers={ "Authorization": f"Bearer {access_token}", "Accept": "application/vnd.github+json", "X-GitHub-Api-Version": GITHUB_VERSION, }, **kwargs, ) response.raise_for_status() return response.json() ``` 注意我们设置了`{"type": "user"}`。智能体拥有的连接在创建时即存储值,而此连接创建时不存储任何值,仅保存应用注册信息。凭据在运行时按调用者传递——若调用者从未授权GitHub或令牌已过期,`connections.get()`将暂停运行并请求授权而非直接失败。该单词仅在`_github`中出现一次。`search_issues`工具和`create_issue`工具均从该辅助函数继承调用者身份,而第三个GitHub工具完全无需鉴权代码。 收益体现在两方面:在编写任何代码前,`search_issues`结果已因调用者而异——私有仓库权限不同导致相同查询、相同部署却返回不同结果。当`create_issue`执行时,问题将由发起请求者创建——响应中的`user.login`是其用户名而非机器人标识。 ## 用户拥有的OAuth(无需注册应用) 某些MCP服务器会自行注册OAuth客户端。此时整个配置只需一个URL: ```bash uv run mda connections create linear-mcp --mcp https://linear.app/mcp ``` ```python # tools/mcp.py from managed_deepagents import connections, define_mcp mcp = define_mcp( servers={ "linear": { "transport": "http", "url": "https://linear.app/mcp", "connection": connections.get("linear-mcp", {"type": "user"}), }, }, ) ``` 无需客户端ID、密钥或应用注册。由于服务器广播其OAuth元数据且自动注册客户端,您甚至无需指定范围——连接创建时已从服务器元数据协商出`read`和`write`权限。与GitHub流程对比:一个需要自有应用,另一个无需任何配置,但读取令牌的代码行完全相同。工具代码在此处完全消失——GitHub需要辅助函数和两个功能函数,而这里只需服务器URL,工具直接由MCP服务器提供。 ## 一次暂停,解决所有缺失授权 当智能体需要跨服务操作时,运行将在首次模型调用前暂停,显示一个中断界面列出调用者未授权的所有连接。授权后运行从中断处恢复。项目中没有回调路由、令牌存储、刷新逻辑或授权屏幕。调用者始终无需打开LangSmith。第二位调用者执行相同操作时,会从相同智能体、相同标识符和相同工作区条目中创建由不同作者发起的第二个问题。这与设计上对所有用户相同的Tavily密钥形成鲜明对比。 您可以通过以下命令检查自己或其他开发者添加到LangSmith的连接: ```bash uv run mda connections list ``` ## 快速开始 连接功能包含在托管式深度智能体预发布版中,OAuth目录内置在二进制文件中,因此您安装的版本决定了`--oauth`的可接受参数: ```bash uv tool install managed-deepagents uv run mda connections catalog ``` 智能体拥有的凭据属于部署本身,因此需先创建一次部署环境再创建凭据。之后每个连接仅需三步:创建、通过`connections.get()`读取、重新部署以包含读取代码。本地开发流程相同:智能体拥有的连接从`.env`中的`MDA_DEV_`变量解析(大写且连字符替换为下划线);用户拥有的连接在`mda dev`环境下将登录开发者解析为真实主体,使授权中断在本地触发,且存储的授权是真实有效的。 除上述三种流程外,`--authorize`会为部署存储一个OAuth授权,使所有调用者作为单一共享账户行动——这是所有者-凭据模型中的第四种情况,适用于需要团队专用账户而非个人身份的场景。`--allowed-scope`限制后续授权可能请求的范围,`--authorize-url`与`--token-url`组合可覆盖目录外的任意提供商。 更多详细信息和示例,请参阅连接文档:https://docs.langchain.com/langsmith/python/managed-deep-agents-connections

相似文章

保障代理身份安全

Lobsters Hottest

一位安全专家讨论了为访问敏感资源的LLM代理保障身份令牌安全的挑战,并提出了一种基于代理的方法,将令牌绑定到特定环境以防止凭证窃取。

存储凭据无法支撑智能体支付

Reddit r/AI_Agents

一位开发者讨论了AI智能体处理日常采购时在凭据管理方面遇到的持续挑战,指出存储凭据存在安全风险,而人工审批又破坏了自主性。