Agent SDK · Reference

Error handling.

Run and stream errors, retry behaviour, and partial results after a failure.

MatildaAgentRunError

Raised on HTTP-level failures (non-2xx response from the server).

Python
class MatildaAgentRunError(MatildaError):
    status: int         # HTTP status code
    response_text: str  # Raw response body

MatildaAgentStreamError

Raised by run() when the stream emits an error event (unless throw_on_stream_error=False). Carries the full AgentRunResult with whatever was collected before the error.

Python
class MatildaAgentStreamError(MatildaError):
    code: str                    # ChatErrorCode of the first error ('unknown' when empty)
    errors: list[StreamErrorDetail]
    result: AgentRunResult
Python
from matilda_agent_sdk import MatildaAgentRunError, MatildaAgentStreamError

try:
    await runner.run(agent, prompt)
except MatildaAgentStreamError as err:
    print("Stream error code:", err.code)
    print("Partial output before error:", err.result.final_output)
    print("All errors:", err.errors)
except MatildaAgentRunError as err:
    print("HTTP error status:", err.status)
    print("Response body:", err.response_text)

SafetyReplaceError

Raised by stream_text(), run_text(), stream_object(), and run_object() when the server replaces the output via a safety filter. str(err) contains the replacement text (or empty string), and categories lists the safety categories.

Python
class SafetyReplaceError(MatildaError):
    categories: list[str]

MatildaObjectParseError

Raised by stream_object() / run_object() when the response cannot be parsed as JSON or fails pydantic validation — e.g. a truncated stream (see Structured output). raw holds the full response text; cause is the underlying json.loads or pydantic error. Safety replacement does not surface here — it raises SafetyReplaceError first.

Python
class MatildaObjectParseError(MatildaError):
    raw: str
    cause: BaseException | str

Client SDK errors (re-exported)

The client SDK's error types are re-exported unchanged: MatildaError (shared base), MatildaAPIError (status, response_text), QuotaExceededError (structured 429 quota attributes), MatildaStreamError (code), and UploadError. AuthError (code, retryable) is importable from matilda_client.

Chat error codes (ChatErrorCode)

These codes are emitted via the ResponseError stream event and appear in AgentRunResult.errors (mirrored on StreamErrorDetail.code):

CodeDescription
internal_errorServer-side failure.
upstream_unavailableThe AI model is not responding.
rate_limitedToo many requests.
content_blockedSafety filter blocked the content.
stream_abortedThe stream was interrupted before completion.
deadline_exceededThe response did not finish before the deadline.
context_too_largeThe conversation is too long for the model.
url_read_incompleteA URL the server tried to read did not finish loading.
request_budget_exceededThe request exceeded its server-side budget.
stalledNo SSE events for the configured stall window.
unknownUnclassified error (old server without typed codes).

Stall watchdog

The streaming parser arms an idle-event watchdog. If no SSE event arrives for stall_timeout_ms milliseconds, the stream is considered dead and aborted with a 'stalled' error.

  • Default: 45_000 ms (DEFAULT_AGENT_STALL_TIMEOUT_MS)
  • Disable: Pass stall_timeout_ms=0 (not recommended)

Retry behaviour

The SDK retries retryable errors within a single turn. Retries are controlled by max_retries (default: 0 — no retries; DEFAULT_MAX_RETRIES).

Retryable errors:

  • HTTP 429 (rate limited), 408 (request timeout), 5xx (server errors)
  • Network errors: httpx.ConnectError, httpx.ConnectTimeout, httpx.ReadTimeout, httpx.WriteTimeout, httpx.PoolTimeout, httpx.RemoteProtocolError
  • SSE stall watchdog (stalled error code)
  • TimeoutError

Retry delay: Exponential backoff with jitter (1 s base), capped at 30 seconds.

Important: Retries only happen when no text has been yielded to the consumer yet. Retrying past that point would replay text the caller already has.

When a retry occurs, a TurnRetrying event is emitted:

Python
async for event in runner.stream(agent, prompt, max_retries=3):
    if event.type == "turn.retrying":
        print(f"Retry {event.attempt}/{event.max_retries} in {event.delay_ms}ms: {event.error['message']}")

Error handling example

Python
import asyncio

from matilda_agent_sdk import (
    MatildaAgentRunError,
    MatildaAgentStreamError,
    Runner,
    SafetyReplaceError,
)


async def main():
    runner = Runner()

    try:
        text = await runner.run_text(agent, "Hello!")
        print(text)
    except MatildaAgentStreamError as err:
        print(f"Stream error: {err.code}{err}")
        print("Partial output:", err.result.final_output)
    except MatildaAgentRunError as err:
        if err.status == 401:
            print("Session expired — re-authenticate.")
        elif err.status == 429:
            print("Rate limited — slow down.")
        else:
            print(f"API error {err.status}: {err.response_text}")
    except SafetyReplaceError as err:
        print(f"Safety filter: {', '.join(err.categories)}")


asyncio.run(main())