← Back to DevBytes

Building a Customer Support Bot with CrewAI: Complete Guide

What is a Customer Support Bot Built with CrewAI?

A customer support bot built with CrewAI is an AI-powered multi-agent system that automates handling customer inquiries, troubleshooting, and ticket resolution. Unlike traditional single-model chatbots, CrewAI orchestrates multiple specialized AI agents—each with defined roles, tools, and goals—to collaborate on complex support workflows. One agent might triage incoming tickets, another searches a knowledge base, a third drafts responses, and a fourth handles escalations. These agents work together as a "crew," sharing information and handing off tasks just like a human support team would.

CrewAI provides the framework to define these agents using natural language role descriptions, assign them tools (APIs, search functions, databases), and sequence their tasks into cohesive workflows. The result is a support bot that can understand nuanced customer issues, gather relevant information, compose empathetic responses, and escalate when necessary—all with minimal human intervention.

Why Building a Support Bot with CrewAI Matters

Customer support teams face mounting pressure: ticket volumes grow while response time expectations shrink. Traditional approaches fall short in several ways:

CrewAI solves these problems by enabling collaborative AI. Multiple agents with distinct expertise (billing, technical troubleshooting, account management) can tackle different facets of a problem simultaneously or sequentially. The system can integrate with your actual support tools—ticket systems, CRM APIs, documentation databases—giving agents real-world context. This architecture dramatically improves accuracy, reduces hallucination through cross-agent verification, and handles complex multi-step issues that stump single-model systems. For developers, CrewAI offers a Python-native, highly composable way to build support automation that mirrors how human teams actually operate.

Setting Up Your Development Environment

Before building your support bot, install the required packages. You'll need CrewAI itself, plus LangChain for tool definitions and an LLM provider. This guide uses OpenAI, but CrewAI supports any LangChain-compatible model.

# Create a new project directory
mkdir crewai-support-bot
cd crewai-support-bot

# Create a virtual environment
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install dependencies
pip install crewai langchain langchain-openai openai

# Set your API key
export OPENAI_API_KEY="your-openai-api-key-here"

Create a project file structure that keeps agents, tasks, tools, and the main crew definition organized:

crewai-support-bot/
├── agents.py          # Agent definitions
├── tasks.py           # Task definitions
├── tools.py           # Custom tool implementations
├── crew.py            # Crew assembly and execution
└── main.py            # Entry point

Designing Your Support Agent Roles

Effective customer support requires specialized roles. For a production-grade bot, define at least these four agent types. Each agent receives a clear role description, a backstory that shapes its behavior, and specific goals.

Triage Agent

The Triage Agent is the first point of contact. It classifies the customer's issue, determines priority, and routes the ticket to the appropriate specialist. It doesn't solve problems directly—it ensures the right agent handles the right issue.

# agents.py

from crewai import Agent

triage_agent = Agent(
    role="Customer Support Triage Specialist",
    goal="Accurately classify incoming customer support tickets by category and priority, "
         "then route them to the correct specialized agent. Never attempt to solve "
         "technical or billing issues yourself—your job is routing only.",
    backstory=(
        "You have 10 years of experience as a support team lead at a major SaaS company. "
        "You've seen thousands of tickets and can instantly recognize patterns. You are "
        "methodical, precise, and never let a ticket go to the wrong team. You always "
        "extract the core issue from verbose customer messages and assign clear categories."
    ),
    allow_delegation=True,
    verbose=True,
)

Knowledge Base Agent

This agent searches your documentation, FAQs, and internal knowledge articles to find relevant solutions. It's the research powerhouse behind accurate answers.

knowledge_base_agent = Agent(
    role="Knowledge Base Researcher",
    goal="Find the most relevant and accurate information from the knowledge base "
         "to resolve the customer's issue. Provide exact article references, steps, "
         "and troubleshooting guides.",
    backstory=(
        "You are the company's walking encyclopedia. You've memorized every support article, "
        "every product spec, every troubleshooting flowchart. You love finding the perfect "
        "knowledge base article that exactly matches the customer's situation. You always "
        "cite your sources so responses are verifiable."
    ),
    allow_delegation=False,
    verbose=True,
)

