Skip to main content

Schema Definition

The messages table stores individual messages within conversations. Messages are created and managed by the AI agent system.

Fields

_id
Id<'messages'>
required
Unique message identifier
conversationId
Id<'conversations'>
required
ID of the conversation this message belongs to
projectId
Id<'projects'>
required
ID of the project (denormalized for efficient querying)
role
string
required
Message sender role
content
string
required
Message content (text)
status
string
Processing status for assistant messages

Indexes

by_conversation
index
Index on conversationId for retrieving all messages in a conversationFields: ["conversationId"]
by_project_status
index
Composite index for finding messages by project and status (used for monitoring processing messages)Fields: ["projectId", "status"]

User-Facing Queries

Messages are typically retrieved through the conversations.getMessages query rather than directly. See Conversations Schema for details.
import { api } from "@/convex/_generated/api";
import { useQuery } from "convex/react";

// Recommended: Get messages through conversations API
function ChatMessages({ conversationId }) {
  const messages = useQuery(api.conversations.getMessages, { 
    conversationId 
  });
  
  return messages?.map(msg => (
    <div key={msg._id}>
      <strong>{msg.role}:</strong> {msg.content}
      {msg.status && <span> ({msg.status})</span>}
    </div>
  ));
}

Internal System Operations

The operations below are internal system APIs that require authentication with POLARIS_CONVEX_INTERNAL_KEY. They are used by the AI agent backend and should not be called directly from client code.

createMessage (Internal)

Create a new message in a conversation.
internalKey
string
required
Internal authentication key
conversationId
Id<'conversations'>
required
Conversation identifier
projectId
Id<'projects'>
required
Project identifier
role
'user' | 'assistant'
required
Message sender role
content
string
required
Message content
status
string
Initial status (typically "processing" for assistant messages)
// Internal system usage example
const messageId = await ctx.runMutation(api.system.createMessage, {
  internalKey: process.env.POLARIS_CONVEX_INTERNAL_KEY,
  conversationId,
  projectId,
  role: "assistant",
  content: "",
  status: "processing"
});
Returns: Id<'messages'> - ID of the newly created message Side effects: Updates conversation’s updatedAt timestamp

updateMessageContent (Internal)

Update message content and mark as completed.
internalKey
string
required
Internal authentication key
messageId
Id<'messages'>
required
Message identifier
content
string
required
New message content
// Internal system usage example
await ctx.runMutation(api.system.updateMessageContent, {
  internalKey: process.env.POLARIS_CONVEX_INTERNAL_KEY,
  messageId,
  content: "Here's the updated response..."
});
Side effects: Sets status to "completed"

updateMessageStatus (Internal)

Update message processing status.
internalKey
string
required
Internal authentication key
messageId
Id<'messages'>
required
Message identifier
status
'processing' | 'completed' | 'cancelled'
required
New status
// Internal system usage example
await ctx.runMutation(api.system.updateMessageStatus, {
  internalKey: process.env.POLARIS_CONVEX_INTERNAL_KEY,
  messageId,
  status: "cancelled"
});

getProcessingMessages (Internal)

Retrieve all messages currently being processed in a project.
internalKey
string
required
Internal authentication key
projectId
Id<'projects'>
required
Project identifier
// Internal system usage example
const processing = await ctx.runQuery(api.system.getProcessingMessages, {
  internalKey: process.env.POLARIS_CONVEX_INTERNAL_KEY,
  projectId
});
Returns: Array of messages with status: "processing" Use case: Monitoring active AI operations, cleanup, and recovery

getRecentMessages (Internal)

Retrieve recent messages from a conversation for AI context.
internalKey
string
required
Internal authentication key
conversationId
Id<'conversations'>
required
Conversation identifier
limit
number
Maximum number of messages to return (default: 10)
// Internal system usage example
const recentMessages = await ctx.runQuery(api.system.getRecentMessages, {
  internalKey: process.env.POLARIS_CONVEX_INTERNAL_KEY,
  conversationId,
  limit: 20
});
Returns: Array of up to limit most recent messages in chronological order Use case: Providing conversation context to AI agent

Message Lifecycle

1

User sends message

User message is created with role: "user" and their input content
2

Assistant message created

System creates assistant message with status: "processing" and empty content
3

AI generates response

AI agent processes the request and streams content updates
4

Message completed

Final content is set and status updated to "completed"

Conversations

Messages belong to conversations. Use conversations.getMessages to retrieve messages.

Source Reference

  • Schema definition: convex/schema.ts:52-66
  • Internal operations: convex/system.ts:29-139

Build docs developers (and LLMs) love