← Back to Field Notes

The AI-Native Salesforce Developer Workflow in 2026

·10 min read

The moment I realised my workflow had inverted was on a Tuesday, looking at a pull request I hadn't typed a single line of. An agent had read the ticket, read the surrounding classes, scaffolded the handler, written the tests, run them against a scratch org, and opened the PR. My whole morning was deciding whether it was right. It mostly was. The parts that weren't were the parts that were always going to need me.

That is the shift I want to describe. Not "AI helps me write code faster" — I covered the tactical version of that in how I use Claude Code to write Apex faster. This is about the shape of the whole loop changing, and the handful of things you have to get right so the loop produces code you'd actually deploy rather than code you spend the afternoon unpicking.

The Loop Runs in a Different Order Now

The old loop was: read the ticket, think, type the code, type the tests, run them, fix, repeat, then get it reviewed. Typing was the bulk of the wall-clock time.

The new loop is: write the intent down clearly enough that an agent can execute it, let it execute across files, then read the result as if a mid-level engineer handed it to you. The bulk of my wall-clock time is now reading and judging, not producing. The centre of gravity moved from the keyboard to the review.

That sounds like a small rearrangement. It is not. It changes which skills matter. Being fast at typing Apex is worth almost nothing now. Being fast at recognising subtly wrong Apex is worth everything, because the volume of code arriving for your judgement has gone up several times over.

Context Is the Most Important File in the Repo

If I could keep only one file to make the agent useful, it would not be any Apex class. It would be the project context file — CLAUDE.md or AGENTS.md at the repo root — that tells the agent how this specific org does things.

An agent generating from a blank slate gives you generic Salesforce code. An agent generating against your conventions gives you code that fits. The difference is entirely in what you've written down. Mine looks something like this:

# Project conventions

- One trigger per object, delegating to a handler in `classes/handlers/`.
  Handlers extend `TriggerHandlerBase` and override only the contexts they use.
- No inline SOQL in handlers. Queries live in selector classes in
  `classes/selectors/` and return bulk-safe results.
- Every class is `with sharing` unless it documents in a header comment why not.
- All DML paths enforce CRUD/FLS via `Security.stripInaccessible`.
- Tests require a 200-record bulk case and a governor-limit assertion
  (< 50 SOQL). Coverage alone is not "done".
- Australian English in user-facing strings. US spelling in API names.

None of that is exotic. It is the same trigger and selector discipline I'd enforce in code review regardless. The point is that writing it down once turns it into a constraint the agent honours on every generation, instead of a thing I correct on every PR. I treat this file the way I treat a linter config — it encodes taste so I don't have to re-argue it.

The opinion I'll state plainly: a stale context file is worse than none. If it describes a pattern the codebase abandoned two years ago, the agent will faithfully reproduce the abandoned pattern and you'll get plausible-looking code that fights the rest of the org. I update this file in the same PR that changes a convention, or the convention doesn't count as changed.

Specs Do the Work Prompts Used To

Early on I prompted conversationally — "add a tier field and calculate it." That produces something, but the something is a negotiation. The version that survives is a written spec the agent executes against, close to how I'd brief a junior engineer who I won't get to speak to again before the PR.

## Feature: Account tier recalculation

When Account.AnnualRevenue changes on insert or update, set Tier__c:
- >= 10,000,000  -> 'Strategic'
- >= 1,000,000   -> 'Growth'
- otherwise      -> 'Standard'

Constraints:
- Only recalculate when AnnualRevenue actually changed (compare against oldMap).
- Bulk-safe. No SOQL or DML inside the record loop.
- Fires from AccountTriggerHandler.beforeInsert and beforeUpdate.
- Null AnnualRevenue -> 'Standard', not an exception.

Handed that, the agent produces the handler method I'd have written:

public void recalculateTier(List<Account> records, Map<Id, Account> oldMap) {
    for (Account acc : records) {
        Account prior = oldMap == null ? null : oldMap.get(acc.Id);
        Boolean changed = prior == null || prior.AnnualRevenue != acc.AnnualRevenue;
        if (!changed) {
            continue;
        }
        Decimal revenue = acc.AnnualRevenue == null ? 0 : acc.AnnualRevenue;
        if (revenue >= 10000000) {
            acc.Tier__c = 'Strategic';
        } else if (revenue >= 1000000) {
            acc.Tier__c = 'Growth';
        } else {
            acc.Tier__c = 'Standard';
        }
    }
}

The interesting part is not the code. It's that the null rule, the "changed" check, and the bulk-safety were in the spec, so they're in the output. The failure mode of conversational prompting is that the agent guesses the edge cases and guesses generously. A spec removes the guessing. The time I now spend writing specs is time I used to spend correcting guesses — it moved earlier in the loop, and it's cheaper there.

