DEV Community

shashank ms
shashank ms

Posted on

LLM for Customer Service Automation: Benefits and Use Cases

We are going to build a stateless customer support agent that classifies intent, looks up orders through a simulated tool, and drafts replies. This helps small support teams deflect repetitive tickets without managing a complex state machine. We will run it on Oxlo.ai using the standard OpenAI SDK, so the only change is the base URL.

What you'll need

Step 1: Bootstrap the Oxlo.ai client

Create a file named agent.py and initialize the client. Oxlo.ai exposes an OpenAI-compatible endpoint, so we import the official SDK and swap the base_url.

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": "Hi, I need help with an order."}],
)
print(response.choices[0].message.content)

Step 2: Write the system prompt

A strict system prompt keeps the agent focused on shipping and order issues. It should refuse unrelated topics and instruct the model to call the tool instead of guessing.

from openai import OpenAI

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

SYSTEM_PROMPT = """You are a concise customer support agent for an online electronics store.
Your job is to answer questions about orders, shipping, and returns.
If a user asks about an order, you must call the lookup_order tool with the order_id.
Do not guess order statuses. Do not answer questions outside shipping, orders, or returns.
Keep responses under three sentences."""

response = client.chat.completions.create(
    model="llama-3.3-70b",
    messages=[
        {"role": "system", "content": SYSTEM_PROMPT},
        {"role": "user", "content": "Do you offer gift wrapping?"},
    ],
)
print(response.choices[0].message.content)

Step 3: Define the order lookup tool

We simulate a database with a dictionary and describe the lookup function to the model using the OpenAI tools schema. Oxlo.ai supports function calling on Llama 3.3 70B, so the model can request the tool natively.

import json
from openai import OpenAI

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

SYSTEM_PROMPT = """You are a concise customer support agent for an online electronics store.
Your job is to answer questions about orders, shipping, and returns.
If a user asks about an order, you must call the lookup_order tool with the order_id.
Do not guess order statuses. Do not answer questions outside shipping, orders, or returns.
Keep responses under three sentences."""

ORDERS_DB = {
    "ORD-1001": {"status": "shipped", "eta": "2026-01-15", "item": "USB-C Hub"},
    "ORD-1002": {"status": "processing", "eta": "2026-01-20", "item": "Mechanical Keyboard"},
}

TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "lookup_order",
            "description": "Get the current status and ETA for an order.",
            "parameters": {
                "type": "object",
                "properties": {
                    "order_id": {
                        "type": "string",
                        "description": "The order ID, for example ORD-1001."
                    }
                },
                "required": ["order_id"]
            }
        }
    }
]

def lookup_order(order_id: str):
    return ORDERS_DB.get(order_id, {"status": "not_found", "eta": None, "item": None})

# Test that the model requests the tool
response = client.chat.completions.create(
    model="llama-3.3-70b",
    messages=[
        {"role": "system", "content": SYSTEM_PROMPT},
        {"role": "user", "content": "Where is order ORD-1001?"},
    ],
    tools=TOOLS,
    tool_choice="auto",
)

tc = response.choices[0].message.tool_calls[0]
print(tc.function.name, tc.function.arguments)

Step 4: Implement the tool calling loop

When the model returns a tool call, we execute the Python function, append the result to the message history, and call the model again so it can write the final answer.

import json
from openai import OpenAI

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

SYSTEM_PROMPT = """You are a concise customer support agent for an online electronics store.
Your job is to answer questions about orders, shipping, and returns.
If a user asks about an order, you must call the lookup_order tool with the order_id.
Do not guess order statuses. Do not answer questions outside shipping, orders, or returns.
Keep responses under three sentences."""

ORDERS_DB = {
    "ORD-1001": {"status": "shipped", "eta": "2026-01-15", "item": "USB-C Hub"},
    "ORD-1002": {"status": "processing", "eta": "2026-01-20", "item": "Mechanical Keyboard"},
}

TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "lookup_order",
            "description": "Get the current status and ETA for an order.",
            "parameters": {
                "type": "object",
                "properties": {
                    "order_id": {
                        "type": "string",
                        "description": "The order ID, for example ORD-1001."
                    }
                },
                "required": ["order_id"]
            }
        }
    }
]

def lookup_order(order_id: str):
    return ORDERS_DB.get(order_id, {"status": "not_found", "eta": None, "item": None})