Response Composer Agent

The Response Composer takes research from the Knowledge Base Agent and crafts a polished, empathetic customer-facing response. It handles tone, formatting, and ensures the message is clear and actionable.

response_agent = Agent(
    role="Customer Response Composer",
    goal="Compose warm, professional, and helpful responses to customers based on "
         "the research provided by the Knowledge Base Agent. Ensure every response "
         "includes a clear solution, next steps, and an empathetic tone.",
    backstory=(
        "You're a former customer success manager with a gift for written communication. "
        "Your responses consistently earn the highest satisfaction ratings. You know how "
        "to de-escalate frustrated customers, explain technical concepts simply, and make "
        "every customer feel heard and valued. You never send a response that sounds robotic."
    ),
    allow_delegation=False,
    verbose=True,
)

Escalation Agent

When issues exceed automated resolution capabilities—billing disputes, outages, sensitive account issues—the Escalation Agent formats a handoff to human agents with complete context.

escalation_agent = Agent(
    role="Escalation Specialist",
    goal="Determine when tickets require human intervention and prepare comprehensive "
         "handoff summaries so human agents can resolve issues immediately without "
         "re-asking questions.",
    backstory=(
        "You are a senior support manager who knows exactly when automation isn't enough. "
        "You've managed escalation queues at Fortune 500 companies. You prepare handoffs "
        "that include the full ticket history, attempted solutions, customer sentiment, "
        "and recommended next steps. Human agents love receiving your handoffs because "
        "they never need to do detective work."
    ),
    allow_delegation=True,
    verbose=True,
)

Building Custom Tools for Your Agents

Agents become truly powerful when equipped with tools—functions they can call to interact with real systems. Below are practical tool implementations using LangChain's tool decorators. Each tool gives agents access to critical support infrastructure.

Ticket Lookup Tool

Simulates fetching ticket history from your support platform (Zendesk, Intercom, etc.). In production, replace this with actual API calls.

# tools.py

from langchain.tools import tool
from typing import Optional
import json

@tool("ticket_lookup")
def lookup_ticket(ticket_id: str) -> str:
    """
    Retrieve full ticket details including customer info, history, and status.
    Use this tool when you need to understand an existing ticket's context.
    
    Args:
        ticket_id: The unique ticket identifier (e.g., 'TKT-12345')
    """
    # Mock database — replace with actual API call in production
    mock_tickets = {
        "TKT-12345": json.dumps({
            "ticket_id": "TKT-12345",
            "customer_name": "Alice Chen",
            "email": "alice.chen@example.com",
            "product": "CloudSync Pro",
            "plan": "Enterprise",
            "status": "open",
            "priority": "high",
            "created_at": "2024-01-15T09:30:00Z",
            "history": [
                {"timestamp": "2024-01-15T09:30:00Z", "action": "ticket_created"},
                {"timestamp": "2024-01-15T09:45:00Z", "action": "auto_response_sent"},
                {"timestamp": "2024-01-15T10:00:00Z", "action": "customer_replied",
                 "note": "Customer says issue persists after restart"}
            ],
            "subject": "Sync failures after latest update",
            "description": "CloudSync Pro stops syncing files after upgrading to v3.2.1. "
                           "Restarted application and machine, issue remains."
        }),
        "TKT-67890": json.dumps({
            "ticket_id": "TKT-67890",
            "customer_name": "Bob Martinez",
            "email": "bob.m@example.com",
            "product": "CloudSync Basic",
            "plan": "Free",
            "status": "open",
            "priority": "medium",
            "created_at": "2024-01-16T14:00:00Z",
            "history": [
                {"timestamp": "2024-01-16T14:00:00Z", "action": "ticket_created"}
            ],
            "subject": "Billing question about overcharge",
            "description": "I was charged $49.99 instead of the expected $9.99 on my last bill."
        })
    }
    
    if ticket_id in mock_tickets:
        return mock_tickets[ticket_id]
    return json.dumps({"error": "Ticket not found", "ticket_id": ticket_id})

