工具与集成
配置外部系统集成 — API 集成、数据库连接、OpenAPI 自动工具生成和 S2S 认证。
工具与集成
集成概述
Integration(集成)是智能体调用外部系统的桥梁。通过创建 Integration,你可以让智能体访问你的业务 API、查询数据库、或自动对接 OpenAPI 兼容的服务。
每个 Integration 包含以下核心属性:
| 属性 | 说明 |
|---|---|
type | 集成类型:api、database、openapi |
authMode | 认证方式:none、apikey、jwt |
config | 类型相关的配置(连接地址、密钥等) |
s2sKey | S2S 密钥,用于服务间 JWT 签发 |
generatedTools | 自动生成的工具定义(OpenAPI 类型) |
┌────────────────────┐ ┌──────────────────────┐ ┌─────────────────┐
│ 智能体 (Agent) │──────│ Integration 配置 │──────│ 外部系统 │
│ │ │ - type: api/db/openapi│ │ - REST API │
│ LangChain Tools │ │ - authMode │ │ - PostgreSQL │
│ DynamicStructured │ │ - s2sKey │ │ - OpenAPI Spec │
│ Tool │ │ - config │ │ │
└────────────────────┘ └──────────────────────┘ └─────────────────┘三种集成类型
API 集成
RESTful HTTP 端点集成,支持 none、apikey、jwt 三种认证方式。适用于对接内部微服务或第三方 REST API。
// API 集成配置
interface ApiIntegrationConfig {
baseUrl: string; // 如 "https://erp.example.com/api"
apiKey?: string; // authMode 为 apikey 时使用
headers?: Record<string, string>; // 自定义请求头
}创建示例:
curl -X POST https://agent.tos.run/api/integrations \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "ERP 系统",
"type": "api",
"authMode": "jwt",
"config": {
"baseUrl": "https://erp.example.com/api",
"headers": {
"X-S2S-Key": "sk-your-s2s-key"
}
},
"s2sKey": "sk-your-s2s-key",
"enabled": true
}'数据库集成
直连 PostgreSQL 数据库,自动 introspect 表结构。智能体可基于表结构信息智能地生成和执行 SQL 查询。
// 数据库集成配置
interface DatabaseIntegrationConfig {
connectionUrl: string; // PostgreSQL 连接串
dbType: 'postgresql'; // 目前支持 PostgreSQL
readOnly: boolean; // 默认 true,限制只读查询
tableMetadata?: Array<{ // introspect 后自动填充
table: string;
schema: string;
columns: Array<{
name: string;
type: string;
nullable: boolean;
comment: string | null;
}>;
}>;
}创建数据库集成后,调用 introspect 端点自动获取表结构:
# 1. 创建数据库集成
curl -X POST https://agent.tos.run/api/integrations \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "业务数据库",
"type": "database",
"authMode": "none",
"config": {
"connectionUrl": "postgres://user:pass@db.example.com:5432/mydb",
"readOnly": true
}
}'
# 2. 自动 introspect 表结构
curl -X POST https://agent.tos.run/api/integrations/{id}/introspect \
-H "Authorization: Bearer $TOKEN"
# 返回: { "tables": [{ "table": "orders", "schema": "public", "columns": [...] }] }Introspect 会查询 information_schema.columns 并获取列注释(pg_description),结果自动保存到 Integration 的 config.tableMetadata 中。智能体在对话中会参考这些元数据生成精准的 SQL。
OpenAPI 集成
导入 OpenAPI 3.x Specification,自动为每个 API 操作生成工具定义。
// OpenAPI 集成配置
interface OpenApiIntegrationConfig {
specUrl?: string; // OpenAPI Spec 的 URL
specContent?: Record<string, any>; // 或直接提供 Spec JSON 内容
baseUrl?: string; // 覆盖 Spec 中的 servers[0].url
}导入 OpenAPI Spec 并自动生成工具:
# 1. 创建 OpenAPI 集成
curl -X POST https://agent.tos.run/api/integrations \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "CRM API",
"type": "openapi",
"authMode": "jwt",
"config": {
"specUrl": "https://crm.example.com/openapi.json",
"baseUrl": "https://crm.example.com"
},
"s2sKey": "sk-crm-secret"
}'
# 2. 导入并生成工具
curl -X POST https://agent.tos.run/api/integrations/{id}/import-openapi \
-H "Authorization: Bearer $TOKEN"
# 返回: { "tools": [...], "count": 12 }S2S 认证
服务间 JWT(S2S)认证用于智能体调用外部 API 时的身份验证。整个流程如下:
┌──────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ 管理员 │ │ Tensor Agent │ │ 外部系统 │
│ │ │ 服务端 │ │ │
│ 1. 创建 │────▶│ 2. 存储 s2sKey │ │ │
│ Integration│ │ (加密) │ │ │
│ + s2sKey │ │ │ │ │
│ │ │ 3. 智能体调用工具 │────▶│ 4. 验证 JWT │
│ │ │ 签发 JWT │ │ 处理请求 │
│ │ │ Bearer token │ │ 返回结果 │
└──────────────┘ └──────────────────┘ └─────────────────┘密钥管理
- 创建 Integration 时提供
s2sKey,服务端加密存储 - API 响应中只暴露
s2sKeyPrefix(前 4 位 +****),不会返回原始密钥 - 密钥存储在数据库中,运行时加载到内存的 JWT Secret Store 中
JWT 签发
当智能体通过 HTTP 工具调用外部 API 时,httpExecutor 自动使用 S2S 密钥签发 JWT:
// http-executor 内部逻辑
// 1. 检测工具 endpoint.headers 中是否包含 X-S2S-Key
const s2sKeyHeader = endpoint.headers?.['X-S2S-Key'];
// 2. 如果有 S2S Key,签发 JWT
if (s2sKeyHeader && context.userId) {
const jwt = issueJwt(s2sKeyHeader, {
userId: context.userId,
orgId: context.orgId,
expiresIn: 3600,
});
// 3. 通过 {{auth.jwt}} 模板变量注入到请求头
// Authorization: Bearer {{auth.jwt}}
}签发的 JWT 会被缓存(按 s2sKey + userId + orgId),避免重复签发。
外部系统验证
你的后端收到智能体的 API 请求后,使用同一个 S2S 密钥验证 JWT:
import jwt from 'jsonwebtoken';
function verifyAgentJwt(token, s2sSecret) {
const decoded = jwt.verify(token, s2sSecret, { algorithms: ['HS256'] });
// decoded.sub — 发起对话的用户 ID
// decoded.org — 组织 ID
return decoded;
}
// 在路由中间件中使用
app.use('/api/agent/*', (req, res, next) => {
const token = req.headers.authorization?.replace('Bearer ', '');
try {
req.agentUser = verifyAgentJwt(token, process.env.S2S_SECRET);
next();
} catch {
res.status(401).json({ error: 'Invalid agent JWT' });
}
});工具桥接架构
Tensor Agent 使用 LangChain 的 DynamicStructuredTool 将工具配置转化为可执行的工具实例。
AgentToolConfig 到 LangChain Tool
// 工具配置定义
interface AgentToolConfig {
id: string;
name: string;
description?: string;
type: 'http' | 'builtin' | 'database';
inputSchema?: Record<string, unknown>; // JSON Schema 格式
endpoint?: {
url: string;
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
headers?: Record<string, string>;
bodyTemplate?: string;
responseMapping?: string;
queryParams?: Record<string, string>;
};
integrationId?: string; // 关联的 Integration
}桥接过程(tool-bridge.ts):
import { DynamicStructuredTool } from '@langchain/core/tools';
import { z } from 'zod';
// 1. JSON Schema → Zod Schema 转换
function zodSchemaFromJson(jsonSchema) {
// 递归将 JSON Schema 转为 Zod 类型
// 支持: string, number, integer, boolean, array, object, enum
}
// 2. 创建 LangChain 工具
function createLangChainTools(toolConfigs, executionContext) {
return toolConfigs.map(config =>
new DynamicStructuredTool({
name: config.id ?? config.name,
description: config.description,
schema: zodSchemaFromJson(config.inputSchema),
func: (input) => executeToolCall(config, input, executionContext),
})
);
}两条执行路径
本地执行(Colocated Integration): 智能体与目标服务部署在同一环境,工具调用直接通过 httpExecutor 或 dbExecutor 执行。
Agent Runtime → tool-bridge → executeToolCall() → httpExecutor / dbExecutor → 目标服务远程 S2S 调用: 外部系统部署在独立环境,智能体通过 S2S API 路由调用。
Agent Runtime → tool-bridge → httpExecutor → POST /api/s2s/... → 外部系统所有 API 端点在 /api/s2s/ 下镜像提供,使用 Bearer JWT 认证。
HTTP Executor
httpExecutor 负责执行所有 type: 'http' 的工具调用。
模板插值
支持三种命名空间的模板变量:
| 模板变量 | 来源 | 示例 |
|---|---|---|
{{input.xxx}} | 工具调用参数 | {{input.orderId}} |
{{context.xxx}} | 执行上下文 | {{context.orgId}} |
{{auth.jwt}} | 自动签发的 JWT | {{auth.jwt}} |
// URL 模板
"url": "https://erp.example.com/api/orders/{{input.orderId}}"
// Body 模板
"bodyTemplate": "{\"name\":\"{{input.name}}\",\"amount\":\"{{input.amount}}\"}"
// Header 中使用 JWT
"headers": {
"Authorization": "Bearer {{auth.jwt}}",
"X-S2S-Key": "sk-your-secret" // 触发 JWT 自动签发
}
// 查询参数
"queryParams": {
"page": "{{input.page}}",
"status": "{{input.status}}"
}响应处理
- 支持
responseMapping使用点号路径提取嵌套字段(如data.results[0].text) - 响应体超过 4000 字符自动截断,附带
[TRUNCATED N chars]提示 - 默认超时 30 秒
认证方式
| 方式 | 配置 |
|---|---|
| 无认证 | 不设置 headers |
| API Key | headers: { "X-API-Key": "your-key" } |
| Bearer Token | headers: { "Authorization": "Bearer {{auth.jwt}}", "X-S2S-Key": "sk-..." } |
| 自定义 | 通过 headers 传入任意认证头 |
Database Executor
dbExecutor 负责执行所有 type: 'database' 的工具调用。
执行流程
// 智能体生成 SQL → dbExecutor 执行
async function dbExecutor(config, input, context) {
const connectionUrl = config.endpoint.url;
const query = input.query; // 智能体生成的 SQL
const readOnly = config.endpoint.headers?.['X-Read-Only'] !== 'false';
const result = await executeQuery(connectionUrl, query, readOnly);
return JSON.stringify({
columns: result.columns,
rows: result.rows, // 最多 500 行
rowCount: result.rowCount,
});
}安全控制
- 默认只读:
readOnly默认为true,使用BEGIN READ ONLY事务执行 - 自动限制行数:查询没有
LIMIT时自动追加LIMIT 501,返回最多 500 行 - 连接池:按连接 URL 缓存连接(最多 20 个),空闲 60 秒自动断开
自动工具生成
从 OpenAPI 3.x Spec 自动生成工具定义。
生成规则
对于 Spec 中的每个 path + method 组合:
- 工具名称 — 使用
operationId,未定义时回退到{method}_{path_sanitized} - 描述 — 使用
summary或description - 输入参数 — 合并
parameters(path/query)和requestBody的属性 - URL 模板 — 路径参数替换为
{{input.param}} - 查询参数 — 自动映射到
queryParams - Body 模板 — 从
requestBody.content.application/json.schema.properties生成
示例
给定 OpenAPI Spec:
paths:
/customers/{id}:
get:
operationId: getCustomer
summary: 获取客户详情
parameters:
- name: id
in: path
required: true
schema:
type: string生成的工具配置:
{
"id": "getCustomer",
"name": "getCustomer",
"description": "获取客户详情",
"type": "http",
"inputSchema": {
"type": "object",
"properties": {
"id": { "type": "string", "description": "id" }
},
"required": ["id"]
},
"endpoint": {
"url": "https://crm.example.com/customers/{{input.id}}",
"method": "GET"
}
}限制
- 仅支持 OpenAPI 3.x(不支持 Swagger 2.0)
inputSchema使用扁平化 JSON Schema,不支持oneOf、allOf、$ref等复杂组合- Body 属性与 Path/Query 参数同名时,自动添加
body_前缀
MCP Server
Tensor Agent 支持注册 Model Context Protocol (MCP) 服务器,通过标准协议扩展智能体的工具能力。
注册 MCP Server
curl -X POST https://agent.tos.run/api/mcp-servers \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "文件系统工具",
"serverKey": "filesystem",
"config": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/data"]
},
"enabled": true
}'传输方式
| 传输 | 配置 | 适用场景 |
|---|---|---|
| stdio | { "command": "npx", "args": [...] } | 本地 CLI 工具 |
| SSE | { "url": "https://mcp.example.com/sse" } | 远程服务 |
多级继承
MCP Server 支持组织层级继承:
组织级 MCP Servers → 部门级覆盖 → 智能体级覆盖- 组织级(
unitId = null):所有智能体共享 - 部门级:该部门下的智能体可用,可覆盖组织级同名服务器
- 智能体级(
mcpServers字段):白名单语义,只启用明确引用的服务器
凭证引用
MCP Server 配置支持 $credential{name} 语法引用加密存储的凭证:
{
"serverKey": "github",
"config": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "$credential{github-token}"
}
}
}运行时 CredentialResolver 自动将 $credential{...} 替换为实际值。凭证通过 /api/credentials 端点管理,值加密存储。
连接桥接
MCP 服务器通过 @langchain/mcp-adapters 的 MultiServerMCPClient 桥接为 LangChain StructuredToolInterface,与原生工具统一调度:
import { MultiServerMCPClient } from '@langchain/mcp-adapters';
const client = new MultiServerMCPClient({
filesystem: { transport: 'stdio', command: 'npx', args: [...] },
github: { transport: 'sse', url: 'https://mcp.example.com/sse' },
});
const tools = await client.getTools(); // StructuredToolInterface[]
// 超时限制: 10s数据变更通知
当智能体通过工具调用修改了业务数据(如创建订单、更新客户),工具可以发送 DataChangePayload 事件,通过 iframe 桥接通知宿主页面。
事件格式
interface DataChangePayload {
integration?: string; // 集成来源标识
resource: string; // 资源类型,如 'orders', 'customers'
action: 'create' | 'update' | 'delete';
ids?: string[]; // 受影响的记录 ID
timestamp: number; // Unix 时间戳 (ms)
}通信流程
工具执行完成(数据变更)
→ iframe 发送 tensor-agent:data-change 消息
→ SDK 接收并验证 origin
→ 触发 onDataChange 回调
→ 宿主页面刷新数据
// postMessage 格式
{
type: 'tensor-agent:data-change',
payload: {
resource: 'customer',
action: 'create',
ids: ['cust-123'],
timestamp: 1713081600000
}
}宿主页面监听
const agent = TensorAgent.init({
jwt: token,
onDataChange(event) {
console.log(`${event.resource} ${event.action}:`, event.ids);
refreshList(event.resource);
},
});
// 监听特定资源
agent.onDataChange('orders', (event) => {
orderListRef.reload();
});
// 监听所有变更
agent.onAnyDataChange((event) => {
queryClient.invalidateQueries([event.resource]);
});<TensorAgentProvider
jwt={token}
onDataChange={(event) => {
queryClient.invalidateQueries([event.resource]);
}}
>
<App />
</TensorAgentProvider><TensorAgentLayout
:jwt="token"
@data-change="handleDataChange"
>
<router-view />
</TensorAgentLayout>
<script setup>
function handleDataChange(payload) {
queryClient.invalidateQueries([payload.resource]);
}
</script>API 参考
Integration CRUD
| 方法 | 端点 | 说明 |
|---|---|---|
GET | /api/integrations | 列出当前组织的所有集成 |
POST | /api/integrations | 创建集成 |
GET | /api/integrations/:id | 获取集成详情 |
PATCH | /api/integrations/:id | 更新集成 |
DELETE | /api/integrations/:id | 删除集成 |
POST | /api/integrations/:id/introspect | 数据库集成:introspect 表结构 |
POST | /api/integrations/:id/import-openapi | OpenAPI 集成:导入 Spec 生成工具 |
所有端点需要 owner 或 admin 角色。S2S 模式下在 /api/s2s/integrations 路径访问。
创建请求体
// POST /api/integrations
{
name: string; // 必填,集成名称
description?: string; // 可选,描述
type: 'api' | 'database' | 'openapi'; // 必填,集成类型
authMode?: 'none' | 'apikey' | 'jwt'; // 默认 'none'
config?: Record<string, unknown>; // 类型相关配置
s2sKey?: string; // S2S 密钥
enabled?: boolean; // 默认 true
}更新请求体
// PATCH /api/integrations/:id
{
name?: string;
description?: string | null;
authMode?: 'none' | 'apikey' | 'jwt';
config?: Record<string, unknown>;
s2sKey?: string; // 更新密钥(旧密钥自动作废)
enabled?: boolean;
}响应格式
{
"id": "a1b2c3d4-...",
"orgId": "org-123",
"name": "ERP 系统",
"description": "企业资源管理系统集成",
"type": "api",
"authMode": "jwt",
"config": { "baseUrl": "https://erp.example.com/api" },
"s2sKeyPrefix": "sk-y****",
"generatedTools": [],
"enabled": true,
"createdBy": "user-456",
"createdAt": "2026-04-14T08:00:00.000Z",
"updatedAt": "2026-04-14T08:00:00.000Z"
}响应中不会包含 s2sKey 原始值,仅返回 s2sKeyPrefix(前 4 位 + 掩码)。密钥创建后请立即保存到你的后端环境变量中。
MCP Server CRUD
| 方法 | 端点 | 说明 |
|---|---|---|
GET | /api/mcp-servers | 列出 MCP 服务器 |
POST | /api/mcp-servers | 注册 MCP 服务器 |
PATCH | /api/mcp-servers/:id | 更新配置 |
DELETE | /api/mcp-servers/:id | 删除 |