In modern business, data is constantly in motion. A new user signs up, a lead gets updated in your CRM, an invoice is paid. Keeping all your systems synchronized is a critical, yet often complex, challenge. A common scenario is needing to enrich your internal database with data from a third-party service. How can you build this integration in a way that is reliable, reusable, and easy to understand?
Enter the atomic action. On the .do platform, an atomic action is the fundamental building block of automation. It's a self-contained unit of work designed to perform one single task perfectly. Today, we'll walk through how to create a powerful 'fetch-and-update' action that enriches user profiles in your database, demonstrating the core principle of the .do platform: Define. Execute. Repeat.
Think of an atomic action as a super-powered function. It’s the smallest, indivisible unit of work in an agentic workflow. This isn't just about code; it's about encapsulating a complete business capability—like send-invoice, update-crm-record, or, in our case, enrich-user-profile—into a reusable, observable, and composable component.
This "atomic" nature is key. By ensuring each action has a single, well-defined responsibility, you create a foundation for reliable and scalable business automation. Debugging becomes simpler, logic becomes clearer, and your entire system becomes more robust.
Let's get practical. Imagine a new user signs up for your application using only their email. To personalize their experience, you want to enrich their profile with data from a service like Clearbit. Our action.do will handle this entire process: take an email, fetch the data, and update your database.
Here’s the complete code, which we'll break down step-by-step.
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);
First, we define the action itself using do.action.create. This is more than just deploying code; it’s registering a managed component on the .do platform.
The handler is where the magic happens. This async function contains the core logic for your workflow step. It receives the validated inputs and performs the task.
Fetch External Data:
const userData = await clearbit.lookup(inputs.email);
The first operation is an API call to an external service (Clearbit in this pseudo-code) using the provided email.
Update Your Database:
const dbResult = await db.users.update({ email: inputs.email, data: userData });
With the enriched data in hand, the handler then performs a second operation: updating the corresponding user record in your internal database.
Return the Result:
return { success: true, userId: dbResult.id };
Finally, the handler returns an object. This output serves two purposes: it signals that the action completed successfully, and it can pass crucial data (like the updated user's ID) to subsequent steps in a larger workflow.
You might be thinking, "This looks like a serverless function." While similar in that they both execute code, a .do Action is a higher-level abstraction designed for building business logic.
An action.do is a fully managed, versioned, and observable entity within the .do platform. It comes with built-in features that you'd otherwise have to build yourself:
It’s the difference between a single tool and a complete, integrated workshop. Actions are purpose-built to be the lego bricks of reliable Business-as-Code.
Crucially, actions are atomic and do not call other actions. So how do you chain them together? Orchestration is handled by a .workflow.do agent.
Our enrich-user-profile action is just one step. It could be part of a larger new-user-onboarding workflow that looks like this:
This separation of concerns—single tasks in action.do and orchestration in workflow.do—is a core principle for building robust, scalable, and easy-to-maintain agentic systems.
Ready to stop writing brittle integration scripts and start building composable business automation? Dive into the .do platform and define your first atomic action today.