Knowledge Base Search Tool

Provides semantic search over your documentation. This example uses a mock vector store; in production, integrate with Pinecone, Weaviate, or a simple embeddings-based search over your docs.

@tool("search_knowledge_base")
def search_knowledge_base(query: str) -> str:
    """
    Search the internal knowledge base for articles matching the query.
    Returns article titles, IDs, and snippets. Use this for technical
    troubleshooting, how-to guides, and policy documentation.
    
    Args:
        query: Natural language search query (e.g., 'sync failure after update')
    """
    # Mock knowledge base — replace with vector search in production
    mock_kb = {
        "sync failure after update": [
            {
                "article_id": "KB-00142",
                "title": "Troubleshooting Sync Failures After Software Updates",
                "snippet": "Clear the local sync cache, verify file permissions, "
                          "and check for conflicting processes.",
                "steps": [
                    "1. Navigate to Settings > Advanced > Clear Sync Cache",
                    "2. Restart CloudSync with administrator privileges",
                    "3. Verify that no antivirus software is blocking sync ports",
                    "4. If issue persists, downgrade to previous version via Settings > Rollback"
                ],
                "relevance_score": 0.95
            },
            {
                "article_id": "KB-00087",
                "title": "Common Sync Error Codes and Resolutions",
                "snippet": "Error code SYNC-403 indicates a permissions conflict.",
                "relevance_score": 0.72
            }
        ],
        "billing overcharge": [
            {
                "article_id": "KB-00210",
                "title": "Understanding Your CloudSync Invoice",
                "snippet": "Detailed breakdown of charges including prorated upgrades.",
                "steps": [
                    "1. Log into billing portal at billing.cloudsync.example.com",
                    "2. Compare line items against your plan's pricing page",
                    "3. Check for mid-cycle plan changes that cause proration"
                ],
                "relevance_score": 0.91
            }
        ],
        "refund policy": [
            {
                "article_id": "KB-00015",
                "title": "Refund Policy and Request Process",
                "snippet": "CloudSync offers refunds within 30 days of purchase.",
                "steps": [
                    "1. Submit refund request through billing portal",
                    "2. Include order number and reason",
                    "3. Refunds processed within 5-7 business days"
                ],
                "relevance_score": 0.88
            }
        ]
    }
    
    # Simple keyword matching — replace with embeddings-based search
    best_match = None
    for key, articles in mock_kb.items():
        if key.lower() in query.lower() or any(
            word in query.lower() for word in key.lower().split()
        ):
            best_match = articles
            break
    
    if best_match:
        return json.dumps(best_match, indent=2)
    return json.dumps([{"article_id": "KB-GENERAL", 
                        "title": "General Support", 
                        "snippet": "No specific article found. Escalate or ask for more details."}])

Response Template Tool

Provides standard response templates that the Response Composer Agent can adapt. Ensures consistency and compliance.

@tool("get_response_template")
def get_response_template(template_type: str) -> str:
    """
    Retrieve a pre-approved response template for common support scenarios.
    Templates are customizable but maintain brand voice and legal compliance.
    
    Args:
        template_type: One of 'solution', 'follow_up', 'escalation', 'greeting', 'closing'
    """
    templates = {
        "greeting": (
            "Hi {customer_name},\n\n"
            "Thank you for reaching out about {issue_summary}. "
            "I've looked into this for you and here's what I found:\n\n"
        ),
        "solution": (
            "Based on our documentation, here's how to resolve this:\n\n"
            "{solution_steps}\n\n"
            "Why this works: {explanation}\n\n"
        ),
        "follow_up": (
            "I wanted to check in and make sure the {solution_provided} resolved "
            "the issue on your end. If you're still experiencing problems, please "
            "let me know and I'll dig deeper.\n\n"
        ),
        "escalation": (
            "I've documented everything and escalated this to our {specialist_team} "
            "team. They have full context of your issue and will reach out within "
            "{timeframe}. Your reference number is {ticket_id}.\n\n"
        ),
        "closing": (
            "If you have any other questions in the meantime, don't hesitate to "
            "reply to this message. We're here to help!\n\n"
            "Best regards,\n"
            "{agent_name}\n"
            "CloudSync Support Team"
        )
    }
    
    if template_type in templates:
        return templates[template_type]
    return json.dumps({"available_types": list(templates.keys())})

