Error Handling
This guide covers how to handle errors from the Relynt gateway, including HTTP error codes, retry strategies, and timeout handling.
HTTP error codes
| Status | Code | Description | Action |
|---|---|---|---|
400 | bad_request | Invalid request body (missing or malformed fields) | Fix the request and retry |
401 | unauthorized | Invalid or missing agent credential | Check credential, rotate if needed |
403 | forbidden | Agent not authorized for this organization | Verify agent registration |
409 | conflict | Idempotency key reused with different parameters | Use a new idempotency key |
422 | policy_error | Policy evaluation failed | Check policy configuration |
429 | rate_limited | Too many requests | Back off and retry |
500 | internal_error | Server error | Retry with backoff |
503 | unavailable | Service temporarily unavailable | Retry with backoff |
Retry strategies
Idempotent retries
Always include an Idempotency-Key header so retries are safe:
JavaScript
async function callGatewayWithRetry(
params: RequestParams,
maxRetries = 3
): Promise<GatewayResponse> {
const idempotencyKey = crypto.randomUUID();
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
const response = await fetch(
`${BASE_URL}/v1/agent-tool-call`,
{
method: "POST",
headers: {
Authorization: `Bearer ${AGENT_ID}:${AGENT_SECRET}`,
"Idempotency-Key": idempotencyKey,
"Content-Type": "application/json",
},
body: JSON.stringify(params),
}
);
if (response.status === 429 || response.status >= 500) {
const delay = Math.pow(2, attempt) * 1000;
await new Promise((r) => setTimeout(r, delay));
continue;
}
return await response.json();
} catch (err) {
if (attempt === maxRetries) throw err;
const delay = Math.pow(2, attempt) * 1000;
await new Promise((r) => setTimeout(r, delay));
}
}
throw new Error("Max retries exceeded");
}Exponential backoff
Use exponential backoff for 429 and 5xx errors:
| Attempt | Delay |
|---|---|
| 1 | 1 second |
| 2 | 2 seconds |
| 3 | 4 seconds |
| 4 | 8 seconds |
The Idempotency-Key ensures that retries don’t create duplicate actions. If a previous request succeeded but the response was lost, the retry returns the original result.
Handling pending approvals
When you receive pending_approval, the agent needs to wait for a human decision:
if (result.decision === "pending_approval") {
// Option 1: Poll for the decision
const approval = await client.pollApproval({
approvalId: result.approvalId!,
timeoutMs: 300_000, // 5 minutes
});
// Option 2: Proceed with a fallback
console.log("Approval pending, queuing for later");
// Option 3: Inform the user
console.log(`Action requires approval: ${result.approvalId}`);
}Timeout handling
Set appropriate timeouts for your agent’s use case:
| Scenario | Recommended timeout |
|---|---|
| Standard gateway call | 30 seconds |
| Approval polling | 5–15 minutes |
| Connector with slow target API | 60 seconds |
If a gateway call times out, always check the receipt before retrying. The action may have been executed even if you didn’t receive the response.
Last updated on