Ask ten vendors what an AI agent is and you'll hear the same pitch: a model with access to your tools that plans and acts on its own. It demos beautifully. Then you put it in production and it does something slightly different every run.
I build AI agents for businesses, and the ones that survive contact with real customers share one design rule: make every step deterministic when possible, and spend the model only where language genuinely needs judgment.
The problem with letting the model do everything
Large language models are probabilistic. The same input can produce a different output tomorrow, and often does. That's useful when you're brainstorming. It's a liability when the step in question is "pick which 100 customers receive this email."
A fully model-driven agent might query the wrong table once in fifty runs. It might email someone your team already contacted. It might invent a flattering fact about a prospect's company because the sentence felt right. Each mistake is small. Across a thousand runs they compound into something you can't explain to a customer, and you can't debug it either, because there is no line of code to point at. There's only a prompt and a probability.
Code decides, the model writes
My rule for AI workflow automation is blunt: if a step has a right answer, write code for it. SQL for selection. Python for API calls. Plain arithmetic for splits and counts. Reserve the model for the narrow slice where judgment about language is the actual job: understanding what the operator asked for, firing the right triggers, and customizing the message for a specific human reader.
In my pipelines the model ends up doing maybe a fifth of the work. The rest is ordinary, boring, reliable software. Boring is the point.
Inside a real pipeline: one cold email batch
Here's how this looks in the outbound email system I run on my own data. An operator types one line: send the A/B campaign to 100 marketing leads, scheduled for Monday morning.
Targeting is a query, not a guess. A Postgres view excludes bounced addresses, junk, and anyone already contacted. The batch is a SELECT with a LIMIT against that view, something like this:
SELECT id, work_email, company, industry
FROM campaign_ready_leads -- view already excludes bounces, junk,
WHERE segment = 'marketing_agencies' -- and anyone we've contacted
ORDER BY id
LIMIT 100;
That's the entire targeting decision. The model never chooses who gets emailed, and if the batch comes back short, that's a finding for a human, not a reason to widen the query.
The A/B split is positional. First row gets variant A, second gets B, alternating. Two lines of logic, impossible to get wrong.
Drafting is the model's slice, and it's fenced. For each lead, an agent fills exactly three slots in a fixed template: the greeting, the company reference, and one opening line. It may only use fields that exist in that lead's database row. If the row offers nothing beyond a company name, the opener stays plain. A true generic sentence beats an invented specific one.
Validation is a second, separate agent. Every draft gets checked against the template contract: no leftover placeholders, no fabricated claims, the right recipient, the fixed copy untouched. Rejected drafts go back for a redraft, two rounds at most.
A human approves the batch. Nothing sends until a person reviews sample drafts and signs off on that specific batch by name.
Sending and recording are pure code. A script posts each message to the email provider's API, throttled, and writes one row per accepted send back to the database. That table feeds the exclusion view, so the next batch's targeting stays honest automatically.
The model never touches the send button. It never writes to the database. It writes sentences, which is what it's good at.
Want an automation like this behind your own outreach, reporting, or ops? This is the work I do for businesses: deterministic pipelines on clean data, with AI only where it earns its place. Book a 15-min fit call and bring one workflow you'd like off your plate.
What you actually gain
Repeatability: the same request produces the same batch, and a dry run today matches the real run tomorrow. Auditability: every send maps to a database row and every targeting decision maps to a query you can read, so when a customer asks "why did I get this?" you have an answer. Lower cost: you pay for model tokens on three sentences per email instead of a full reasoning chain per lead. And when something breaks, it's a failing query or an API error with a status code. You fix a line, not a vibe.
Where to draw the line in your own operation
Walk through any workflow you want to automate and ask one question per step: does this step have a single correct answer? If yes, it belongs in code. If it genuinely requires judgment about language, tone, or intent, give it to the model, then wrap it in validation and ground it in your own data.
That last part matters more than which model you pick. AI agents are only as good as the data underneath them. A clean database view is worth more than a clever prompt. If your data isn't there yet, that's the first fix, and it's the same foundation I build for clients through Agency Data Ops.
Frequently asked questions
What is a deterministic AI agent?
An automation where every step with a right answer runs as plain code (SQL, Python, API calls) and the language model only handles the parts that need judgment about language, like personalizing a message or interpreting a request.
Why not let the LLM run the whole workflow?
Language models are probabilistic: the same input can produce a different output tomorrow. That's fine for drafting text and risky for choosing recipients, sending messages, or writing to a database. Code is repeatable, auditable, and debuggable.
Do deterministic AI agents cost less to run?
Yes. You pay for model tokens on a few sentences per item instead of a full reasoning chain per item, and debugging time drops because failures are readable errors with a line number, not a prompt to second-guess.
Does this approach work outside email automation?
Yes. The same split applies to reporting, CRM syncs, lead scoring, and any repetitive workflow: code for every step with one correct answer, the model for the language parts, and a human approval gate before anything irreversible.
Augment your team with AI and solid data
I help businesses augment their teams with AI agents built exactly this way: deterministic where correctness matters, model-driven where language matters, sitting on data you can trust. If you want automation that runs the same on Friday as it did on Monday, let's talk.
Book a 15-min fit call, bring one workflow, and I'll map the code-versus-model split with you live on the call.