DEV Community

shashank ms
shashank ms

Posted on

Agentic Workload for LLM: A Guide with Oxlo

I have shipped enough internal agents to know the bottleneck is never the LLM itself. It is the loop: verify a fact, call a tool, check the result, decide what to do next. In this guide we will build a refund resolution agent that looks up orders, checks policy, and approves or escalates. We will run it on Oxlo.ai, where flat per-request pricing keeps costs predictable even when the conversation grows. You can see the exact pricing at https://oxlo.ai/pricing.

What you will need

  • Python 3.10 or newer
  • The openai SDK: pip install openai
  • An Oxlo.ai API key from https://portal.oxlo.ai
  • A virtual environment (optional but recommended)

Step 1: Configure the Oxlo.ai client

Create a file named refund_agent.py. Start with the Oxlo.ai client initialization. I always send a one-word ping to confirm the endpoint and credentials before I add any logic.

from openai import OpenAI
import json

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

# Verify connectivity
response = client.chat.completions.create(
    model="llama-3.3-70b",
    messages=[{"role": "user", "content": "ping"}],
)
print(response.choices[0].message.content)

Step 2: Define tools and mock backend

Next, add a mock database and the tool definitions. In production these functions will hit your CRM or ERP. For now we use an in-memory dictionary so we can test the agent loop without external dependencies.

# Mock database
ORDERS = {
    "ORD-2024-8892": {
        "customer_email": "alex@example.com",
        "amount": 299.00,
        "days_since_purchase": 5,
        "status": "delivered",
    }
}

def get_order_details(order_id: str):
    return ORDERS.get(order_id, {"error": "Order not found"})

def calculate_refund(amount: float, days: int):
    if days <= 14:
        return {"eligible": True, "refund_amount": amount, "fee": 0.0}
    if days <= 30:
        return {"eligible": True, "refund_amount": amount * 0.8, "fee": amount * 0.2}
    return {"eligible": False, "refund_amount": 0.0, "reason": "Outside 30-day window"}

def escalate_to_human(reason: str):
    return {"escalated": True, "ticket_id": f"TKT-{abs(hash(reason)) % 100000}"}

TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "get_order_details",
            "description": "Retrieve order details by order ID.",
            "parameters": {
                "type": "object",
                "properties": {
                    "order_id": {
                        "type": "string",
                        "description": "Order identifier, e.g. ORD-2024-8892"
                    }
                },
                "required": ["order_id"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "calculate_refund",
            "description": "Calculate refund eligibility and net amount.",
            "parameters": {
                "type": "object",
                "properties": {
                    "amount": {"type": "number"},
                    "days": {"type": "number"}
                },
                "required": ["amount", "days"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "escalate_to_human",
            "description": "Escalate to a human agent.",
            "parameters": {
                "type": "object",
                "properties": {
                    "reason": {"type": "string"}
                },
                "required": ["reason"]
            }
        }
    }
]

Step 3: Write the system prompt

The system prompt is the contract. It tells the model when to ask for data, when to calculate, and when to hand off to a human. Keep it under 200 tokens if you can. Verbose prompts drift.

SYSTEM_PROMPT = """You are a support agent for an electronics store.

Your goal is to resolve refund requests in as few steps as possible.

Workflow:
1. If the user does not provide an order ID, ask for it once.
2. Call get_order_details to verify the order exists.
3. Call calculate_refund with the order amount and days_since_purchase.
4. If the user is angry or uses profanity, call escalate_to_human and apologize.
5. If eligible, confirm the refund amount and state it will arrive in 3 to 5 business days.
6. If ineligible, explain the policy clearly.

Always use tools when data is needed. Do not guess."""

Step 4: Build the execution loop

Now the core loop. We send the conversation to Oxlo.ai, check if the model requested tool calls, execute them in Python, and feed the results back. I cap the loop at five rounds to avoid runaway recursion.

def run_agent(user_message: str, history: list = None) -> str:
    messages = history or [{"role": "system", "content": SYSTEM_PROMPT}]
    messages.append({"role": "user", "content": user_message})

    for _ in range(5):
        response = client.chat.completions.create(
            model="llama-3.3-70b",
            messages=messages,
            tools=TOOLS,
            tool_choice="auto",
        )

        message = response.choices[0].message

        if message.tool_calls:
            # Record the assistant's intent to call tools
            messages.append({
                "role": "assistant",
                "content": message.content or "",
                "tool_calls": [
                    {
                        "id": tc.id,
                        "type": "function",
                        "function": {
                            "name": tc.function.name,
                            "arguments": tc.function.arguments,
                        }
                    }
                    for tc in message.tool_calls
                ]
            })

            # Execute each tool and append results
            for tc in message.tool_calls:
                name = tc.function.name
                args = json.loads(tc.function.arguments)

                if name == "get_order_details":
                    result = get_order_details(**args)
                elif name == "calculate_refund":
                    result = calculate_refund(**args)
                elif name == "escalate_to_human":
                    result = escalate_to_human(**args)
                else:
                    result = {"error": f"Tool {name} not found"}

                messages.append({
                    "role": "tool",
                    "tool_call_id": tc.id,
                    "content": json.dumps(result),
                })
        else:
            # Final answer
            messages.append({"role": "assistant", "content": message.content})
            return message.content

    return "Agent stopped after maximum tool rounds."

Step 5: Add test cases

Finally, add the test cases at the bottom of the file. The first is a standard refund request. The second is a hostile message that should trigger the escalation tool.

if __name__ == "__main__":
    print("=== Scenario A ===")
    reply_a = run_agent("I want a refund for ORD-2024-8892. The item arrived scratched.")
    print(reply_a)

    print("\n=== Scenario B ===")
    reply_b = run_agent("This is garbage. I want my money back immediately or I will dispute the charge.")
    print(reply_b)

Run it

Execute the script from your terminal.

python refund_agent.py

You should see output similar to this. Exact wording varies by LLM temperature.

=== Scenario A ===
I have verified order ORD-2024-8892. Because it is within the 14-day window, you are eligible for a full refund of $299.00. The funds will return to your original payment method in 3 to 5 business days.

=== Scenario B ===
I am sorry for the frustration. I have escalated this to a specialist who will contact you within one hour. Your ticket ID is TKT-48291.

Wrap-up

Two concrete next steps. First, replace the ORDERS dictionary with real API calls to your CRM or OMS. Second, if you need deeper reasoning for complex policy edge cases, swap llama-3.3-70b for deepseek-v3.2 or kimi-k2.6 in the run_agent call. Both are available on Oxlo.ai with the same flat per-request structure, so you can experiment without watching token meters climb.

Top comments (0)