Business automation is often a double-edged sword. While powerful, it can quickly devolve into a tangled web of brittle scripts, monolithic functions, and hard-to-debug processes. What if you could build complex automations from simple, lego-like bricks?
Welcome to the world of atomic actions. On the .do platform, an action.do is the fundamental building block of automation. It's a small, self-contained, and reusable unit of work that performs one single task perfectly. Think of it as encapsulating a single business capability—like "send an invoice" or "enrich user data"—into a durable, observable, and composable component.
This approach is the foundation of reliable Business-as-Code. In this step-by-step tutorial, we'll show you how to define, create, and register your very first action.do in under five minutes using the .do SDK.
An atomic action is the smallest, indivisible unit of work in a workflow. It's designed to do one thing and do it well. This "atomicity" is its superpower.
Unlike a standard serverless function, a .do Action is a fully managed, versioned, and observable entity. It comes with input validation, logging, and security out-of-the-box, letting you focus on the business logic, not the boilerplate infrastructure.
We're going to create a simple but practical action: send-welcome-message. This action will take a new user's name and email, generate a personalized message, and return a success status.
Open your terminal and run the following commands to create a new project folder, initialize a Node.js project, and install the .do SDK.
# Create and enter the new project directory
mkdir do-action-tutorial && cd do-action-tutorial
# Initialize a new Node.js project
npm init -y
# Install the .do SDK
npm install @do-platform/sdk
Next, create a file named index.js in this directory. This is where we'll define our action.
Finally, set your API key as an environment variable. This is the most secure way to handle credentials.
# Replace 'your_api_key_here' with your actual key from the .do platform
export DO_API_KEY='your_api_key_here'
Now for the fun part. Open your index.js file and add the following code. Let's break down what each part does.
// index.js
import { Do } from '@do-platform/sdk';
const run = async () => {
// 1. Initialize the .do client with your API key from the environment
const doClient = new Do(process.env.DO_API_KEY);
console.log('Client initialized. Creating action...');
try {
// 2. Define and create the new atomic action
const sendWelcomeAction = await doClient.action.create({
name: 'send-welcome-message',
description: 'Generates a personalized welcome message for a new user.',
// 3. Define the inputs (the contract for this action)
inputs: {
name: 'string',
email: 'string',
},
// 4. Define the handler (the code that executes)
handler: async (inputs) => {
// The logic for your action lives here.
// In a real action, you might call an email API like SendGrid.
const message = `Welcome, ${inputs.name}! A confirmation has been sent to ${inputs.email}.`;
console.log(`[ACTION LOG]: ${message}`);
// 5. Return a structured result
return { success: true, messageSent: message };
}
});
console.log('✅ Action created successfully!');
console.log('Action ID:', sendWelcomeAction.id);
console.log('You can now use this action in any of your agentic workflows!');
} catch (error) {
console.error('❌ Failed to create action:', error);
}
};
run();
Code Breakdown:
You're all set! Save your index.js file and run it from your terminal.
node index.js
You should see an output similar to this:
Client initialized. Creating action...
✅ Action created successfully!
Action ID: act_a1b2c3d4e5f6
You can now use this action in any of your agentic workflows!
Congratulations! You have just defined and registered a versioned, reusable, and atomic action on the .do platform. It's now a permanent, composable component in your automation toolkit, ready to be called by name (send-welcome-message) from any agentic workflow.
You've created the building block. The true power of the .do platform is unlocked when you start composing these actions into larger agentic workflows.
Actions are designed to be atomic and cannot call other actions directly. This is a deliberate design choice that enforces clean architecture. Orchestration is handled by a .workflow.do agent, which can execute a series of actions, handle conditional logic, and manage the flow of data between them.
Imagine a workflow that:
Each step is a simple, reliable action.do. Together, they form a robust and scalable business process.
Ready to move beyond simple scripts? Start building your automation on .do today.