backend-ai-tools
Skill1 starsChanged 10 months agoMITView on GitHub
Create AI tools for use with Vercel AI SDK agents. Use when asked to "create AI tools", "add agent tools", "create tool for AI", or "add tools to agent".
In this repository14 other files it gives its agents.
- AGENTS.mdAGENTS.md
- skill-creatorSkill
- backend-ai-agentSkill
- backend-auth-clerkSkill
- backend-compressionSkill
- backend-metricsSkill
- backend-model-creationSkill
- backend-route-creationSkill
- backend-scaffoldingSkill
- backend-websocketSkill
- frontend-auth-clerkSkill
- frontend-hooks-creationSkill
- frontend-scaffoldingSkill
- new-project-scaffoldingSkill
The file
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 1 is distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 8
Create tools for AI agents using the Vercel AI SDK tool() function with Zod schemas.
- Distinctive: line 66
When tools need user context or other dependencies:
- Very specific: line 109
Import enum options from @{project}/types:
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Backend AI Tools Creation
Create tools for AI agents using the Vercel AI SDK tool() function with Zod schemas.
Overview
Tools allow AI agents to:
- Query databases
- Create/update records
- Call external APIs
- Perform calculations
- Validate data
File Structure
apps/backend/src/ai/tools/
├── workflow.ts # Workflow-related tools
├── workflowRun.ts # Workflow run tools
└── {resource}.ts # New resource toolsCreating Tools
Basic Tool Pattern
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:
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 })) };
},
});Schema Design
Descriptive Field Descriptions
The .describe() method is crucial - it tells the AI what each field means:
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:
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
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
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
// 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 })) };Using Tools with Agents
// 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 });Complete Example
See references/complete-example.md for a full project tools implementation with CRUD operations.
Checklist
- Create tool file in
apps/backend/src/ai/tools/{resource}.ts - Define Zod schemas with descriptive
.describe()on each field - Create tools using
tool()from 'ai' package - Write clear descriptions explaining purpose and return values
- Handle errors with
success: falseresponses - Export tool collection as named object
- Import in agent and pass to agent constructor
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

