In today's fast-paced digital landscape, automation is no longer a luxury—it's a necessity. We build complex systems to handle everything from customer onboarding to financial reconciliation. But as these systems grow, so does their complexity. Business logic becomes scattered across microservices, serverless functions, and monolithic backends, leading to brittle, hard-to-debug, and difficult-to-maintain code.
What if we could break down this complexity into its fundamental components? What if every single task could be an independent, reusable, and observable building block?
This is the core principle behind action.do: defining atomic units for agentic workflows. It’s time to move towards a more robust paradigm: Business-as-Code.
At its heart, an action.do is the smallest, indivisible unit of work in any automated process. Think of it as a supercharged function that performs a single, specific task.
An atomic action is a self-contained, reusable function that performs one well-defined task, like 'send an invoice,' 'update a CRM record,' or 'enrich user data.'
This concept of atomicity is crucial. By ensuring an action does one thing and does it well, you gain massive benefits in reliability and simplicity. If a multi-step process fails, you know exactly which workflow step was the point of failure, dramatically simplifying debugging and recovery.
Instead of monolithic services, you build a library of composable actions, the foundational layer for reliable business automation.
The best way to understand the power of action.do is to see it in action. Let's say we want to create a reusable task that enriches a new user's profile by looking up their email with a third-party service like Clearbit and then updating our internal database.
Here’s how you would define this as an atomic action on the .do platform:
import { Do } from '@do-platform/sdk';
// Initialize the .do client with your API key
const doClient = new Do(process.env.DO_API_KEY);
// Define a new atomic action to enrich user data
const enrichUserAction = await doClient.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 created, enrich-user-profile becomes a reusable asset in your organization, ready to be executed by any agent or workflow.
You might be thinking, "This looks a lot like a serverless function." While the concept is similar, an action.do is a higher-level abstraction designed specifically for building robust business processes.
Here’s how it’s different:
If actions can't call other actions, how do you build complex business logic? The answer lies in the separation of concerns.
To link enrich-user-profile with send-welcome-email, you don't modify the actions themselves. Instead, you create a workflow agent that executes them in sequence. This makes your system incredibly flexible. Need to add a step to 'assign-support-tier'? Simply update the workflow to call a new action.do—no downstream code changes are required.
This model is the future of Services-as-Software, where complex capabilities are composed from a marketplace of reliable, atomic units. It's the key to building truly scalable and maintainable agentic workflows that can adapt as your business evolves.
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.