We are going to build a root-cause analysis agent that ingests large system logs and outputs a structured incident report. Mixture of Experts models excel at this because they route tokens to specialized sub-networks, making them efficient at deep reasoning over lengthy inputs. We will run it on Oxlo.ai using their OpenAI-compatible endpoint and the MoE-based DeepSeek V3.2 model.
What you'll need
- An Oxlo.ai API key from https://portal.oxlo.ai
- Python 3.10 or newer
- The OpenAI SDK:
pip install openai
Step 1: Initialize the Oxlo.ai client
I keep the model name in a constant so I can switch later. Oxlo.ai hosts several MoE options, including DeepSeek R1 671B MoE and GLM 5, but we will start with DeepSeek V3.2 because it is efficient and available on the free tier.
from openai import OpenAI
client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")
MODEL_NAME = "deepseek-v3.2"
Step 2: Write the system prompt
The system prompt tells the model to act as a site reliability engineer and enforces a strict output format. I treat this as a config variable so I can tweak it without touching the request logic.
SYSTEM_PROMPT = """You are a senior site reliability engineer analyzing a production incident.
Read the provided logs carefully and produce a structured incident report with exactly these sections:
- Summary: One sentence describing the issue.
- Root Cause: The specific error or failure pattern.
- Affected Services: A bullet list of impacted components.
- Suggested Fix: Concrete remediation steps.
Format the report in Markdown with clear headers."""
Step 3: Prepare the log payload
In production you might stream logs from S3 or Datadog. Here we will use a long multiline string that simulates a realistic cascade failure across nginx, Postgres, and Redis. This is where MoE models shine, because the input is thousands of tokens but the model only activates a subset of parameters per token.
def load_sample_logs() -> str:
return """
[2024-05-21T14:02:01Z] nginx: 502 Bad Gateway upstream prematurely closed connection
[2024-05-21T14:02:02Z] app: ERROR ConnectionPool timeout after 30s db-host-03
[2024-05-21T14:02:03Z] postgres: FATAL: remaining connection slots are reserved
[2024-05-21T14:02:04Z] app: ERROR Retry 1/3 failed for job ID 9912
[2024-05-21T14:02:05Z] redis: LOADING Redis is loading the dataset in memory
[2024-05-21T14:02:06Z] app: ERROR Circuit breaker opened for payment-service
[2024-05-21T14:02:07Z] nginx: 502 Bad Gateway upstream prematurely closed connection
[2024-05-21T14:02:08Z] postgres: FATAL: remaining connection slots are reserved
[2024-05-21T14:02:09Z] app: ERROR Dropping message on queue "orders" due to timeout
[2024-05-21T14:02:10Z] redis: LOADING Redis is loading the dataset in memory
"""
Step 4: Send the request to the MoE model
Now we pass the logs to Oxlo.ai. Because the platform uses request-based pricing, the cost is flat regardless of how long the log tail is. That makes iterating on large traces predictable.
def analyze_logs(logs: str) -> str:
response = client.chat.completions.create(
model=MODEL_NAME,
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": f"Analyze these logs and produce the report:\n\n{logs}"},
],
)
return response.choices[0].message.content
Step 5: Add error handling and wrap the script
For a shipped tool, I wrap the call in a small retry loop. Oxlo.ai has no cold starts on popular models, so failures are usually transient network blips.
import time
def analyze_logs_safe(logs: str, retries: int = 2) -> str:
for attempt in range(retries + 1):
try:
response = client.chat.completions.create(
model=MODEL_NAME,
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": f"Analyze these logs and produce the report:\n\n{logs}"},
],
)
return response.choices[0].message.content
except Exception:
if attempt == retries:
raise
time.sleep(1)
return ""
if __name__ == "__main__":
logs = load_sample_logs()
print(analyze_logs_safe(logs))
Run it
Save the script as log_agent.py, set your OXLO_API_KEY, and run python log_agent.py. You should see output similar to this.
## Summary
A cascading failure started when Postgres connection slots were exhausted, causing nginx to return 502 errors.
## Root Cause
Postgres reached its max_connections limit, which blocked the application connection pool. The application then spammed retries, worsening the bottleneck. Redis was simultaneously reloading its dataset, so fallback caching was unavailable.
## Affected Services
- nginx (502 Bad Gateway)
- app (connection pool timeouts, circuit breaker open)
- postgres (FATAL: remaining connection slots are reserved)
- redis (LOADING state)
## Suggested Fix
1. Immediately raise Postgres max_connections or enable pgbouncer connection pooling.
2. Restart Redis and verify RDB persistence settings to prevent reload stalls.
3. Close the circuit breaker for payment-service once health checks pass.
4. Add connection pool limits and exponential backoff in the app tier to avoid retry storms.
Next steps
Turn this into a true agent by adding Oxlo.ai function calling. Define a restart_service tool and let the model decide whether to invoke it after analysis. If you need deeper multi-hop reasoning for cross-service outages, swap the model to deepseek-r1-671b-moe or glm-5. Because Oxlo.ai charges per request rather than per token, escalating to larger MoE models for long log dumps will not spike your bill the way token-based providers do. See https://oxlo.ai/pricing for plan details.
Top comments (0)