Start here. This is the direct spoken answer to practice first.
Overview
These outcomes have different causes and recovery paths, so the integration needs an explicit result contract rather than a single exception bucket.
I classify the outcome first. A refusal is a model decision and may require safer context, a narrower task, or a user explanation; it is not automatically a transient error. A timeout may be retried only when the operation is safe and the deadline allows it. A rate limit uses bounded backoff, provider guidance, capacity controls, or a fallback. Malformed output fails schema and semantic validation and may get one constrained repair attempt. Every path has a user-visible result instead of returning invented content.