How to Build a Customer Support Agent with Claude
Building a customer support agent with Claude means combining a well-scoped system prompt, access to your support data through tool use, and a reliable API layer that handles streaming, retries, and usage tracking. You don't need a complex framework to get started — you need Claude's Messages API, a few tools for looking up orders or tickets, and clear rules about when the agent should hand off to a human.
This guide walks through the actual architecture: how to structure the system prompt, which tools to give the agent, how to handle escalation, and how to deploy it behind an API your product can call reliably.
What a Support Agent Actually Needs
A support agent isn't just a chatbot with a friendly prompt. It needs:
- Context retrieval — access to order history, account status, or a knowledge base
- Tool use — the ability to call functions like
lookup_orderorcreate_ticket - Guardrails — clear boundaries on what it can promise (refunds, deadlines, etc.)
- Escalation logic — knowing when to stop and route to a human
- Conversation memory — maintaining context across a multi-turn thread
Claude handles all of this through standard chat completions with tool definitions. The hard part isn't the model — it's wiring the tools and deciding what the agent is and isn't allowed to do.
Step 1: Write a Scoped System Prompt
Keep the system prompt focused on role, tone, and boundaries. Avoid stuffing it with every edge case — that's what tools and few-shot examples are for.
You are a support agent for Acme Shipping. You help customers track
orders, request refunds under $50, and answer FAQ questions.
Rules:
- Never promise refunds above $50 without escalating to a human.
- Always look up the order before answering questions about it.
- If the customer is angry or asks for a manager, escalate immediately.
- Keep responses under 4 sentences unless listing steps.
This gives Claude a clear job and clear limits. The refund threshold and escalation trigger are the two rules most teams forget to encode explicitly, and they're the two that cause the most support complaints when missing.
Step 2: Define Tools for Real Data Access
Claude's tool use lets the model call functions you define instead of hallucinating order statuses or policy details. A minimal support agent usually needs three tools:
[
{
"name": "lookup_order",
"description": "Fetch order status and details by order ID",
"input_schema": {
"type": "object",
"properties": {
"order_id": { "type": "string" }
},
"required": ["order_id"]
}
},
{
"name": "create_support_ticket",
"description": "Escalate the conversation to a human agent",
"input_schema": {
"type": "object",
"properties": {
"summary": { "type": "string" },
"priority": { "type": "string", "enum": ["low", "medium", "high"] }
},
"required": ["summary", "priority"]
}
},
{
"name": "search_help_articles",
"description": "Search the knowledge base for relevant articles",
"input_schema": {
"type": "object",
"properties": {
"query": { "type": "string" }
},
"required": ["query"]
}
}
]
When Claude decides it needs data, it returns a tool_use block instead of a text answer. Your backend executes the function, sends the result back, and Claude continues the conversation with that result in context. The /docs/tools page covers the full request/response shape if you're implementing this against SubToAPI.
Step 3: Call the API
Once your system prompt and tools are defined, the actual request is a single call. If you're routing through SubToAPI, the call looks like this:
curl https://api.subtoapi.app/v1/messages \
-H "Authorization: Bearer $SUBTOAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4",
"system": "You are a support agent for Acme Shipping...",
"messages": [
{"role": "user", "content": "Where is my order #38291?"}
],
"tools": [...]
}'
SubToAPI turns your existing Claude access into a standard HTTPS API with application-specific keys (sub_live_...), so each product or environment gets its own key without sharing credentials. That matters for a support agent because you'll likely want separate keys for staging, production, and any internal testing bot — and separate usage metadata per key to see what's actually costing you tokens. See /docs/quickstart to get a key running in a few minutes, and /docs/messages for the full request reference.
Step 4: Handle Multi-Turn Conversations
Support conversations rarely end in one exchange. Keep the full message history and append each turn, including tool calls and tool results, so Claude has full context:
const messages = [
{ role: "user", content: "My package hasn't arrived" },
{ role: "assistant", content: [{ type: "tool_use", id: "t1", name: "lookup_order", input: { order_id: "38291" } }] },
{ role: "user", content: [{ type: "tool_result", tool_use_id: "t1", content: "Status: in transit, ETA Thursday" }] }
];
For agents that stream responses to a live chat widget, use streaming so the customer sees tokens as they arrive instead of waiting on a full response. /docs/streaming covers the event format if you need server-sent events wired into your frontend.
Step 5: Build in Escalation and Logging
Two things separate a production support agent from a demo:
- Escalation paths — when the agent calls
create_support_ticket, actually route that to your helpdesk (Zendesk, Intercom, whatever you use) rather than just logging it. - Usage visibility — track which conversations use the most tokens, which tool calls fail, and where the agent gets stuck in loops. This is as much a cost problem as a reliability one.
If you're running this across a team — multiple engineers testing prompts, a staging environment, and production traffic — a shared dashboard with per-key usage avoids surprises on the bill. SubToAPI's plans start at €9/month for solo use and scale to team seats at €19/seat if you need shared billing and role access; see /pricing for details.
questions
Do I need a framework like LangChain to build a Claude support agent? No. A direct integration with the Messages API and tool use covers most support agent use cases with far less overhead and fewer moving parts to debug.
How do I stop the agent from making false promises about refunds or policies? Encode hard limits in the system prompt (dollar thresholds, approval rules) and back them with tools — have the agent check actual policy or order data instead of reasoning from training knowledge alone.
What's the best way to hand off to a human agent? Give Claude an explicit create_support_ticket tool with a priority field, and trigger it on clear signals: repeated frustration, requests for a manager, or questions outside the defined scope.