跳到主要内容

Composio — Tool Router 与自定义工具

本章讲什么: 两个进阶能力。Tool Router——工具多到塞不进上下文时,怎么用「会话 + 搜工具/执行工具元工具」让 agent 按需取用。自定义工具——怎么把你自己的本地函数注册成工具,并在进程内直接执行(不走 Composio 后端)。

1. 问题:工具太多,上下文塞不下

Composio 有上千个工具。如果一股脑全 wrapTools 塞给模型,光工具 schema 就吃光上下文窗口,模型还选不准。

两种应对思路:

思路做法缺点
静态裁剪tools.get 只取少数 toolkit/important 工具得提前知道要哪些
动态检索给 agent「搜工具」能力,用到再搜多一次检索往返

Tool Router 走的是第二条:把「全部工具」藏起来,只暴露两把「元工具」——一把搜、一把执行。

2. Tool Router 的核心点子

类比: 不把整个图书馆的书都搬到你桌上,而是给你一张「检索卡 + 取书单」。要什么书先检索,再点名取。

agent 上下文里只有两把「元工具」:
┌─────────────────────────────┐
│ search(query) ──▶ 按语义找出相关工具 + 它们的 schema/用法 │
│ execute(slug, args) ──▶ 真正执行某个被搜出来的工具 │
└─────────────────────────────┘
│ 这些都在一个「会话(session)」里

Composio 后端:持有全部工具 + 这个 session 的连接/沙箱配置

agent 的典型回合:search('send a slack message') → 后端返回 SLACK_SEND_MESSAGE 及其 schema → agent 用 execute('SLACK_SEND_MESSAGE', {...}) 执行。上下文里始终只有两把元工具,不随工具总数膨胀。

3. 创建会话

composio.sessions.create(userId, config)(composio.tssessions/create 是同一个,models/ToolRouter.ts:177-290)创建一个绑定到某用户的会话:

// 示意,基于 ToolRouter.ts:158-172 的 doc 示例
const session = await composio.sessions.create('user_123', {
toolkits: ['gmail'], // 限定可搜的范围(也可不限)
manageConnections: true, // 让 session 能自己发起 OAuth 授权
});

console.log(session.sessionId);
// session.mcp.url / session.mcp.headers —— 可作为 MCP endpoint 直接给支持 MCP 的客户端

创建时 config 经过一连串 transform* 函数转成后端 wire 格式(models/ToolRouter.ts:222-255):toolkits、tools、tags、manageConnections、sandbox、multiAccount 各转一道。这一步把「用户友好的 TS 配置」翻译成「后端 API 参数」。

manageConnections 的妙处

开了 manageConnections,会话自己就能发起授权:session.authorize(toolkit) 返回一个 connectionRequest(models/ToolRouterSession.ts:380-440),复用了第 03 章createConnectionRequest。于是「搜工具 → 发现没连 → 当场授权 → 继续执行」可以全在一个会话里闭环。

4. 会话里的元工具

ToolRouterSession 暴露的关键方法(models/ToolRouterSession.ts):

方法干什么行号
search({query, toolkits?})按语义检索工具,返回 schema + 用法指引:504-525
execute(slug, args, opts?)执行一个工具(本地或远程):540-589
authorize(toolkit, opts?)在会话内发起 OAuth,返回 connectionRequest:380-440
tools()列出会话当前暴露的工具:188
toolkits()查会话内各 toolkit 的连接状态:445

search 的入参其实是 { use_case: query } 的语义检索(models/ToolRouterSession.ts:514-518)——你描述「想干什么」,后端返回相关工具,而不是关键字精确匹配。

5. 自定义工具:把本地函数变成工具

除了 Composio 的现成工具,你能注册自己的本地工具(如「读本地文件」「查内部数据库」)。用 experimental_createTool(models/CustomTool.ts:1-20 的 doc 示例):

// 示意,基于 CustomTool.ts 顶部示例
const grep = experimental_createTool('GREP', {
name: 'Grep Search',
description: 'Search for patterns in files',
inputParams: z.object({ pattern: z.string() }), // zod schema
execute: async (input) => ({ matches: [] }), // ← 你的本地逻辑
});

