In the world of business automation, we dream of seamless, intelligent workflows that run like clockwork. But reality often looks different. An automation to process a new customer order might charge their credit card, but then fail before creating their account, leaving you with a charged customer and no record—a data integrity nightmare. The system is left in an inconsistent state, requiring manual intervention, frustrating customers, and eroding trust.
The root of this fragility often lies in how we structure our workflows. When a single step tries to do too much, it introduces multiple points of failure. If any part of that jumbo-step fails, the entire process is compromised.
The solution is a principle borrowed from database design: atomicity. By breaking down complex processes into their smallest, indivisible components—atomic actions—we can build robust, reliable, and scalable agentic workflows.
In computing, an atomic transaction is an all-or-nothing operation. It either completes successfully in its entirety, or it fails completely, rolling back to its original state as if it never happened.
An atomic action applies this same principle to a workflow step. It is a self-contained, reusable function designed to perform one single, specific task.
Think of it like a LEGO brick. It's a complete, standardized unit. You can't break it in half. Its purpose is clear and singular. You combine these simple, reliable bricks to build incredibly complex structures.
On the .do platform, an atomic action is the fundamental building block of all automation. It encapsulates a single task—like 'send an invoice,' 'update a CRM record,' or 'enrich a user profile'—into a managed, observable unit.
Let's revisit our failed customer onboarding process. A traditional, non-atomic approach might look like a single function called processNewOrder() that does the following:
This seems efficient, but it's a house of cards. What if the email service API (Step 5) is down? The function fails, but not before charging the card, creating a user, and adding them to a list. The system is now in an inconsistent state. Debugging becomes a forensic investigation: Where did it break? What was the state of the data before the failure? How do we clean up the mess without making it worse?
Now, let's architect this process using atomic actions, the way you would on the .do platform. The single, fragile function is broken down into a sequence of distinct, atomic workflow steps:
If send-welcome-email fails now, the situation is completely different. The workflow engine knows exactly which atomic action failed. The preceding steps (charge-card, create-database-user) are guaranteed to have completed successfully. This gives us powerful advantages:
Here’s how simple it is to define a new atomic action on the .do platform, encapsulating business logic into a reusable unit.
import { Do } from '@do-platform/sdk';
// Initialize the .do client with your API key
const-do = new Do(process.env.DO_API_KEY);
// Define a new atomic action to enrich user data
const enrichUserAction = await-do.action.create({
name: 'enrich-user-profile',
description: 'Fetches user data from Clearbit and updates the DB.',
inputs: {
email: 'string',
},
handler: async (inputs) => {
const userData = await clearbit.lookup(inputs.email);
const dbResult = await db.users.update({ email: inputs.email, data: userData });
return { success: true, userId: dbResult.id };
}
});
console.log('Action created:', enrichUserAction.id);
This isn't just a serverless function; it's a fully managed, versioned, and observable component within the .do ecosystem, designed to be the foundation of reliable automation.
The core philosophy is a separation of concerns. action.do units are for execution—perfectly performing a single task. workflow.do agents are for orchestration—sequencing, branching, and managing the flow of these atomic actions. Actions don't call other actions; this prevents the creation of tangled, monolithic dependencies and enforces the principle of atomicity.
By embracing atomic design, you move from building brittle scripts to engineering resilient systems. You ensure data integrity, dramatically simplify debugging, and create a composable library of business capabilities that can be assembled into powerful agentic workflows.
Stop cleaning up after failed automations. Start building on a foundation of reliability.
What is an 'atomic action' on the .do platform?
An atomic action is the smallest, indivisible unit of work in a workflow. It's a self-contained, reusable function that performs a single, specific task, like 'send an invoice' or 'update a CRM record'. This atomicity ensures reliability and simplifies debugging.
How is an action.do different from a serverless function?
While similar, a .do Action is a fully managed, versioned, and observable entity within our platform. It includes built-in input validation, logging, and security, and is designed to be seamlessly composed into larger Agentic Workflows, abstracting away infrastructure concerns.
Can actions call other actions?
No, actions are designed to be atomic. To orchestrate a sequence of actions, you use a .workflow.do agent. This separation of concerns—single tasks in action.do and orchestration in workflow.do—is a core principle for building robust and scalable systems.
What kind of logic can I put inside an action?
An action handler can contain virtually any code: API calls to third-party services, data transformations, database queries, or complex business logic. The key is that the action should focus on successfully completing one well-defined task.