Composio Connected Accounts API 完全指南:用 TypeScript 管理用户第三方服务连接
【免费下载链接】composioComposio powers 1000+ toolkits, tool search, context management, authentication, and a sandboxed workbench to help you build AI agents that turn intent into action.项目地址: https://gitcode.com/GitHub_Trending/co/composio
导读
Connected Accounts(连接账户)是 Composio 中承载用户与外部服务(toolkit)之间认证关系的核心实体,它存储 OAuth Token、API Key 等访问凭据。本文以ts/docs/api/connected-accounts.md为主干,结合 ConnectedAccounts 类源码、AuthScheme 源码 与 官方示例,系统讲解composio.connectedAccounts全部公开方法的调用方式、12 种认证方案的配置细节、连接状态机与多连接管理策略,读完即可在真实 Agent 应用中完成"创建连接 → 用户授权 → 等待激活 → 执行工具"的完整闭环。
认识 ConnectedAccounts:Agent 与外部服务的凭据枢纽
在 Composio 的架构中,Agent 要真正"把意图变成行动",就必须调用 Gmail、GitHub、Slack 等外部服务的工具,而这些工具无一例外需要用户的授权凭据。ConnectedAccounts类就是管理这些凭据的统一入口:
- 每条连接账户对应一个用户(
userId)与一个外部服务(toolkit); - 连接账户内部保存访问令牌及访问该服务所需的其他信息;
- SDK 通过 ConnectedAccounts.ts 暴露
list、link、initiate、waitForConnection、get、delete、refresh、updateStatus、enable、disable等一整套生命周期方法。
从源码结构看,ConnectedAccounts类在构造时注入底层ComposioClient,并对每一次调用做了遥测埋点(telemetry.instrument(this, 'ConnectedAccounts')),因此所有方法都支持通过可选的requestOptions透传signal实现请求取消(withCancellation包装)。这意味着你可以把任何一个连接操作挂接到 AbortController 上。
连接账户的查询与检索
list(query?):按筛选条件列出连接账户
list用于按条件批量查询连接账户,支持按用户、按 toolkit、按认证配置、按状态组合过滤:
// 列出所有连接账户 const allAccounts = await composio.connectedAccounts.list(); // 列出指定用户的连接账户 const userAccounts = await composio.connectedAccounts.list({ userIds: ['user123'], }); // 列出指定 toolkit 的连接账户 const githubAccounts = await composio.connectedAccounts.list({ toolkitSlugs: ['github'], });参数与返回值
query(ConnectedAccountListParams):可选的过滤参数;- 返回值:
Promise<ConnectedAccountListResponse>——一个分页列表; - 抛错:
ValidationError(当 query 未通过 Zod 模式校验时)。
在 ConnectedAccounts.ts 的实现中,list会先用ConnectedAccountListParamsSchema.safeParse(query)做运行时校验,再把 camelCase 的 SDK 参数转换为 wire 格式(snake_case)下发给底层 client,最后经transformConnectedAccountListResponse把响应重新规范化为 SDK 类型。因此传参时务必保证字段名、类型与类型定义一致,否则会直接抛ValidationError。
get(nanoid):按 ID 获取单个连接账户
// 根据连接账户 ID 获取详情 const account = await composio.connectedAccounts.get('conn_abc123'); console.log(account.status); // 例如 'ACTIVE' console.log(account.toolkit.slug); // 例如 'github'参数与返回值
nanoid(string):连接账户的唯一标识;- 返回值:
Promise<ConnectedAccountRetrieveResponse>; - 抛错:连接账户不存在或 API 出错时抛
Error。
建立连接:link 与 initiate 双路径
Composio 提供了两条创建连接的路径,分别面向"托管式 OAuth 授权页"与"手动传入凭据"两种场景。
link(userId, authConfigId, options?):生成 Composio Connect 托管授权链接
link为指定用户和 auth config 创建一条 Composio Connect Link,返回一个外部链接,用户通过该链接在 Composio 托管的认证流程中完成授权:
// 创建连接请求,并把用户重定向到 redirect URL const connectionRequest = await composio.connectedAccounts.link('user_123', 'auth_config_123'); const redirectUrl = connectionRequest.redirectUrl; console.log(`Visit: ${redirectUrl} to authenticate your account`); // 等待连接建立 const connectedAccount = await connectionRequest.waitForConnection();// 携带回调 URL 创建连接请求 const connectionRequest = await composio.connectedAccounts.link('user_123', 'auth_config_123', { callbackUrl: 'https://your-app.com/callback' }); const redirectUrl = connectionRequest.redirectUrl; console.log(`Visit: ${redirectUrl} to authenticate your account`); // 也可以直接在 ConnectedAccounts 上等待 const connectedAccount = await composio.connectedAccounts.waitForConnection(connectionRequest.id);参数与返回值
userId(string):外部用户 ID;authConfigId(string):要连接到的 auth config ID;options(CreateConnectedAccountLinkOptions):可选配置,其中callbackUrl是用户完成连接后跳转的 URL;- 返回值:
Promise<ConnectionRequest>——携带redirectUrl的连接请求对象; - 抛错:
ValidationError:options 校验失败;ComposioFailedToCreateConnectedAccountLink:链接创建失败。
从 link 的实现 可以看到几个关键行为:
- 创建前会执行一次"预检":按
userIds + authConfigIds + ACTIVE 状态调用list,若已存在活动连接且未开启allowMultiple,直接抛ComposioMultipleConnectedAccountsError,避免静默产生重复连接; - 请求体支持
callbackUrl、alias(人类可读别名,需在同一项目内对 userId + toolkit 唯一)以及实验性的experimental块(用于 SHARED 连接与 ACL); - 服务端对 PRIVATE 连接拒绝 ACL 时会抛
ComposioAclOnlyForSharedError,其余失败统一包装为ComposioFailedToCreateConnectedAccountLink; - 返回的
ConnectionRequest初始状态为INITIATED。
initiate(userId, authConfigId, options?):手动传参创建连接
initiate通过手动提交参数创建连接账户,并返回一个连接请求对象,随后可用waitForConnection等待连接就绪:
// OAuth 类 auth config(无需额外参数) const oauthConnection = await composio.connectedAccounts.initiate('user_123', 'auth_config_123', { callbackUrl: 'https://myapp.com/auth/callback', }); // 需要额外参数的 OAuth config(如 Zendesk、PostHog) const zendeskConnection = await composio.connectedAccounts.initiate('user_123', 'zendesk_auth_config', { config: AuthScheme.OAuth2({ subdomain: "yout_subdomain_here" }) }); // API Key 类 auth config(需要额外参数) const apiKeyConnection = await composio.connectedAccounts.initiate('user_123', 'auth_config_456', { config: AuthScheme.ApiKey({ api_key: 'your_api_key_here', }), }); // Basic Auth 类 auth config(需要用户名/密码) const basicAuthConnection = await composio.connectedAccounts.initiate( 'user_123', 'auth_config_789', { config: AuthScheme.Basic({ username: 'your_username', password: 'your_password', }), } ); // redirectUrl 是 OAuth 流程中应把用户重定向去完成认证的地址 console.log(oauthConnection.redirectUrl); // 等待用户完成连接 const connectedAccount = await oauthConnection.waitForConnection();参数与返回值
userId(string):连接账户所属用户 ID;authConfigId(string):连接账户所属 auth config ID;options(CreateConnectedAccountOptions):config:通过AuthScheme辅助函数构造的连接配置;callbackUrl:OAuth 认证完成后的跳转 URL;- 另有源码中定义的
allowMultiple(是否允许多连接)与alias(连接别名);
- 返回值:
Promise<ConnectionRequest>。
重要:initiate 的迁移提示。在 ConnectedAccounts.ts 源码注释 中明确标注:对于 Composio 托管的 OAuth(OAuth1、OAuth2、DCR_OAUTH),initiate底层包装的旧版POST /api/v3/connected_accounts端点正在退役——新组织于 2026-05-08、其余组织于 2026-07-03 切换。切换后,initiate对"Composio 托管 + 可重定向 OAuth 方案"这一组合会抛ComposioLegacyConnectedAccountsEndpointRetiredError。服务端还会通过响应头的Deprecation字段(RFC 9745)发出一次性进程级警告。建议对 Composio 托管 OAuth 一律改用link()——它适用于所有可重定向方案,且返回结构与initiate一致。自定义 OAuth 应用与非 OAuth 方案(API Key、Bearer Token、Basic Auth)不受影响,继续使用initiate即可。
waitForConnection(connectedAccountId, timeout?):等待连接变为 ACTIVE
waitForConnection会持续轮询 Composio API,直到连接进入 ACTIVE 终态、进入错误终态或超时:
// 使用默认超时(60 秒) const connectedAccount = await composio.connectedAccounts.waitForConnection('conn_123abc'); // 使用自定义超时(2 分钟) const connectedAccount = await composio.connectedAccounts.waitForConnection('conn_123abc', 120000);参数与返回值
connectedAccountId(string):要等待的连接账户 ID;timeout(number):最大等待毫秒数,默认 60 秒;- 返回值:
Promise<ConnectedAccountRetrieveResponse>; - 抛错:
ComposioConnectedAccountNotFoundError:连接账户不存在;ConnectionRequestFailedError:连接进入 failed、expired 或 deleted 状态;ConnectionRequestTimeoutError:超时未完成。
从 ConnectionRequest.ts 可以看到轮询的底层机制:先做一次快速检查(若已 ACTIVE 直接返回,若处于 FAILED/EXPIRED/REVOKED 终态立即抛ConnectionRequestFailedError,若 404 则抛ComposioConnectedAccountNotFoundError),随后以1000ms 间隔循环轮询,直到Date.now() - start >= timeout才抛ConnectionRequestTimeoutError。返回的ConnectionRequest对象还带toJSON()/toString()便于日志输出。官方示例 README 还演示了用try/catch分别捕获ConnectionRequestTimeoutError与ConnectionRequestFailedError的推荐写法。
连接账户的生命周期管理:删除、刷新与启停
delete(nanoid):永久删除连接
// 删除一个连接账户 await composio.connectedAccounts.delete('conn_abc123');nanoid(string):要删除的连接账户 ID;- 返回值:
Promise<ConnectedAccountDeleteResponse>; - 抛错:账户不存在或无法删除时抛
Error。
该操作不可撤销,并会吊销与该账户关联的访问令牌(见 源码注释)。
refresh(nanoid):刷新认证凭据
// 刷新连接账户的凭据 const refreshedAccount = await composio.connectedAccounts.refresh('conn_abc123');nanoid(string):要刷新的连接账户 ID;- 返回值:
Promise<ConnectedAccountRefreshResponse>; - 抛错:账户不存在或凭据无法刷新时抛
Error。
当 OAuth Token 已过期或即将过期时,refresh会尝试刷新令牌。源码还支持ConnectedAccountRefreshOptions(含redirectUrl与validateCredentials两个可选字段,分别对应query_redirect_url与validate_credentials参数),用于在刷新后重定向并校验凭据有效性。
updateStatus(nanoid, params):更新连接状态
// 更新连接账户状态 const updatedAccount = await composio.connectedAccounts.updateStatus('conn_abc123', { enabled: true, });nanoid(string):连接账户 ID;params(ConnectedAccountUpdateStatusParams):{ enabled: boolean };- 返回值:
Promise<ConnectedAccountUpdateStatusResponse>。
enable(nanoid) 与 disable(nanoid):快捷启停
// 启用一个连接账户 const enabledAccount = await composio.connectedAccounts.enable('conn_abc123'); // 禁用一个连接账户 const disabledAccount = await composio.connectedAccounts.disable('conn_abc123');两者分别是updateStatus(nanoid, { enabled: true })与updateStatus(nanoid, { enabled: false })的语法糖(见 ConnectedAccounts.ts)。updateStatus亦可携带reason说明禁用原因。
补充:源码中还有实验性的
updateAcl(nanoid, params)(仅对 SHARED 连接生效,对 PRIVATE 连接抛ComposioAclOnlyForSharedError)与update(nanoid, params),前者用于按用户维度控制共享连接的使用权限,后者等价于带校验的updateStatus。
核心类型速查
ConnectedAccountListParams
interface ConnectedAccountListParams { authConfigIds?: string[]; // 按 auth config ID 过滤 cursor?: string; // 分页游标 labels?: string[]; // 按标签过滤 limit?: number; // 限制返回数量 orderBy?: string; // 排序字段(源码中限定为 'created_at' | 'updated_at') statuses?: string[]; // 按状态过滤 toolkitSlugs?: string[]; // 按 toolkit slug 过滤 userIds?: string[]; // 按用户 ID 过滤 }在 connectedAccounts.types.ts 中,statuses被ConnectedAccountStatusSchema约束为枚举:INITIALIZING、INITIATED、ACTIVE、FAILED、EXPIRED、INACTIVE、REVOKED;此外还有实验性的accountType('PRIVATE' | 'SHARED' | 'ALL',缺省只返回 PRIVATE)。
ConnectedAccountListResponse
interface ConnectedAccountListResponse { items: ConnectedAccountRetrieveResponse[]; // 连接账户列表 nextCursor: string | null; // 下一页游标 totalPages: number; // 总页数 }ConnectedAccountRetrieveResponse
interface ConnectedAccountRetrieveResponse { id: string; // 连接账户 ID status: string; // 状态(如 'ACTIVE'、'PENDING') statusReason: string | null; // 状态原因 userId: string; // 用户 ID toolkit: { // 关联的 toolkit id: string; // Toolkit ID slug: string; // Toolkit slug name: string; // Toolkit 名称 }; authConfig: { // 关联的 auth config id: string; // Auth config ID authScheme: string; // 认证方案(如 'oauth2') isComposioManaged: boolean; // 是否由 Composio 托管 isDisabled: boolean; // 是否被禁用 }; isDisabled: boolean; // 连接账户是否被禁用 meta: Record<string, unknown>; // 附加元数据 createdAt: string; // 创建时间戳 updatedAt: string; // 最后更新时间戳 testRequestEndpoint: string | null; // 用于测试连接的端点 }从响应转换器 connectedAccounts.ts 的实现看,SDK 会把 wire 层的 snake_case 字段(auth_scheme、is_composio_managed、status_reason、created_at等)统一转换为 camelCase,并用ConnectionDataSchema安全解析state字段——遇到暂不支持的 auth scheme 时只会告警并忽略该字段,不会让整个请求失败。
CreateConnectedAccountOptions
interface CreateConnectedAccountOptions { config?: ConnectionData; // 使用 AuthScheme 辅助函数构造的连接配置 callbackUrl?: string; // 认证完成后的跳转 URL // 源码中另有:allowMultiple?: boolean; alias?: string; }CreateConnectedAccountLinkOptions
interface CreateConnectedAccountLinkOptions { callbackUrl?: string; // 用户完成连接后跳转的 URL // 源码中另有:alias?: string; allowMultiple?: boolean; experimental?: {...} }回调 URL 的语义(见 类型定义注释):连接成功时会在回调 URL 上追加查询参数status=success,失败时追加status=failed。
ConnectedAccountUpdateStatusParams
interface ConnectedAccountUpdateStatusParams { enabled: boolean; // 账户是否应被启用 }AuthScheme 辅助函数:12 种认证方案全解析
AuthScheme类(AuthScheme.ts)为每一种认证方案提供类型安全的静态工厂函数,返回经过 Zod 校验的ConnectionData对象。连接状态规则:OAuth2、OAuth1 与 Composio Link 方案初始为INITIALIZING,其余方案初始为ACTIVE。
OAuth2— 无需额外参数(重定向流程);若传入
access_token则状态直接为ACTIVE(Token 导入场景):await composio.connectedAccounts.initiate(userId, authConfigId);OAuth1— 无需额外参数:
await composio.connectedAccounts.initiate(userId, authConfigId);API Key— 需要
api_key:await composio.connectedAccounts.initiate(userId, authConfigId, { config: AuthScheme.ApiKey({ api_key: 'your_api_key', }), });Basic Auth— 需要
username与password:await composio.connectedAccounts.initiate(userId, authConfigId, { config: AuthScheme.Basic({ username: 'your_username', password: 'your_password', }), });Bearer Token— 需要
token:await composio.connectedAccounts.initiate(userId, authConfigId, { config: AuthScheme.BearerToken({ token: 'your_bearer_token', }), });Google Service Account— 需要
credentials_json:await composio.connectedAccounts.initiate(userId, authConfigId, { config: AuthScheme.GoogleServiceAccount({ credentials_json: 'your_credentials_json', }), });Basic with JWT— 需要
username、password与 JWT:await composio.connectedAccounts.initiate(userId, authConfigId, { config: AuthScheme.BasicWithJwt({ username: 'your_username', password: 'your_password', jwt: 'your_jwt_token', }), });Bill.com Auth— 需要
sessionId与devKey:await composio.connectedAccounts.initiate(userId, authConfigId, { config: AuthScheme.BillcomAuth({ sessionId: 'your_session_id', devKey: 'your_dev_key', }), });Composio Link— 无需额外参数:
await composio.connectedAccounts.initiate(userId, authConfigId, { config: AuthScheme.ComposioLink(), });Cal.com Auth— 无需额外参数:
await composio.connectedAccounts.initiate(userId, authConfigId, { config: AuthScheme.CalcomAuth(), });Snowflake— 无需额外参数:
await composio.connectedAccounts.initiate(userId, authConfigId, { config: AuthScheme.Snowflake(), });No Auth— 无需额外参数:
await composio.connectedAccounts.initiate(userId, authConfigId, { config: AuthScheme.NoAuth(), });
源码实现细节:AuthScheme.OAuth2的val.status会根据是否传入access_token自动判定——有 token 视为 Token 导入(ACTIVE),无 token 视为重定向流程(INITIALIZING);OAuth1则要求oauth_token与oauth_token_secret同时存在才判定为ACTIVE(见 AuthScheme.ts)。此外 connectedAccountAuthStates.types.ts 中还定义了面向特定服务商的附加字段(如 Zendesk/PostHog 的subdomain、Shopify 的shop、Salesforce 的instanceEndpoint等),以及S2S_OAUTH2、DCR_OAUTH、SERVICE_ACCOUNT、SAML等更多底层方案 schema,需要时可直接查阅该文件。
多连接管理:allowMultiple 与默认去重策略
默认行为:同一 auth config 仅允许一个活动连接
默认情况下,Composio 禁止同一用户对同一 auth config 建立多个连接账户,以避免冲突并保证行为一致。若用户已存在该 auth config 的活动连接,再次创建会抛ComposioMultipleConnectedAccountsError:
// 用户已有连接时会抛错 try { await composio.connectedAccounts.initiate('user_123', 'auth_config_123'); } catch (error) { if (error instanceof ComposioMultipleConnectedAccountsError) { console.log('User already has a connected account for this auth config'); } }这一守卫在 initiate 与 link 的实现 中都是先以userIds + authConfigIds + ACTIVE 状态做预检查询实现的。
开启多连接:allowMultiple: true
如果应用确实需要同一 auth config 对应多个连接(例如让一个用户同时连接多个 GitHub 账号),传入allowMultiple即可:
// 允许创建多个连接 const connection = await composio.connectedAccounts.initiate('user_123', 'auth_config_123', { allowMultiple: true, });开启后:
- 同一用户与 auth config 允许存在多个活动连接;
- SDK 会输出一条
[Warn:AllowMultiple]警告日志,便于追踪该行为(见 ConnectedAccounts.ts); - 应用逻辑需要自行管理"具体使用哪条连接执行操作"。
注意:开启多连接需要应用侧额外的处理逻辑来区分与选择连接,请谨慎评估后再启用。
实战:完整的连接生命周期示例
综合以上内容,一个典型的"GitHub 连接 + 工具调用"流程如下(可对照 ts/examples/connected-accounts 中的toolkit-authorize.ts示例):
import { Composio, AuthScheme, ComposioMultipleConnectedAccountsError } from 'composio-core'; const composio = new Composio({ apiKey: process.env.COMPOSIO_API_KEY }); // 1. 生成托管授权链接(推荐用于 Composio 托管 OAuth) const connectionRequest = await composio.connectedAccounts.link( 'user_123', 'github_auth_config', { callbackUrl: 'https://your-app.com/callback' } ); console.log(`请访问授权页: ${connectionRequest.redirectUrl}`); // 2. 等待用户完成授权(默认 60s,可自定义超时) try { const account = await connectionRequest.waitForConnection(120000); console.log('连接成功:', account.id, account.toolkit.slug); } catch (error) { if (error instanceof ConnectionRequestTimeoutError) { console.error('连接超时,请重试'); } else if (error instanceof ConnectionRequestFailedError) { console.error('连接失败:', error.message); } } // 3. 需要手动注入凭据时使用 initiate + AuthScheme const apiKeyConn = await composio.connectedAccounts.initiate('user_123', 'some_api_auth_config', { config: AuthScheme.ApiKey({ api_key: process.env.SERVICE_API_KEY! }), }); // 4. 查询、刷新、启停、删除 const activeGithub = await composio.connectedAccounts.list({ userIds: ['user_123'], toolkitSlugs: ['github'], statuses: ['ACTIVE'], }); await composio.connectedAccounts.refresh(activeGithub.items[0].id); await composio.connectedAccounts.disable(activeGithub.items[0].id); await composio.connectedAccounts.enable(activeGithub.items[0].id); await composio.connectedAccounts.delete(activeGithub.items[0].id);运行前提:TypeScript SDK 需要先安装依赖并设置COMPOSIO_API_KEY环境变量,然后传入userId(应用侧外部用户 ID)与authConfigId(在 Composio 控制台或通过 Auth Configs API 预先配置)。
扩展阅读路径
- 类完整实现(含
updateAcl、update等实验性方法):ts/packages/core/src/models/ConnectedAccounts.ts - 认证方案工厂:ts/packages/core/src/models/AuthScheme.ts
- 连接状态机与轮询实现:ts/packages/core/src/models/ConnectionRequest.ts
- 全部类型定义与 Zod 校验 schema:ts/packages/core/src/types/connectedAccounts.types.ts、ts/packages/core/src/types/connectedAccountAuthStates.types.ts
- 响应规范化转换器:ts/packages/core/src/utils/transformers/connectedAccounts.ts
- 可直接运行的示例工程:ts/examples/connected-accounts
- 对应的 Python SDK 文档与测试:python/docs/development.md、python/tests/test_connected_accounts.py
- 相关产品概念:docs/api-overviews/connected-accounts.mdx
【免费下载链接】composioComposio powers 1000+ toolkits, tool search, context management, authentication, and a sandboxed workbench to help you build AI agents that turn intent into action.项目地址: https://gitcode.com/GitHub_Trending/co/composio
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考