We are going to build a tier-1 customer support agent that handles order lookups, basic troubleshooting, and automatic escalation to human agents. It runs on Oxlo.ai's request-based API, so long customer threads do not inflate inference costs. If you need to ship a working support bot this afternoon, this tutorial is for you.
What you'll need
- Python 3.10 or newer
pip install openai- An Oxlo.ai API key from https://portal.oxlo.ai
Step 1: Initialize the Oxlo.ai client
Instantiate the OpenAI SDK client pointing at Oxlo.ai. I pull the API key from the environment so it never sits in source control.
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.oxlo.ai/v1",
api_key=os.environ.get("OXLO_API_KEY", "YOUR_OXLO_API_KEY")
)
Step 2: Define the system prompt
The system prompt is the only part you need to edit to change personality or policy. It forces JSON output and defines exactly when to call the order lookup tool or escalate to a human.
SYSTEM_PROMPT = """You are a support agent for an electronics store. You help customers with order status, troubleshooting, and refunds.
Rules:
- Stay concise. Ask for the order ID if it is missing.
- If the user is angry or asks for a human, set escalate_to_human to true.
- To look up an order, respond with action: {"tool": "lookup_order", "order_id": "..."}.
- Never invent tracking numbers or shipping dates.
- Respond in JSON with keys: reply_text, escalate_to_human, action."""
Step 3: Build the agent class with memory
We wrap the client in a class that persists conversation history. Each turn appends to the messages list so the model remembers prior context across the session.
import json
class SupportAgent:
def __init__(self, api_key: str, model: str = "llama-3.3-70b"):
self.client = OpenAI(
base_url="https://api.oxlo.ai/v1",
api_key=api_key
)
self.model = model
self.messages = [{"role": "system", "content": SYSTEM_PROMPT}]
def chat(self, user_input: str) -> dict:
self.messages.append({"role": "user", "content": user_input})
response = self.client.chat.completions.create(
model=self.model,
messages=self.messages,
response_format={"type": "json_object"},
temperature=0.2,
)
content = response.choices[0].message.content
self.messages.append({"role": "assistant", "content": content})
return json.loads(content)
Step 4: Add the order lookup tool
Next we add a simulated order database and a tool loop. If the model requests a lookup, we execute it and feed the result back into the conversation chain before returning the final answer to the user.
class SupportAgent:
def __init__(self, api_key: str, model: str = "llama-3.3-70b"):
self.client = OpenAI(
base_url="https://api.oxlo.ai/v1",
api_key=api_key
)
self.model = model
self.messages = [{"role": "system", "content": SYSTEM_PROMPT}]
def lookup_order(self, order_id: str) -> dict:
return {
"order_id": order_id,
"status": "shipped",
"carrier": "FedEx",
"eta": "2025-06-12",
}
def chat(self, user_input: str) -> dict:
self.messages.append({"role": "user", "content": user_input})
while True:
response = self.client.chat.completions.create(
model=self.model,
messages=self.messages,
response_format={"type": "json_object"},
temperature=0.2,
)
content = response.choices[0].message.content
parsed = json.loads(content)
action = parsed.get("action")
if isinstance(action, dict) and action.get("tool") == "lookup_order":
order_data = self.lookup_order(action["order_id"])
self.messages.append({"role": "assistant", "content": content})
self.messages.append({
"role": "user",
"content": f"Tool result: {json.dumps(order_data)}"
})
continue
self.messages.append({"role": "assistant", "content": content})
return parsed
Step 5: Handle escalation to humans
Finally, we add a thin run wrapper that inspects the escalate_to_human flag. In production, this is where you would open a Zendesk ticket or post to a Slack channel.
class SupportAgent:
def __init__(self, api_key: str, model: str = "llama-3.3-70b"):
self.client = OpenAI(
base_url="https://api.oxlo.ai/v1",
api_key=api_key
)
self.model = model
self.messages = [{"role": "system", "content": SYSTEM_PROMPT}]
def lookup_order(self, order_id: str) -> dict:
return {
"order_id": order_id,
"status": "shipped",
"carrier": "FedEx",
"eta": "2025-06-12",
}
def chat(self, user_input: str) -> dict:
self.messages.append({"role": "user", "content": user_input})
while True:
response = self.client.chat.completions.create(
model=self.model,
messages=self.messages,
response_format={"type": "json_object"},
temperature=0.2,
)
content = response.choices[0].message.content
parsed = json.loads(content)
action = parsed.get("action")
if isinstance(action, dict) and action.get("tool") == "lookup_order":
order_data = self.lookup_order(action["order_id"])
self.messages.append({"role": "assistant", "content": content})
self.messages.append({
"role": "user",
"content": f"Tool result: {json.dumps(order_data)}"
})
continue
self.messages.append({"role": "assistant", "content": content})
return parsed
def run(self, user_input: str) -> dict:
result = self.chat(user_input)
if result.get("escalate_to_human"):
print("ALERT: Escalating to human agent.")
# Post to Slack or create ticket here
return result
Step 6: Run it
We instantiate the agent and test two scenarios: a standard order lookup and an angry customer who should be escalated.
if __name__ == "__main__":
agent = SupportAgent(api_key=os.environ["OXLO_API_KEY"])
print("=== Scenario 1: Order lookup ===")
out = agent.run("Where is my order? It is ID-90210.")
print(json.dumps(out, indent=2))
print("\n=== Scenario 2: Angry customer ===")
out = agent.run("This is the third delay. I want a human now.")
print(json.dumps(out, indent=2))
Example output:
=== Scenario 1: Order lookup ===
{
"reply_text": "Your order ID-90210 has shipped via FedEx and is estimated to arrive on June 12, 2025.",
"escalate_to_human": false,
"action": null
}
=== Scenario 2: Angry customer ===
ALERT: Escalating to human agent.
{
"reply_text": "I completely understand your frustration. I am connecting you with a human agent right now.",
"escalate_to_human": true,
"action": null
}
Wrap-up and next steps
This agent is already cheaper to operate on Oxlo.ai than on token-based providers when your users send long emails or chat histories, because the cost is flat per request. See https://oxlo.ai/pricing for plan details.
Two concrete next steps: expose this behind a FastAPI endpoint and wire it to your helpdesk webhooks, or swap in Oxlo.ai's Qwen 3 32B model for multilingual support without changing any client code.
Top comments (0)