What Are AI Agent Service Level Agreements?
An AI Agent Service Level Agreement (SLA) is a formal contract between you—the provider of an AI-powered agent or autonomous system—and your client that defines measurable performance guarantees, reliability thresholds, and remediation terms. Unlike traditional software SLAs that focus on uptime and response latency, AI agent SLAs must account for probabilistic outputs, chain-of-reasoning failures, tool-calling errors, hallucination rates, and the inherent non-determinism of large language models.
Think of it as a warranty for autonomous decision-making. When your agent acts on behalf of a customer—scheduling meetings, processing support tickets, executing financial operations—you are promising that those actions will meet specific accuracy, latency, and safety bars. The SLA translates fuzzy "AI will try its best" language into concrete, measurable commitments that build trust and set clear expectations.
Core Components of an AI Agent SLA
A well-structured AI agent SLA typically includes these dimensions:
- Task Completion Rate — the percentage of user intents or workflows the agent resolves without human escalation
- Correctness / Hallucination Rate — the proportion of factual statements, extracted entities, or tool parameters that are accurate
- End-to-End Latency — the p50, p95, and p99 time from user input to actionable output or tool execution
- Tool Call Reliability — success rate of API invocations, database queries, or external service integrations the agent performs
- Safety Guardrail Adherence — percentage of responses that pass content policy checks, refusal triggers, and PII leakage filters
- Availability / Uptime — the traditional measure of service reachability, including model inference endpoints and orchestration layers
- Cost per Interaction — a ceiling on token consumption or compute spend per task, protecting clients from runaway agent loops
Why AI Agent SLAs Matter
Clients are increasingly embedding autonomous agents into mission-critical workflows—customer support, legal document review, medical triage, code generation in CI/CD pipelines. Without an SLA, a client absorbs all the risk of unpredictable behavior. With an SLA, you share that risk and commit to a baseline of quality. This matters for several reasons:
- Enterprise Procurement Requires It — most organizations cannot approve budget for AI tools without contractual performance guarantees and penalty clauses
- Regulatory Compliance — industries like finance (SOX, GDPR) and healthcare (HIPAA) demand auditable proof that automated decisions meet accuracy thresholds
- Operational Trust — teams building on top of your agent need to know when they can rely on its output versus when they must implement fallback human review
- Cost Predictability — an SLA caps the worst-case latency and token burn, preventing a single malformed prompt from spiraling into thousands of dollars of inference cost
- Incident Response Clarity — when the agent fails, the SLA defines who is responsible, how quickly remediation begins, and what compensation the client receives
Designing Measurable SLA Metrics for AI Agents
Step 1: Define the Evaluation Harness
Before you can promise anything, you need a rigorous evaluation pipeline that measures your agent's performance against ground-truth data. This harness should run continuously—not just at release time—because model updates, tool API changes, and prompt drift can silently degrade performance.
Here is a practical evaluation framework in Python that computes the core SLA metrics:
from dataclasses import dataclass, field
from typing import List, Dict, Optional
import json
import time
import numpy as np
from enum import Enum
class MetricStatus(Enum):
COMPLIANT = "compliant"
BREACHED = "breached"
DEGRADED = "degraded"
@dataclass
class SLAEvaluationResult:
"""Structured output from an SLA evaluation run."""
task_completion_rate: float # 0.0 to 1.0
hallucination_rate: float
latency_p50_ms: float
latency_p95_ms: float
latency_p99_ms: float
tool_call_success_rate: float
guardrail_pass_rate: float
cost_per_interaction_usd: float
total_samples: int
sla_compliant: bool
breached_metrics: List[str] = field(default_factory=list)
class AgentSLAEvaluator:
"""Evaluates agent performance against defined SLA thresholds."""
def __init__(self, sla_config: Dict):
self.config = sla_config
self.thresholds = sla_config["thresholds"]
def evaluate_run(
self,
results: List[Dict],
ground_truth: List[Dict]
) -> SLAEvaluationResult:
"""Run full SLA evaluation over a batch of agent interactions."""
n = len(results)
if n == 0:
raise ValueError("Empty results set")
# Task completion: did the agent resolve the intent?
completed = sum(
1 for r in results
if r.get("status") == "resolved" and not r.get("escalated", False)
)
task_completion = completed / n
# Hallucination check against ground truth
hallucinations = 0
total_checks = 0
for r, gt in zip(results, ground_truth):
for field in gt.get("critical_fields", []):
total_checks += 1
if r.get("extracted", {}).get(field) != gt["values"].get(field):
hallucinations += 1
hallucination_rate = hallucinations / max(total_checks, 1)
# Latency percentiles
latencies = [r.get("total_latency_ms", 0) for r in results]
latency_p50 = float(np.percentile(latencies, 50))
latency_p95 = float(np.percentile(latencies, 95))
latency_p99 = float(np.percentile(latencies, 99))
# Tool call reliability
tool_calls_total = sum(r.get("tool_calls_count", 0) for r in results)
tool_calls_failed = sum(r.get("tool_failures", 0) for r in results)
tool_success = 1.0 - (tool_calls_failed / max(tool_calls_total, 1))
# Guardrail adherence
guardrail_pass = sum(
1 for r in results
if r.get("guardrail_triggered", False) is False
) / n
# Cost per interaction
total_cost = sum(r.get("total_cost_usd", 0) for r in results)
avg_cost = total_cost / n
# Threshold checking
breached = []
if task_completion < self.thresholds.get("min_task_completion", 0.90):
breached.append("task_completion_rate")
if hallucination_rate > self.thresholds.get("max_hallucination_rate", 0.05):
breached.append("hallucination_rate")
if latency_p95 > self.thresholds.get("max_latency_p95_ms", 5000):
breached.append("latency_p95")
if latency_p99 > self.thresholds.get("max_latency_p99_ms", 10000):
breached.append("latency_p99")
if tool_success < self.thresholds.get("min_tool_success_rate", 0.95):
breached.append("tool_call_success_rate")
if guardrail_pass < self.thresholds.get("min_guardrail_pass_rate", 0.99):
breached.append("guardrail_pass_rate")
if avg_cost > self.thresholds.get("max_cost_per_interaction_usd", 0.50):
breached.append("cost_per_interaction")
return SLAEvaluationResult(
task_completion_rate=task_completion,
hallucination_rate=hallucination_rate,
latency_p50_ms=latency_p50,
latency_p95_ms=latency_p95,
latency_p99_ms=latency_p99,
tool_call_success_rate=tool_success,
guardrail_pass_rate=guardrail_pass,
cost_per_interaction_usd=avg_cost,
total_samples=n,
sla_compliant=len(breached) == 0,
breached_metrics=breached
)
# Example usage
sla_config = {
"thresholds": {
"min_task_completion": 0.92,
"max_hallucination_rate": 0.03,
"max_latency_p95_ms": 4000,
"max_latency_p99_ms": 8000,
"min_tool_success_rate": 0.97,
"min_guardrail_pass_rate": 0.995,
"max_cost_per_interaction_usd": 0.35
}
}
evaluator = AgentSLAEvaluator(sla_config)
# results and ground_truth populated from your test suite
# eval_result = evaluator.evaluate_run(results, ground_truth)
Step 2: Build a Continuous SLA Monitoring Pipeline
Point-in-time evaluation is insufficient. You need a production monitoring system that samples live traffic, computes SLA metrics on a rolling window, and triggers alerts when thresholds are at risk. Below is a skeleton for a streaming monitor that integrates with your agent's logging infrastructure:
import threading
import time
from collections import deque
from datetime import datetime, timedelta
import logging
logger = logging.getLogger("sla-monitor")
class RollingSLAMonitor:
"""Continuously monitors SLA metrics over a sliding window."""
def __init__(
self,
evaluator: AgentSLAEvaluator,
window_minutes: int = 60,
sample_interval_seconds: int = 30,
alert_callback=None
):
self.evaluator = evaluator
self.window = timedelta(minutes=window_minutes)
self.sample_interval = sample_interval_seconds
self.alert_callback = alert_callback or self._default_alert
self.buffer = deque()
self.ground_truth_buffer = deque()
self._lock = threading.Lock()
self._running = False
def ingest(self, result: Dict, ground_truth: Optional[Dict] = None):
"""Ingest a single agent interaction result."""
timestamp = datetime.now()
with self._lock:
self.buffer.append({"timestamp": timestamp, "result": result})
if ground_truth:
self.ground_truth_buffer.append(
{"timestamp": timestamp, "ground_truth": ground_truth}
)
self._prune_buffer()
def _prune_buffer(self):
"""Remove entries outside the sliding window."""
cutoff = datetime.now() - self.window
while self.buffer and self.buffer[0]["timestamp"] < cutoff:
self.buffer.popleft()
while (
self.ground_truth_buffer
and self.ground_truth_buffer[0]["timestamp"] < cutoff
):
self.ground_truth_buffer.popleft()
def evaluate_window(self) -> Optional[SLAEvaluationResult]:
"""Compute SLA metrics over the current window."""
with self._lock:
results = [entry["result"] for entry in self.buffer]
ground_truths = [
entry["ground_truth"]
for entry in self.ground_truth_buffer
]
if len(results) < 50: # Minimum sample size for statistical validity
return None
return self.evaluator.evaluate_run(results, ground_truths)
def _default_alert(self, metric_name: str, current_value: float, threshold: float):
logger.warning(
f"SLA BREACH RISK: {metric_name} = {current_value:.3f} "
f"(threshold: {threshold:.3f})"
)
def run(self):
"""Start the monitoring loop."""
self._running = True
while self._running:
time.sleep(self.sample_interval)
result = self.evaluate_window()
if result is None:
continue
# Check each metric and alert on breach or approaching breach
metrics = {
"task_completion_rate": (
result.task_completion_rate,
self.evaluator.thresholds["min_task_completion"]
),
"hallucination_rate": (
result.hallucination_rate,
self.evaluator.thresholds["max_hallucination_rate"]
),
"latency_p95_ms": (
result.latency_p95_ms,
self.evaluator.thresholds["max_latency_p95_ms"]
),
"tool_call_success_rate": (
result.tool_call_success_rate,
self.evaluator.thresholds["min_tool_success_rate"]
),
"guardrail_pass_rate": (
result.guardrail_pass_rate,
self.evaluator.thresholds["min_guardrail_pass_rate"]
),
"cost_per_interaction_usd": (
result.cost_per_interaction_usd,
self.evaluator.thresholds["max_cost_per_interaction_usd"]
)
}
for name, (value, threshold) in metrics.items():
# Warning zone: within 10% of threshold
warning_margin = 0.10
if name in ("hallucination_rate", "latency_p95_ms", "cost_per_interaction_usd"):
# For metrics where lower is better
if value > threshold * (1 - warning_margin):
self.alert_callback(name, value, threshold)
else:
# For metrics where higher is better
if value < threshold * (1 + warning_margin):
self.alert_callback(name, value, threshold)
# Full breach detection
if not result.sla_compliant:
logger.error(
f"SLA BREACHED on metrics: {result.breached_metrics}"
)
def stop(self):
self._running = False
# Integration example
# monitor = RollingSLAMonitor(evaluator, window_minutes=30)
# threading.Thread(target=monitor.run, daemon=True).start()
# In your agent's request handler:
# monitor.ingest(result_dict, ground_truth_dict)
Step 3: Formalize the SLA Contract Structure
The SLA contract itself should be machine-readable and versioned. Here is a JSON schema you can use as the canonical SLA definition that both parties sign off on, and that your monitoring system can load directly:
{
"$schema": "https://example.com/sla-schema/v1",
"sla_version": "2.1.0",
"effective_date": "2025-06-01T00:00:00Z",
"service_name": "CustomerSupportAgent",
"service_description": "Autonomous agent handling Tier-1 customer support tickets",
"parties": {
"provider": {
"name": "AgentCo Inc.",
"contact": "sla-team@agentco.example.com",
"escalation_contact": "oncall@agentco.example.com"
},
"client": {
"name": "Acme Corp",
"contact": "ai-ops@acme.example.com"
}
},
"measurement_window": {
"type": "rolling",
"period": "calendar_month",
"minimum_sample_size": 1000
},
"metrics": {
"task_completion_rate": {
"description": "Percentage of user intents resolved without escalation",
"target": 0.94,
"minimum": 0.90,
"measurement_method": "Automated evaluation against resolution labels",
"exclusions": ["scheduled_maintenance", "declared_model_updates"]
},
"hallucination_rate": {
"description": "Proportion of critical factual fields that are incorrect",
"target": 0.02,
"maximum": 0.05,
"measurement_method": "Comparison against verified ground truth dataset",
"critical_fields": [
"account_number", "transaction_amount", "compliance_status",
"product_sku", "customer_email", "refund_eligibility"
]
},
"latency_p95_ms": {
"description": "95th percentile end-to-end latency",
"target": 3500,
"maximum": 5000,
"measurement_method": "Server-side timing from request receipt to final output"
},
"latency_p99_ms": {
"description": "99th percentile end-to-end latency",
"target": 7000,
"maximum": 10000
},
"tool_call_success_rate": {
"description": "Success rate of API calls made by the agent",
"target": 0.98,
"minimum": 0.95,
"measurement_method": "HTTP status code 2xx on agent-initiated calls",
"exclusions": ["third_party_outages_with_verified_status_page"]
},
"guardrail_pass_rate": {
"description": "Responses passing safety and PII leakage checks",
"target": 0.998,
"minimum": 0.99,
"measurement_method": "Post-processing guardrail evaluation"
},
"cost_per_interaction_usd": {
"description": "Average compute and API cost per resolved interaction",
"target": 0.25,
"maximum": 0.40,
"measurement_method": "Sum of LLM token costs + tool API costs divided by interaction count"
}
},
"remediation": {
"breach_notification_window_hours": 4,
"resolution_time_target_hours": 24,
"credits": {
"calculation": "5% of monthly fee per breached metric per measurement period",
"cap_percentage": 30,
"cap_currency": "total_monthly_bill"
},
"escape_clauses": [
"force_majeure_model_provider_outage",
"client_data_quality_issues_documented",
"client_side_network_failures"
]
},
"reporting": {
"frequency": "weekly",
"format": "dashboard_url_plus_pdf_export",
"access": "https://sla-dashboard.agentco.example.com/client/acme",
"raw_data_export": true
},
"signatures": {
"provider_signed_by": "",
"client_signed_by": "",
"signed_date": ""
}
}
What You Can (and Cannot) Promise
Promises You Can Realistically Make
- Measured latency percentiles — with proper infrastructure, you can guarantee p95 and p99 latency within engineered bounds, excluding cold starts
- Tool call success rates — API reliability is deterministic and you can achieve 99%+ with retries, circuit breakers, and proper error handling
- Guardrail pass rates — deterministic safety filters produce measurable pass/fail outcomes
- Cost ceilings — by enforcing token budgets and maximum reasoning steps per interaction, you can cap costs reliably
- Availability / uptime — standard infrastructure SLAs apply to your inference endpoints and orchestration services
Promises That Require Careful Framing
- Task completion rate — this is probabilistic and varies by intent complexity; frame it as "on intents within the defined complexity class" and exclude adversarial inputs
- Hallucination rate — you can bound it on known entity types but not on open-ended creative generation; tie the guarantee to specific extractable fields with ground-truth validation
- "Correctness" of reasoning — for open-ended analytical tasks, substitute with "faithfulness to provided context" rather than absolute truth
What You Should Never Promise
- Zero hallucinations — this is impossible with current LLM architectures; even a 0.1% rate is ambitious
- Perfect task completion on ambiguous intents — ambiguity is inherent; instead, define a clear escalation path for low-confidence scenarios
- Deterministic identical outputs — temperature-based sampling means outputs will vary; guarantee the schema and critical fields, not verbatim text
- Unbounded domain expertise — scope the agent's knowledge domain explicitly and exclude out-of-domain queries from SLA coverage
Implementing SLA-Aware Agent Architecture
To meet SLA commitments, your agent architecture must be built with SLA compliance as a first-class concern. Here is a production-grade agent loop that incorporates latency tracking, cost budgeting, circuit breaking, and guardrail enforcement—all wired to feed the SLA monitoring pipeline:
import time
import asyncio
from typing import Dict, Optional, List
from dataclasses import dataclass
from enum import Enum
class AgentStepType(Enum):
INTENT_CLASSIFICATION = "intent_classification"
TOOL_SELECTION = "tool_selection"
TOOL_EXECUTION = "tool_execution"
RESPONSE_GENERATION = "response_generation"
GUARDRAIL_CHECK = "guardrail_check"
@dataclass
class SLAContext:
"""Runtime SLA constraints injected into every agent interaction."""
max_total_latency_ms: int = 8000
max_token_budget: int = 4000
max_tool_calls: int = 5
max_cost_usd: float = 0.50
require_guardrail: bool = True
escalation_threshold_confidence: float = 0.70
class SLAAwareAgent:
"""Agent that respects SLA constraints throughout its execution."""
def __init__(self, sla_config: SLAContext, sla_monitor: RollingSLAMonitor):
self.sla_config = sla_config
self.monitor = sla_monitor
self.tokens_used = 0
self.cost_accrued = 0.0
self.tool_calls_made = 0
self.start_time = None
self.guardrail_triggered = False
async def execute(self, user_input: str, session_context: Dict) -> Dict:
"""Execute a single SLA-constrained agent interaction."""
self.start_time = time.time()
interaction_result = {
"user_input": user_input,
"status": "processing",
"steps": [],
"escalated": False,
"total_latency_ms": 0,
"total_cost_usd": 0,
"tool_calls_count": 0,
"tool_failures": 0,
"guardrail_triggered": False,
"extracted": {}
}
try:
# Step 1: Intent classification with cost tracking
step_start = time.time()
intent_result = await self._classify_intent(user_input)
self._check_cost_budget(intent_result, interaction_result)
interaction_result["steps"].append({
"type": AgentStepType.INTENT_CLASSIFICATION.value,
"latency_ms": (time.time() - step_start) * 1000,
"confidence": intent_result.get("confidence", 0.0)
})
# SLA check: low confidence triggers escalation, not a guess
if intent_result.get("confidence", 0.0) < self.sla_config.escalation_threshold_confidence:
interaction_result["status"] = "escalated"
interaction_result["escalated"] = True
interaction_result["escalation_reason"] = "low_confidence_intent"
return self._finalize(interaction_result)
# Step 2: Tool execution loop with circuit breaker
tool_calls = intent_result.get("required_tools", [])
for tool in tool_calls[:self.sla_config.max_tool_calls]:
# Check latency budget before each tool call
elapsed = (time.time() - self.start_time) * 1000
if elapsed > self.sla_config.max_total_latency_ms * 0.7:
# Circuit breaker: escalate remaining work
interaction_result["status"] = "partial_escalation"
interaction_result["escalated"] = True
interaction_result["escalation_reason"] = "latency_budget_exhausted"
break
tool_start = time.time()
try:
tool_result = await self._execute_tool(tool, session_context)
interaction_result["tool_calls_count"] += 1
if not tool_result.get("success", False):
interaction_result["tool_failures"] += 1
interaction_result["steps"].append({
"type": AgentStepType.TOOL_EXECUTION.value,
"tool_name": tool.get("name"),
"latency_ms": (time.time() - tool_start) * 1000,
"success": tool_result.get("success", False)
})
# Extract structured data for hallucination checking
if "extracted" in tool_result:
interaction_result["extracted"].update(tool_result["extracted"])
except Exception as e:
interaction_result["tool_failures"] += 1
interaction_result["steps"].append({
"type": AgentStepType.TOOL_EXECUTION.value,
"tool_name": tool.get("name"),
"error": str(e),
"success": False
})
# Step 3: Response generation
if not interaction_result["escalated"]:
response = await self._generate_response(
user_input, interaction_result
)
interaction_result["response"] = response
# Step 4: Guardrail check
if self.sla_config.require_guardrail:
guardrail_result = await self._run_guardrails(
interaction_result.get("response", "")
)
interaction_result["guardrail_triggered"] = not guardrail_result["passed"]
if not guardrail_result["passed"]:
interaction_result["status"] = "blocked"
interaction_result["response"] = guardrail_result.get(
"fallback_message",
"I'm unable to process this request."
)
return self._finalize(interaction_result)
except Exception as e:
interaction_result["status"] = "error"
interaction_result["error"] = str(e)
return self._finalize(interaction_result)
def _check_cost_budget(self, step_result: Dict, interaction_result: Dict):
"""Track and enforce cost budget."""
step_tokens = step_result.get("tokens_used", 0)
step_cost = step_tokens * 0.00003 # Example: $0.03 per 1k tokens
self.tokens_used += step_tokens
self.cost_accrued += step_cost
if self.cost_accrued > self.sla_config.max_cost_usd:
raise CostBudgetExceededError(
f"Cost budget exceeded: ${self.cost_accrued:.4f}"
)
interaction_result["total_cost_usd"] = self.cost_accrued
def _finalize(self, interaction_result: Dict) -> Dict:
"""Compute final metrics and feed the SLA monitor."""
interaction_result["total_latency_ms"] = (
(time.time() - self.start_time) * 1000
)
# Feed monitor asynchronously (fire and forget)
asyncio.ensure_future(
self._feed_monitor(interaction_result)
)
return interaction_result
async def _feed_monitor(self, result: Dict):
"""Send interaction result to the SLA monitor."""
self.monitor.ingest(result, ground_truth=None) # ground truth may arrive later
async def _classify_intent(self, user_input: str) -> Dict:
# Your intent classification implementation
...
async def _execute_tool(self, tool: Dict, context: Dict) -> Dict:
# Your tool execution with retry logic
...
async def _generate_response(self, user_input: str, ctx: Dict) -> str:
# Your response generation
...
async def _run_guardrails(self, response: str) -> Dict:
# Your guardrail evaluation
...
class CostBudgetExceededError(Exception):
pass
Client-Facing SLA Dashboard and Reporting
Transparency builds trust. Provide a real-time dashboard where clients can independently verify SLA compliance. Below is a FastAPI endpoint that serves the current SLA status, suitable for both dashboard rendering and automated client-side monitoring:
from fastapi import FastAPI, HTTPException
from fastapi.responses import JSONResponse
from datetime import datetime
import json
app = FastAPI()
# Assume sla_monitor is a globally available RollingSLAMonitor instance
# and sla_config is loaded from the JSON contract
@app.get("/sla/current-status")
async def get_sla_status():
"""Return current SLA compliance status for the client dashboard."""
result = sla_monitor.evaluate_window()
if result is None:
return JSONResponse({
"status": "insufficient_data",
"message": "Not enough samples in current window for reliable SLA computation",
"minimum_samples": 50,
"current_samples": len(sla_monitor.buffer),
"timestamp": datetime.now().isoformat()
}, status_code=200)
return {
"timestamp": datetime.now().isoformat(),
"window_samples": result.total_samples,
"sla_compliant": result.sla_compliant,
"breached_metrics": result.breached_metrics,
"metrics": {
"task_completion_rate": {
"value": round(result.task_completion_rate, 4),
"threshold": sla_config["thresholds"]["min_task_completion"],
"status": "compliant" if result.task_completion_rate >= sla_config["thresholds"]["min_task_completion"] else "breached"
},
"hallucination_rate": {
"value": round(result.hallucination_rate, 4),
"threshold": sla_config["thresholds"]["max_hallucination_rate"],
"status": "compliant" if result.hallucination_rate <= sla_config["thresholds"]["max_hallucination_rate"] else "breached"
},
"latency_p95_ms": {
"value": round(result.latency_p95_ms, 2),
"threshold": sla_config["thresholds"]["max_latency_p95_ms"],
"status": "compliant" if result.latency_p95_ms <= sla_config["thresholds"]["max_latency_p95_ms"] else "breached"
},
"latency_p99_ms": {
"value": round(result.latency_p99_ms, 2),
"threshold": sla_config["thresholds"]["max_latency_p99_ms"],
"status": "compliant" if result.latency_p99_ms <= sla_config["thresholds"]["max_latency_p99_ms"] else "breached"
},
"tool_call_success_rate": {
"value": round(result.tool_call_success_rate, 4),
"threshold": sla_config["thresholds"]["min_tool_success_rate"],
"status": "compliant" if result.tool_call_success_rate >= sla_config["thresholds"]["min_tool_success_rate"] else "breached"
},
"guardrail_pass_rate": {
"value": round(result.guardrail_pass_rate, 4),
"threshold": sla_config["thresholds"]["min_guardrail_pass_rate"],
"status": "compliant" if result.guardrail_pass_rate >= sla_config["thresholds"]["min_guardrail_pass_rate"] else "breached"
},
"cost_per_interaction_usd": {
"value": round(result.cost_per_interaction_usd, 4),
"threshold": sla_config["thresholds"]["max_cost_per_interaction_usd"],
"status": "compliant" if result.cost_per_interaction_usd <= sla_config["thresholds"]["max_cost_per_interaction_usd"] else "breached"
}
},
"health_score": round(
(7 - len(result.breached_metrics)) / 7 * 100, 1
) if not result.breached_metrics else round(
(7 - len(result.breached_metrics)) / 7 * 100, 1
)
}
@app.get("/sla/history")
async def get_sla_history(days: int = 30):
"""Return historical SLA compliance data for trend analysis."""
# Query your time-series database for historical SLA snapshots
# Returns a list of daily compliance summaries
history = await sla_history_repository.query(days=days)
return {
"period_days": days,
"daily_snapshots": history,
"breach_events": [
snap for snap in history if not snap["sla_compliant"]
],
"total_breach_days": sum(
1 for snap in history if not snap["sla_compliant"]
)
}
@app.get("/sla/remediation-status")
async def get_remediation_status():
"""Show active remediations and credit calculations."""
return {
"active_breaches": sla_monitor.get_active_breaches(),
"remediation_deadlines": sla_monitor.get_remediation_deadlines(),
"accrued_credits_usd": sla_monitor.calculate_accrued_credits(),
"credit_cap_usd": sla_config["remediation"]["cap_currency"],
"next_credit_application_date": sla_monitor.next_credit_date()
}
Best Practices for AI Agent SLAs
1. Start with Internal SLAs Before External Commitments
Run your SLA evaluation pipeline internally for at least two billing cycles before publishing numbers to clients. Use this period to understand variance across traffic patterns, model updates, and edge cases. Only commit to thresholds you have consistently beaten in production for at least 30 days.
2. Define Exclusion Windows Explicitly
Every SLA needs documented exclusions. For AI agents, common exclusions include: model provider outages (force majeure), scheduled maintenance windows, client-side data quality issues, adversarial prompt injection attempts, and the first 24 hours after a major model version bump. Document these in the SLA JSON and enforce them in your monitoring—excluded periods should not count toward breach calculations.
3. Use Graduated Severity Levels
Not all SLA breaches are equal. Implement a tiered system:
- Warning (within 10% of threshold) — automated alert, no credit obligation, internal investigation triggered
- Soft Breach (metric below target but above minimum) — partial credit accrual, remediation plan required within 48 hours
- Hard Breach (metric below contractual minimum) — full credit accrual, executive escalation, mandatory post-mortem