Dev.to AI πŸ€– Ai πŸ‘ 0 πŸ“– 5 min read

Introduction to Large Language Models: What You Need to Know

We are going to build a support ticket triage agent that reads incoming customer messages, classifies the issue, looks up account details via a mock tool, and drafts a response. This saves time if you run a help desk and

We are going to build a support ticket triage agent that reads incoming customer messages, classifies the issue, looks up account details via a mock tool, and drafts a response. This saves time if you run a help desk and want to cut first-response latency before a human takes over. I use Oxlo.ai because its OpenAI-compatible API and flat per-request pricing keep the code simple and costs predictable even when ticket histories get long. See https://oxlo.ai/pricing for details.

What you'll need

  • Python 3.10 or newer
  • An Oxlo.ai API key from https://portal.oxlo.ai
  • The OpenAI SDK. Install it with pip install openai

Step 1: Verify the connection

Before adding logic, make sure you can reach Oxlo.ai and get a completion back. I start with Llama 3.3 70B because it is a reliable general-purpose model for this workflow.

from openai import OpenAI

client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")

response = client.chat.completions.create(
    model="llama-3.3-70b",
    messages=[
        {"role": "user", "content": "How do I reset my password?"},
    ],
)

print(response.choices[0].message.content)

Step 2: Define the agent's system prompt

A raw model answers generically. We need a system prompt that tells it to act as a triage agent and return structured data. Here is the prompt I use. You can edit the categories or tone to match your product.

SYSTEM_PROMPT = """You are a support ticket triage agent.
Your job is to analyze the customer's message and produce a structured assessment.
Output valid JSON with these keys:
- category: one of Billing, Technical, Account, General
- urgency: Low, Medium, or High
- draft_reply: a brief, empathetic response or escalation note
Be concise. Do not ask follow-up questions."""

Step 3: Enforce JSON output

Parsing free text is fragile. Oxlo.ai supports JSON mode, so we can force valid JSON by setting response_format. This removes the need to beg the model to output JSON inside the prompt.

import json

user_message = "I was charged twice for my subscription this month. Please fix this immediately."

response = client.chat.completions.create(
    model="llama-3.3-70b",
    messages=[
        {"role": "system", "content": SYSTEM_PROMPT},
        {"role": "user", "content": user_message},
    ],
    response_format={"type": "json_object"},
)

result = json.loads(response.choices[0].message.content)
print(json.dumps(result, indent=2))

Step 4: Give the model a tool

For real triage, we need data. We will define a mock function called get_account_status and let the model call it. I switch to Qwen 3 32B here because it handles agent workflows and tool use well.

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_account_status",
            "description": "Retrieve billing and plan details for a user.",
            "parameters": {
                "type": "object",
                "properties": {
                    "user_id": {
                        "type": "string",
                        "description": "The customer user ID.",
                    },
                },
                "required": ["user_id"],
            },
        },
    }
]

def get_account_status(user_id: str):
    # Mock lookup. In production, query your database.
    return {"user_id": user_id, "plan": "Pro", "payment_issue": True}

user_message = "User u-8821 says they were double charged. Can you check?"

messages = [
    {"role": "system", "content": SYSTEM_PROMPT},
    {"role": "user", "content": user_message},
]

response = client.chat.completions.create(
    model="qwen-3-32b",
    messages=messages,
    tools=tools,
    tool_choice="auto",
)

message = response.choices[0].message

if message.tool_calls:
    tool_call = message.tool_calls[0]
    function_name = tool_call.function.name
    arguments = json.loads(tool_call.function.arguments)

    if function_name == "get_account_status":
        tool_result = get_account_status(**arguments)

        messages.append(message)
        messages.append({
            "role": "tool",
            "tool_call_id": tool_call.id,
            "content": json.dumps(tool_result),
        })

        final_response = client.chat.completions.create(
            model="qwen-3-32b",
            messages=messages,
            tools=tools,
        )

        print(final_response.choices[0].message.content)
else:
    print(message.content)

Step 5: Wrap it in a reusable class

Now we tie everything together into a clean Python class that accepts a ticket, runs the tool loop, and returns structured JSON. I use Kimi K2.6 for this final version because its reasoning and agentic coding capabilities make the tool loop reliable.

class SupportTriageAgent:
    def __init__(self, api_key: str):
        self.client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key=api_key)
        self.model = "kimi-k2.6"
        self.system_prompt = SYSTEM_PROMPT
        self.tools = [
            {
                "type": "function",
                "function": {
                    "name": "get_account_status",
                    "description": "Retrieve billing and plan details for a user.",
                    "parameters": {
                        "type": "object",
                        "properties": {
                            "user_id": {
                                "type": "string",
                                "description": "The customer user ID.",
                            },
                        },
                        "required": ["user_id"],
                    },
                },
            }
        ]

    def get_account_status(self, user_id: str):
        return {"user_id": user_id, "plan": "Pro", "payment_issue": True}

    def triage(self, user_message: str):
        messages = [
            {"role": "system", "content": self.system_prompt},
            {"role": "user", "content": user_message},
        ]

        response = self.client.chat.completions.create(
            model=self.model,
            messages=messages,
            tools=self.tools,
            tool_choice="auto",
            response_format={"type": "json_object"},
        )

        message = response.choices[0].message

        if message.tool_calls:
            tool_call = message.tool_calls[0]
            function_name = tool_call.function.name
            arguments = json.loads(tool_call.function.arguments)

            if function_name == "get_account_status":
                tool_result = self.get_account_status(**arguments)

                messages.append(message)
                messages.append({
                    "role": "tool",
                    "tool_call_id": tool_call.id,
                    "content": json.dumps(tool_result),
                })

                response = self.client.chat.completions.create(
                    model=self.model,
                    messages=messages,
                    tools=self.tools,
                    response_format={"type": "json_object"},
                )
                message = response.choices[0].message

        return json.loads(message.content)

Run it

Here is how I call the finished agent against two sample tickets.

if __name__ == "__main__":
    agent = SupportTriageAgent(api_key="YOUR_OXLO_API_KEY")

    tickets = [
        "User u-9912 cannot log in after the latest update.",
        "User u-8821 was charged twice. Please check their account.",
    ]

    for ticket in tickets:
        result = agent.triage(ticket)
        print(f"Ticket: {ticket}")
        print(json.dumps(result, indent=2))
        print()

Example output:

Ticket: User u-9912 cannot log in after the latest update.
{
  "category": "Technical",
  "urgency": "High",
  "draft_reply": "We are sorry you are locked out. Our engineering team is investigating the update. I will escalate this to our technical team immediately and follow up within 30 minutes."
}

Ticket: User u-8821 was charged twice. Please check their account.
{
  "category": "Billing",
  "urgency": "High",
  "draft_reply": "I have reviewed your account and confirmed a duplicate charge on your Pro plan. I have issued a refund which will appear in 3 to 5 business days."
}

Next steps

Deploy this agent as a FastAPI endpoint and wire it into your existing help desk via webhook. For tickets that require code-level debugging, swap the model to DeepSeek V3.2 or DeepSeek R1 671B to let the model reason through stack traces before replying.

πŸ“° Read the original article on Dev.to AI

Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.