DEV Community

shashank ms
shashank ms

Posted on

Building Conversational AI Models with Oxlo

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

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)