Defining Tasks for the Support Workflow

Tasks in CrewAI are units of work assigned to agents. They have clear descriptions, expected outputs, and can depend on other tasks' completion. Below are the core tasks for a complete support pipeline.

# tasks.py

from crewai import Task
from agents import (
    triage_agent,
    knowledge_base_agent,
    response_agent,
    escalation_agent
)
from tools import lookup_ticket, search_knowledge_base, get_response_template

# Task 1: Triage the incoming ticket
triage_task = Task(
    description=(
        "A new support ticket has arrived. Analyze the ticket content to determine:\n"
        "1. The primary category (Technical, Billing, Account Management, General Inquiry)\n"
        "2. Priority level (Critical, High, Medium, Low)\n"
        "3. Which specialized agent should handle it (Knowledge Base Agent for technical "
           "issues, direct escalation for billing disputes)\n"
        "4. A one-sentence summary of the core issue\n\n"
        "Ticket ID to analyze: {ticket_id}\n\n"
        "Use the ticket_lookup tool to fetch full ticket details. Do NOT attempt to "
        "solve the issue—classification and routing only."
    ),
    expected_output=(
        "A structured JSON object with keys: category, priority, assigned_agent, "
        "issue_summary. Example:\n"
        "{\n"
        '  "category": "Technical",\n'
        '  "priority": "High",\n'
        '  "assigned_agent": "Knowledge Base Agent",\n'
        '  "issue_summary": "Sync failures after v3.2.1 update"\n'
        "}"
    ),
    agent=triage_agent,
    tools=[lookup_ticket],
)

# Task 2: Research the issue in the knowledge base
research_task = Task(
    description=(
        "Based on the triage results, search the knowledge base for articles that "
        "address this customer's issue.\n\n"
        "Issue summary from triage: {triage_result.issue_summary}\n"
        "Category: {triage_result.category}\n\n"
        "Use the search_knowledge_base tool with a well-formed query derived from the "
        "issue summary. Find the most relevant article(s) and extract:\n"
        "1. The exact solution steps\n"
        "2. Any prerequisites or warnings\n"
        "3. The article ID for reference\n\n"
        "If no relevant article is found, report that clearly."
    ),
    expected_output=(
        "A JSON object with: article_id, title, solution_steps (as a list), "
        "explanation (why the solution works), and confidence_level (High/Medium/Low)."
    ),
    agent=knowledge_base_agent,
    tools=[search_knowledge_base],
    context=[triage_task],  # This task depends on triage_task completing first
)

# Task 3: Compose the customer response
compose_task = Task(
    description=(
        "Using the research findings, compose a complete, empathetic response to "
        "the customer. The response must include:\n\n"
        "1. A personalized greeting using the customer's name\n"
        "2. Acknowledgment of their frustration if priority is High/Critical\n"
        "3. Clear, numbered solution steps from the research\n"
        "4. A plain-English explanation of why the solution works\n"
        "5. A professional closing\n\n"
        "Customer name: {customer_name}\n"
        "Issue: {triage_result.issue_summary}\n"
        "Research: {research_result}\n\n"
        "Use the get_response_template tool for structure, but personalize heavily. "
        "Never copy-paste templates verbatim."
    ),
    expected_output=(
        "A complete, ready-to-send customer email with greeting, body, solution steps, "
        "explanation, and closing. The tone should be warm and helpful."
    ),
    agent=response_agent,
    tools=[get_response_template],
    context=[research_task],
)

