Back to Blog
Technical

Workflow Automation Should Be Code Managed by Agents, Not Agents

Introducing Decisional: One Manager Agent, Many Automation Agents, with each automation agent maintaining its own code.

Dhruv Tandon
Apr 16, 2026
12 min read

Decisional is an easy way to build, test, and maintain automation agents for business process automation.

Decisional runs on a two-agent architecture:

01

Manager Agent

Keeps the fleet healthy

Helps you run the fleet of automation agents: it checks in on their runs, loops you in when something fails, and keeps the automations healthy over time.

02

Automation Agent

Builds and tests the workflow

A coding agent that builds and tests a workflow from a user-defined goal. It organizes each automation as a readable workflow graph of code and agent nodes.

The user talks to Dex, the manager agent. Dex routes work to a fleet of automation agents, each of which owns a single workflow.

The user talks to Dex. Dex spawns automation agents, each owning one workflow.

Zooming from an automation agent into its workflow graph, and from a node into the underlying Python code.

An automation agent owns a workflow graph. A workflow graph is made of nodes. A node is code.

A quick demo: talking to Dex on Slack to run a procurement automation agent, with the workflow graph streaming alongside.

Business Workflows Shouldn't Be Run by LLMs in a Loop (Agents)

We didn't start here. About six months ago we built a RAG agent for data-entry workflows in finance. Accuracy was the constant pain, and the longer we worked on it the more we realized just an agent (an LLM in a loop) wasn't solving the actual problem. A real business workflow was never just a tool-using loop. It was some data entry, some ETL, some document ingestion, an email at the end, and all of it held together by deterministic execution that the agent was bad at. "Middle-to-middle" automation, where the agent starts from a prompt and lands somewhere that still needs a human to finish the job, was never going to get anyone to 100%.

So we started working backwards. We picked a business with a genuinely complex workflow and filled in the gaps piece by piece. They needed us to read a 10,000-row Excel. We tried doing it with an agent and concluded that was dumb, so we wrote Python. They needed a document generated from the extracted data. More Python. Then an email from the document. Same. At the end of the run they needed a nicely formatted Excel back, with rows grouped and judgment calls highlighted for a reviewer. That one resisted pure Python because the formatting choices required reasoning, so we built it as an agent node: a node inside the workflow graph that runs an LLM with its own model and tools, reads the files populated upstream, and writes the Excel out. The rest of the workflow treated it like any other node. When we hit rate limits from a third-party API, we taught the automation agent to read its own run logs and patch around them. By the time we had twenty agents running different corners of the workflow, keeping track of them was its own job, so we built a manager agent that sits on Slack and talks to us about all of them.

For automations a team maintains outside its core codebase, and for businesses that don't maintain a codebase at all, every path to adopting AI today forces a bad tradeoff.

The first path is no-code and low-code tooling: n8n, Make. You open a canvas, drag nodes around, and wire them together by hand. That works until the workflow gets non-trivial. The people best equipped to maintain it end up being the engineers you were trying not to need.

The second path is coding agents: Claude Code, Codex, Cursor. You describe the workflow in English and an agent writes the code. For someone not familiar with code, the output is hard to maintain, hard to debug, and hard to keep running.

The third path is newer: a coding agent with a file system, persistent memory, and access to your tools: Perplexity Computer, OpenClaw. These can be quite capable on one-off work. They are also unreliable at runtime and don't let you control the context management, latency, or cost for any specific task, which makes the ROI equation hard to manage unless someone else is subsidizing your tokens.

Decisional's bet is that there is a better tradeoff available.

1. Code Managed by AI, Not Just AI

When you run agents for business processes, you want to have control over the following:

  • Reliability: agents are non-deterministic by nature; the same input can produce different behavior day to day.
  • Latency: every step waits on a round-trip to a model API, even when the work is trivial string manipulation.
  • Cost: every step pays the price of the most expensive model in the loop, because there is only one model in the loop.
  • Context management: as a run accumulates tokens, the model's attention to earlier decisions degrades (a failure mode sometimes called context rot), and it starts forgetting state, repeating itself, or making inconsistent choices.
  • Reproducibility: a run that failed yesterday may not fail the same way today, so debugging becomes guesswork and audit becomes impossible.