const session = await composio.sessions.create('user_1', {
experimental: { customTools: [grep] }, // 注册进会话
});

本地工具的执行:不走后端

这是关键差异:自定义工具在你的进程内直接执行,不发到 Composio 后端。session.execute 先查这个 slug 是不是本地工具,是就走 in-process 分支(models/ToolRouterSession.ts:546-565):

const entry = findCustomTool(this.customToolsMap, toolSlug);
if (entry) {
// 本地工具:in-process 执行用户的 execute 函数
const result = await executeCustomTool(entry, arguments_ ?? {}, this.sessionContext!, {...});
return { data: result.data, error: result.error, logId: '' };
}
// 否则:远程,发到后端

executeCustomTool 先用你给的 zod schema 校验并转换入参(应用 default/coercion/transform),再调你的函数(models/customToolExecution.ts:64-80)。所以自定义工具自带输入校验,LLM 给的脏参数会先被 zod 兜一道。

slug 的小心机:LOCAL_ 前缀

后端给本地工具的最终 slug 会加 LOCAL_ 前缀(models/CustomTool.ts:48)。findCustomTool 同时按「最终 slug(LOCAL_X,给 LLM 看的)」和「原始 slug(X,给程序员手调用的)」两套 map 查(models/customToolExecution.ts:17-27),兼顾两类调用方;原始 slug 在多个自定义 toolkit 里重名时会被标为 ambiguous 并拒绝裸用(models/customToolExecution.ts:34-54)。

6. 巧妙之处

  • 上下文与工具数解耦:Tool Router 让上下文成本恒定(两把元工具),和后端有多少工具无关——这是「工具规模化」的核心招。
  • 本地与远程工具同一个 execute 入口:session.execute 内部按 slug 自动分流本地 in-process / 远程 HTTP,调用方无感(models/ToolRouterSession.ts:546-572)。
  • 会话即 MCP endpoint:每个 session 自带 mcp.url/mcp.headers,可直接交给任意 MCP 客户端,等于「零代码把这套工具暴露成 MCP server」(models/ToolRouter.ts:280-289)。
  • 自定义工具复用 zod 校验:用户写工具只管业务逻辑,输入校验/默认值由注册时的 zod schema 免费提供(models/customToolExecution.ts:76-80)。

7. 边界与局限

  • 自定义工具的取消是协作式的:session.execute 会在调用前检查 abort,但你的长任务不会自动观察到后续取消,除非你把 signal 接进自己的 fetch/工作里(models/ToolRouterSession.ts:549-559)。
  • customTools 仍是 experimental:工厂叫 experimental_createTool,API 形状可能变。
  • composio.mcp 已废弃:独立的 MCP server 管理 API 标了 deprecated,推荐用「session 的 MCP endpoint」(composio.ts:208-216)。

8. 横向对比

  • Tool Router 的「search+execute 元工具」与 MCP 的 tools/list + tools/call 思路一致,但多了「语义检索」而非全量列举——更适合海量工具。
  • 自定义工具的 in-process 执行,与「全部工具都走托管后端」是一种务实折中:私有逻辑留在你这边,公共 API 交给 Composio。

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

主题文件关键符号
创建/复用会话ts/packages/core/src/models/ToolRouter.tsToolRouter.createToolRouter.use
会话元工具ts/packages/core/src/models/ToolRouterSession.tssearchexecuteauthorizetoolkits
配置转 wirets/packages/core/src/lib/toolRouterParams.tstransformToolRouterToolkitsParams
自定义工具工厂ts/packages/core/src/models/CustomTool.tsexperimental_createToolLOCAL_TOOL_PREFIXfindCustomTool
本地执行ts/packages/core/src/models/customToolExecution.tsexecuteCustomToolassertUnambiguousCustomToolSlug
preload 常量ts/packages/core/src/lib/toolRouterConstants.tsPRELOAD_TOOLS_ALL
Python 对应python/composio/core/models/tool_router.pyToolRouter(Python)