# Task 4: Escalation check and handoff (conditional)
escalation_task = Task(
    description=(
        "Review the composed response and determine if this ticket requires human "
        "escalation. Escalate if ANY of these conditions are true:\n"
        "- The issue is a billing dispute or refund request\n"
        "- The customer explicitly demands to speak with a human\n"
        "- The research confidence level is 'Low'\n"
        "- The priority is 'Critical'\n\n"
        "If escalation is needed, prepare a handoff summary that includes:\n"
        "1. Full ticket context (customer, issue, what was tried)\n"
        "2. The composed draft response (so humans can review before sending)\n"
        "3. Recommended specialist team\n"
        "4. Urgency justification\n\n"
        "If no escalation needed, approve the response for sending and output 'APPROVED'."
    ),
    expected_output=(
        "Either: An escalation handoff JSON with fields: escalate (true), handoff_summary, "
        "specialist_team, urgency, draft_response.\n"
        "Or: A JSON with: escalate (false), status (APPROVED), approved_response (the final text)."
    ),
    agent=escalation_agent,
    context=[compose_task],
)

Assembling and Running the Crew

With agents and tasks defined, assemble them into a Crew that orchestrates the workflow. The crew manages execution order, context passing between tasks, and agent interactions.

# crew.py

from crewai import Crew, Process
from agents import (
    triage_agent,
    knowledge_base_agent,
    response_agent,
    escalation_agent
)
from tasks import triage_task, research_task, compose_task, escalation_task

def create_support_crew():
    """
    Assembles the customer support crew with all agents and tasks.
    Returns a Crew instance ready for kickoff.
    """
    support_crew = Crew(
        agents=[
            triage_agent,
            knowledge_base_agent,
            response_agent,
            escalation_agent
        ],
        tasks=[
            triage_task,
            research_task,
            compose_task,
            escalation_task
        ],
        process=Process.sequential,  # Tasks execute in defined order
        verbose=True,                # Shows agent reasoning in console
    )
    return support_crew

def run_support_workflow(ticket_id: str):
    """
    Executes the full support workflow for a given ticket ID.
    Returns the final output (either an approved response or escalation handoff).
    """
    crew = create_support_crew()
    
    # The inputs dictionary feeds dynamic values into task descriptions
    # Variables like {ticket_id}, {customer_name} get replaced at runtime
    result = crew.kickoff(inputs={
        "ticket_id": ticket_id,
        # customer_name and triage_result are populated by agents during execution
    })
    
    return result

Entry Point Script

Create a simple entry point that accepts a ticket ID and runs the workflow.

# main.py

import sys
from crew import run_support_workflow

def main():
    if len(sys.argv) < 2:
        print("Usage: python main.py ")
        print("Example: python main.py TKT-12345")
        sys.exit(1)
    
    ticket_id = sys.argv[1]
    print(f"\n{'='*60}")
    print(f"Starting support workflow for ticket: {ticket_id}")
    print(f"{'='*60}\n")
    
    result = run_support_workflow(ticket_id)
    
    print(f"\n{'='*60}")
    print("WORKFLOW COMPLETE")
    print(f"{'='*60}")
    print(f"\nFinal Output:\n{result}\n")

if __name__ == "__main__":
    main()

Run the bot with:

python main.py TKT-12345

For the billing ticket example, run:

python main.py TKT-67890

Understanding the Execution Flow

When you run the crew, here's what happens step by step:

Best Practices for Production Support Bots

1. Implement Robust Error Handling

Agents calling tools can encounter API failures, timeouts, or unexpected responses. Wrap tool calls with retry logic and fallback values. Never let a tool exception crash the entire crew—gracefully degrade with a clear error note that the Escalation Agent can act on.