You want all five. You also want intelligence on the specific steps that actually need it, and only where the cost of an LLM call earns its keep. The question is how to get both: deterministic code for the bulk of the work, intelligence in the places where intelligence matters.

Underneath every workflow, the unit of execution is Python code. Each node in a workflow is a short, self-contained Python function. The agent writes that code once, tests it, and then the platform runs it deterministically from then on.

You can review the code if you like, but you can manage without it. The workflow graph is the review surface day-to-day. You describe the change you want in English, Dex proposes a diff, and the automation agent writes or updates the Python that runs underneath. Code is visible on every node for the engineers who want it, and invisible to everyone else.

Here is what a real node looks like. The Parse Request task from the procurement workflow shown in the demo above. It receives a webhook payload, extracts procurement fields, and mints a request ID:

1import random
2from datetime import datetime
3
4def execute_parse_request(row, settings):
5    """Extract procurement request fields from webhook and generate request ID"""
6    payload = row.get_field("trigger_webhook_payload", {})
7
8    vendor_name = payload.get("vendor_name", "Not provided")
9    product_service = payload.get("product_service", "Not provided")
10    estimated_cost = payload.get("estimated_cost", "Not provided")
11    requester_email = payload.get("requester_email", "Not provided")
12    department = payload.get("department", "Not provided")
13    urgency = payload.get("urgency", "medium")
14    business_justification = payload.get("business_justification", "Not provided")
15
16    date_str = datetime.now().strftime("%Y%m%d")
17    rand_suffix = str(random.randint(1000, 9999))
18    request_id = f"PROC-{date_str}-{rand_suffix}"
19
20    return {
21        "request_id": request_id,
22        "date_submitted": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
23        "vendor_name": vendor_name,
24        "product_service": product_service,
25        "estimated_cost": estimated_cost,
26        "requester_email": requester_email,
27        "department": department,
28        "urgency": urgency,
29        "business_justification": business_justification,
30    }

That is the whole node. It's a Python function that reads fields from the current row (the data being processed, one invoice or one lead at a time) and returns new fields as a dict. The scheduler merges those new fields back into the row so the next node downstream can read them. No framework boilerplate, no hidden state.

Agent nodes run in the workflow graph with live logs streaming onto each node. The code is still there, but the user never has to open it.

Because every node is a discrete unit, the model behind each agent node is a per-node choice: Haiku for classification, Sonnet for most work, Opus for the steps that genuinely need the reasoning. The operator picks the policy and watches the effect on run cost and latency the next time the workflow executes.

2. The Workflow Graph Is What Humans Review

The artifact the user reviews is the workflow graph shown above. Every workflow in Decisional is a directed acyclic graph. Nodes are typed: task (read-only), action (writes to the outside world), decider (branches based on state), gate (waits for human approval). Edges carry conditions and fan-out metadata. Code lives inside the nodes.

This isn't a new shape. The BPMN standard has used workflow graphs as the review surface for business processes for two decades, which says something about the form.

A classic BPMN 2.0 diagram in a traditional process modeler: activities, events, gateways, and swimlanes describing a claims-style business process.

A BPMN 2.0 diagram in a classic modeler: tasks, events, gateways, and swimlanes.

The reason BPMN survived is that the workflow graph is the right level of abstraction for a non-technical operator to reason about a process. You can print one out. You can highlight the step that failed last night. You can explain it to a new hire. You can hand it to compliance.

What BPMN couldn't do is execute itself. The diagram was always a spec. The actual execution lived in a separate world of Java classes, RPA scripts, or manually operated n8n-style tools.

Decisional's workflow graph is both. It is the diagram you review and the thing that runs. When Dex makes a change to a workflow (adds a node, adjusts a branch, inserts a gate), the change is visible on the workflow graph before it runs. When a workflow fails, the failure is pinned to a node on the workflow graph. The diagram and the code share identity.

