Error Handling for AI Agents

Consistent, machine-parseable error format designed for programmatic consumption by AI agents and automated systems.

Error Envelope

All API errors return a JSON object with a single error key. This shape is stable and safe for programmatic parsing.

json
{
  "error": {
    "message": "Human-readable error description",
    "type": "error_category",
    "code": 400,
    "param": "field_name"
  }
}

Error Fields

NameTypeRequiredDescription
error.message
stringRequiredHuman-readable description. Always present. Safe to display to users.
error.type
stringRequiredError category for programmatic branching. One of: invalid_request_error, authentication_error, rate_limit_error, api_error, insufficient_credits.
error.code
integer | stringRequiredHTTP status code (integer) for standard errors. Semantic string (e.g. 'insufficient_credits') for extended errors.
error.param
string | nullThe request parameter that caused the error. Null when not applicable.

Error Types Reference

NameTypeRequiredDescription
invalid_request_error
400Malformed request, missing required fields, or invalid parameter values. Check error.param for the offending field.
authentication_error
401Missing, invalid, or expired API key. Verify the Authorization header.
insufficient_credits
402Account balance too low. Extended payload includes error.balance with current/threshold values.
rate_limit_error
429Request quota exceeded. Read the Retry-After header for backoff seconds.
api_error
500/502/503Gateway or upstream provider failure. Safe to retry with exponential backoff.

Agent Retry Strategy

Recommended decision tree for AI agents handling errors:

retry-strategy.py
import time
import openai

def call_with_retry(client, max_retries=3, **kwargs):
    for attempt in range(max_retries):
        try:
            return client.chat.completions.create(**kwargs)
        except openai.RateLimitError as e:
            # 429: wait for Retry-After header value
            wait = int(e.response.headers.get("Retry-After", 2 ** attempt))
            time.sleep(wait)
        except openai.APIStatusError as e:
            error_type = e.body.get("error", {}).get("type", "")

            if error_type == "insufficient_credits":
                raise  # Cannot retry — top up credits

            if error_type == "authentication_error":
                raise  # Cannot retry — fix API key

            if error_type == "invalid_request_error":
                raise  # Cannot retry — fix request payload

            if e.status_code >= 500:
                # Server error: retry with backoff
                time.sleep(2 ** attempt)
            else:
                raise

    raise RuntimeError("Max retries exceeded")

Insufficient Credits (402) Extended Shape

The 402 error includes additional fields for balance awareness:

json
{
  "error": {
    "type": "insufficient_credits",
    "message": "Insufficient credit balance",
    "code": "insufficient_credits",
    "balance": {
      "current": 2.5,
      "threshold": 5,
      "currency": "credits"
    },
    "actions": {
      "top_up_url": "/v1/customer/credits/packages",
      "support_url": "/support"
    }
  }
}

Diagnostic Headers

NameTypeRequiredDescription
x-request-id
string (UUID)Always present. Use this for debugging and when contacting support.
Retry-After
integerPresent on 429 responses. Number of seconds to wait before retrying.
X-RateLimit-Remaining
integerRemaining requests in the current rate limit window.
X-RateLimit-Reset
integerUnix epoch timestamp when the rate limit window resets.
Parsing Tip
Always check for the presence of error key first. A successful response never contains an error field. This makes error detection a single boolean check: if ("error" in response).