We are going to build a customer support agent that handles order lookups, returns, and policy questions through natural conversation. This kind of agent cuts down on repetitive tickets for e-commerce and SaaS teams. I will walk through the exact code I shipped, using Oxlo.ai's OpenAI-compatible API and Llama 3.3 70B for fast, capable reasoning.
What you'll need
- Python 3.10 or newer
- An Oxlo.ai API key from https://portal.oxlo.ai
- The OpenAI SDK:
pip install openai
Step 1: Initialize the Oxlo.ai client
The first thing I do in any project is verify the connection with a simple completion. Oxlo.ai exposes a fully OpenAI-compatible endpoint, so the setup is a drop-in replacement. I use Llama 3.3 70B here because it is responsive for conversational tasks.
from openai import OpenAI
import os
client = OpenAI(
base_url="https://api.oxlo.ai/v1",
api_key=os.environ.get("OXLO_API_KEY")
)
response = client.chat.completions.create(
model="llama-3.3-70b",
messages=[
{"role": "user", "content": "Say hello and confirm you are online."}
]
)
print(response.choices[0].message.content)
Step 2: Write the system prompt
I treat the system prompt as the agent's job description. It needs to set boundaries, define tone, and list the tools the model can ask for. I keep it explicit but short.
SYSTEM_PROMPT = """You are a customer support agent for an electronics store named TechFlow.
Your job is to help users with order status, return policies, and troubleshooting.
Be concise, friendly, and never make up order details.
If a user asks about an order, request their order ID and call the lookup_order function.
Current return policy: returns accepted within 30 days with receipt."""
Step 3: Manage conversation history
A support agent needs memory. I use a simple list that prepends the system prompt and appends each turn. This keeps the implementation transparent and easy to debug.
class SupportAgent:
def __init__(self, client):
self.client = client
self.messages = [{"role": "system", "content": SYSTEM_PROMPT}]
def chat(self, user_message):
self.messages.append({"role": "user", "content": user_message})
response = self.client.chat.completions.create(
model="llama-3.3-70b",
messages=self.messages,
temperature=0.3
)
reply = response.choices[0].message.content
self.messages.append({"role": "assistant", "content": reply})
return reply
Step 4: Add a tool for order lookups
Real agents need to do real work. I define a mock order database and a function schema so the model can request a lookup. Oxlo.ai supports function calling on Llama 3.3 70B, which makes this straightforward.
import json
ORDERS = {
"ORD-1001": {"status": "shipped", "item": "Wireless Headphones", "delivery": "2025-01-15"},
"ORD-1002": {"status": "processing", "item": "USB-C Cable", "delivery": "pending"}
}
def lookup_order(order_id: str):
return ORDERS.get(order_id.upper(), {"error": "Order not found"})
tools = [
{
"type": "function",
"function": {
"name": "lookup_order",
"description": "Retrieve order status by order ID",
"parameters": {
"type": "object",
"properties": {
"order_id": {"type": "string", "description": "The order ID, e.g. ORD-1001"}
},
"required": ["order_id"]
}
}
}
]
Step 5: Build the agent loop
Now I wire the pieces together. The agent sends the conversation to Oxlo.ai with the tool definitions. If the model requests a tool call, I execute it locally, append the result, and send everything back for the final answer.
class SupportAgent:
def __init__(self, client):
self.client = client
self.messages = [{"role": "system", "content": SYSTEM_PROMPT}]
def chat(self, user_message):
self.messages.append({"role": "user", "content": user_message})
# First call: let the model decide if it needs a tool
response = self.client.chat.completions.create(
model="llama-3.3-70b",
messages=self.messages,
tools=tools,
tool_choice="auto",
temperature=0.3
)
message = response.choices[0].message
# Handle tool calls
if message.tool_calls:
self.messages.append({
"role": "assistant",
"content": message.content or "",
"tool_calls": [tc.model_dump() for tc in message.tool_calls]
})
for tc in message.tool_calls:
if tc.function.name == "lookup_order":
args = json.loads(tc.function.arguments)
result = lookup_order(args["order_id"])
self.messages.append({
"role": "tool",
"tool_call_id": tc.id,
"content": json.dumps(result)
})
# Second call: get the final natural language response
final_response = self.client.chat.completions.create(
model="llama-3.3-70b",
messages=self.messages,
temperature=0.3
)
reply = final_response.choices[0].message.content
else:
reply = message.content
self.messages.append({"role": "assistant", "content": reply})
return reply
Run it
Here is how I test the finished agent. I ask about an order and then follow up with a policy question. Because Oxlo.ai charges per request, not per token, these multi-turn tool calls stay predictable in cost.
if __name__ == "__main__":
agent = SupportAgent(client)
# Test 1: Order lookup that triggers the tool
print("User: Where is my order ORD-1001?")
print("Agent:", agent.chat("Where is my order ORD-1001?"))
print()
# Test 2: Return policy question
print("User: Can I return something after 25 days?")
print("Agent:", agent.chat("Can I return something after 25 days?"))
Example output:
User: Where is my order ORD-1001?
Agent: Your order ORD-1001 for Wireless Headphones has been shipped and is scheduled for delivery on January 15, 2025.
User: Can I return something after 25 days?
Agent: Yes, you can return items within 30 days of purchase with a receipt, so 25 days is within the return window. Would you like help starting a return?
Wrap-up and next steps
This agent is already useful, but it is just a starting point. I would suggest two concrete upgrades next: wire the SupportAgent class into a FastAPI endpoint so it can serve a frontend chat widget, or swap the model to qwen-3-32b or kimi-k2.6 if you need stronger multilingual reasoning or vision support for ticket screenshots. You can explore Oxlo.ai's request-based pricing at https://oxlo.ai/pricing, which keeps long conversation threads affordable because cost does not scale with token count.
Top comments (0)