# Example of resilient tool design
@tool("robust_ticket_lookup")
def robust_ticket_lookup(ticket_id: str) -> str:
    try:
        response = api_client.get_ticket(ticket_id, timeout=5)
        return json.dumps(response)
    except TimeoutError:
        return json.dumps({
            "error": "API timeout",
            "partial_data": True,
            "message": "Ticket system is slow. Proceed with available context."
        })
    except Exception as e:
        return json.dumps({
            "error": str(e),
            "requires_escalation": True,
            "message": "Critical tool failure—escalate to human agent."
        })

2. Use Context Windows Wisely

LLMs have limited context windows. Keep task outputs concise and structured (JSON works well). Avoid passing entire conversation histories between tasks—summarize and extract key facts. If a customer has a 50-message thread, have the Triage Agent distill it to a 200-word summary before passing it downstream.

3. Implement Guardrails and Compliance Checks

Customer support bots handle sensitive data and must stay on-brand. Add a final validation task or agent that checks responses for:

# Example guardrail agent
compliance_agent = Agent(
    role="Compliance and Quality Assurance Specialist",
    goal="Review all customer-facing responses for PII exposure, policy accuracy, "
         "and brand voice consistency before delivery.",
    backstory="You are a meticulous QA lead who has caught hundreds of potential "
              "compliance violations before they reached customers.",
    allow_delegation=False,
    verbose=True,
)

compliance_task = Task(
    description=(
        "Review the approved response below. Check for:\n"
        "1. Any exposed PII (full names are OK if customer provided them, but never "
           "expose passwords, payment methods, or internal account IDs)\n"
        "2. Policy accuracy (do stated refund terms match actual policy?)\n"
        "3. Brand voice (is it empathetic, professional, and consistent?)\n\n"
        "Response to review: {approved_response}\n\n"
        "Output: PASS with minor fixes, PASS as-is, or FAIL with specific corrections."
    ),
    expected_output="A JSON with status (PASS/FAIL) and corrections if needed.",
    agent=compliance_agent,
)

4. Log Everything for Continuous Improvement

Every agent decision, tool call, and final output should be logged. Use these logs to:

import logging
import json
from datetime import datetime

def log_agent_action(agent_name: str, action: str, input_data: dict, output_data: dict):
    log_entry = {
        "timestamp": datetime.utcnow().isoformat(),
        "agent": agent_name,
        "action": action,
        "input": input_data,
        "output": output_data,
    }
    with open("support_bot_logs.jsonl", "a") as f:
        f.write(json.dumps(log_entry) + "\n")

5. Design for Human-in-the-Loop

Not every ticket should be fully automated. Design your escalation paths thoughtfully. The Escalation Agent should produce handoffs that require zero back-and-forth—human agents should be able to read the summary and act immediately. Consider adding a confidence threshold: if any agent's confidence drops below 70%, trigger a human review.

6. Test with Diverse Scenarios

Build a test suite with varied ticket types: technical bugs, billing disputes, feature requests, angry customers, vague descriptions, and multi-issue tickets. Verify that:

7. Keep Agents Single-Purpose

Resist the urge to create a "super agent" that does everything. CrewAI's strength comes from specialization. An agent that triages, researches, and responds will perform worse on each task than three focused agents. If you find an agent's role description exceeding two sentences, split it into multiple agents.

8. Manage Costs with Model Selection

Not every agent needs GPT-4. Consider using more cost-effective models for straightforward tasks:

# Use GPT-3.5 for simple classification
triage_agent = Agent(
    role="Customer Support Triage Specialist",
    goal="...",
    backstory="...",
    llm="gpt-3.5-turbo",  # Fast and cheap for classification
)

# Reserve GPT-4 for complex composition
response_agent = Agent(
    role="Customer Response Composer",
    goal="...",
    backstory="...",
    llm="gpt-4-turbo",  # Better for nuanced, empathetic writing
)

Complete Working Example

Below is a consolidated version of all components in a single runnable script. This demonstrates the full pipeline end-to-end.

