Skip to content
mordn
Esc
↑↓navigate↵open⌘Jpreview
On this page

Models & tools

Choose a Vercel AI SDK v6 model and build request-scoped tools with guaranteed cleanup.

A model is required in code unless hosted configuration supplies one. A store is also required by the current handler.

Model selection

createChatHandler({
  getUserId: getChatUserId,
  model: anthropic('claude-sonnet-4-5'),
  store: createDrizzleChatStore(),
});

For per-user selection, pass a function of the verified request context:

createChatHandler({
  getUserId: getChatUserId,
  store: createDrizzleChatStore(),
  model: async (ctx) => {
    const plan = await getUserPlan(ctx.userId);
    return plan === 'pro'
      ? anthropic('claude-sonnet-4-5')
      : openai('gpt-4o');
  },
});

@mordn/chat-widget/models exports MODELS, the package’s hosted gateway-string catalog. Provider SDK calls use provider-native ids; hosted config uses gateway strings such as anthropic/claude-sonnet-4-5.

Request-scoped tools

import { tool } from 'ai';
import { z } from 'zod';

createChatHandler({
  getUserId: getChatUserId,
  model,
  store,
  buildTools: async (ctx) => {
    const client = await connectMcp(ctx.userId);

    return {
      tools: {
        searchDocs: tool({
          description: 'Search the documentation.',
          inputSchema: z.object({ query: z.string() }),
          execute: async ({ query }) => client.search(query),
        }),
      },
      cleanup: () => client.close(),
    };
  },
});

AI SDK v6 tool definitions use inputSchema. Do not copy v5 examples that use parameters.

cleanup runs exactly once after success, error, or abort. Use it for MCP clients, transactions, or other per-request resources. Omit it for stateless tools.

Client tool rendering

toolRenderers receives ToolPartLike and may render custom JSX. Return null to fall through to the default row. Use actionRenderers when a declarative status card is enough, and derive status from actual tool state/output.

See MCP tools and AI UX extras.