跳到主要内容

Composio — 鉴权与连接账户

本章讲什么: Composio 怎么替你管「每个用户对每个第三方服务的登录态」。三层模型(authConfig / connectionRequest / connectedAccount)各是什么,OAuth 授权怎么发起、怎么轮询等待完成,执行工具时凭据怎么自动挂上。想接真实有鉴权的 toolkit(几乎所有都有)必读。

1. 它要解决的小问题

你的 agent 要替 alice@acme.org 读她的 Gmail。Gmail 要 OAuth:Alice 得去 Google 点「同意授权」,你的服务才能拿到她的 token。而且:

  • token 会过期,要刷新;
  • 每个用户一套 token,要按用户存;
  • 不同服务鉴权方式不同(OAuth2 / API Key / Bearer / Basic)。

Composio 把这一坨全托管。你的代码只处理「发起授权 → 等用户点完 → 之后正常执行工具」,token 的存储/刷新/挂载都在它后端。

2. 三层模型(先建立心智)

这是最容易绕晕的地方,先用一张图把三个概念的关系钉死。

怎么读这张图

从左到右是「配置 → 一次授权 → 长期连接」的时间顺序。authConfig 是复用的模板(整个 app 配一次);connectionRequest 是一次性的授权流程;connectedAccount 是授权成功后长期存在的连接

┌──────────────┐ 定义「用哪套 OAuth app /
│ authConfig │ 哪种鉴权方式」(每个 toolkit 配一次)
└──────┬───────┘
│ 基于它,为某个 userId 发起授权

┌──────────────────┐ 一次性流程:返回 redirectUrl,
│ connectionRequest │ 用户去点同意;可 waitForConnection() 轮询
└──────┬───────────┘
│ 用户授权完成 → status: ACTIVE

┌──────────────────┐ 长期存在:userId × toolkit 的已连接凭据
│ connectedAccount │ 执行工具时后端自动按它挑 token
└──────────────────┘

一句话各自职责

概念是什么类比
authConfig「某 toolkit 用哪套 OAuth app + 哪种鉴权 scheme」的模板「Google 登录按钮」的配置
connectionRequest一次具体的授权流程(有 redirectUrl,可等待)用户正在「同意授权」的那个页面会话
connectedAccount授权成功后的长期连接(带 status)已绑定的「Alice 的 Gmail 账户」

3. 鉴权 scheme:不止 OAuth

AuthScheme 这个工具类列出了支持的鉴权方式,各有一个工厂方法(models/AuthScheme.ts:8-120):

scheme工厂方法用于
OAuth2AuthScheme.OAuth2(...)Gmail、GitHub、Slack 等主流
API KeyAuthScheme.APIKey(...)很多 SaaS 的 key 鉴权
Bearer TokenAuthScheme.BearerToken(...)直接给 token 的服务

OAuth2 走「跳转授权」流程(下一节);API Key / Bearer 这类「你直接有凭据」的不需要跳转,创建连接时直接带上凭据即可。

4. 主线:发起 OAuth 并等待完成

端到端流程

composio.connectedAccounts.initiate(userId, authConfigId) // 或 .link(...)


返回 connectionRequest:{ id, status: INITIATED, redirectUrl }

把 redirectUrl 给用户 ──▶ 用户在浏览器点「同意」

你的代码:await connectionRequest.waitForConnection(timeout)
│ 每 1s 轮询后端 connectedAccounts.retrieve(id)

status 变成 ACTIVE → 返回完整的 connectedAccount
(或 FAILED/EXPIRED/REVOKED → 抛错;超时 → 抛 timeout 错)

waitForConnection 的轮询逻辑

核心是个「先查一次,没 active 就每秒轮询直到超时」的循环(models/ConnectionRequest.ts:75-135)。两个设计细节值得看:

(1) 终态错误立即抛,不傻等。FAILED/EXPIRED/REVOKED 是终态,撞上就直接抛 ConnectionRequestFailedError,不浪费剩余 timeout(models/ConnectionRequest.ts:75-97):

