In building any modern application, especially the intelligent, agentic workflows of tomorrow, we face a constant battle: managing data securely and efficiently. Every piece of logic, every function, juggles a triad of information: the data provided by the user (Inputs), the sensitive credentials it needs (Secrets), and the environmental information about its execution (Context). Get this wrong, and you're left with brittle, insecure, and unmanageable code.
This is where action.do introduces a paradigm shift. An action.do isn't just a function; it's a well-defined, atomic component designed for flawless execution. The platform's power lies in its deliberate and structured handling of inputs, secrets, and context. By treating each as a distinct and first-class concern, action.do enables you to build robust, scalable, and observable automations.
Let's dive deep into the anatomy of an action and see how this structured approach transforms business logic into a reliable asset.
Think of an action's inputs as its public API contract. It's a strictly-defined schema that declares exactly what data the action needs to perform its single, focused task. This isn't just a suggestion; it's a rule enforced by the platform.
Consider this action.do for processing a payment:
import { Do } from '@do-sdk/core';
// Define an atomic action to process a payment
const processPayment = Do.action('process-payment', {
inputs: {
customerId: 'string',
amount: 'number',
},
handler: async ({ inputs, context }) => {
// ... logic using inputs.customerId and inputs.amount
console.log(`Processing payment of $${inputs.amount} for ${inputs.customerId}`);
// ...
return { success: true, transactionId: `txn_${context.runId}` };
},
});
By defining inputs: { customerId: 'string', amount: 'number' }, you gain several immediate advantages:
The cardinal rule of modern development is never hardcode secrets. API keys, database credentials, and private certificates have no place in your source code. Yet, traditional serverless functions often make it clumsy to manage them, leading to risky workarounds.
action.do solves this with a built-in, secure secret management system.
// Inside your handler
handler: async ({ inputs, context }) => {
// The secret is injected securely by the platform
const stripeApiKey = context.secrets.STRIPE_API_KEY;
// ... connect to the payment provider using the key
console.log('Securely accessed API key.');
// ...
},
This approach provides immense benefits:
If inputs are the "what" and secrets are the "how," context is the "where" and "when." The context object is a rich set of metadata provided by the .do platform about the specific execution run.
This includes crucial information like:
Look again at the return statement from our example:
return { success: true, transactionId: `txn_${context.runId}` };
This simple line is incredibly powerful. By embedding the context.runId into the result, you create a direct, unbreakable link between the external system's transaction txn_... and the internal execution log on the .do platform.
This enables:
By separating these three concerns, action.do elevates a simple piece of logic into a secure, scalable, and manageable business asset.
| Concern | Naive Function | action.do | Advantage |
|---|---|---|---|
| Inputs | Mixed in function body, manual validation | Defined schema, automatic validation | Reliability & Composability |
| Secrets | Hardcoded or in env vars, risky | Injected from secure vault at runtime | Security & Manageability |
| Context | Absent or requires custom instrumentation | Rich object with unique run IDs | Observability & Traceability |
This "Business as Code" philosophy is the key to building the next generation of automation. Actions become predictable, composable building blocks that both humans and AI agents can trust and orchestrate into powerful agentic workflows.
Ready to stop wrestling with data and start building flawless automations? Define your first atomic action on the .do platform today.