In modern software development, we live and breathe APIs. They are the glue that connects our services, powers our products, and enables our business processes. But let's be honest: managing API integrations can be a messy affair. Scattered credentials, inconsistent error handling, and duplicated boilerplate code across projects make our systems brittle and hard to scale.
What if we could treat every API interaction—every single business operation—not as a one-off piece of code, but as a standardized, reusable, and powerful building block?
This is the core philosophy behind the .do platform. We believe in the Atomic Unit of Work. By transforming any API call into a self-contained Atomic Action, you can unlock unprecedented levels of automation, reusability, and scalability for your agentic workflows.
This post will guide you through the art of wrapping any API—whether it's a third-party service like Slack or your own internal microservice—into a clean, robust, and programmable Atomic Action.
Before we dive into the code, let's understand why thinking "atomically" is a game-changer. An API call buried deep within your application code is just that—a line of code. An Atomic Action, on the other hand, is a first-class citizen in your system.
An Atomic Action is:
By adopting this approach, you're not just writing integratiions; you're building a library of composable business capabilities—true "business as code."
Let's get practical. A common requirement is to send a notification to a Slack channel when a significant event occurs. Instead of calling the Slack API directly from various points in our codebase, we'll wrap it in an Atomic Action on the .do platform.
Here’s how you define a send-slack-message action using the .do TypeScript SDK.
import { Action } from '@do-co/agent';
import { WebClient } from '@slack/web-api';
// Assume SLACK_BOT_TOKEN is securely managed by the .do platform's environment
const slackClient = new WebClient(process.env.SLACK_BOT_TOKEN);
// Define a new atomic action to send a Slack message
const sendSlackMessage = new Action('send-slack-message', {
title: 'Send Slack Message',
description: 'Posts a message to a specified Slack channel.',
// 1. Define the "contract" for this action's inputs
input: {
channel: {
type: 'string',
required: true,
description: 'The Slack channel ID or name (e.g., #general)'
},
text: {
type: 'string',
required: true,
description: 'The message content to post.'
},
},
// 2. Implement the core logic in the handler
async handler({ channel, text }) {
try {
console.log(`Sending message to Slack channel ${channel}...`);
const result = await slackClient.chat.postMessage({ channel, text });
if (!result.ok) {
throw new Error(`Slack API Error: ${result.error}`);
}
console.log(`Message sent successfully. Timestamp: ${result.ts}`);
// 3. Return a standardized, predictable output
return {
success: true,
messageTimestamp: result.ts
};
} catch (error) {
console.error('Failed to send Slack message:', error);
return { success: false, error: error.message };
}
},
});
// Example of how to execute the action
const result = await sendSlackMessage.run({
channel: '#dev-alerts',
text: 'New user signed up: Alex (new.user@example.com)',
});
console.log(result);
Let's break down what makes this so powerful:
You've just turned a messy, ad-hoc integration into a robust, reusable, and secure business capability.
The true power of Atomic Actions is realized when you compose them into Agentic Workflows. An individual action is a building block; a workflow is the complete structure.
Consider a "New Customer Onboarding" workflow. It's no longer a monolithic script but an orchestration of discrete, atomic actions:
Because every action is a standardized unit, an orchestrator (or an AI agent) can be given a high-level goal like "Onboard new customer 'Alex'" and intelligently discover, sequence, and execute this chain of actions, passing the output of one as the input to the next. This is the foundation of powerful, adaptive automation.
Execute. Automate. Scale.
By wrapping your APIs into Atomic Actions, you are future-proofing your business logic. You're creating a decoupled, highly maintainable ecosystem of capabilities that can be reused across countless automations and agentic workflows. It’s time to stop writing integration code and start building your library of programmable business blocks.
Ready to transform your APIs into powerful building blocks? Get started with the .do platform today and build your first Atomic Action.
Q: What is an atomic action in the .do platform?
A: An atomic action is the smallest, indivisible unit of work in a workflow. It's a self-contained, executable task—like sending an email, querying a database, or calling an external API as we showed above. Each action is designed to do one thing well.
Q: How are actions different from workflows?
A: Actions are the individual steps, while workflows are the orchestration of multiple actions in a specific sequence or logic. You build complex workflows by composing simple, reusable actions together.
Q: Can I create my own custom actions?
A: Absolutely. The .do SDK allows you to define custom actions with specific inputs, outputs, and business logic. This transforms your unique business operations into reusable, programmable building blocks for any workflow.