DatabaseChat
Reference

Client Wrapper

defineDatabaseChat configuration and methods.

defineDatabaseChat creates a DatabaseChatClient that wraps the component endpoints with a consistent API.

import { defineDatabaseChat } from "./components/databaseChat/client";

const chat = defineDatabaseChat(components.databaseChat, {
  model: "openai/gpt-4o",
  systemPrompt: "You are a helpful assistant.",
  toolGuidance: "auto",
  tools,
  maxMessagesForDisplay: 100,
  maxMessagesForLLM: 50,
  // Recommended: resolve identity server-side once, and every method
  // routes through ownership-checked endpoints automatically.
  getExternalId: async (ctx) => {
    const userId = await getAuthUserId(ctx); // your auth
    if (!userId) throw new Error("Unauthorized");
    return `user:${userId}`;
  },
});

Configuration options

  • model: default model for chat.send (default: openai/gpt-4o).
  • systemPrompt: default prompt for chat.send.
  • toolGuidance: standard tool-result guidance. Use "auto" or omit for generated guidance, "disabled" to opt out, or a custom string to append instead.
  • tools: explicit tool definitions with already-created handler strings.
  • autoTools: generate tools from schema-like definitions.
  • maxMessagesForDisplay: default message limit for getMessages (default: 100).
  • maxMessagesForLLM: default message limit for LLM context (default: 50).
  • maxToolLoops: maximum tool-calling rounds per message before giving up (default: 5).
  • streamThrottleMs: minimum ms between stream delta writes (default: 100).
  • maxToolResultChars: max characters of a serialized tool result sent to the LLM (default: 16000). Oversized results are truncated and flagged with { truncated: true }.
  • httpReferer / xTitle: OpenRouter attribution headers.
  • getExternalId: async resolver called inside your app's Convex functions to derive the caller's externalId. Works with Convex Auth, Clerk, or any identity provider.

Identity is required

Data-access methods throw when no identity can be resolved - neither a configured getExternalId nor an explicit server-derived externalId argument. This prevents accidentally skipping access control. Raw component endpoints remain available for advanced setups; see Security & Multi-tenant Access.

autoTools shape

autoTools: {
  tables: TableInfo[];
  handlers: {
    query: string;
    count: string;
    aggregate?: string;
    search?: string;
    getById?: string;
  };
  allowedTables: string[];
  excludeFields?: Record<string, string[]>;
  tableDescriptions?: Record<string, string>;
  fieldDescriptions?: Record<string, string>;
}

Common methods

All data-access methods accept an optional { externalId } override (must be derived server-side, never from client input) and route through ownership-checked endpoints when identity is resolvable.

  • createConversation(ctx, { externalId?, title? })
  • getConversation(ctx, conversationId, { externalId? }?)
  • listConversations(ctx, externalId?)
  • getMessages(ctx, conversationId, { externalId?, limit? }?)
  • getStreamState(ctx, conversationId, { externalId? }?)
  • getStreamDeltas(ctx, streamId, cursor, { externalId? }?)
  • abortStream(ctx, conversationId, reason?, { externalId? }?)
  • send(ctx, { conversationId, message, apiKey, model?, systemPrompt?, toolGuidance?, toolContext?, externalId?, maxToolLoops?, streamThrottleMs?, maxToolResultChars? })

send always routes through the scoped chat.sendForExternalId action.

Streaming behavior

  • Only the final round of a tool-calling loop streams to clients.
  • If generation is interrupted (user abort, timeout, error), content streamed so far is persisted as an assistant message with partial: true.

Advanced methods

  • addMessage(ctx, conversationId, role, content, { toolCalls?, toolResults? })
  • getMessagesForLLM(ctx, conversationId, { systemPrompt?, includeTools?, toolGuidance? })
  • getTools() and getToolsForLLM()
  • getSystemPromptWithTools(basePrompt?, toolGuidance?)

Runtime function handles

Convex createFunctionHandle(...) is asynchronous and should be called inside a Convex function. If your app builds tool handles at request time, call components.databaseChat.chat.send directly and pass config.tools from that action. Use defineDatabaseChat when your tool handler strings are already available at construction time.