Chatbot

Your project includes an AI-powered chatbot that uses the Claude API with streaming responses. The chatbot can execute MCP tools to interact with your application data, filtered by user permissions.

Setting up

Add your Anthropic API key to packages/backend/.env:

ANTHROPIC_API_KEY=sk-ant-...

Without this key, the chatbot feature is disabled and a warning is logged at startup.

How it works

  1. User opens the chatbot panel and sends a message.
  2. Frontend sends a POST /api/chatbot/message request.
  3. Backend acquires a concurrency lock, checks rate limits, and streams the response via SSE.
  4. The chatbot uses Claude Haiku 4.5 with an agentic loop (up to 10 iterations) — it can call MCP tools to read and modify data, then provide a final answer.
  5. Token usage is tracked per user, organization, and globally.

Rate limiting

Three-tier daily token limits prevent abuse:

TierDefault limitEnvironment variable
User50,000CHATBOT_DAILY_TOKEN_LIMIT_USER
Organization1,000,000CHATBOT_DAILY_TOKEN_LIMIT_ORGANIZATION
Global1,000,000CHATBOT_DAILY_TOKEN_LIMIT_GLOBAL

Usage is stored in the ChatbotUsage table with daily upserts. Limits reset at midnight UTC.

Concurrency control

Only one chatbot request per user is allowed at a time. A Redis-based lock (with in-memory fallback for development) prevents concurrent requests from mixing responses. Locks have a 5-minute TTL to prevent permanent locks from crashes.

MCP tool integration

The chatbot loads all MCP tools via getAllMcpTools() and filters them by the current user's permissions using Better Auth roles. Tools are converted to Anthropic format and executed in an agentic loop until Claude provides a final answer.

For example, a user with member: ['read'] permission can ask the chatbot to list members, and the chatbot will call the member_list tool automatically.

Permissions

The chatbot requires the chatbot:use permission. Both admin and member roles have this permission by default.

Frontend components

ComponentPurpose
ChatbotSheetSlide-out panel with header, messages, input
ChatbotMessagesScrollable message list with auto-scroll
ChatbotMessageIndividual message with markdown rendering
ChatbotToolCallTool execution indicator with spinner
ChatbotInputText input with send/cancel buttons
ChatbotButtonFloating action button to open chat

Assistant messages are rendered as Markdown via react-markdown with remark-gfm support.

SSE event types

The streaming response sends these event types:

TypeDescription
textStreaming text chunk
tool_useTool invocation started
tool_resultTool execution result
usageToken counts (input/output)
doneStream complete
errorError message

Error handling

HTTPErrorMeaning
409concurrent_requestUser already has active request
429limit_exceededDaily token quota exceeded

Environment variables

VariableRequiredDefaultDescription
ANTHROPIC_API_KEYYesAnthropic API key for Claude
CHATBOT_DAILY_TOKEN_LIMIT_USERNo50000Per-user daily token limit
CHATBOT_DAILY_TOKEN_LIMIT_ORGANIZATIONNo1000000Per-organization daily token limit
CHATBOT_DAILY_TOKEN_LIMIT_GLOBALNo1000000Global daily token limit

Key files

FileDescription
backend/src/features/chatbot/chatbotService.tsAI streaming + tool execution
backend/src/features/chatbot/chatbotController.tsRequest orchestration
backend/src/features/chatbot/chatbotLockService.tsConcurrency control
backend/src/features/chatbot/chatbotUsageService.tsRate limiting
frontend/src/features/chatbot/chatbotStore.tsZustand state management
frontend/src/features/chatbot/useChatbot.tsSSE client hook
frontend/src/features/chatbot/ChatbotSheet.tsxMain UI container