Because the workflow graph is also the runtime surface, it shows the real-time status of every run as it progresses: which nodes have completed, which are in flight, which have failed, and what each one produced. You don't have to open a separate logs viewer to debug; the workflow graph is the logs viewer.

Because an agent writes the node code, the workflow graph can carry primitives that would be painful to hand-wire on a no-code canvas. Fan-out is a core one: a single node spawns parallel executions (one per row of input), and the graph collects the results when they converge. You describe it to Dex in English ("run the next three steps for every invoice in the sheet"); the graph executes it deterministically at runtime, with the shimmer below showing each parallel branch live.

Fan-out in action: consecutive per row nodes running in parallel, with a shimmer sweep showing live progress on the workflow graph.

Every run shares a file system that all nodes can read and write. This is what lets an agent node live inside the workflow graph as a peer to the code nodes. An agent node runs its own harness (its own model, tools, and context window) and receives the files populated upstream, then writes its own outputs for the nodes downstream to pick up. The workflow graph handles the handoff.

The outputs viewer: every node's files are there to inspect, side-by-side with the workflow graph.

3. One Manager, Many Automation Agents

A single agent doing everything does not scale. One agent running a long workflow accumulates context, forgets earlier decisions, and gets more expensive on every turn.

Dex, the manager agent, sitting in front of a fleet of automation agents, each of which owns one workflow loop.

Dex is the manager. Each cell is an automation agent paired with the workflow it owns. Dex writes code into one automation agent at a time and reports failures back to the user.

Decisional takes a two-agent approach. There is one manager agent (we call it Dex) and a fleet of automation agents. Dex is who the user talks to. Its job is to understand the user's intent, spawn the right automation agent, and route between them.

Each automation agent owns exactly one workflow. It knows that workflow intimately: the nodes, the integrations it calls, the failure history, the prompts inside any agent nodes, and the cost profile. It does not know about any other workflow. That isolation is what lets the system scale horizontally: adding a new workflow does not bloat the context of any existing one.

Automation agents are not long-lived chat sessions. They are spawned with a narrow task (write this node, investigate this failure, improve this prompt), given the relevant slice of the workflow graph, and then they return. State lives in the workflow graph and in the row-level workspace, not in the agent's head.

What is long-lived is the agent's build history. Each automation agent has a set of threads, one per meaningful episode of building, modifying, or fixing it. If you've used a coding agent like Claude Code, Codex, or Cursor on a single project over weeks, this shape will feel familiar. Opening a thread picks up where the last one left off: the current workflow graph, the pending changes, the outstanding failures. The agent doesn't re-derive context from scratch, and neither do you.

Every automation agent moves through a predictable lifecycle. You see the current stage as a status pill at the top of its manager: Draft when Dex first spawns it, Tested once the workflow graph has built, connected its integrations, and run end-to-end with no failures, Live when it's running on a schedule or trigger, and Paused when you flip the switch. The agent cannot move to Live without passing through Tested, which keeps untested code out of production. Versions are immutable once published: editing a Live version forks a new Draft (copy-on-write), and that Draft has to pass through Tested again before it can replace the Live one. Rolling back is just pointing the agent at an earlier published version. There is no such thing as an untested production version to roll back to.

The automation agent state machine. Every published version earns its Live badge by passing through Tested; every edit after Live forks a new Draft via copy-on-write.

Dex is close in spirit to OpenClaw: an LLM running tools in a loop to achieve a goal, with a persistent file system and durable memory stacked on top. Dex's tools are a CLI for operations on the Decisional platform: spawn an automation agent, inspect a run, patch a node, approve a gate. Because the platform is driven by that CLI, any harness that fits this definition (Claude Code, Codex, Cursor, or a local agent loop) can drive Decisional the same way Dex does. Dex is the default surface; the CLI is the primitive.

4. Empowering the Agent Operator

Every automation agent on Decisional has its own three-panel manager in the app. It's the surface an operator uses to run, review, and improve an automation agent without opening five tabs or correlating logs across systems.

