backend-ai-tools
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBackend AI Tools Creation
后端AI工具创建
Create tools for AI agents using the Vercel AI SDK function with Zod schemas.
tool()使用Vercel AI SDK的函数结合Zod schema为AI Agent创建工具。
tool()Overview
概述
Tools allow AI agents to:
- Query databases
- Create/update records
- Call external APIs
- Perform calculations
- Validate data
工具可让AI Agent实现以下功能:
- 查询数据库
- 创建/更新记录
- 调用外部API
- 执行计算
- 验证数据
File Structure
文件结构
apps/backend/src/ai/tools/
├── workflow.ts # Workflow-related tools
├── workflowRun.ts # Workflow run tools
└── {resource}.ts # New resource toolsapps/backend/src/ai/tools/
├── workflow.ts # 工作流相关工具
├── workflowRun.ts # 工作流运行工具
└── {resource}.ts # 新资源工具Creating Tools
创建工具
Basic Tool Pattern
基础工具模式
typescript
import { tool } from 'ai';
import { z } from 'zod';
import { ResourceStatusOptions } from '@{project}/types';
import Resource from '../../models/Resource';
const createResourceSchema = z.object({
name: z.string().describe('Name of the resource'),
description: z.string().optional().describe('Optional description'),
status: z.enum(ResourceStatusOptions).optional().describe('Initial status'),
});
export const createResourceTool = tool({
description: `Create a new resource in the database.
Returns the resourceId for use in subsequent operations.`,
inputSchema: createResourceSchema,
execute: async (input) => {
const resource = new Resource({
name: input.name,
description: input.description,
status: input.status || 'active',
});
await resource.save();
return {
success: true,
resourceId: resource.id,
message: `Created resource "${input.name}" with ID: ${resource.id}`,
};
},
});typescript
import { tool } from 'ai';
import { z } from 'zod';
import { ResourceStatusOptions } from '@{project}/types';
import Resource from '../../models/Resource';
const createResourceSchema = z.object({
name: z.string().describe('Name of the resource'),
description: z.string().optional().describe('Optional description'),
status: z.enum(ResourceStatusOptions).optional().describe('Initial status'),
});
export const createResourceTool = tool({
description: `Create a new resource in the database.
Returns the resourceId for use in subsequent operations.`,
inputSchema: createResourceSchema,
execute: async (input) => {
const resource = new Resource({
name: input.name,
description: input.description,
status: input.status || 'active',
});
await resource.save();
return {
success: true,
resourceId: resource.id,
message: `Created resource "${input.name}" with ID: ${resource.id}`,
};
},
});Tool with Context
带上下文的工具
When tools need user context or other dependencies:
typescript
export interface ToolContext {
userId: string;
accountId: string;
}
// Tool factory that accepts context
export const createListUserTasksTool = (context: ToolContext) => tool({
description: 'List tasks for the current user',
inputSchema: z.object({
status: z.enum(['pending', 'completed', 'all']).optional().describe('Filter tasks by status'),
limit: z.number().optional().default(10).describe('Maximum number of tasks to return'),
}),
execute: async (input) => {
const query: Record<string, unknown> = { userId: context.userId };
if (input.status && input.status !== 'all') query.status = input.status;
const tasks = await Task.find(query).limit(input.limit || 10).sort({ createdAt: -1 });
return { success: true, count: tasks.length, tasks: tasks.map(t => ({ id: t.id, title: t.title, status: t.status })) };
},
});当工具需要用户上下文或其他依赖项时:
typescript
export interface ToolContext {
userId: string;
accountId: string;
}
// 接收上下文的工具工厂
export const createListUserTasksTool = (context: ToolContext) => tool({
description: 'List tasks for the current user',
inputSchema: z.object({
status: z.enum(['pending', 'completed', 'all']).optional().describe('Filter tasks by status'),
limit: z.number().optional().default(10).describe('Maximum number of tasks to return'),
}),
execute: async (input) => {
const query: Record<string, unknown> = { userId: context.userId };
if (input.status && input.status !== 'all') query.status = input.status;
const tasks = await Task.find(query).limit(input.limit || 10).sort({ createdAt: -1 });
return { success: true, count: tasks.length, tasks: tasks.map(t => ({ id: t.id, title: t.title, status: t.status })) };
},
});Schema Design
Schema设计
Descriptive Field Descriptions
描述性字段说明
The method is crucial - it tells the AI what each field means:
.describe()typescript
const addNodeSchema = z.object({
workflowId: z.string().describe('The workflowId of the workflow to add the node to'),
id: z.string().describe('Unique identifier for the node (use format: node-1, node-2, etc.)'),
type: z.enum(NodeTypeOptions).describe('The type of node based on its purpose'),
title: z.string().describe('Short title for the step (max 50 characters)'),
content: z.string().describe('Detailed instructions for this step'),
});.describe()typescript
const addNodeSchema = z.object({
workflowId: z.string().describe('The workflowId of the workflow to add the node to'),
id: z.string().describe('Unique identifier for the node (use format: node-1, node-2, etc.)'),
type: z.enum(NodeTypeOptions).describe('The type of node based on its purpose'),
title: z.string().describe('Short title for the step (max 50 characters)'),
content: z.string().describe('Detailed instructions for this step'),
});Enum Fields
枚举字段
Import enum options from :
@{project}/typestypescript
import { StatusOptions, PriorityOptions } from '@{project}/types';
const updateSchema = z.object({
status: z.enum(StatusOptions).describe('New status: active, inactive, or archived'),
priority: z.enum(PriorityOptions).optional().describe('Priority level if changing'),
});从导入枚举选项:
@{project}/typestypescript
import { StatusOptions, PriorityOptions } from '@{project}/types';
const updateSchema = z.object({
status: z.enum(StatusOptions).describe('New status: active, inactive, or archived'),
priority: z.enum(PriorityOptions).optional().describe('Priority level if changing'),
});Tool Description Best Practices
工具描述最佳实践
Be Specific About Purpose
明确说明用途
typescript
export const addNodeTool = tool({
description: `Add a new node (step) to an existing workflow.
Node types:
- 'action': Steps that require doing something
- 'inspection': Steps that require checking
- 'decision': Yes/No branching points
- 'warning': Safety-critical steps`,
inputSchema: addNodeSchema,
execute: async (input) => { /* ... */ },
});typescript
export const addNodeTool = tool({
description: `Add a new node (step) to an existing workflow.
Node types:
- 'action': Steps that require doing something
- 'inspection': Steps that require checking
- 'decision': Yes/No branching points
- 'warning': Safety-critical steps`,
inputSchema: addNodeSchema,
execute: async (input) => { /* ... */ },
});Explain Return Values
解释返回值
typescript
export const createWorkflowTool = tool({
description: `Create a new workflow in the database.
Call this first before adding nodes and edges.
Returns the workflowId which you'll need for subsequent addNode and addEdge calls.`,
inputSchema: createWorkflowSchema,
execute: async (input) => { /* ... */ },
});typescript
export const createWorkflowTool = tool({
description: `Create a new workflow in the database.
Call this first before adding nodes and edges.
Returns the workflowId which you'll need for subsequent addNode and addEdge calls.`,
inputSchema: createWorkflowSchema,
execute: async (input) => { /* ... */ },
});Return Value Patterns
返回值模式
typescript
// Success
return { success: true, resourceId: resource.id, message: `Created resource "${input.name}"` };
// Success with count
return { success: true, message: `Added node`, nodeCount: result.nodes.length };
// Error
return { success: false, message: `Workflow with ID "${workflowId}" not found` };
// List response
return { success: true, count: items.length, items: items.map(item => ({ id: item.id, name: item.name })) };typescript
// 成功
return { success: true, resourceId: resource.id, message: `Created resource "${input.name}"` };
// 带计数的成功返回
return { success: true, message: `Added node`, nodeCount: result.nodes.length };
// 错误
return { success: false, message: `Workflow with ID "${workflowId}" not found` };
// 列表响应
return { success: true, count: items.length, items: items.map(item => ({ id: item.id, name: item.name })) };Using Tools with Agents
在Agent中使用工具
typescript
// Direct export
import { projectTools } from '../tools/project';
const agent = new MyAgent(context, projectTools);
// Combining multiple tool sets
const allTools = { ...workflowTools, ...projectTools };
const agent = new MyAgent(context, allTools);
// Context-aware tools
const tools = createProjectTools({ userId: user.uid, accountId: user.accountId });typescript
// 直接导入
import { projectTools } from '../tools/project';
const agent = new MyAgent(context, projectTools);
// 组合多个工具集
const allTools = { ...workflowTools, ...projectTools };
const agent = new MyAgent(context, allTools);
// 上下文感知工具
const tools = createProjectTools({ userId: user.uid, accountId: user.accountId });Complete Example
完整示例
See references/complete-example.md for a full project tools implementation with CRUD operations.
查看references/complete-example.md获取包含CRUD操作的完整项目工具实现。
Checklist
检查清单
- Create tool file in
apps/backend/src/ai/tools/{resource}.ts - Define Zod schemas with descriptive on each field
.describe() - Create tools using from 'ai' package
tool() - Write clear descriptions explaining purpose and return values
- Handle errors with responses
success: false - Export tool collection as named object
- Import in agent and pass to agent constructor
- 创建工具文件 在路径下
apps/backend/src/ai/tools/{resource}.ts - 定义Zod Schema 为每个字段添加描述性的
.describe() - 创建工具 使用'ai'包中的函数
tool() - 编写清晰的描述 说明用途和返回值
- 处理错误 返回的响应
success: false - 导出工具集合 作为命名对象导出
- 在Agent中导入 并传入Agent构造函数