In the Agent Script post, I ended with an open question I had been dodging the whole way through: where is the line between Agent Script and Flow? Both are now “deterministic orchestration on the platform.” For a given piece of logic, when do you script the agent, build a Flow, or drop into Apex?
This post answers it. Not with a vibe, not with “it depends,” but with an actual framework you can apply on a Monday morning when a stakeholder is standing at your desk.
Here is why the question matters more in 2026 than it ever has. For most of Salesforce’s history, the decision was binary and tribal. Developers reached for Apex because Apex was theirs. Admins reached for Flow because Flow was theirs. The choice was made by who you were, not by what the problem needed. It worked, more or less, because there were only two tools and the boundary between them was reasonably clear.
Then Agent Script arrived and added a third option that does not fit cleanly on either side of the old tribal line. Now there are three places business logic can live, the boundaries between them overlap, and the “use the tool that belongs to my job title” heuristic produces actively wrong answers. People are scripting agents to do things a Flow does better. People are building forty-element Flows that should have been ten lines of Apex. People are writing Apex for automation that an admin could have owned in a Flow in an afternoon.
The cost of choosing wrong is not abstract. It is a maintenance burden that lands on whoever inherits the org, a performance problem that surfaces at scale, or a workflow nobody can safely change because it lives in the wrong layer. So let us build the framework that gets it right.
The TL;DR
If you want the decision before the reasoning:
- Start with the trigger, not the tool. Is the logic triggered by a conversation (a person talking to an agent) or by a transaction (a record saved, a button clicked, a schedule firing)? That single question routes you to the right half of the platform.
- Conversation-shaped logic → Agent Script. It is the orchestration layer for agent runtime, and nothing else belongs there.
- Transaction-shaped logic → Flow first, Apex when Flow can’t. This is Salesforce’s own guidance and it is correct: reach for the declarative tool by default, and drop to code only when complexity, bulk volume, or performance demands it.
- Within an agent, the second choice is
->vs|. Deterministic guarantees use the arrow; reasoning uses the pipe. That is the internal decision Agent Script forces, and it is separate from the tool choice. - They compose — this is the part people miss. An Agent Script calls a Flow as an action; the Flow calls an Apex method for the heavy lifting. The right architecture for a serious workflow often uses all three, each at the layer it is best at. The question is rarely “which one.” It is “which one for this part.”
The rest of this builds the framework that makes those calls automatic.
What Each Tool Actually Is
You cannot choose well between three things you have only a fuzzy sense of. So, precisely:
Apex is Salesforce’s pro-code language — Java-like, fully deterministic, running inside the platform’s transaction context with access to the entire data model and the full governor-limit budget. It is the scalpel: maximum control, maximum power, and maximum responsibility. It needs a developer to write, test classes to deploy, and discipline to maintain. You reach for it when you need to do something precisely, at scale, or in a way the declarative tools simply cannot express.
Flow is Salesforce’s low-code automation engine — visual, declarative, deterministic, also running in the transaction context. It is the power tool: it covers the enormous middle of business automation without code, an admin can own it, and it has quietly absorbed most of what used to require Apex. It is excellent up to a point and gets genuinely painful past it — large loops, high data volume, and deeply nested complexity are where Flow starts fighting you.
Agent Script is the orchestration layer for Agentforce agents — a real language (covered in depth here) that runs in the agent runtime, not the transaction context. It is unique among the three because it blends deterministic execution (the -> arrow) with probabilistic LLM reasoning (the | pipe) in the same file. It exists for one thing the other two cannot do at all: orchestrate a natural-language conversation where some steps reason and some steps must obey.
Here is the diagram that makes the relationship click:
CONVERSATION CONTEXT TRANSACTION CONTEXT
(agent runtime) (record save / click / schedule)
┌──────────────────┐ ┌──────────────────────────────┐
│ Agent Script │ │ Flow ───────► Apex │
│ | reasoning │ │ (declarative) (pro-code) │
│ -> determinism │ │ │
└────────┬─────────┘ └──────────────────────────────┘
│ ▲
│ agent actions call ─────────────┘
│ Flows and Apex
▼
(the layers compose — they are not rivals)
Read that diagram carefully, because it dissolves most of the confusion. Agent Script and Flow/Apex live in different runtime contexts. One handles conversations; the other handles transactions. They are not three rivals competing for the same job. They are three layers, and an agent’s actions are frequently implemented as Flows or Apex. The overlap that causes arguments is narrow: it is only the “deterministic orchestration” sliver, and even there, the context tells you which to use.
The Axes That Actually Matter
When the choice feels genuinely ambiguous, it is because you are looking at the tools instead of the problem. Step back and score the problem on these axes. They are listed in priority order — the first one usually settles it on its own.
Axis 1: Conversation or transaction? (the master axis)
This is the question that routes everything. Ask: what kicks this logic off?
- A person talking to an agent in natural language → conversation context → Agent Script.
- A record being saved, a button being clicked, a batch running on a schedule, a platform event firing → transaction context → Flow or Apex.
Ninety percent of the time, this axis alone gives you the answer, and the remaining decision is just Flow-vs-Apex within the transaction branch. The mistake people make is skipping this axis and arguing about determinism or complexity first. Don’t. Start here.
Axis 2: Does it need LLM reasoning?
Within the conversation branch, this is moot — you are already in agent territory. But it is worth stating the inverse as a guard: if the logic does not require natural-language understanding or generation, it does not belong in an agent at all. Do not build an Agentforce agent to run a nightly data cleanup. That is a scheduled Flow or an Apex batch. Reasoning capability is expensive and probabilistic; spend it only where you actually need a machine to understand language.
Axis 3: Complexity and who maintains it (the Flow-vs-Apex axis)
Once you are in the transaction branch, this axis decides between Flow and Apex:
- Low to medium complexity, admin-maintainable → Flow. Record-triggered automation, screen flows for guided UI, approval routing, the boring-but-essential middle. If an admin can own it, it should live where an admin can own it.
- High complexity, bulk-sensitive, performance-critical, or genuinely beyond declarative expression → Apex. Complex data transformations, processing thousands of records efficiently, intricate callout orchestration with real error handling, reusable service logic. If it needs a developer to do safely, it belongs in code.
The honest tell: if you find yourself building a Flow with nested loops over large collections, a dozen decision elements, and a diagram nobody can read, you have passed the Flow-to-Apex boundary and should refactor into code. Conversely, if you are writing an Apex trigger to do a simple field update on save, you have under-shot — that is a Flow, and you have just created code debt an admin cannot touch.
Axis 4: Determinism — the choice inside Agent Script
This axis does not choose between the three tools. It chooses within Agent Script, between the arrow and the pipe — and it is worth naming because people conflate it with the tool choice. Inside an agent: anything that must happen the same way every time (verification, eligibility gates, mandatory ordering) is an -> logic instruction; anything that benefits from natural phrasing and judgment is a | prompt instruction. The Agent Script post covers this in depth. The point here is only that “I need determinism” does not mean “I need Apex” — within an agent, determinism is an arrow, not a callout to code.
The Decision Tree
Put the axes together and you get a flowchart you can run in your head:
What triggers this logic?
│
├─ A person talking in natural language?
│ │
│ └─► AGENT SCRIPT
│ │
│ └─ within it, per step:
│ ├─ must happen identically every time? ──► -> (arrow / logic)
│ └─ needs language reasoning / phrasing? ─► | (pipe / prompt)
│ └─ needs heavy work or a real transaction?
│ └─► call a Flow or Apex *as an action*
│
└─ A record save / click / schedule / event?
│
└─ Is it admin-maintainable, low-to-medium complexity?
│
├─ Yes ──► FLOW
│
└─ No (bulk, complex, performance-critical, beyond declarative)
│
└─► APEX
(and expose it as an invocable action so Flows
and agents can call it)
Notice the recursion at the bottom of the agent branch: when an agent needs to do something heavy or transactional, it does not do it in the script. It calls a Flow or an Apex action. The script orchestrates the conversation; the Flow or Apex does the transactional work. This is the composition pattern, and it is the single most important thing to internalize.
The Comparison, Side by Side
For the table-skimmers:
| Dimension | Apex | Flow | Agent Script |
|---|---|---|---|
| Runtime context | Transaction | Transaction | Conversation (agent) |
| Paradigm | Pro-code, imperative | Low-code, declarative visual | Hybrid: deterministic + LLM reasoning |
| Determinism | Total | Total | Per-line (-> total, | probabilistic) |
| Who maintains it | Developer | Admin / Admin Plus | Admin Plus / Developer |
| Best at | Complex logic, bulk, performance, callouts | Business-process automation, guided UI, the middle 80% | Conversational workflows needing reasoning + guardrails |
| Falls apart when | Used for simple field updates (code debt) | Used for bulk loops / deep complexity | Used for non-conversational logic |
| Version control | Native (it’s code) | Improving, but clunkier to diff | Native (it’s a file) |
| Testing | Apex test classes | Harder; manual + some Flow testing | Agent evals (sf agent test) |
Worked Examples
A framework is only as good as its behavior on real problems. Four scenarios, run through the tree.
Scenario 1: “When an Opportunity closes won, create a renewal Opportunity 11 months out.” Trigger: a record save (Opportunity moves to Closed Won). That is the transaction branch. Complexity: low, admin-maintainable — create a related record with a calculated date. Verdict: Flow. A record-triggered Flow does this cleanly, an admin owns it, and reaching for Apex here would create code debt for no benefit.
Scenario 2: “Recalculate complex commission splits across thousands of line items nightly, with tiered rules.” Trigger: a schedule. Transaction branch. Complexity: high — bulk processing thousands of records, intricate tiered logic, performance-sensitive. A Flow looping over thousands of line items will fight governor limits and become unreadable. Verdict: Apex (a scheduled batch). This is exactly the “beyond declarative” case. Expose nothing to an agent; nobody is talking to it.
Scenario 3: “A customer chats in to report a claim; verify them, collect details in order, escalate if there are injuries.”
Trigger: a person talking in natural language. Conversation branch. Verdict: Agent Script — with -> arrows for the mandatory verification and escalation, | pipes for the warm conversation, and the actual claim creation done by calling a Flow or Apex action. This is the Meridian Insurance example from the Agent Script post, and it shows all three layers in one workflow: script orchestrates, the action (Flow/Apex) executes the transaction.
Scenario 4: “Let employees ask ‘how much PTO do I have left?’ in Slack and get an answer.”
Trigger: a person asking a question in natural language. Conversation branch → Agent Script. But notice: the answer requires fetching a real number from a record. So the agent reasons about the question (|), then calls an action — a Flow or Apex method that queries the PTO balance — and reads the result back. Again: three potential layers, each doing its job. The script never queries the database directly; it delegates to an action built for the transaction context.
See the pattern across all four? The master axis (conversation vs transaction) settles the primary tool every time, and the serious workflows compose layers rather than picking one.
The Anti-Patterns (Choosing Wrong)
Each tool has a characteristic failure mode — the way people reach for it when they shouldn’t. Learn to recognize them in code review.
The Apex-for-everything developer. Writes a trigger and a service class to do a field update that a record-triggered Flow would handle in three clicks. The result is code that only a developer can change, for logic an admin should own. Symptom: trivial automations buried in Apex that the business cannot evolve without a deployment.
The Flow-for-everything admin. Builds a sprawling, forty-element Flow with nested loops over large collections because “we don’t do code here.” The result is an unmaintainable, performance-fragile diagram that hits governor limits at scale and that nobody — including the person who built it — can safely modify six months later. Symptom: a Flow that takes ten minutes to understand and breaks when the data volume grows.
The Agent-Script-for-everything enthusiast. Just discovered the new tool and now wants to script everything, including a nightly batch job. The result is an AI agent runtime doing work that has no conversation and needs no reasoning — slower, more expensive, and more fragile than the scheduled Flow it should have been. Symptom: an “agent” that no human ever talks to.
The “determinism means Apex” reflex. Needs a guaranteed step inside a conversational workflow and concludes they must therefore write Apex and bolt it onto a builder-only agent. The result misses that Agent Script’s whole point is deterministic orchestration inside the conversation — the guarantee is an -> arrow, not a reason to abandon the agent layer. Symptom: brittle agent-plus-Apex contraptions where a clean script would have done.
The common root of all four: choosing by identity or familiarity instead of by the problem’s actual shape. The framework exists precisely to override that reflex.
They Compose — Stop Thinking “Either/Or”
The single most valuable shift in this whole post: for any workflow with real stakes, the question is almost never “which one of the three.” It is “which one for each part.”
A mature, production-grade Agentforce workflow routinely looks like this:
- Agent Script orchestrates the conversation — reasoning where it helps, hard guarantees where they matter.
- It calls Flow actions for the admin-ownable transactional steps — create the record, route the approval, update the status.
- Those Flows, in turn, call Apex for the heavy lifting a Flow can’t do well — the complex calculation, the bulk operation, the intricate callout.
Three layers, one workflow, each tool doing the thing it is best at and nothing it is bad at. The admin owns the Flow layer. The developer owns the Apex layer. The Admin Plus (see the Admin Plus roadmap) increasingly owns the agent layer that ties them together. This is not a compromise. This is the correct architecture, and it is what separates a workflow that survives contact with production from one that collapses under its own cleverness.
The wrong question is “Apex or Flow or Agent Script?” The right question is “which layer does this part belong in?” Almost every serious workflow uses more than one.
The Honest Gray Areas
I would be selling you a too-clean framework if I pretended every case is obvious. The genuinely ambiguous zones:
Medium-complexity Flow vs. Apex. There is a real band where a Flow is possible but an Apex method would be cleaner, and reasonable architects disagree. My tiebreaker: who needs to maintain it and how often will it change? Frequently-changing business logic that an admin should own leans Flow even at some complexity cost. Stable, complex logic leans Apex. There is no universal line here, and anyone who claims one is overselling.
Logic in the agent action vs. logic in the script. When an agent needs a deterministic multi-step operation, should those steps be -> arrows in the script, or pushed into a single Flow/Apex action the script calls once? My heuristic: conversation-adjacent logic (collect this, then check that, then ask this) stays in the script as arrows; transaction-adjacent logic (create the record and its three children atomically) goes into one action. But the boundary is fuzzy, and it is exactly the open question I raised originally. I have a working answer; I do not have a provably correct one.
The “should this even be automated” question. Sometimes the right answer is none of the three. Not every process needs platform logic; some need a better manual process, a page-layout change, or a conversation with the business about why the requirement exists at all. The most senior move in the room is occasionally to talk someone out of building anything. The framework chooses between tools; it does not relieve you of asking whether to build at all.
Open Questions
Still genuinely working through these:
-
Will the Flow/Agent-Script boundary blur further? Both are “declarative-ish deterministic orchestration.” As Salesforce evolves both, does the line I drew (conversation vs transaction) hold, or do the tools start to overlap enough that the context distinction weakens? I think context endures as the cleaner axis. I am watching.
-
Where does AI-generated Flow/Apex change the calculus? If the in-platform AI can draft a Flow or the equivalent Apex from the same prompt, does the “who maintains it” axis shift? When generation is cheap, maintainability and readability matter even more, not less — but the decision dynamics are moving.
-
Does “composition” scale organizationally? Three layers maintained by three roles (admin, Admin Plus, developer) is architecturally clean but organizationally demanding. Smaller teams may not have all three roles. What is the right framework for a two-person team where one person owns all three layers? The technical answer is the same; the practical answer is messier.
The Verdict
For a decade, the Apex-vs-Flow question was answered by job title, and it mostly worked because the boundary was clear and there were only two tools. Agent Script broke the old heuristic by adding a third option that does not sit on either side of the developer/admin line — and the “use the tool that belongs to my role” reflex now produces wrong answers often enough to matter.
The fix is to choose by the problem’s shape, not your own. Start with the master axis: conversation or transaction. That routes you to agent runtime or transaction context, and it settles most cases outright. Within the transaction branch, let complexity and maintainability choose between Flow and Apex — Flow first, Apex when Flow can’t. Within the agent branch, let determinism choose between arrows and pipes. And for anything with real stakes, expect to compose all three, each doing its one job well.
Get this right and you stop producing the characteristic failures — the Apex field-update, the forty-element Flow, the agent nobody talks to. You start producing architectures where the admin owns what admins should own, the developer owns what developers should own, and the conversation layer ties them together cleanly. That is not just better engineering. In the bifurcating ecosystem, the person who can make these calls correctly — who can reason across all three layers instead of defaulting to the one they own — is exactly the person the market is promoting.
The framework is the map. The judgment is yours. But now, at least, you are choosing by the problem.
Further Reading
The connected pieces:
- Agent Script: When Your AI Agent Needs a Spine — Deep dive on the third tool, including the
->vs|decision this framework references. - The ‘Admin Plus’ Survival Guide — Why the ability to reason across all three layers is the skill the market now pays for.
- The Great Salesforce Bifurcation — The career context: cross-layer judgment is what separates the promoted from the squeezed.
- Agentforce for Developers — The agent fundamentals underneath the conversation layer.
- Salesforce Headless 360 in Practice — Where agent actions get invoked from, and how the layers connect to the wider platform.
The framework is deliberately simple because the situations are not. Run the tree, respect the composition pattern, and when you hit a genuine gray area, choose for the person who has to maintain it next. That last instinct will not steer you wrong.