The Deploy That Looked Clean
Two agents, one story: “you handle the flow, I’ll handle the page layout.” Reasonable split — except we hadn’t split the object, we’d split the request. Both agents ended up touching the same page-layout XML in the same run. One added a related list for open cases. The other reordered two fields per a design note from three sprints back. The deploy went out clean. Zero errors, zero warnings.
Two weeks later, a sales rep asked where the related list had gone. It hadn’t been deleted. Last-write-wins on a shared metadata file had simply kept one agent’s version of the layout and thrown away the other’s — and nothing in a Salesforce deploy log tells you “by the way, I just overwrote someone else’s work.”
Nobody had broken a rule. Nobody had even done anything careless by the standard we’d judge a developer against. We’d handed two specialists the same file with no coordination between them, and Salesforce metadata doesn’t merge the way application code does — it overwrites, quietly, and the deploy log has no opinion about it either way.
That’s not a story about AI being unreliable. It’s a story about what happens when you get the convenience of Claude Code without an actual delivery process behind it. So we built one.
What I Built Instead
If you’ve sat through a pull request process, you already know the shape of this: someone proposes a change, someone reviews it, there’s a gate before it merges, and the record of where things stand doesn’t live only in someone’s head. The real difference here is that two of the “someones” are Claude Code subagents — specialists briefed for one job, who do the work and hand back a result without ever seeing the rest of the conversation that led up to it.
Four roles. Two points where a person has to actually decide something rather than the model deciding for them. One shared record — I use Jira — that every stage reads from and writes back to, so the process survives a crashed session even when nobody’s memory does.
The Rules That Came Out of This
Each one exists because of a specific failure, not as general hygiene — and each says exactly what to do about it, not just what to believe.
You decide when to proceed, not the model. Don’t take “design looks solid” from the architect agent as approval — read the proposal yourself and manually move the ticket forward before the developer stage starts. If nobody does that read-and-approve step, the pipeline doesn’t advance. Full stop.
Write status to Jira after every stage, not just at the end. A session can run out of context or crash mid-task, and the agent’s memory dies with it — the ticket doesn’t. Update it the moment a stage finishes, so whoever picks the work up next knows where it actually left off, not what the last conversation happened to remember.
Wire deploy validation, static analysis, and tests as hooks that fire automatically — don’t ask an agent to remember to run them. A prompt that says “please test before finishing” is a suggestion a model can skip under pressure. A hook fires whether anyone asks or not.
Give each developer agent its own metadata boundary before you give it a task. Decide up front which agent owns which object, layout, or permission set, and never let two agents open the same file in the same run. That’s the actual fix for the related-list story above — not “communicate better,” an actual boundary.
Configure read-only roles at the tool level, not in the instructions. Tell the architect, reviewer, and documentor subagents they get Read and Grep only, in their real configuration — not a polite line in the prompt asking them not to edit anything. A permission a model can talk itself out of isn’t a permission.
Why Four Roles, Not Six
The instinct once you see a pipeline like this is to add more stages — a dedicated tester, a security reviewer, a QA pass. Resist it. Every role added inside the loop is somewhere a rejection can bounce back and forth and context can quietly drop — that’s the real cost of a role, not the compute. The documentor skips that tax because it sits at the exit: it runs once, it’s read-only, and a person reads its output immediately.
A dedicated tester subagent doesn’t earn its place, for a different reason. Testing has to be a command that actually runs against a sandbox. An agent reasoning about tests without running them produces confident writing and zero information. Keep the execution. Drop any role that only talks about it.
Add stages later, one at a time, only once you’ve watched a specific failure the new stage would have caught. Ours added itself after two weeks and a missing related list. Let yours be cheaper.
Before You Build Any of This Yourself
A good part of the developer and reviewer layer above already ships as an official plugin. Salesforce released one for Claude Code bundling skills from the open-source sf-skills library, MCP servers for org and metadata context, hooks for deploy validation, and a read-only architecture reviewer. Install it first and see what’s genuinely missing before writing anything custom:
/plugin marketplace add forcedotcom/sf-skills
/plugin install salesforce-development@salesforce
/salesforce-development:setup
Worth being precise here, because it’s easy to conflate with something else currently in the news. Claudeforce — the partnership Salesforce and Anthropic just announced — is a different product for a different audience: Claude answering questions and updating records for account executives, inside Salesforce itself. Not a delivery pipeline for the people building on the platform. One is about the deal getting worked. The other is about the change getting shipped without quietly losing a related list along the way. Both can be true in the same org, for different teams, at the same time.
Which is the actual question worth sitting with if you’re evaluating any of this: is the investment you’re making aimed at your sales team moving faster, or your delivery team shipping safer? Most orgs I’ve seen are further along on the first than the second — and it’s worth knowing which one you’re actually building toward before you pick a tool.
