Most support teams handle tickets in languages their agents do not speak. I will walk you through a lightweight triage bot I shipped that detects a customer's language, classifies the issue, and drafts a reply in the same language. It runs on Oxlo.ai using Qwen 3 32B, a model built for multilingual reasoning and agent workflows.
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: Configure the Oxlo.ai client
I use the OpenAI SDK as a drop-in replacement pointing at Oxlo.ai. There are no cold starts on popular models, so the script feels snappy even when I rerun it repeatedly during testing.
from openai import OpenAI
client = OpenAI(
base_url="https://api.oxlo.ai/v1",
api_key="YOUR_OXLO_API_KEY"
)
Step 2: Define the system prompt
The triage step needs strict JSON output. I keep the system prompt in its own variable so I can iterate on wording without touching the request logic.
SYSTEM_PROMPT = """You are a multilingual support analyst.
Analyze the customer message and output raw JSON with exactly these keys:
- detected_language: the language name
- issue_category: one of Billing, Technical, Account, or General
- urgency: Low, Medium, or High
- english_summary: one sentence for the internal CRM
Rules:
1. Output raw JSON only. No markdown fences, no commentary.
2. If the language is ambiguous, default to English."""
Step 3: Classify the ticket
I send the customer message to Qwen 3 32B on Oxlo.ai, which handles multilingual reasoning well. The response is parsed from JSON into a Python dict.
import json
def classify_ticket(user_message: str) -> dict:
response = client.chat.completions.create(
model="qwen-3-32b",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_message},
],
)
content = response.choices[0].message.content.strip()
# Handle accidental markdown fences
if content.startswith("
```"):
content = content.split("\n", 1)[1].rsplit("```
", 1)[0].strip()
return json.loads(content)
Step 4: Draft a localized reply
With the analysis in hand, I make a second call to generate the actual response. I pass the original message and the analysis so the reply is contextual and written in the correct language.
REPLY_PROMPT = """You are a polite support agent.
Write a concise reply in the customer's language.
Acknowledge the issue, set expectations, and ask for any missing information.
Do not include signatures or ticket IDs."""
def draft_reply(user_message: str, analysis: dict) -> str:
context = (
f"Customer language: {analysis['detected_language']}\n"
f"Category: {analysis['issue_category']}\n"
f"Urgency: {analysis['urgency']}\n"
f"Customer wrote: {user_message}\n\n"
f"Draft a helpful reply."
)
response = client.chat.completions.create(
model="qwen-3-32b",
messages=[
{"role": "system", "content": REPLY_PROMPT},
{"role": "user", "content": context},
],
)
return response.choices[0].message.content.strip()
Step 5: Wire up the CLI
The main loop ties both steps together. I hardcoded three messages in Spanish, Japanese, and German to verify behavior across scripts.
if __name__ == "__main__":
tickets = [
"No puedo acceder a mi cuenta y necesito facturar urgentemente.",
"アプリがクラッシュします。支払いの問題ですか?",
"Mein Passwort reset funktioniert nicht, bitte helfen Sie schnell.",
]
for msg in tickets:
print("=" * 50)
print(f"Incoming: {msg}")
analysis = classify_ticket(msg)
reply = draft_reply(msg, analysis)
print(f"Language: {analysis['detected_language']}")
print(f"Category: {analysis['issue_category']}")
print(f"Urgency: {analysis['urgency']}")
print(f"Summary: {analysis['english_summary']}")
print(f"Reply:\n{reply}\n")
Run it
Save the file as support_agent.py, export your key, and run it.
export OXLO_API_KEY="YOUR_OXLO_API_KEY"
python support_agent.py
Example output:
==================================================
Incoming: No puedo acceder a mi cuenta y necesito facturar urgentemente.
Language: Spanish
Category: Account
Urgency: High
Summary: Customer cannot access account and needs to invoice urgently.
Reply:
Entiendo que no puede acceder a su cuenta y que esto es urgente para facturar.
Para ayudarle a recuperar el acceso de inmediato, por favor proporcione el correo electrónico asociado a su cuenta. Nuestro equipo de cuentas revisará su caso con prioridad alta y le enviará los pasos para restablecer el acceso en los próximos minutos.
¿Hay algún otro detalle que pueda compartir con nosotros mientras tanto?
==================================================
Incoming: アプリがクラッシュします。支払いの問題ですか?
Language: Japanese
Category: Technical
Urgency: Medium
Summary: Customer reports app crashes and asks if it is a payment issue.
Reply:
アプリがクラッシュしているとのこと、お手数をおかけして申し訳ございません。
現時点では、お支払いの問題とは別の技術的な不具合である可能性が高いです。解決のため、ご利用の端末のOSバージョンと、アプリのバージョンをお教えいただけますでしょうか。
また、クラッシュは特定の操作時に発生していますか、それとも起動時にも発生していますか?
==================================================
Incoming: Mein Passwort reset funktioniert nicht, bitte helfen Sie schnell.
Language: German
Category: Account
Urgency: High
Summary: Customer's password reset is not working and requests quick help.
Reply:
Es tut mir leid, dass der Passwort-Reset nicht funktioniert.
Um Ihnen schnell zu helfen, prüfen Sie bitte zuerst Ihren Spam-Ordner auf die Reset-E-Mail. Falls Sie diese nicht erhalten haben, teilen Sie mir bitte die E-Mail-Adresse mit, die mit Ihrem Konto verknüpft ist. Ich werde den Vorgang sofort manuell anstoßen.
Benötigen Sie außerdem Zugriff auf bestimmte Rechnungen, während wir das Problem lösen?
Next steps
This agent is already useful for a small support queue. Two concrete ways to extend it are to expose it as a FastAPI endpoint and wire it to your ticketing system via webhooks, or to add a memory layer with SQLite or Redis so multi-turn threads stay coherent across replies.
Because Oxlo.ai uses request-based pricing, the cost of these two-step agent calls stays predictable even when customers write long messages in verbose languages. See the exact plan details at https://oxlo.ai/pricing.
Top comments (0)