Best Practices
Guidelines for building effective human-in-the-loop AI agents with RelayRail.
Approval Request Design
Be Specific and Actionable
Write approval messages that clearly explain what action will be taken and why approval is needed.
❌ Bad
"Proceed?"
✓ Good
"Deploy v2.3.1 to production? This will affect 1,200 active users. Changes: bug fixes for auth flow."
Include Context
Provide enough information for users to make informed decisions without needing additional research.
request_approval({
message: `Delete 47 unused feature flags?
Flags older than 90 days:
- enable_legacy_checkout (created: 2024-03-15)
- beta_recommendations (created: 2024-02-28)
- [+45 more]
This action cannot be undone.`,
type: "yes_no"
})Channel Selection
Use SMS for Urgent Requests
SMS has higher open rates and faster response times. Reserve it for time-sensitive approvals.
| Scenario | Recommended Channel |
|---|---|
| Production deployment | SMS |
| Database migration | SMS |
| Weekly report summary | |
| Non-urgent code review | |
| Error alert (high severity) | SMS |
Let Users Choose
When urgency isn't critical, omit the channel parameter to let users receive messages via their preferred method.
Timeout Handling
Always plan for cases where users don't respond. Set appropriate timeouts and define fallback behavior.
// Set a 30-minute timeout for production deploys
const result = await request_approval({
message: "Deploy to production?",
type: "yes_no",
timeout_minutes: 30
});
if (result.status === "expired") {
// Notify and abort
await send_notification({
message: "Deployment cancelled: approval timed out after 30 minutes."
});
return;
}
if (result.approved) {
// Proceed with deployment
}Tip: For critical operations, consider sending a reminder notification before the timeout expires.
Notification Frequency
Avoid Notification Fatigue
Too many notifications lead to users ignoring them. Batch updates when possible.
❌ Bad
Send a notification for every file processed in a batch of 100 files.
✓ Good
Send one notification when the batch completes: "Processed 100 files. 98 succeeded, 2 failed."
Reserve High Priority
Use priority: "high" sparingly—only for errors or truly urgent situations.
Security Considerations
- 1.Never expose API keys in client code
Keep your RelayRail API key server-side only.
- 2.Rotate keys periodically
Generate new API keys every 90 days or after team changes.
- 3.Use one agent per function
Create separate agents for different purposes (deploy-agent, cleanup-agent) rather than one shared agent.
- 4.Avoid sensitive data in messages
Don't include passwords, API keys, or PII in notification messages.
Error Handling
Always handle potential failures gracefully:
const result = await request_approval({
message: "Proceed with migration?",
type: "yes_no"
});
// Check for errors
if (!result.success) {
console.error("RelayRail error:", result.error);
// Implement fallback behavior
return;
}
// Check for explicit denial
if (!result.approved) {
console.log("User denied the request");
return;
}
// Proceed with approved actionTesting
- -Test in development first — Verify your approval flows work before deploying to production
- -Use test phone numbers — Avoid sending SMS to real users during development
- -Simulate timeouts — Ensure your agent handles expired approvals correctly
- -Test denial paths — Make sure "No" responses trigger appropriate behavior
Summary Checklist
- ☐Approval messages are specific and include context
- ☐SMS reserved for urgent requests only
- ☐Timeouts are set with fallback behavior defined
- ☐Notifications are batched to avoid fatigue
- ☐API keys are stored securely server-side
- ☐Error handling covers all failure modes
- ☐Flows tested in development before production