As developers, we've all been there. A complex workflow fails, and our first instinct is to litter our code with console.log('here 1'), console.log(variable), console.log('did it get here?'). It's a trusty, battle-hardened technique, but in the world of distributed systems, microservices, and scalable automation, it’s like navigating a modern city with a crumpled, hand-drawn map. You might find your way eventually, but it’s inefficient, frustrating, and you have no real sense of the bigger picture.
When you're building robust, agentic workflows, you need more than just logs; you need observability. You need to understand not just if a task failed, but why, where, and what its impact was on the entire process.
This is where action.do transforms from a simple task executor into a powerful diagnostics tool. It's designed to provide full observability out-of-the-box, moving you from reactive debugging to proactive monitoring.
In a modern automation stack, a single business process—like onboarding a new user—might involve half a dozen services: authenticating, creating a database record, sending a welcome email, provisioning resources, and adding them to a CRM.
If the welcome email fails to send, console.log in your email service gives you a tiny piece of the puzzle. You're left asking:
Scouring through disparate log files from multiple services to piece together this story is a time-consuming nightmare. action.do was built to solve this.
When you execute a task with action.do, you're not just calling a function; you're invoking a managed, observable service. Every execution becomes a transparent, analyzable event on the .do platform. This provides three pillars of observability: rich logging, end-to-end tracing, and performance monitoring.
Forget grep-ing through plain text files. Every action.do execution is automatically captured as a structured log with critical context.
Let's look at our simple sendWelcomeEmail example:
import { Do } from '@do-sdk/core';
// Initialize the .do client with your API key
const doClient = new Do({ apiKey: 'YOUR_API_KEY' });
// Execute a single, atomic action like sending an email
async function sendWelcomeEmail(to: string, name: string) {
try {
const result = await doClient.action('email.send').run({
to,
subject: `Welcome to our platform, ${name}! Robustly.`,
body: `Hi ${name},\n\nWe're thrilled to have you join us.`
});
console.log('Action Succeeded:', result.id); // Every run has a unique ID!
return result;
} catch (error) {
console.error('Action Failed:', error);
}
}
When this action runs, the .do platform doesn't just see a function call. It records an event that looks something like this:
{
"executionId": "exec_1a2b3c4d5e",
"actionName": "email.send",
"status": "succeeded",
"timestamp": "2023-10-27T10:00:05Z",
"durationMs": 152,
"input": {
"to": "new.user@example.com",
"subject": "Welcome to our platform, Alex! Robustly.",
"body": "Hi Alex,\n\nWe're thrilled to have you join us."
},
"output": {
"messageId": "msg_xyz789"
},
"retries": 0
}
Instantly, you have a queryable, centralized record of exactly what happened. You can search for all executions of email.send, filter for failures, or find the exact action run that corresponds to new.user@example.com. This is the power of treating your business logic as Business-as-Code—every step is an accountable, auditable event.
The real magic happens when you compose multiple atomic actions. The .do platform automatically traces the execution flow, linking individual actions into a complete workflow graph.
Imagine an onboardUser workflow that calls three actions in sequence:
If the crm.addContact action fails, you don't just see an isolated error. The platform provides a trace that visualizes the entire journey:
Workflow: onboardUser (Trace ID: trace_abc123)
|
+-- 1. action: db.createUser (succeeded)
| - Duration: 55ms
| - Input: { email: 'alex@example.com', name: 'Alex' }
|
+-- 2. action: email.sendWelcome (succeeded)
| - Duration: 120ms
| - Input: { to: 'alex@example.com', name: 'Alex' }
|
+-- 3. action: crm.addContact (failed) <-- PROBLEM IDENTIFIED
- Duration: 250ms
- Input: { email: 'alex@example.com', name: 'Alex' }
- Error: "API Key Invalid"
This trace tells you the full story instantly. You know the exact point of failure, the data that caused it, and which preceding steps succeeded. This is invaluable for debugging complex, multi-step processes and pinpointing bottlenecks.
Debugging isn't just about fixing what's broken; it's about understanding system health. Because action.do captures structured data for every run, it becomes a goldmine for monitoring.
On the .do platform, you can build dashboards and alerts based on aggregated action data to answer critical questions:
This proactive approach allows you to detect systemic issues, performance degradation, and unusual activity long before they become critical incidents for your users. The built-in retry logic and error handling further ensure that your agentic workflows are resilient by default.
Shifting your mindset from function calls to managed action.do executions is a leap in building reliable systems. You gain an entire layer of logging, tracing, and monitoring without writing any extra boilerplate code.
Stop hunting for clues in scattered log files. Start building with action.do and let observability be an integral part of your development lifecycle.
Ready to gain full visibility into your automations? Explore the .do platform and start executing your atomic actions with precision and clarity.