ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

5 分钟搞定 Composio Tool Router:多用户 MCP 会话隔离与工具精细管控

5 分钟搞定 Composio Tool Router:多用户 MCP 会话隔离与工具精细管控 5 分钟搞定 Composio Tool Router多用户 MCP 会话隔离与工具精细管控【免费下载链接】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想象这样一个场景Alice 让她的 Agent「帮我看看 #release 频道刚才聊了什么」而同一时刻 Bob 在同一个服务里查自己的工单。如果你的后端只是把连接和工具一股脑喂给所有请求那么 Alice 的 Agent 一步就能读到 Bob 的频道消息任何用户都能触发发信工具往任意频道写内容。把 Composio 接到多租户产品上时最常见的事故就出在这里——工具和连接都没有用户边界。Composio 给出的解法叫 Tool Router它为每个用户创建一个独立的 MCP 会话MCP即 Model Context Protocol一个让 AI 应用对接外部工具的开放协议Toolkit 白名单、工具级开关、认证范围都挂在会话维度上。你的 AI 客户端只需连到该会话的 MCP 地址天然拿到的就是「这个用户能用、也只能用」的工具集。按这篇走完你可以 5 分钟内跑通第一个多用户会话并且清楚每个权限开关在源码里的位置。读完你能做到用composio.create()建出带 MCP 地址的用户会话并用use()/delete()管理它的生命周期用toolkits/tools/tags/authConfigs/connectedAccounts精确裁剪每个会话的工具面沿「拿工具 → 搜工具 → 执行工具 → 代理调用」的链路完成一次完整的 Agent 调用把authorize()和waitForConnections串成一条从发起到连接就绪的授权闭环把会话接入 Vercel AI SDK、LangChain、OpenAI Agents、Claude Agents SDK并判断什么时候需要 provider。⚡ 五分钟上手从安装到复用第一个会话先装包。仓库当前版本为 0.18.1# 任选其一 npm i composio/core0.18.1 pnpm add composio/core0.18.1 yarn add composio/core0.18.1装完写一个最小可运行示例这里给 Alice 开一个只含 Slack 的会话import { Composio } from composio/core; const composio new Composio(); // 给 alice 建会话只放行 slackmcp: true 让类型层面暴露 MCP 端点 const session await composio.create(alice, { toolkits: [slack], mcp: true, }); console.log(session.sessionId); // 会话 ID后续复用全靠它 console.log(session.mcp.url); // 任何 MCP 客户端都可以连这个地址 console.log(session.mcp.headers); // 已注入认证头三行配置你就拿到了一个别人碰不到的 Slack 工具入口。注意mcp: true这个细节每个会话运行时其实都有 MCP 端点但只有显式传了这个标志返回类型里才会出现session.mcp否则拿到的是SessionWithoutMcp类型。这是一种「MCP 需显式声明」的类型设计。会话的完整生命周期就三个动词都在同一个对象上创建composio.create(alice, config)等价于composio.sessions.create()。内部先用ToolRouterCreateSessionConfigSchema.parse()校验你的配置再把配置翻译成 wire 负载发给后端最后把响应包装成ToolRouterSession实例。复用composio.use(sessionId)等价于composio.sessions.use()。不带自定义工具时走session.retrieve()直接取回携带自定义工具时走session.attach()先把本地工具挂到既有会话上再取回。删除await session.delete()或composio.sessions.delete(id)。删完后该会话立刻不可检索、不可执行对一个不存在的 ID 调删除会直接透传后端的 404。// 第二次请求进来先查存储命中就复用不命中才新建 const knownId await redis.get(tr:alice); const session knownId ? await composio.use(knownId) : await composio.create(alice, { toolkits: [slack], mcp: true }); if (!knownId) await redis.set(tr:alice, session.sessionId); 源码走查ts/packages/core/src/models/ToolRouter.tsL187–290 的create()实现L321–392 的use()L400–405 的delete()。use()里「有自定义工具则 attach、否则 retrieve」的分支在 L337–348。 权限矩阵8 个配置项一张表讲完create()的配置对象在 Tool Router 类型定义 的ToolRouterCreateSessionConfigSchemaL203–362里有完整 Zod 校验。先上总表后面只展开最常用的几个字段取值形态默认一句话说明toolkitsstring[]|{ enable }|{ disable }不传 不按 toolkit 过滤Toolkit 级白名单 / 黑名单toolsRecordslug, string[] \| { enable } \| { disable } \| { tags }不传 工具级不过滤单个 Toolkit 内按工具再切一刀tags数组 |{ enable } / { disable }不传按行为提示只读 / 破坏性等过滤authConfigsRecordtoolkit, authConfigId{}把 Toolkit 钉到指定认证配置connectedAccountsRecordtoolkit, id \| id[]{}把 Toolkit 钉到指定已连接账户manageConnectionsboolean|{ enable, callbackUrl, waitForConnections }true会话是否自带连接管理能力sandbox旧名workbench二选一{ enable, enableProxyExecution, autoOffloadThreshold, sandboxSize }enable: true规格standard代码执行沙箱的开关与算力experimental{ assistivePrompt, customTools, customToolkits }无实验特性辅助提示词、本地自定义工具另外三个不在这张表里、但会出现在你代码里的字段先一句话带过sessionPreset: direct_tools工具全已知时直接铺开、关掉辅助工具、preload.tools跳过搜索步骤预热工具、multiAccount一个 Toolkit 挂多个账户上限 2–10 个。给会话加权限的最小配置toolkits是最常用的开关。数组写法即白名单黑名单适合「几乎所有都要只砍几个」的场景// 白名单alice 只能碰到 slack 和 jira const s1 await composio.create(alice, { toolkits: [slack, jira], }); // 黑名单team-42 是全功能团队唯独禁掉 calendar const s2 await composio.create(team-42, { toolkits: { disable: [calendar] }, });数组形态在发给后端前会被统一改写成{ enable: [...] }。让 LLM 只看到只读工具tags用四个行为提示做过滤readOnlyHint只读、destructiveHint会改 / 删数据、idempotentHint可安全重试、openWorldHint面向开放世界上下文。全局 tags 作用于所有 Toolkit单个 Toolkit 还能在tools里用自己的 tags 覆盖全局const session await composio.create(alice, { toolkits: [slack, jira], tags: [readOnlyHint], // 全局只读模式 tools: { // jira 这一个 toolkit 放开删除类工具与全局 tags 二选一不能混写 jira: { disable: [JIRA_ARCHIVE_ISSUE] }, }, });一个容易踩的校验点tools里每个 Toolkit 的配置对象中enable/disable/tags只能出现一个多写会直接抛校验错误。 源码走查ts/packages/core/src/lib/toolRouterParams.tsL21–69 的transformToolRouterToolsParams()负责把数组形态转成{ enable }「三选一」约束由ToolRouterConfigToolsSchema.superRefine执行见ts/packages/core/src/types/toolRouter.types.tsL163–200。关掉代码沙箱或给它升级内存sandbox旧别名workbench两者不能同传同传会抛ValidationError控制会话里的代码执行环境// 纯对话型会话彻底关掉代码执行 const safe await composio.create(alice, { toolkits: [slack], sandbox: { enable: false }, }); // 重负载场景升到 large4 vCPU / 4 GB并调大自动卸载阈值 const heavy await composio.create(team-42, { toolkits: [jira], sandbox: { enable: true, enableProxyExecution: true, autoOffloadThreshold: 400000, // 响应超 40 万字符自动挪进沙箱 sandboxSize: large, }, });sandboxSize共四档standard1 vCPU / 1 GB默认、medium2/2 GB、large4/4 GB、xlarge8/8 GB。注意改规格会重建沙箱内存文件系统会丢/mnt/files/持久目录保留。 源码走查规格表定义在ts/packages/core/src/types/toolRouter.types.tsL26–38wire 字段名enable_proxy_execution、auto_offload_threshold、sandbox_size见ts/packages/core/src/lib/toolRouterParams.tsL130–143。 调用链路拿工具 → 搜工具 → 执行工具 → 代理调用拿到会话之后一次典型的 Agent 回合会沿这四步走。理解这条链路比记住每个方法签名重要得多。第一步拿工具tools()把会话里当前可用的工具按你的框架格式吐出来。它在内部先取原始工具再套用modifySchema修饰符、追加预加载的自定义工具最后交给 provider 的wrapTools()包装。// 构造函数里带 provider 才走这条路 const tools await session.tools(); // → 框架可直接消费的工具数组第二步搜工具工具多的时候不需要全量铺开让会话按语义找。search()会把你的问题包成{ queries: [{ use_case }] }发后端const found await session.search({ query: 在 slack 里找未读最多的频道 }); for (const hit of found.results) { console.log(hit.useCase, hit.primaryToolSlugs); } console.log(found.nextStepsGuidance, found.toolkitConnectionStatuses);响应里除了results还有toolSchemas候选工具的输入输出 schema、toolkitConnectionStatuses哪些 Toolkit 没连上、nextStepsGuidance和timeInfo都是给 LLM 规划下一步用的原料。第三步执行工具execute()对本地自定义工具和远程工具提供完全一致的 API。命中本地工具就在进程内跑没命中就发后端。多账户会话还能通过options.account指定用哪个账户执行。const result await session.execute(SLACK_POST_MESSAGE, { channel: C0123, text: 构建完成 ✅, }); console.log(result.data, result.error, result.logId);返回结构被固定为{ data, error, logId }三件套logId留给你做审计追踪。第四步代理调用有时候你要调的 API 根本不在 Composio 工具目录里但认证关系已经在会话里了。proxyExecute()就能让请求借道会话的已连接账户走 Composio 认证层const res await session.proxyExecute({ toolkit: jira, endpoint: https://your-domain.atlassian.net/rest/api/3/myself, method: GET, parameters: [{ in: query, name: fields, value: name }], }); console.log(res.status, res.data, res.headers); // 二进制响应会多一个 binaryDatamethod只接受GET | POST | PUT | DELETE | PATCHparameters每项是{ in: query | header, name, value }写错会在 SDK 边界抛ValidationError。 源码走查ts/packages/core/src/models/ToolRouterSession.ts——tools()在 L192–245注意 L229–234绑定自定义工具时没配 provider 会直接抛错search()在 L536–557execute()在 L573–622本地工具是协作式取消AbortSignal透传给你自己的代码proxyExecute()在 L631–662。 授权闭环从用户点击到连接就绪授权这件事有三种姿势按「自动化程度」从高到低排。姿势一全自动manageConnections保持默认true会话里自带连接管理 meta tools用户说「帮我连一下 Slack」Agent 自己就会发起 OAuth、把跳转链接给用户。适合交互式产品多数情况这是你的默认选择。姿势二自动但先等在姿势一基础上加waitForConnections: true会话在创建后先阻塞等所有必需连接真正就绪才放行走后续流程。对应 wire 字段是enable_wait_for_connections。const session await composio.create(team-42, { toolkits: [slack, jira], manageConnections: { enable: true, callbackUrl: https://your-domain.com/auth/callback, waitForConnections: true, // 没连完不继续 }, });姿势三全手动manageConnections: false你自己编排每一步。核心方法是authorize()它底层调session.link()返回一个带redirectUrl的ConnectionRequestconst request await session.authorize(slack, { callbackUrl: https://your-domain.com/auth/slack, }); console.log(request.redirectUrl); // 引导用户打开这个地址完成授权 const account await request.waitForConnection(); console.log(连接就绪:, account);把整条链路拉直看状态变化是这样的create()→ 会话成立Toolkit 处于未连接状态Agent 触发连接meta tools或你调authorize()→ 后端建一个INITIATED状态的连接请求返回redirectUrl用户在浏览器完成 OAuth → 回调打到你的callbackUrl连接状态推进为ACTIVEwaitForConnection()/waitForConnections解除阻塞Agent 继续干活随时可用session.toolkits()核对items[].connection.isActive由后端账户状态是否为ACTIVE推导支持toolkits/isConnected/search过滤和cursor/limit分页。 源码走查authorize()的选项校验callbackUrl/alias/ 实验性 SHARED 账户 ACL每个 ACL 列表 ≤1000 条、userId1–256 字符超限抛ValidationError在ts/packages/core/src/models/ToolRouterSession.tsL393–471toolkits()的状态推导在 L477–530。 四大主流框架的接入路径四条路分两类走 provider 的「原生工具」路和走 MCP 地址的「协议」路。先记住结论MCP 路径一律不需要 providerprovider 路径必须传。Vercel AI SDKprovider 路径import { openai } from ai-sdk/openai; import { Composio } from composio/core; import { VercelProvider } from composio/vercel; import { stepCountIs, streamText } from ai; const composio new Composio({ provider: new VercelProvider() }); const session await composio.create(alice, { toolkits: [slack] }); const tools await session.tools(); const stream await streamText({ model: openai(gpt-4o-mini), prompt: 汇总 #release 频道今天的消息, stopWhen: stepCountIs(10), tools, }); for await (const chunk of stream.textStream) process.stdout.write(chunk);要 provider因为session.tools()的输出形态取决于 provider。该模式与示例工程 ts/examples/tool-router 保持一致。Vercel AI SDKMCP 路径import { openai } from ai-sdk/openai; import { experimental_createMCPClient } from ai-sdk/mcp; import { Composio } from composio/core; import { stepCountIs, streamText } from ai; const composio new Composio(); // 没有 provider const { mcp } await composio.create(alice, { toolkits: [slack], mcp: true, tools: { slack: { disable: [SLACK_POST_MESSAGE] } }, // 顺便只读化 }); const client await experimental_createMCPClient({ transport: { type: http, url: mcp.url, headers: mcp.headers }, }); const tools await client.tools(); await streamText({ model: openai(gpt-4o-mini), prompt: 今天团队聊了什么, stopWhen: stepCountIs(10), tools });不需要 provider——客户端直接从 MCP 地址拉工具mcp.headers里已经带好认证。LangChainimport { MultiServerMCPClient } from langchain/mcp-adapters; import { ChatOpenAI } from langchain/openai; import { createAgent } from langchain; import { Composio } from composio/core; const composio new Composio(); // 不需要 provider const session await composio.create(alice, { toolkits: [jira], mcp: true }); const client new MultiServerMCPClient({ composio: { transport: http, url: session.mcp.url, headers: session.mcp.headers }, }); const agent createAgent({ name: jira-helper, systemPrompt: 你负责帮团队整理 Jira 工单。, model: new ChatOpenAI({ model: gpt-4o }), tools: await client.getTools(), }); await agent.invoke({ messages: [{ role: user, content: 把前端项目的 open 工单列出来 }] });OpenAI Agents SDKimport { Agent, run, hostedMcpTool } from openai/agents; import { Composio } from composio/core; const composio new Composio(); // 不需要 provider const session await composio.create(team-42, { toolkits: [jira], mcp: true }); const mcpTool hostedMcpTool({ serverLabel: composio, serverUrl: session.mcp.url, headers: session.mcp.headers, }); const agent new Agent({ name: jira-copilot, instructions: 帮团队维护 Jira 工单。, tools: [mcpTool], }); const result await run(agent, 总结本周新提的工单, { stream: true }); for await (const event of result.toStream()) { if (event.type raw_model_stream_event event.data.delta) { process.stdout.write(event.data.delta); } }Claude Agents SDKimport { query } from anthropic-ai/claude-agent-sdk; import { Composio } from composio/core; const composio new Composio(); // 不需要 provider const session await composio.create(alice, { toolkits: [slack], mcp: true }); const stream await query({ prompt: 用工具拉取 #support 频道最近的三条消息, options: { model: claude-sonnet-4-5-20250929, permissionMode: bypassPermissions, mcpServers: { composio: { type: http, url: session.mcp.url, headers: session.mcp.headers }, }, }, }); for await (const event of stream) { if (event.type result event.subtype success) process.stdout.write(event.result); }️ 进阶玩法知道什么时候该用再动手想给工具执行加上下文用会话级 modifiers当你要做执行审计、参数校验或结果改写又不想散落各处时session.tools()接受一个 modifiers 对象。它的参数比普通的 modifiers 多了sessionId跨用户会话的日志能精确归因。类型叫SessionExecuteMetaModifiers组合进 meta tools 配置时是SessionMetaToolOptionsconst tools await session.tools({ modifySchema: ({ toolSlug, toolkitSlug, schema }) { if (toolkitSlug slack) { schema.description ${schema.description}回复请保持 500 字以内; } return schema; }, beforeExecute: ({ toolSlug, sessionId, params }) { console.log([${sessionId}] 即将调用 ${toolSlug}); return params; // 也可以在这里改参数 }, afterExecute: ({ toolSlug, sessionId, result }) { // 统一打点、脱敏 return result; }, });想让 LLM 少绕路控制 meta tools 与预加载默认会话除了业务工具还带一组辅助 meta tools搜索、批量执行、连接管理、沙箱这是 Agent「自己想办法」的基础设施。如果所有工具都事先已知、不需要这些辅助轮直接用 preset 把它们关掉并把允许的工具全部铺开const session await composio.create(alice, { toolkits: [slack], sessionPreset: direct_tools, // 全量直出关闭 meta tools });这个 preset 在 schema 预处理阶段会自动补三个默认值manageConnections: false、sandbox: { enable: false }、preload: { tools: all }。更细的粒度是preload.tools传工具 slug 数组或allall必须搭配toolkits/tools/tags这类正向过滤器把高频工具预热进session.tools()和 MCP 工具列表省掉搜索那一跳。想在会话里存文件用虚拟文件系统每个会话自带一个虚拟文件挂载挂在session.experimental.files下覆盖上传支持本地路径、URL、File、buffer、列表带游标分页、下载返回RemoteFile可buffer()/save()、删除。Agent 工作流里「下载附件 → 处理 → 存回会话」这种模式不用你再建一套存储const file await session.experimental.files.upload(/tmp/report.pdf); const listing await session.experimental.files.list({ path: / }); const remote await session.experimental.files.download(report.pdf); await remote.save(/tmp/report-back.pdf); await session.experimental.files.delete(/tmp/cache.json);挂载对象在会话构造时就用sessionId绑定好了use()恢复的会话同样可用。想让自己的代码和远程工具混跑自定义工具与工具箱experimental_createTool/experimental_createToolkit从composio/core导出让你把本地函数注册进会话。三种形态import { experimental_createTool, experimental_createToolkit } from composio/core; import { z } from zod/v3; // 独立工具无认证纯本地 const localGrep experimental_createTool(LOCAL_GREP, { name: Repo Grep, description: 在本地代码库中搜索模式, inputParams: z.object({ pattern: z.string(), path: z.string() }), execute: async (input) ({ matches: [] }), }); // 扩展工具继承 Composio Toolkit 的连接 const digest experimental_createTool(SLACK_CHANNEL_DIGEST, { name: Channel Digest, description: 汇总频道消息, extendsToolkit: slack, // 复用 slack 的已连接账户 inputParams: z.object({ channel: z.string() }), execute: async (input, ctx) { const msgs await ctx.execute(SLACK_FETCH_CHANNELS_HISTORY, { channel: input.channel }); return { count: (msgs.data as unknown[]).length }; }, }); // 自定义工具箱把多个无认证工具打包 const devKit experimental_createToolkit(DEV_KIT, { name: Dev Kit, description: 本地开发工具集, tools: [localGrep], });const session await composio.create(alice, { toolkits: [slack], experimental: { customTools: [digest], customToolkits: [devKit] }, }); // 直接按 slug 执行和远程工具一个 API await session.execute(LOCAL_GREP, { pattern: TODO, path: /src }); await session.execute(SLACK_CHANNEL_DIGEST, { channel: C0123 });运行机制值得知道自定义工具和远程工具一起被搜索索引LLM 一次批量调用COMPOSIO_MULTI_EXECUTE_TOOL会被 SDK 拦截本地工具在进程内并行执行、远程工具并行发后端最后按原始顺序合并并给出total_count/success_count/error_count统计。另一个硬约束会话绑定了自定义工具时create()的 userId 不能缺构造器会直接抛错。 源码走查本地/远程分流逻辑在ts/packages/core/src/models/ToolRouterSession.ts的routeMultiExecute()COMPOSIO_MULTI_EXECUTE_TOOL拦截见 L207–227userId 强校验在构造函数 L142–144customTools()/customToolkits()两个列举方法可用来查注册结果L343–395。✅ 生产清单上线前对着勾一遍一用户一会话sessionId存进 Redis 之类的存储请求进来先use()再考虑create()避免反复建会话最小 toolkit 集白名单优先只有「全都要、砍几个」的场景才用disable默认只读对外 Agent 挂tags: [readOnlyHint]写操作按 Toolkit 单独放开并记审计钉死认证用authConfigs/connectedAccounts指定账户别依赖组织默认连接onboarding 用waitForConnections新用户首次会话设true防止 Agent 在授权完成前空转按需关沙箱纯对话会话sandbox: { enable: false }大响应场景调autoOffloadThreshold和sandboxSize工具全已知就上 presetsessionPreset: direct_tools或preload.tools砍掉搜索环节留审计尾迹execute()的logId落库定期用toolkits()巡检isActive失效连接主动提醒用户重连。 速查附录核心类型与新特性三个最值得钉在文档里的类型完整定义见 Tool Router 类型文件// 创建会话的配置 interface ToolRouterCreateSessionConfig { toolkits?: string[] | { enable: string[] } | { disable: string[] }; tools?: Recordstring, string[] | { enable: string[] } | { disable: string[] } | { tags: ToolTag[] }; tags?: ToolTag[] | { enable?: ToolTag[]; disable?: ToolTag[] }; authConfigs?: Recordstring, string; connectedAccounts?: Recordstring, string | string[]; manageConnections?: boolean | { enable?: boolean; callbackUrl?: string; waitForConnections?: boolean }; sandbox?: { enable?: boolean; enableProxyExecution?: boolean; autoOffloadThreshold?: number; sandboxSize?: SandboxSize }; preload?: { tools: string[] | all }; sessionPreset?: direct_tools; experimental?: { assistivePrompt?: { userTimezone?: string }; customTools?: CustomTool[]; customToolkits?: CustomToolkit[] }; } type ToolTag readOnlyHint | destructiveHint | idempotentHint | openWorldHint; type SandboxSize standard | medium | large | xlarge;// 会话本体mcp: true 时的完整形态 interface Session { sessionId: string; mcp: { type: http | sse; url: string; headers?: Recordstring, string }; configVersion?: number; warnings: ToolRouterSessionWarning[]; tools: (modifiers?: SessionMetaToolOptions) PromiseTools; authorize: (toolkit: string, options?: { callbackUrl?: string; alias?: string }) PromiseConnectionRequest; toolkits: (options?: ToolRouterToolkitsOptions) PromiseToolkitConnectionsDetails; search: (params: { query: string; toolkits?: string[] }) PromiseToolRouterSessionSearchResponse; execute: (toolSlug: string, args?: Recordstring, unknown, options?: { account?: string }) PromiseToolRouterSessionExecuteResponse; update: (config: ToolRouterUpdateSessionConfig) Promisevoid; delete: () PromiseToolRouterSessionDeleteResponse; proxyExecute: (params: SessionProxyExecuteParams) PromiseToolRouterSessionProxyExecuteResponse; experimental: { assistivePrompt?: string; files: ToolRouterSessionFilesMount }; }// 执行结果三件套 interface ToolRouterSessionExecuteResponse { data: Recordstring, unknown; error: string | null; logId: string; }当前版本值得重点关注的四项能力waitForConnections连接就绪前会话不跑onboarding 场景的关键开关wire 字段enable_wait_for_connections会话级 modifiersmodifySchema/beforeExecute/afterExecute全部携带sessionId审计可精确到用户sandbox 统一与算力档位sandbox取代workbench后者为兼容别名二者不能同传新增sandboxSize四档规格改档会重建沙箱但保留/mnt/files/preload与direct_toolspreset跳过搜索直出工具preset 还会自动关闭 meta tools、连接管理与沙箱。顺带一提会话建完之后配置并非冻结session.update()支持部分更新只改传入字段未传字段原样保留并就地同步configVersion/preload/warnings比如临时给某会话追加tags: [readOnlyHint]。️ 资源入口资源路径Tool Router API 文档ts/docs/api/tool-router.md可运行示例工程pnpm start/pnpm preload/pnpm direct-toolsts/examples/tool-router/会话创建 / 复用 / 删除实现ts/packages/core/src/models/ToolRouter.ts会话方法实现tools / search / execute / authorize / proxyExecutets/packages/core/src/models/ToolRouterSession.ts全部 Zod schema 与类型定义ts/packages/core/src/types/toolRouter.types.ts配置到 wire 字段的转换逻辑ts/packages/core/src/lib/toolRouterParams.tsModifiers 类型ts/packages/core/src/types/modifiers.types.ts【免费下载链接】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),仅供参考
返回列表