← Blog

How to Build a Customer Support Bot with Claude API

2026-10-18 · 5 min read · SubToAPI Team

Building a customer support bot with Claude API means connecting a language model to your support knowledge, letting it answer common questions accurately, and handing off to a human when it can't help. The core pieces are: a system prompt that defines scope and tone, a way to feed it your documentation or ticket history, tool calls for actions like looking up orders, and a fallback path to a human agent. None of this requires a custom ML pipeline — it's mostly prompt design, a thin API layer, and a few integration points with your existing support stack.

This guide walks through the architecture and the actual code, from a minimal Q&A bot to one that can check order status and escalate tickets.

Architecture overview

A production support bot has five moving parts:

  1. Intake — chat widget, Slack app, email parser, or help desk webhook
  2. Context retrieval — pulling relevant docs, FAQs, or account data for the question
  3. Claude call — the model generates a response, optionally calling tools
  4. Action execution — tools that check order status, create tickets, or update CRM records
  5. Escalation — detecting when to route to a human

You don't need all five on day one. A useful bot can ship with just intake, a static knowledge base in the system prompt, and the Claude call.

Step 1: Define the system prompt

The system prompt is where most of the bot's behavior lives. Keep it specific about scope, tone, and what it should not do.

You are a support assistant for Acme Cloud Storage.
Only answer questions about billing, storage limits, file sharing,
and account settings. If asked about anything else, or if you are
unsure, say you'll connect them with a human agent.
Never guess at pricing — use the lookup_plan tool for plan details.
Keep responses under 4 sentences unless the user asks for detail.

Vague prompts ("be helpful and friendly") produce vague bots. Explicit boundaries reduce hallucinated policy answers, which is the single biggest source of support bot complaints.

Step 2: Feed it your knowledge base

For most support bots, you don't need a full RAG pipeline on day one. If your FAQ and policy docs fit in a reasonable token budget, paste them directly into the system prompt or a preceding user message. Claude's large context window handles tens of thousands of tokens of reference material without a vector database.

const systemPrompt = `
You are a support assistant for Acme Cloud Storage.
Reference material:
${faqText}
Only use the reference material above to answer. If the answer
isn't in there, say you're not sure and offer to escalate.
`;

Once your docs outgrow what fits comfortably in context, move to a retrieval step that fetches only the relevant sections before each call — but don't build that infrastructure until you actually need it.

Step 3: Make the first API call

Here's a minimal request/response loop:

const response = await fetch("https://api.subtoapi.app/v1/messages", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.SUBTOAPI_KEY}`,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    model: "claude-sonnet-4-20250514",
    max_tokens: 500,
    system: systemPrompt,
    messages: [
      { role: "user", content: "Why was I charged twice this month?" }
    ]
  })
});

const data = await response.json();
console.log(data.content[0].text);

If you're routing Claude access through SubToAPI, every ticket runs through a single sub_live_... key, with usage metadata per request so you can see token cost per conversation without stitching together separate billing exports. See the quickstart and the messages endpoint for the full request shape.

Step 4: Add tools for real actions

A support bot that can only answer FAQ questions is useful but limited. The real value comes from letting it look up order status, check subscription tier, or create a ticket — using Claude's tool use feature.

const tools = [
  {
    name: "lookup_order",
    description: "Get the status and details of a customer order by order ID",
    input_schema: {
      type: "object",
      properties: {
        order_id: { type: "string" }
      },
      required: ["order_id"]
    }
  }
];

When Claude decides it needs order data, it returns a tool_use block instead of plain text. Your backend executes the actual lookup against your database, then sends the result back as a tool_result so Claude can finish the answer. This keeps Claude from guessing at account details it has no access to — it only states what your systems confirm. Full details on request/response shapes are in the tools docs.

Step 5: Stream responses for chat UIs

For a live chat widget, streaming tokens as they're generated makes the bot feel responsive instead of making users stare at a blank bubble for a few seconds.

curl https://api.subtoapi.app/v1/messages \
  -H "Authorization: Bearer $SUBTOAPI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4-20250514",
    "max_tokens": 500,
    "stream": true,
    "messages": [{"role": "user", "content": "How do I reset my password?"}]
  }'

See the streaming docs for handling server-sent events on the client side.

Step 6: Build the escalation path

Decide up front what triggers a handoff: explicit user request ("talk to a human"), the bot saying it's unsure, a sentiment signal like repeated frustration, or a hard rule like refund amounts over a threshold. The cleanest implementation is a dedicated instruction in the system prompt plus a check in your backend — if the response contains an escalation phrase, stop the automated flow and create a ticket in your help desk instead of sending the message.

Step 7: Test against real tickets, not hypotheticals

Before launch, run your bot against a sample of actual closed tickets from your help desk — not invented test questions. Real tickets expose the ambiguous phrasing, typos, and multi-part questions that clean test cases miss. Track where the bot would have given a wrong or overconfident answer and tighten the system prompt or add a tool for that case.

Managing cost and access as you scale

Support bots run constantly and across many team members building and testing flows, so centralized key management matters early. Instead of sharing one raw API key across the team, SubToAPI gives each environment or developer their own sub_live_... key under one billing account, with per-key usage visible in the dashboard. Plans start at Solo (€9) for individuals, Team (€19/seat) for shared support engineering, and Scale (€49/seat) for larger teams running multiple bots or high ticket volume — see pricing for details.

questions

Does the bot need a vector database to answer support questions? Not necessarily. If your FAQ and policy docs fit within a reasonable context size, paste them directly into the prompt. Add retrieval only once your knowledge base grows too large for that.

How do I stop the bot from making up refund policies or pricing? Be explicit in the system prompt that it must use a tool for pricing/policy lookups rather than answering from memory, and instruct it to escalate when unsure rather than guessing.

What's the fastest way to add order lookups or account actions? Use Claude's tool use feature: define a schema for the action, let Claude request it as a tool_use block, execute it in your backend, and return the result as a tool_result. See the tools docs for the exact format.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →