In the world of business automation, complexity is the enemy of reliability. As we build increasingly sophisticated systems—automating everything from customer onboarding to financial reporting—our workflows can become monolithic, tangled scripts. They're difficult to build, a nightmare to debug, and nearly impossible to reuse. What if we could build complex automation not with giant scripts, but with simple, predictable, and composable building blocks?
Enter action.do, the fundamental building block of modern automation on the .do platform. An action is an atomic unit of work, designed to do one thing and do it well. It's the foundation of reliable, scalable Business-as-Code.
Think of action.do as a supercharged LEGO brick for your business logic. Each action is a self-contained, reusable function that performs a single, specific task.
This principle of atomicity is what makes the system so powerful. By encapsulating a single task—from sending an email to running a complex calculation—into a reusable, observable, and composable Action, you create a library of reliable capabilities. The mantra is simple: Define. Execute. Repeat.
When a workflow fails, you don't have to debug a 500-line script; you can instantly pinpoint which specific action failed, inspect its inputs and logs, and fix it. This modularity transforms how you build and maintain agentic workflows.
Defining an action is incredibly straightforward. You specify its name, describe what it does, define its inputs, and provide a handler function containing the core logic.
Here’s how you would define an action.do to enrich a user 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) => {
// 1. Call a third-party API
const userData = await clearbit.lookup(inputs.email);
// 2. Update your internal database
const dbResult = await db.users.update({ email: inputs.email, data: userData });
// 3. Return a structured result
return { success: true, userId: dbResult.id };
}
});
console.log('Action created:', enrichUserAction.id);
In this example, two distinct steps (calling an external API and writing to a database) are encapsulated into one single atomic action: enrich-user-profile. This action can now be called from any workflow, by any agent, with the simple guarantee that it will perform its designated task.
You might be thinking, "This looks a lot like a serverless function." While there are similarities, an action.do is much more. It's a fully managed entity within the .do ecosystem, designed specifically for composing agentic workflows.
Unlike a standard serverless function, an action.do comes with:
This approach treats your business capabilities as Services-as-Software, abstracting away infrastructure concerns so you can focus purely on logic.
A crucial design principle of the .do platform is the separation of concerns. Actions perform tasks; workflows orchestrate them.
Therefore, actions cannot call other actions.
This might seem limiting at first, but it's a core feature that ensures robustness. To orchestrate a sequence of actions (e.g., enrich-user-profile -> add-to-onboarding-sequence -> send-welcome-email), you use a .workflow.do agent. The workflow defines the flow, handles the logic between steps, and passes the output of one action as the input to the next.
This keeps your actions pure, independent, and truly atomic, preventing complex, nested dependencies that are prone to breaking.
By breaking down complex processes into simple, atomic action.do units, you build a more reliable, scalable, and maintainable automation engine for your business. You stop writing disposable scripts and start building a permanent library of business capabilities.
Ready to build your first atomic action? Dive into the .do platform and discover a better way to automate.
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.