In the world of software development and operations, automation is king. Yet, as our automated processes grow, they often become tangled webs of complex scripts—brittle, hard to debug, and nearly impossible to reuse. What if we could break down these monolithic processes into their fundamental, indivisible parts?
This is the core philosophy behind action.do: to provide The Building Block of Automation. We empower you to encapsulate any single, repeatable task into a powerful, API-callable atomic action. This approach allows you to simplify complexity and build robust, scalable agentic workflows from the ground up.
Let's dive in and build your very first action.
Before we write any code, let's clarify the central concept. Think of an atomic action as the smallest, indivisible unit of work in any process. It's a single, well-defined task that has only two possible outcomes: it completes successfully, or it fails entirely. There are no partial states.
This atomicity is crucial. It guarantees that your workflows are predictable and reliable. A task is either done or not done, eliminating the ambiguity that plagues complex scripts.
Imagine you need to send a welcome email to new users who sign up for your service. This is a perfect candidate for an action.do. Instead of burying the email logic inside a larger "sign-up" function, we can define it as a standalone, reusable action.
Here’s how you would define a send-welcome-email action using our SDK:
import { action } from '@do-sdk/core';
export const sendWelcomeEmail = action({
name: 'send-welcome-email',
description: 'Sends a welcome email to a new user.',
inputs: {
to: { type: 'string', required: true },
name: { type: 'string', required: true }
},
handler: async ({ inputs, context }) => {
const { to, name } = inputs;
// Email sending logic would go here (e.g., using SendGrid, Nodemailer)
console.log(`Sending welcome email to ${name} at ${to}`);
return { success: true, messageId: 'xyz-123' };
},
});
This might look like a simple object definition, but it’s packed with power. Let's break it down.
name: 'send-welcome-email'
This is the unique, human-readable identifier for your action. It's how you'll call it via an API or reference it in a larger workflow. It’s business-as-code in its purest form.
description: '...'
Self-documentation is built-in. This description makes your action discoverable and understandable to other developers—or even AI agents—in your system.
inputs: { ... }
This is the action's contract. It defines exactly what data the action needs to run. Our platform uses this schema to automatically validate incoming requests. Here, we've declared that both a to email address and a name are required strings. No more manual if (!email) checks.
handler: async ({ inputs, context }) => { ... }
This is where the magic happens. The handler is an async function that contains your business logic.
Simple. Atomic. Powerful.
You’ve now defined an action. But its true power lies in its reusability. This single send-welcome-email action can now be invoked from anywhere, without ever rewriting the email logic:
By building with atomic actions, you are creating a library of capabilities, not just writing one-off scripts. You are embracing the DRY (Don't Repeat Yourself) principle for your entire business logic, leading to faster development, easier maintenance, and incredibly robust workflow automation.
Q: What is an 'atomic action' in the context of .do?
A: An atomic action is the smallest, indivisible unit of work in a workflow. It represents a single, well-defined task, like 'send an email' or 'create a user record', ensuring that it either completes successfully or fails entirely, without partial states.
Q: How is an action.do different from a full workflow.do?
A: An action.do represents a single task. A workflow.do is a collection of one or more actions orchestrated to achieve a larger business process. Actions are the building blocks; workflows are the blueprints that connect them.
Q: Can I reuse actions across different workflows?
A: Absolutely. Actions are designed to be modular and reusable. You can define an action once, like 'generate-report', and call it from any number of different workflows, promoting DRY (Don't Repeat Yourself) principles in your automations.
Q: What kind of logic can I put inside an action's handler?
A: The handler can contain any Node.js/TypeScript logic. This includes making API calls to third-party services, performing data transformations, interacting with databases, or executing any custom business logic required to complete the task.