const terminalErrorStates = [
ConnectedAccountStatuses.FAILED,
ConnectedAccountStatuses.EXPIRED,
ConnectedAccountStatuses.REVOKED,
];
const failIfTerminal = (response) => {
if (terminalErrorStates.includes(response.status)) {
throw new ConnectionRequestFailedError(
`Connection request failed with status: ${response.status}...`, {...});
}
};

(2) 默认超时 60s,轮询间隔 1s(models/ConnectionRequest.ts:123-127)。这是个朴素的轮询,不是 webhook 推送——简单可靠,代价是最坏多等 1s。

原理演示(简化的端到端)

// 示意,非源码:让某用户连上 GitHub
const req = await composio.connectedAccounts.initiate('alice@acme.org', githubAuthConfigId);

console.log('请去这里授权:', req.redirectUrl); // 把链接发给用户

const account = await req.waitForConnection(120_000); // 阻塞等最多 2 分钟
console.log('已连接!account id =', account.id);

// 之后正常执行工具,后端会自动用这个 connectedAccount 的凭据
await composio.tools.execute('GITHUB_CREATE_ISSUE',
{ userId: 'alice@acme.org', arguments: {...}, dangerouslySkipVersionCheck: true });

重点看:execute你不传任何 token——只传 userId。后端按 userId × toolkit 找到对应 connectedAccount,自己挂凭据。这就是「托管鉴权」的核心体验。

5. 执行时凭据怎么挂上

tools.execute 的请求体里其实有几个可选鉴权字段(models/Tools.ts:900-920):

  • connected_account_id:显式指定用哪个连接账户(不传则后端按 userId+toolkit 自动找)。
  • custom_auth_params:临时覆盖鉴权参数(自定义 base_url / header 等)。

绝大多数情况你都不用碰——传 userId 让后端自动解析最省心。只有「一个用户对一个服务有多个连接」或「要临时用别的凭据」时才显式传。

6. 边界与局限

  • 轮询不是推送:waitForConnection 是客户端轮询,长时间挂起的请求要自己管好超时。需要事件驱动可用 webhook/triggers(见代码地图里的 Triggers)。
  • legacy initiate 正在退役:对 Composio 托管的 OAuth(OAuth1/OAuth2/DCR_OAUTH),老的 initiate() 端点在分阶段退役,推荐改用 connectedAccounts.link();自定义 OAuth app 和非 OAuth scheme 不受影响(models/ConnectedAccounts.ts:146-160)。
  • 凭据本身 SDK 看不到:token 存在 Composio 后端,SDK 只拿到 connectedAccount 的元数据和 status,不直接持有 access token。

7. 横向对比

  • 多数 agent 框架(LangChain 等)不管鉴权——你得自己接 OAuth、自己存 token。Composio 把这层托管掉,是它相对「裸框架 + 自己写工具」的主要省力点。
  • 与 MCP server 的鉴权相比:Composio 把「每个终端用户的连接」作为一等概念(connectedAccount 带 userId),适合多租户 SaaS 场景。

8. 代码地图(导航索引)

主题文件关键符号
连接账户管理ts/packages/core/src/models/ConnectedAccounts.tsConnectedAccounts.listinitiatelink
OAuth 轮询等待ts/packages/core/src/models/ConnectionRequest.tscreateConnectionRequestwaitForConnection
鉴权方式工厂ts/packages/core/src/models/AuthScheme.tsAuthScheme.OAuth2APIKeyBearerToken
鉴权模板配置ts/packages/core/src/models/AuthConfigs.tsAuthConfigs(类)
执行时凭据字段ts/packages/core/src/models/Tools.tsexecuteComposioTool(connected_account_id / custom_auth_params)
连接状态枚举ts/packages/core/src/types/connectedAccounts.types.tsConnectedAccountStatuses
Python 对应python/composio/core/models/connected_accounts.pyConnectedAccounts(Python)