DEV Community

shashank ms
shashank ms

Posted on

Serverless Computing with LLM: A Step-by-Step Guide

Building a serverless customer support triage agent that classifies incoming tickets, drafts first-pass replies, and routes them to the correct team. We will deploy it as an AWS Lambda function backed by Oxlo.ai, where flat per-request pricing keeps costs predictable even when customers paste long logs or full chat histories. Details are at https://oxlo.ai/pricing.

What you'll need

  • Python 3.10 or newer
  • An AWS account with Lambda and API Gateway access
  • An Oxlo.ai API key from https://portal.oxlo.ai
  • The OpenAI SDK: pip install openai

Step 1: Scaffold the Lambda handler and dependencies

Create a new directory and a requirements file that pins the OpenAI SDK. We will keep everything in a single handler file so deployment stays simple.

mkdir serverless-triage && cd serverless-triage
cat > requirements.txt << 'EOF'
openai>=1.0.0
EOF

cat > handler.py << 'EOF'
import json
import os
from openai import OpenAI

OXLO_API_KEY = os.environ["OXLO_API_KEY"]

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

def lambda_handler(event, context):
    # Parse the incoming support ticket
    body = json.loads(event.get("body", "{}"))
    ticket = body.get("ticket", "")
    
    return {
        "statusCode": 200,
        "body": json.dumps({"received": ticket})
    }
EOF

Step 2: Define the system prompt

The agent needs to return structured JSON every time. I use a system prompt that forces a strict schema so downstream routing logic never has to guess.

SYSTEM_PROMPT = """You are a support triage agent. Analyze the ticket below and return ONLY a JSON object with no markdown formatting.

Required keys:
- urgency: one of "critical", "high", "normal", "low"
- team: one of "billing", "technical", "account", "general"
- reply: a polite first-pass response to the customer
- reason: one sentence explaining the classification

Rules:
- If the ticket contains payment errors or refund requests, team is "billing".
- If the ticket contains API errors, integration questions, or code snippets, team is "technical".
- Keep the reply under 100 words.
- Do not include

 ```json or ```

 markers."""

Step 3: Wire the Oxlo.ai inference call

I use Llama 3.3 70B because it follows structured instructions reliably and handles long ticket threads without issue. Because Oxlo.ai charges per request instead of per token, pasting a 4,000-word log transcript costs the same as a single sentence. Update handler.py with the inference logic.

import json
import os
from openai import OpenAI

OXLO_API_KEY = os.environ["OXLO_API_KEY"]

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

SYSTEM_PROMPT = """You are a support triage agent. Analyze the ticket below and return ONLY a JSON object with no markdown formatting.

Required keys:
- urgency: one of "critical", "high", "normal", "low"
- team: one of "billing", "technical", "account", "general"
- reply: a polite first-pass response to the customer
- reason: one sentence explaining the classification

Rules:
- If the ticket contains payment errors or refund requests, team is "billing".
- If the ticket contains API errors, integration questions, or code snippets, team is "technical".
- Keep the reply under 100 words.
- Do not include

 ```json or ```

 markers."""

def lambda_handler(event, context):
    body = json.loads(event.get("body", "{}"))
    ticket = body.get("ticket", "")
    
    if not ticket:
        return {"statusCode": 400, "body": json.dumps({"error": "missing ticket"})}
    
    response = client.chat.completions.create(
        model="llama-3.3-70b",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": ticket},
        ],
    )
    
    raw = response.choices[0].message.content
    result = json.loads(raw)
    
    return {
        "statusCode": 200,
        "headers": {"Content-Type": "application/json"},
        "body": json.dumps(result)
    }

Step 4: Add validation and error handling

Lambda retries can get expensive if the function crashes on malformed LLM output. I add a small guard that catches JSON decode errors and falls back to a safe default.

import json
import os
import traceback
from openai import OpenAI

OXLO_API_KEY = os.environ["OXLO_API_KEY"]

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

SYSTEM_PROMPT = """You are a support triage agent. Analyze the ticket below and return ONLY a JSON object with no markdown formatting.

Required keys:
- urgency: one of "critical", "high", "normal", "low"
- team: one of "billing", "technical", "account", "general"
- reply: a polite first-pass response to the customer
- reason: one sentence explaining the classification

Rules:
- If the ticket contains payment errors or refund requests, team is "billing".
- If the ticket contains API errors, integration questions, or code snippets, team is "technical".
- Keep the reply under 100 words.
- Do not include

 ```json or ```

 markers."""

def lambda_handler(event, context):
    body = json.loads(event.get("body", "{}"))
    ticket = body.get("ticket", "")
    
    if not ticket:
        return {"statusCode": 400, "body": json.dumps({"error": "missing ticket"})}
    
    try:
        response = client.chat.completions.create(
            model="llama-3.3-70b",
            messages=[
                {"role": "system", "content": SYSTEM_PROMPT},
                {"role": "user", "content": ticket},
            ],
        )
        
        raw = response.choices[0].message.content.strip()
        result = json.loads(raw)
        
        # Validate required keys
        for key in ("urgency", "team", "reply", "reason"):
            if key not in result:
                raise ValueError(f"missing key: {key}")
                
    except Exception:
        traceback.print_exc()
        result = {
            "urgency": "normal",
            "team": "general",
            "reply": "Thanks for reaching out. A support agent will review your ticket shortly.",
            "reason": "Fallback due to parsing error."
        }
    
    return {
        "statusCode": 200,
        "headers": {"Content-Type": "application/json"},
        "body": json.dumps(result)
    }

Step 5: Deploy to AWS Lambda

Package the OpenAI SDK alongside the handler, create the function, and set the Oxlo.ai key as an environment variable. I keep the timeout at 30 seconds because Oxlo.ai serves popular models with no cold starts, so the first invocation after idle time still returns quickly.

pip install openai -t python/
zip -r function.zip handler.py python/

aws lambda create-function \
    --function-name support-triage-agent \
    --runtime python3.11 \
    --handler handler.lambda_handler \
    --role arn:aws:iam::YOUR_ACCOUNT:role/lambda-execution-role \
    --zip-file fileb://function.zip \
    --environment Variables="{OXLO_API_KEY=YOUR_OXLO_API_KEY}" \
    --timeout 30 \
    --memory-size 256

Run it

Invoke the function with a test ticket containing a long error trace. Notice that the cost stays flat even though the input is several thousand tokens.

aws lambda invoke \
    --function-name support-triage-agent \
    --payload '{"body": "{\"ticket\": \"I was charged twice for my Pro subscription this month. My account email is dev@example.com and I need a refund immediately.\"}"}' \
    response.json && cat response.json

Expected output:

{"urgency": "high", "team": "billing", "reply": "We are sorry for the double charge. Our billing team is reviewing your account and will issue a refund within 24 hours.", "reason": "The ticket explicitly mentions a duplicate charge and requests a refund."}

Next steps

Wire the Lambda to an API Gateway endpoint so your helpdesk software can POST tickets directly. If you start handling multilingual tickets, swap the model to qwen-3-32b in the client call without changing any other code.

Top comments (0)