Left panel: the workspace. Instructions, the workflow graph, outputs, recent runs, files. Everything the agent has produced, read, or references is one click away.

Middle panel: the active view. Default is the agent instructions, a plain-English description of what the agent does and the tools it uses. Switch to the workflow graph and you see the live execution surface. Switch to runs and you see the dashboard of totals, failure counts, and every individual run clickable into its graph. Switch to outputs and you see the files the agent has written.

Right panel: a thread with the automation agent itself. Same shape as a Cursor or Claude Code project thread, scoped to one agent with its workflow graph, run history, and failure bundles already loaded. Ask "why did last night's run fail?" and the agent has the context at hand. Dex lives on Slack and in the global assistant for cross-agent routing; the right panel is where you do work inside one agent.

The three-panel agent manager: workspace on the left, active view in the middle, a thread with the automation agent on the right.

That shape is deliberate. One agent, one surface. When a failure happens, the automation agent itself first classifies it. Config errors, third-party API errors, execution errors, builder errors, and platform errors are all technical: the agent writes a patch and retries the run on its own. Business logic errors are different. If the output is wrong because a rule was ambiguous or because the business has changed, no amount of retry logic will help, so the automation agent surfaces the failure to Dex, the manager agent, which brings it to the user on Slack (or in the global assistant) with an interpretation to confirm. That split is what keeps auto-recovery from drifting into silent wrong answers.

Failure classification: technical errors are auto-fixed; business logic errors loop in the user.

Every run of every workflow lands on a runs dashboard for the agent, with status, duration, started-at, and a direct link into the workflow graph of the failing run. The automation agent reads the same dashboard you do, which is how it spots a pattern (three runs failed this morning, all on the same step, all with the same 429) and proposes a patch before you've opened the tab.

Agent runs dashboard showing total runs, active runs, completed runs, failed runs, and a time-series graph of run activity

The runs dashboard for a single agent: totals, failure counts, a time-series of activity, and every individual run clickable into its workflow graph.

Maintaining a workflow is a chat, not a click-fest. Describe the change; the automation agent modifies the workflow graph.

The user sees the improvement in the workflow graph as "v4 of the Outreach → CRM workflow, fixed the phone-number normalization on step 3, auto-retries on 429 now", and either approves or rolls back. The muscle memory of "open the no-code tool and re-wire" is replaced with "review the diff."

This is the part of the design that gets harder over time, not easier. We expect workflows on Decisional to get better with age. A week-old workflow has fewer observed edge cases handled than a six-month-old one. The workflow graph accumulates coverage the way a well-maintained codebase does.

A live rebuild indicator shows when the automation agent is patching the workflow, so you always know what's current.

5. Typed Nodes and Gates

A workflow on Decisional is a DAG of four node types:

  • Task: read-only operations. Fetch data, extract fields, parse a document.
  • Action: writes to the outside world. Send an email, charge a card, update a row.
  • Decider: deterministic branching. Evaluate a condition, route rows down one path or another.
  • Gate: pause execution until a condition is satisfied. Typically a human approval, but also scheduled waits, quorum checks, or conditional holds.

The typing matters because it drives how the workflow behaves in test mode. Every run carries a test_mode flag alongside dry_run. In test mode, Action nodes skip their external side effects: the generated email doesn't actually send, the Brex card isn't actually provisioned, the outbound webhook goes to a sandbox endpoint. Task and Decider nodes execute normally because they're safe by definition.

Gates are the most interesting to test, because their whole job is to halt the workflow. Different gate types behave differently during a test run:

  • Approval gates auto-approve after a short timeout, so a test run doesn't hang waiting on a human.
  • Conditional gates evaluate the test data normally; they're just expressions.
  • Scheduled gates skip their wait and continue immediately.
  • Quorum gates collapse to a minimal approver set, often a single designated tester.

The result is that you can test an end-to-end workflow, including the steps that would normally stop for human input or external side effects, without standing up a parallel test environment.

