Convex Actions and General Guidelines Skill
This skill provides comprehensive guidance for Convex actions, HTTP endpoints, validators, schema design, file storage, environment variables, scheduling, and TypeScript best practices.
When to Use This Skill
Use this skill when:
- Implementing action functions for external API calls and long-running tasks
- Creating HTTP endpoints for webhooks or public APIs
- Defining validators for function arguments and database schemas
- Designing database schemas with tables, indexes, and search capabilities
- Setting up environment variables for secrets and configuration
- Implementing cron jobs and scheduled tasks
- Working with file storage for uploads and downloads
- Using Convex-specific TypeScript patterns and types
- Understanding Convex limits and performance constraints
Skill Resources
This skill includes comprehensive reference documentation in references/actions-and-general.md that covers:
Actions and HTTP
- Actions: Defining actions with
"use node" for Node.js modules
- V8 vs Node runtime differences
- Action limitations (10-minute timeout, no database access)
- Calling external APIs and services
- HTTP Endpoints: Setting up
convex/http.ts with httpRouter
- Path registration and exact matching
- Request/response handling
- Method definitions (POST, GET, etc.)
Validators and Types
- Complete validator reference for all Convex types
- Common validators:
v.object(), v.array(), v.string(), v.number(), v.id(), v.boolean(), v.null()
- Discriminated union types with
v.union() and v.literal()
- ASCII field name requirements for objects
- Size and element count limits
Function Development
- New function syntax for all function types
- Function registration patterns (
query, mutation, action, internalQuery, internalMutation, internalAction)
- Function calling patterns across runtimes
- Function references via
api and internal objects
- File-based routing conventions
API Design
- Organizing public and private functions
- Thoughtful file structure within
convex/ directory
- Public vs. internal function visibility
- API surface consistency
Database and Schema
- Schema Definition:
convex/schema.ts structure
- System fields (
_id, _creationTime)
- Table definitions with validators
- Indexes: Creating efficient indexes
- Built-in indexes (by_id, by_creation_time)
- Custom index naming and field ordering
- Multiple field indexes for complex queries
- Full Text Search: Search index definitions
- Search fields and filter fields
- Nested field paths with dot notation
Environment and Configuration
- Environment Variables: Using
process.env
- Storing secrets (API keys, credentials)
- Per-deployment configuration
- Access from any function type
- Scheduling:
- Crons: Using
crons.interval() and crons.cron()
- Scheduler: Using
ctx.scheduler.runAfter() from mutations/actions
- Auth state propagation (doesn't propagate to scheduled jobs)
- Timing constraints and best practices
File Storage
- Upload URL generation with
ctx.storage.generateUploadUrl()
- Signed URL retrieval with
ctx.storage.getUrl()
- File metadata from
_storage system table
- Blob conversion for storage operations
- Complete example: image upload in chat application
Limits and Performance
- Function arguments and return values: 8 MiB maximum
- Database operations: 8192 document writes per mutation, 16384 reads per query
- Execution timeouts: 1 second for queries/mutations, 10 minutes for actions
- Array element limits: 8192 maximum
- Object/Record field limits: 1024 maximum
- Nesting depth: 16 maximum
- Record size: 1 MiB maximum
- HTTP streaming: 20 MiB maximum output
TypeScript
Id<'tableName'> types for strict document IDs
Doc<'tableName'> types for document type safety
Record<KeyType, ValueType> with proper typing
as const for discriminated unions
- Type annotations for same-file function calls
@types/node for Node.js modules
How to Use This Skill
- Read the reference documentation at
references/actions-and-general.md for comprehensive patterns
- Follow the syntax for defining actions with proper Node.js module handling
- Use validators correctly for all function arguments and schema fields
- Design schemas with appropriate indexes for your access patterns
- Set up environment variables for secrets and configuration
- Implement scheduling for background tasks using crons or the scheduler
- Handle file storage with proper URL generation and metadata lookup
- Understand limits and design applications to respect them
- Use TypeScript strictly with
Id types and proper generics
Key General Guidelines
- ALWAYS use argument validators for all functions (queries, mutations, actions)
- Do NOT store file URLs in the database; store file IDs instead
- Remapping non-ASCII characters (emoji) to ASCII codes before storing in objects
- Auth state does NOT propagate to scheduled jobs; use internal functions
- Scheduled functions should not run more than once every 10 seconds
- Never call actions from other actions unless crossing runtimes (V8 to Node)
- Objects in Convex must have ASCII-only field names
- Be strict with TypeScript types, especially for document IDs
Example: Complete Action with HTTP Endpoint
// convex/ai.ts
"use node";
import { action } from "./_generated/server";
import { v } from "convex/values";
import { internal } from "./_generated/api";
import OpenAI from "openai";
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
export const generateResponse = action({
args: {
channelId: v.id("channels"),
},
handler: async (ctx, args) => {
// Actions can't access ctx.db, but can call mutations
const context = await ctx.runQuery(internal.functions.loadContext, {
channelId: args.channelId,
});
const response = await openai.chat.completions.create({
model: "gpt-4o-mini",
messages: context,
});
const content = response.choices[0].message.content;
if (!content) throw new Error("No content in response");
await ctx.runMutation(internal.functions.writeAgentResponse, {
channelId: args.channelId,
content,
});
return null;
},
});
Example: HTTP Endpoint
// convex/http.ts
import { httpRouter } from "convex/server";
import { httpAction } from "./_generated/server";
const http = httpRouter();
http.route({
path: "/webhook",
method: "POST",
handler: httpAction(async (ctx, req) => {
const body = await req.json();
// Process webhook payload
return new Response(JSON.stringify({ success: true }), { status: 200 });
}),
});
export default http;
For more detailed information and additional patterns, refer to the complete reference documentation.
1---2name: convex-actions-general3description: This skill should be used when working with Convex actions, HTTP endpoints, validators, schemas, environment variables, scheduling, file storage, and TypeScript patterns. It provides comprehensive guidelines for function definitions, API design, database limits, and advanced Convex features.4---5
6# Convex Actions and General Guidelines Skill
7
8This skill provides comprehensive guidance for Convex actions, HTTP endpoints, validators, schema design, file storage, environment variables, scheduling, and TypeScript best practices.
9
10## When to Use This Skill
11
12Use this skill when:
13- Implementing action functions for external API calls and long-running tasks
14- Creating HTTP endpoints for webhooks or public APIs
15- Defining validators for function arguments and database schemas
16- Designing database schemas with tables, indexes, and search capabilities
17- Setting up environment variables for secrets and configuration
18- Implementing cron jobs and scheduled tasks
19- Working with file storage for uploads and downloads
20- Using Convex-specific TypeScript patterns and types
21- Understanding Convex limits and performance constraints
22
23## Skill Resources
24
25This skill includes comprehensive reference documentation in `references/actions-and-general.md` that covers:
26
27### Actions and HTTP
28- **Actions**: Defining actions with `"use node"` for Node.js modules
29 - V8 vs Node runtime differences
30 - Action limitations (10-minute timeout, no database access)
31 - Calling external APIs and services
32- **HTTP Endpoints**: Setting up `convex/http.ts` with httpRouter
33 - Path registration and exact matching
34 - Request/response handling
35 - Method definitions (POST, GET, etc.)
36
37### Validators and Types
38- Complete validator reference for all Convex types
39- Common validators: `v.object()`, `v.array()`, `v.string()`, `v.number()`, `v.id()`, `v.boolean()`, `v.null()`
40- Discriminated union types with `v.union()` and `v.literal()`
41- ASCII field name requirements for objects
42- Size and element count limits
43
44### Function Development
45- New function syntax for all function types
46- Function registration patterns (`query`, `mutation`, `action`, `internalQuery`, `internalMutation`, `internalAction`)
47- Function calling patterns across runtimes
48- Function references via `api` and `internal` objects
49- File-based routing conventions
50
51### API Design
52- Organizing public and private functions
53- Thoughtful file structure within `convex/` directory
54- Public vs. internal function visibility
55- API surface consistency
56
57### Database and Schema
58- **Schema Definition**: `convex/schema.ts` structure
59 - System fields (`_id`, `_creationTime`)
60 - Table definitions with validators
61- **Indexes**: Creating efficient indexes
62 - Built-in indexes (by_id, by_creation_time)
63 - Custom index naming and field ordering
64 - Multiple field indexes for complex queries
65- **Full Text Search**: Search index definitions
66 - Search fields and filter fields
67 - Nested field paths with dot notation
68
69### Environment and Configuration
70- **Environment Variables**: Using `process.env`
71 - Storing secrets (API keys, credentials)
72 - Per-deployment configuration
73 - Access from any function type
74- **Scheduling**:
75 - **Crons**: Using `crons.interval()` and `crons.cron()`
76 - **Scheduler**: Using `ctx.scheduler.runAfter()` from mutations/actions
77 - Auth state propagation (doesn't propagate to scheduled jobs)
78 - Timing constraints and best practices
79
80### File Storage
81- Upload URL generation with `ctx.storage.generateUploadUrl()`
82- Signed URL retrieval with `ctx.storage.getUrl()`
83- File metadata from `_storage` system table
84- Blob conversion for storage operations
85- Complete example: image upload in chat application
86
87### Limits and Performance
88- Function arguments and return values: 8 MiB maximum
89- Database operations: 8192 document writes per mutation, 16384 reads per query
90- Execution timeouts: 1 second for queries/mutations, 10 minutes for actions
91- Array element limits: 8192 maximum
92- Object/Record field limits: 1024 maximum
93- Nesting depth: 16 maximum
94- Record size: 1 MiB maximum
95- HTTP streaming: 20 MiB maximum output
96
97### TypeScript
98- `Id<'tableName'>` types for strict document IDs
99- `Doc<'tableName'>` types for document type safety
100- `Record<KeyType, ValueType>` with proper typing
101- `as const` for discriminated unions
102- Type annotations for same-file function calls
103- `@types/node` for Node.js modules
104
105## How to Use This Skill
106
1071. **Read the reference documentation** at `references/actions-and-general.md` for comprehensive patterns
1082. **Follow the syntax** for defining actions with proper Node.js module handling
1093. **Use validators** correctly for all function arguments and schema fields
1104. **Design schemas** with appropriate indexes for your access patterns
1115. **Set up environment variables** for secrets and configuration
1126. **Implement scheduling** for background tasks using crons or the scheduler
1137. **Handle file storage** with proper URL generation and metadata lookup
1148. **Understand limits** and design applications to respect them
1159. **Use TypeScript strictly** with `Id` types and proper generics
116
117## Key General Guidelines
118
119- ALWAYS use argument validators for all functions (queries, mutations, actions)
120- Do NOT store file URLs in the database; store file IDs instead
121- Remapping non-ASCII characters (emoji) to ASCII codes before storing in objects
122- Auth state does NOT propagate to scheduled jobs; use internal functions
123- Scheduled functions should not run more than once every 10 seconds
124- Never call actions from other actions unless crossing runtimes (V8 to Node)
125- Objects in Convex must have ASCII-only field names
126- Be strict with TypeScript types, especially for document IDs
127
128## Example: Complete Action with HTTP Endpoint
129
130```ts
131// convex/ai.ts
132"use node";
133import { action } from "./_generated/server";
134import { v } from "convex/values";
135import { internal } from "./_generated/api";
136import OpenAI from "openai";
137
138const openai = new OpenAI({
139 apiKey: process.env.OPENAI_API_KEY,
140});
141
142export const generateResponse = action({
143 args: {
144 channelId: v.id("channels"),
145 },
146 handler: async (ctx, args) => {
147 // Actions can't access ctx.db, but can call mutations
148 const context = await ctx.runQuery(internal.functions.loadContext, {
149 channelId: args.channelId,
150 });
151
152 const response = await openai.chat.completions.create({
153 model: "gpt-4o-mini",
154 messages: context,
155 });
156
157 const content = response.choices[0].message.content;
158 if (!content) throw new Error("No content in response");
159
160 await ctx.runMutation(internal.functions.writeAgentResponse, {
161 channelId: args.channelId,
162 content,
163 });
164
165 return null;
166 },
167});
168```
169
170## Example: HTTP Endpoint
171
172```ts
173// convex/http.ts
174import { httpRouter } from "convex/server";
175import { httpAction } from "./_generated/server";
176
177const http = httpRouter();
178
179http.route({
180 path: "/webhook",
181 method: "POST",
182 handler: httpAction(async (ctx, req) => {
183 const body = await req.json();
184 // Process webhook payload
185 return new Response(JSON.stringify({ success: true }), { status: 200 });
186 }),
187});
188
189export default http;
190```
191
192For more detailed information and additional patterns, refer to the complete reference documentation.