"""
Complete Customer Support Bot with CrewAI
Single-file demonstration — run with: python support_bot.py TKT-12345
"""

import sys
import json
import os
from typing import Optional

from crewai import Agent, Task, Crew, Process
from langchain.tools import tool

# ============================================================================
# TOOLS
# ============================================================================

@tool("ticket_lookup")
def lookup_ticket(ticket_id: str) -> str:
    """Fetch full ticket details by ID."""
    tickets = {
        "TKT-12345": json.dumps({
            "ticket_id": "TKT-12345",
            "customer_name": "Alice Chen",
            "email": "alice.chen@example.com",
            "product": "CloudSync Pro",
            "plan": "Enterprise",
            "status": "open",
            "priority": "high",
            "subject": "Sync failures after latest update",
            "description": "CloudSync Pro stops syncing files after upgrading "
                           "to v3.2.1. Restarted app and machine, issue remains."
        }),
        "TKT-67890": json.dumps({
            "ticket_id": "TKT-67890",
            "customer_name": "Bob Martinez",
            "email": "bob.m@example.com",
            "product": "CloudSync Basic",
            "plan": "Free",
            "status": "open",
            "priority": "medium",
            "subject": "Billing question about overcharge",
            "description": "I was charged $49.99 instead of the expected $9.99 "
                           "on my last bill."
        })
    }
    return tickets.get(ticket_id, json.dumps({"error": "Ticket not found"}))


@tool("search_knowledge_base")
def search_knowledge_base(query: str) -> str:
    """Search internal knowledge base for relevant articles."""
    kb = {
        "sync failure": [{
            "article_id": "KB-00142",
            "title": "Troubleshooting Sync Failures After Software Updates",
            "steps": [
                "Clear the local sync cache via Settings > Advanced > Clear Sync Cache",
                "Restart CloudSync with administrator privileges",
                "Verify antivirus software is not blocking sync ports (443, 8080)",
                "If issue persists, roll back to v3.2.0 via Settings > Rollback"
            ],
            "explanation": "Updates can corrupt the local sync manifest cache. "
                           "Clearing it forces a fresh reconciliation with the server.",
            "confidence": "High"
        }],
        "billing": [{
            "article_id": "KB-00210",
            "title": "Understanding Your CloudSync Invoice",
            "steps": [
                "Log into billing.cloudsync.example.com",
                "Compare line items against your plan's pricing page",
                "Check for mid-cycle plan changes causing proration"
            ],
            "explanation": "Mid-cycle upgrades generate prorated charges that "
                           "can appear as overcharges.",
            "confidence": "Medium"
        }]
    }
    for key, articles in kb.items():
        if key in query.lower():
            return json.dumps(articles, indent=2)
    return json.dumps([{"article_id": "KB-GENERAL", "title": "General Support"}])


@tool("get_response_template")
def get_response_template(template_type: str) -> str:
    """Get pre-approved response templates."""
    templates = {
        "greeting": "Hi {customer_name},\n\nThank you for reaching out about "
                    "{issue_summary}. I've looked into this and here's what I found:\n\n",
        "solution": "Based on our documentation, here's how to resolve this:\n\n"
                    "{solution_steps}\n\nWhy this works: {explanation}\n\n",
        "closing": "If you have any other questions, don't hesitate to reply. "
                   "We're here to help!\n\nBest regards,\nCloudSync Support Team"
    }
    return templates.get(template_type, json.dumps({"available": list(templates.keys())}))


# ============================================================================
# AGENTS
# ============================================================================

triage_agent = Agent(
    role="Customer Support Triage Specialist",
    goal="Classify incoming tickets by category and priority, route to correct agent.",
    backstory="Support team lead with 10 years experience. Expert at pattern recognition "
              "and precise classification. Never solves issues—only routes them.",
    allow_delegation=True,
    verbose=True,
)

knowledge_base_agent = Agent

— Ad —

Google AdSense will appear here after approval

← Back to all articles