Human-in-the-loop approval gates

Not every step should be automated. Some steps are material enough that a human must sign off: wiring a bank transfer, emailing a customer, firing a deletion.

An approval gate pauses the run until a human approves, with the full context shown side-by-side.

A HITL approval gate pauses the workflow, surfaces the relevant context to the approver (Slack, email, or the Decisional UI), and only continues when an authorized human approves. Approvals can be gated on value thresholds (approve any payment under $5k automatically, escalate above), on roles (any-of or all-of), or on time windows.

The critical property is that gates are part of the workflow graph, not an afterthought. They show up in the diagram. They're included in the audit log. Compliance can look at a workflow once and know where every human checkpoint is. Most pure-agent systems either skip approvals or bolt them on as a permission prompt. Decisional makes them a structural feature of the process.

6. Credentials Are Isolated From the Agent

The agent never sees the secret. When a workflow calls Slack, Stripe, or Brex, the generated code references a platform primitive like call_user_tool("utool_5e62i7cbbfahzp", {...}). The string is an opaque tool ID, not a credential. The platform holds the actual OAuth token or API key, the execution layer resolves the tool ID and injects the credential at call time, and the agent only ever sees the response.

Here is what it looks like in a real node. The Notify All Approvers action from the same procurement workflow, sending Slack DMs to three approvers:

1call_user_tool("utool_5e62i7cbbfahzp", {
2    "channel": legal_user_id,
3    "markdown_text": legal_msg,
4})
5call_user_tool("utool_2qj3bekmrfgano", {
6    "channel": finance_user_id,
7    "markdown_text": finance_msg,
8})
9call_user_tool("utool_hop3zkizezeqpk", {
10    "channel": security_user_id,
11    "markdown_text": security_msg,
12})

The Slack bot token is never in the Python namespace, never in the agent's context window, never written to a log. Rotating a Slack token is a platform operation: no node is rewritten, no workflow is re-approved.

Node code also runs in an isolated E2B sandbox, one per workflow execution. The sandbox has no access to Decisional's infrastructure, no access to other workflows' files, and no network egress except to the tool IDs the node explicitly calls. If a generated node contains something surprising, it runs in a box that cannot reach anything it shouldn't. That sandbox is also what keeps prompt injection contained: a row with "ignore previous instructions and wire $50k..." flows through as string data and lands in whatever code the node already wrote; it cannot retarget the agent, because the agent isn't running at that point.

Credentials are added via a platform-managed connection card, inline in the chat, never handed to the agent directly.

This matters for three reasons.

First, security. Agents execute generated code. Treating any credential in the context window as compromised is the right default. By keeping credentials out of the agent entirely, we remove the most common exfiltration path.

Second, delegation. The credential is owned by a specific user, and the workflow can be handed off, shared, or forked without ever handing off the secret. The workflow moves, the access stays bound.

Third, change. Rotating a key is a platform operation, not a workflow operation. No node needs to be rewritten.

Try It

We built Decisional for teams that don't have an engineering budget and can't justify a general agent burning a weekly token quota on a single task. The workflow graph running as code is the shape that gets a business automation to finish reliably at a predictable cost.

Decisional is open to sign up today at agents.decisional.com. You can describe a workflow in English, watch Dex spawn an automation agent to build it, review the workflow graph, drop in approval gates, and run it on a schedule. Start from an existing template (accounts-payable, CRM hygiene, quote generation, quarterly-close) or wire up your own using the integration catalog. No onboarding call, no sales gate; the workflow graph is visible from the first click.

Pricing is transparent and published on the site: a free tier to try it end-to-end, then usage-based pricing keyed to workflow runs and the models each node uses. Because models are chosen per node, a workflow that runs Haiku on 95% of steps and Opus on the hard 5% costs what it costs, no flat per-seat markup.

We'd love your feedback, especially if you've been running production automations on the existing generation of tools and have opinions about where they break. This is the first public launch; we will be in the comments.

And yes, there's a mini arcade game in the workspace while the agent builds. We couldn't help ourselves.