def run_agent(user_message: str) -> str:
    messages = [
        {"role": "system", "content": SYSTEM_PROMPT},
        {"role": "user", "content": user_message},
    ]

    response = client.chat.completions.create(
        model="llama-3.3-70b",
        messages=messages,
        tools=TOOLS,
        tool_choice="auto",
    )

    msg = response.choices[0].message

    if msg.tool_calls:
        messages.append({
            "role": "assistant",
            "content": msg.content or "",
            "tool_calls": [tc.model_dump() for tc in msg.tool_calls]
        })

        for tc in msg.tool_calls:
            if tc.function.name == "lookup_order":
                args = json.loads(tc.function.arguments)
                result = lookup_order(args["order_id"])
                messages.append({
                    "role": "tool",
                    "tool_call_id": tc.id,
                    "content": json.dumps(result),
                })

        final = client.chat.completions.create(
            model="llama-3.3-70b",
            messages=messages,
            tools=TOOLS,
        )
        return final.choices[0].message.content

    return msg.content

print(run_agent("Where is order ORD-1001?"))

Step 5: Add intent guardrails

Before we invoke the main agent, we run a cheap classification check to reject off-topic or abusive input. This keeps the support scope clean and prevents wasted tool loops.

import json
from openai import OpenAI

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

SYSTEM_PROMPT = """You are a concise customer support agent for an online electronics store.
Your job is to answer questions about orders, shipping, and returns.
If a user asks about an order, you must call the lookup_order tool with the order_id.
Do not guess order statuses. Do not answer questions outside shipping, orders, or returns.
Keep responses under three sentences."""

ORDERS_DB = {
    "ORD-1001": {"status": "shipped", "eta": "2026-01-15", "item": "USB-C Hub"},
    "ORD-1002": {"status": "processing", "eta": "2026-01-20", "item": "Mechanical Keyboard"},
}

TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "lookup_order",
            "description": "Get the current status and ETA for an order.",
            "parameters": {
                "type": "object",
                "properties": {
                    "order_id": {
                        "type": "string",
                        "description": "The order ID, for example ORD-1001."
                    }
                },
                "required": ["order_id"]
            }
        }
    }
]

def lookup_order(order_id: str):
    return ORDERS_DB.get(order_id, {"status": "not_found", "eta": None, "item": None})

def is_on_topic(query: str) -> bool:
    prompt = (
        "You are a classifier. Respond with ONLY the word YES or NO. "
        "Is the following a customer service question about an order, shipping, or return?\n\n"
        f"Query: {query}"
    )
    r = client.chat.completions.create(
        model="llama-3.3-70b",
        messages=[{"role": "user", "content": prompt}],
        temperature=0.0,
    )
    return r.choices[0].message.content.strip().upper() == "YES"

def run_agent(user_message: str) -> str:
    if not is_on_topic(user_message):
        return "I can only help with orders, shipping, and returns. Please contact sales for other questions."

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

    response = client.chat.completions.create(
        model="llama-3.3-70b",
        messages=messages,
        tools=TOOLS,
        tool_choice="auto",
    )

    msg = response.choices[0].message

    if msg.tool_calls:
        messages.append({
            "role": "assistant",
            "content": msg.content or "",
            "tool_calls": [tc.model_dump() for tc in msg.tool_calls]
        })

        for tc in msg.tool_calls:
            if tc.function.name == "lookup_order":
                args = json.loads(tc.function.arguments)
                result = lookup_order(args["order_id"])
                messages.append({
                    "role": "tool",
                    "tool_call_id": tc.id,
                    "content": json.dumps(result),
                })

        final = client.chat.completions.create(
            model="llama-3.3-70b",
            messages=messages,
            tools=TOOLS,
        )
        return final.choices[0].message.content

    return msg.content

if __name__ == "__main__":
    print(run_agent("Where is order ORD-1001?"))
    print(run_agent("Write me a poem about the moon."))

Run it

Execute the script from your terminal. You should see the agent answer the order query and deflect the off-topic request.

$ python agent.py
Your order ORD-1001 (USB-C Hub) has shipped and is expected to arrive on 2026-01-15.
I can only help with orders, shipping, and returns. Please contact sales for other questions.

Wrap-up and next steps

You now have a working support agent that classifies intent, calls tools, and stays on topic. For a production deployment, persist the message history to Redis or a database so the agent remembers context across sessions. You could also add a second tool to initiate returns, using the same loop on Oxlo.ai.

Top comments (0)