Review Moved to the Front of the Loop

The uncomfortable truth of an AI-native workflow is that it makes it very easy to ship confident, well-formatted, subtly wrong code. Agents write the parts that look like security correctness — a stripInaccessible call here, an isAccessible() check there — without the judgement about whether those calls are in the right place or covering the right operation.

So the review I used to do last, I now do first and hardest, specifically on anything touching data access. Before a generated change goes near a scratch org, it goes through the same CRUD/FLS enforcement checklist I'd apply to a human's PR, and I assume the agent got the security-sensitive parts subtly wrong until I've read them line by line. It's not paranoia. It's that the failure is invisible in the happy path and only shows up when a user without field access hits the code.

I've stopped trusting green tests as evidence here. An agent that writes both the code and the tests can write tests that pass against its own misunderstanding. Bulk cases and governor-limit assertions catch a class of error; they do not catch "this enforces sharing on the wrong object." A person still has to read that.

Agents Belong in the Pipeline, Not Just the Editor

The editor is where most people meet AI. The bigger productivity move for me was pushing agents into CI, so the boring verification runs without me. The deploy-and-test job is unremarkable and does the load-bearing work — it's the same discipline from what actually works for CI/CD on Salesforce:

name: pr-checks
on: pull_request

jobs:
  apex-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install Salesforce CLI
        run: npm install --global @salesforce/cli
      - name: Authenticate to CI org
        run: |
          echo "${{ secrets.SF_AUTH_URL }}" > ./AUTH_URL.txt
          sf org login sfdx-url --sfdx-url-file ./AUTH_URL.txt --alias ci --set-default
      - name: Deploy and run local tests
        run: sf project deploy start --test-level RunLocalTests --wait 60 --target-org ci

On top of that, I run a headless agent as a first-pass reviewer — not a gate, a triage. It reads the diff and flags the obvious gaps before I open the PR, so my human review starts from a shortlist rather than a blank page:

git diff --staged | claude -p "Flag only concrete CRUD/FLS gaps and \
missing bulk-safety in this diff. File and line for each. No summary, no praise."

The rule I hold to is that the agent triages and the pipeline verifies, but neither one approves. Approval is a human deciding to put their name on it. I've seen too many teams quietly let the bot's tick become the merge criterion, and that is how you optimise your way into shipping fast and wrong.

The Underwriting Rebuild That Made the Point

Last year I helped an APRA-regulated insurer rebuild an underwriting module. The existing code was around 340 Apex classes, most of it a decade old, most of it written before anyone on the current team arrived. We ran the whole rebuild on the workflow above.

The scaffolding evaporated. Handlers, selectors, test classes, the custom metadata bypass records — the plumbing that would have eaten a fortnight was generated and reviewed in a couple of days. That part was every bit as good as the promise.

The risk-scoring logic was a different story. The agent kept generating scoring rules that were plausible and confidently wrong against the actuarial spec — off-by-one band boundaries, a rounding rule applied at the wrong step. We caught most in review. One slipped through to UAT: a rounding behaviour that misclassified roughly one policy in forty into the wrong premium band. An analyst named Hannah found it by reconciling against the old system, not because any test failed. We fixed it, but it wasn't a clean win — it was a reminder that the tool accelerates the parts that were never the bottleneck, and the part that mattered took exactly as long as it always would have. The module's been live and stable since, and I've mostly stopped flinching about it. Mostly.

When AI-Native Isn't the Answer

The workflow assumes there's something for the agent to anchor on. In a codebase with real conventions and a decent context file, it's a multiplier. In a greenfield org with no patterns yet, it's a liability — the agent invents conventions inconsistently and you spend more time normalising its output than you'd have spent writing the first few classes yourself. I now write the first slice of any new org by hand, precisely to give the agent something to imitate.

It's also the wrong tool for the genuinely hard calls. Whether a requirement belongs in a Flow or Apex, whether to extend an object or add one, whether to build now or wait for the platform to ship the feature next release — the agent will hand you a balanced essay and no decision. Those are still mine to make. And for the security-critical core of anything AppExchange-bound, I write it myself and use the agent only for the surrounding plumbing, because the cost of a subtle miss there isn't a bug, it's a failed review.

The honest framing is that AI-native isn't a mode you flip on for everything. It's a workflow that's excellent at volume and mediocre at judgement, and the skill is knowing which of those a given task actually needs. If you want a second pair of eyes on how your team's loop is really running — where the agent is helping and where it's quietly shipping debt — that's the kind of review I do.

Three years ago my day was mostly typing and a little thinking. Now it's mostly reading and a lot of judging. The typing was never the job.

Liked this?

New essays in your inbox when I publish. No cadence, no spam.