backend-ai-tools

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Backend AI Tools Creation

后端AI工具创建

Create tools for AI agents using the Vercel AI SDK
tool()
function with Zod schemas.
使用Vercel AI SDK的
tool()
函数结合Zod schema为AI Agent创建工具。

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 tools
apps/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
.describe()
method is crucial - it tells the AI what each field means:
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()
方法至关重要——它告诉AI每个字段的含义:
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}/types
:
typescript
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}/types
导入枚举选项:
typescript
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

检查清单

  1. Create tool file in
    apps/backend/src/ai/tools/{resource}.ts
  2. Define Zod schemas with descriptive
    .describe()
    on each field
  3. Create tools using
    tool()
    from 'ai' package
  4. Write clear descriptions explaining purpose and return values
  5. Handle errors with
    success: false
    responses
  6. Export tool collection as named object
  7. Import in agent and pass to agent constructor
  1. 创建工具文件
    apps/backend/src/ai/tools/{resource}.ts
    路径下
  2. 定义Zod Schema 为每个字段添加描述性的
    .describe()
  3. 创建工具 使用'ai'包中的
    tool()
    函数
  4. 编写清晰的描述 说明用途和返回值
  5. 处理错误 返回
    success: false
    的响应
  6. 导出工具集合 作为命名对象导出
  7. 在Agent中导入 并传入Agent构造函数