In the world of business automation, complexity is the enemy. As we build increasingly sophisticated agentic workflows—automating everything from lead enrichment to customer invoicing—our codebases can quickly become tangled webs of logic. Scripts become brittle, difficult to debug, and nearly impossible to reuse. What if we could break down this complexity into manageable, reliable, and reusable pieces?
This is the core philosophy behind action.do. It's not just another function; it's The Building Block of Automation. An action.do allows you to encapsulate any single task—from sending an email to running a complex calculation—into an atomic, observable, and composable unit. This is the foundation of reliable Business-as-Code.
Think of an atomic action as the smallest, indivisible unit of work in your automation. It’s a self-contained, reusable function designed to perform one single, specific task perfectly.
Examples of atomic actions could include:
By enforcing this "atomicity," you gain immense benefits in reliability and debugging. If a workflow fails, you know exactly which single unit of work was the source of the problem, rather than hunting through hundreds of lines of interconnected code.
Creating an action on the .do platform is designed to be simple and declarative. You define what the action does, what inputs it expects, and how it handles the logic. The platform takes care of the rest.
Let's look at a practical example. Here’s how you would define an atomic action to enrich a user's profile using Clearbit and update your database.
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);
Let's break this down:
Once defined, this enrich-user-profile action becomes a first-class citizen in your automation toolkit, ready to be executed on its own or composed into a larger workflow.
"Wait," you might ask, "how is this different from a simple serverless function like AWS Lambda?"
While the concept is similar, an action.do is a higher-level abstraction built specifically for agentic workflows. Unlike a generic serverless function, an action.do is a fully managed, stateful entity within the .do ecosystem. This provides several key advantages out-of-the-box:
This approach lets you operate at the speed of business, not the speed of infrastructure.
A core principle of the .do platform is the separation of concerns. Actions are atomic and cannot call other actions.
This is a deliberate and powerful design choice. It forces you to keep your building blocks simple and focused. To orchestrate a sequence of tasks, you use a .workflow.do agent.
This is where the true power of Services-as-Software emerges. You can build a complex business process by simply chaining together your pre-built atomic actions:
If you ever need to change how you send welcome emails, you only update the send-welcome-email action. Every workflow that uses it automatically gets the update without any risk of breaking other parts of the process. This is the key to building robust, maintainable, and scalable business automation.
Q: What is an 'atomic action' on the .do platform?
A: 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.
Q: How is an action.do different from a serverless function?
A: 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.
Q: Can actions call other actions?
A: 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.
Q: What kind of logic can I put inside an action?
A: 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.