In the world of workflow automation, we often focus on the "happy path"—the ideal scenario where every API is available, every payload is perfect, and every action executes flawlessly. But as any seasoned developer knows, reality is far messier. Networks glitch, services have downtime, and inputs are occasionally malformed. In complex agentic workflows, a single, unhandled failure can bring an entire business process to a grinding halt.
What happens when an action fails? Dropping it is not an option, especially when it represents a critical step like processing a payment or creating a user account. This is where a robust strategy for error handling, retries, and failure management becomes not just a feature, but a necessity.
The .do platform is built on the principle of guaranteed execution. By treating every operation as a managed, atomic action, we can build resilient systems that anticipate and gracefully handle failure. Let's dive deep into the mechanisms that make this possible.
Imagine building a simple new user onboarding workflow:
What happens if the email service is temporarily unavailable when you call send-welcome-email? A simple try/catch block in your code might log the error, but the action is lost. The user never gets their welcome email.
You could build your own retry logic—a for loop with a sleep timer. But this is brittle. What if your application crashes or restarts during the sleep interval? The context is lost, and the retry never happens. Building a truly resilient retry system requires state management, background workers, and persistent storage—a significant engineering effort that distracts from your core business logic.
This is the fundamental challenge of building scalable workflow automation: boilerplate error handling is complex, repetitive, and mission-critical.
When you execute an action with action.do, you're not just making a function call; you're handing off the responsibility of execution to a managed platform.
// Hand off the action to the .do platform
const result = await an.action.do('send-email', {
to: `user-usr_12345@example.com`,
templateId: 'welcome-template-v1'
});
This single line is more powerful than it looks. When the .do platform receives this request, it doesn't just run it once. It guarantees its execution according to a pre-defined, configurable policy.
If the send-email action fails due to a temporary issue (like a 503 Service Unavailable error from your email provider), the .do platform doesn't give up. It automatically initiates a retry process using exponential backoff with jitter.
This intelligent retry logic is built-in. Your application code remains clean and focused on the "happy path," while the platform handles the messy reality of transient failures.
But what if an action fails for a permanent reason? Perhaps the templateId is incorrect, or the user's email address is invalid. Retrying indefinitely would be pointless.
After exhausting the configured number of retry attempts, a naive system might finally give up and drop the action. This is where data loss occurs. The .do platform takes a different approach: the Dead-Letter Queue (DLQ).
A Dead-Letter Queue is a safe holding place for actions that have failed all retry attempts. It's the ultimate safety net for your agentic workflows.
When an action lands in the DLQ, it's not just the payload that's saved. The platform captures a complete record of the failure, including:
By combining atomic actions, intelligent retries, and the safety net of a Dead-Letter Queue, action.do transforms potentially fragile automation scripts into robust and auditable business processes.
Let's revisit our onboarding flow:
If the action had failed permanently due to a bad templateId, it would have landed in the DLQ, generated an alert, and allowed your team to diagnose and fix the root cause without losing the record of the task that needed to be done.
This is the power of building on a platform designed for resilience. Stop building boilerplate error-handling logic and start defining your Business-as-Code with the confidence that it will execute, no matter what.