Intuit Rebuilt Its Agent Stack Twice. Here's Why.

Your first AI agent works in the demo, then falls over the second a real customer touches it. You rewrite. It falls over again. Now you're wondering if you picked the wrong framework, the wrong model, or the wrong problem entirely.
That exact question hit a company most engineers assume has this figured out. At VB Transform 2026, Intuit VP of AI Nhung Ho described rebuilding the company's agent architecture twice in roughly four months — first collapsing a fleet of specialist agents into a central orchestrator, then throwing out the orchestrator for a skills-and-tools model. If a Fortune 500 with a dedicated AI org rewrites twice, the lesson for a five-person SMB isn't "you're doing it wrong." It's that the field hasn't converged, and the fastest path forward is expecting to rewrite.
This post breaks down what actually happened, why each architecture broke, and what a solo builder or small ops team should do differently on Monday morning.
What Intuit actually shipped, in order
Intuit's arc, per Ho's Transform talk, went through three architectures in about four months. Version one was a fleet of specialist agents — one per task (invoicing, categorization, customer help). Version two consolidated those into a central orchestration layer that routed intent to the right agent. Version three ditched the orchestration layer entirely for a skills-and-tools system where a smaller number of general agents call discrete, well-defined skills.
That's the shape most in-house AI teams are converging on right now, even if they arrive by different roads. The important detail isn't which version "won." It's that shipping v1 was what taught them v2 was needed, and shipping v2 was what taught them v3 was needed. You can't reason your way to the right architecture from a whiteboard.
| Version | Design | Why it broke |
|---|---|---|
| v1 | Specialist agents per task | Too many agents to coordinate; overlapping capabilities; unclear ownership of shared state |
| v2 | Central orchestrator routing to specialists | Orchestrator became a bottleneck and a second source of truth; every new agent required orchestrator changes |
| v3 | Skills-and-tools called by general agents | Simpler surface; tools are versioned and testable; agents stay thin |
Why "specialist agents" collapse first
Specialist agents feel right on paper. One agent per job maps cleanly to how you'd divide work among humans. The problem is that real user requests don't respect those boundaries. A customer emailing about an invoice mismatch is asking three things at once: retrieve a transaction, explain the discrepancy, and probably kick off a refund workflow. Which specialist owns that?
You end up with one of two failure modes. Either the specialists start calling each other (now you have a distributed system with no clear graph), or you build a router in front. Congratulations, you're on the path to v2.
A more concrete symptom: shared state. Two specialists both need customer context. Do they each fetch it? Do they share a cache? Who invalidates it? These are the same problems microservices teams solved a decade ago, and the answers are the same — but LLM agents make them worse because non-determinism means the same input can trigger different agent paths, so your caching assumptions break silently.
Why the orchestration layer was the next thing to go
An orchestrator solves the routing problem by centralizing it. Every request comes in, the orchestrator classifies intent, picks the right specialist, and returns the result. Clean diagram. Terrible operational reality.
Three things go wrong, based on what teams I've talked to have hit:
- The orchestrator becomes a second brain. It has its own prompt, its own model, its own eval suite. When a downstream agent fails, is it the agent's fault or the orchestrator's classification? You now debug two LLM calls per request.
- Every new capability requires orchestrator surgery. Want to add a new skill? Update the router. Update the intent taxonomy. Re-run the classification evals. This is the opposite of the modularity you were promised.
- Latency and cost stack. Two LLM calls minimum per user turn, plus the specialist's own tool calls. On a 10,000-request day, you're paying for classification twice.
The skills-and-tools model that Intuit landed on inverts this. Instead of an orchestrator picking an agent, a smaller number of general agents pick tools directly. The routing intelligence lives inside a single LLM call, using the model's own function-calling.
What "skills and tools" actually means in code
The pattern is unglamorous, which is why it works. You define tools as plain functions with typed schemas. The agent, given a system prompt and the user's message, decides which tools to call and in what order. That's it. No router, no supervisor agent, no meta-planner.
Here's the shape in Python, using a tool-calling loop against any modern model API:
tools = [
{
"name": "get_invoice",
"description": "Fetch an invoice by ID. Use when the user references a specific invoice number.",
"input_schema": {
"type": "object",
"properties": {"invoice_id": {"type": "string"}},
"required": ["invoice_id"],
},
},
{
"name": "list_recent_transactions",
"description": "List transactions in a date range. Use when the user asks about activity without a specific ID.",
"input_schema": {
"type": "object",
"properties": {
"customer_id": {"type": "string"},
"days": {"type": "integer", "default": 30},
},
"required": ["customer_id"],
},
},
{
"name": "issue_refund",
"description": "Issue a refund. REQUIRES prior human approval token.",
"input_schema": {
"type": "object",
"properties": {
"transaction_id": {"type": "string"},
"approval_token": {"type": "string"},
},
"required": ["transaction_id", "approval_token"],
},
},
]
Two things to notice. First, the descriptions are written for the model, not for humans reading docs — that's where routing intelligence lives. Second, issue_refund requires an approval token the LLM cannot forge. Destructive actions have a human gate. This is how you avoid the "AI agent refunded 400 customers" postmortem.
The agent loop itself is boring:
def run_agent(user_message, context):
messages = [{"role": "user", "content": user_message}]
while True:
response = client.messages.create(
model="claude-sonnet-4-5", # check current model name on Anthropic's pricing page
system=SYSTEM_PROMPT,
tools=tools,
messages=messages,
)
if response.stop_reason == "end_turn":
return response.content[-1].text
for block in response.content:
if block.type == "tool_use":
result = dispatch_tool(block.name, block.input, context)
messages.append({"role": "assistant", "content": response.content})
messages.append({
"role": "user",
"content": [{"type": "tool_result", "tool_use_id": block.id, "content": result}],
})
That's the whole thing. No orchestrator. If you need a second agent for a genuinely different domain (say, one that talks to customers and one that runs internal ops), you spin up a second instance with a different tool set. You don't build a supervisor to coordinate them until you have concrete evidence you need one.
The MCP question: when protocol beats bespoke
The reason to care about Model Context Protocol here is that "skills and tools" is exactly what MCP standardizes. Instead of hand-coding every tool integration into your agent, you point the agent at MCP servers that expose tools over a shared protocol. Your CRM, your billing system, your internal database — each becomes an MCP server, and any agent can consume them.
The tradeoff is real: MCP adds a protocol layer and a running process. For a single tool called from a single agent, raw function calling is simpler. The break-even I've measured in production tends to hit around the third or fourth tool that's shared across more than one agent or codebase. Below that, bespoke wins. Above it, you're reimplementing MCP badly.
For an SMB with one or two agents and fewer than five tools, don't reach for MCP on day one. Ship the raw tool-calling loop. When you find yourself copy-pasting tool definitions across projects, that's the signal to move.
How to design agents you won't rewrite in four months
You won't avoid rewrites entirely — Intuit couldn't, and they have a real AI org. But you can push the first rewrite from month two to month twelve by making a few decisions early.
Start with one agent, not a fleet. One agent, one set of tools, one clear job. The urge to build "the invoicing agent AND the support agent AND the lead-qualification agent" as separate services is the same urge that got Intuit to v1. Resist it until you have a specific reason two agents can't share a loop.
Make tools the unit of reuse, not agents. Tools are testable, versionable, and stateless. Agents are prompts plus a loop — they change constantly as you tune behavior. If your reusable logic lives in tools, you can rewrite the agent freely. If it lives in agent-to-agent protocols, every rewrite is a migration.
Gate every destructive action. Refunds, deletions, emails to customers, anything that touches money or reputation. The gate can be a human approval, a dollar threshold, a rate limit — but it exists outside the LLM. This is the single cheapest thing you can do to make an agent safe to leave running.
Instrument everything from turn one. Log every tool call, every model response, every decision the loop makes. When something breaks — and it will — you need the trace. Don't wait until you have a production incident to add observability.
Write evals before you write features. A dozen realistic conversations that your agent must handle correctly, checked into git, run on every prompt or tool change. Without this, you have no signal that a "small tweak" didn't regress your top use case.
Common mistakes I see SMBs make
Building a supervisor agent because a blog post said to. Multi-agent architectures are seductive because they look like org charts. For anything under maybe five distinct domains, one agent with more tools beats two agents with a coordinator. Every additional agent is another prompt, another eval suite, another failure surface.
Confusing "agent" with "chatbot." An agent takes actions. A chatbot answers questions. If your "agent" only responds with text and doesn't call tools that change the world, you built a chatbot with extra steps. That's fine — but price and design accordingly.
Optimizing the wrong thing. Teams spend weeks tuning prompts when the real problem is that their tool descriptions are ambiguous or their approval flow is broken. When the agent picks the wrong tool, the fix is usually in the tool schema, not the system prompt.
Treating the LLM as a database. Any fact that matters — customer IDs, prices, policies — belongs in a tool call, not in the prompt. Prompts drift, get truncated, get stale. Tools return today's data.
How BizFlowAI approaches this
We build small-team automations for SMBs on the skills-and-tools model, mostly on Claude with a thin MCP layer where it earns its keep. That means one agent per real workflow, tools that map to concrete business actions (fetch invoice, draft reply, flag for review), and hard human gates on anything that touches money or a customer inbox. It's less impressive on a diagram than a multi-agent orchestration, and that's the point — the systems that survive contact with real invoices are the ones you can debug at 11pm without paging a specialist.
The Intuit story is a useful sanity check. If a team with their resources needed two rewrites to land on this pattern, a five-person shop trying to skip straight to a multi-agent orchestrator is signing up for the same lessons at their own expense. If you want to talk through a specific workflow before committing to an architecture, book a discovery call and we'll sketch what a v1 that survives to v2 actually looks like for your stack.
What to take from Intuit's two rewrites
The headline is that a fast path exists, but it doesn't look like getting the architecture right on the first try. It looks like shipping the simplest thing that answers a real user request, watching where it breaks, and being willing to throw the design away when the evidence says so.
Concretely, for a solopreneur or small ops team starting now:
- One agent, one tool set, one gated action. Ship it in a week.
- Log every turn. Write ten evals before you write feature two.
- Don't reach for orchestration, multi-agent, or MCP until you can point at a specific pain that pattern solves.
- Expect a rewrite in month three. Design tools that will survive it.
Intuit's four-month arc isn't a warning that AI agents are too hard for small teams. It's the opposite — proof that even the well-resourced teams are converging on patterns simple enough for a small team to run. The advantage of being small is you can skip v1 and v2 and start at v3, as long as you're honest that v3 is where the field currently is, not where it will be forever.
Work with BizFlowAI
If you'd rather have this built for you, that's what we do: production AI automation for solo founders and small teams — agents, integrations, and document pipelines that actually ship.
Book a free discovery call — 30 minutes, we map the highest-ROI automation in your workflow. No pitch deck, just engineering.
More guides like this on the BizFlowAI blog.
Frequently asked questions
Why do specialist AI agent architectures usually fail?
Specialist agents fail because real user requests cross task boundaries, forcing either agent-to-agent calls or a central router. Shared state between agents creates cache invalidation and ownership problems similar to microservices, but worse due to LLM non-determinism. The same input can trigger different agent paths, silently breaking assumptions. Most teams end up rebuilding as a routed or skills-based system within months.
What is the skills and tools pattern for AI agents?
Skills and tools is an architecture where a small number of general LLM agents call discrete, typed functions (tools) directly, using the model's native function calling to route. There is no separate orchestrator or supervisor agent. Tools are versioned, testable, and described in prompts written for the model. Destructive tools require external approval tokens the LLM cannot forge.
When should I use MCP instead of raw tool calling?
Use Model Context Protocol (MCP) when the same tools are shared across multiple agents or codebases, typically once you have three or four reusable integrations. For a single agent with fewer than five tools, raw function calling is simpler and faster to ship. MCP adds a protocol layer and running server process, which is overhead you only recoup at scale. The signal to migrate is copy-pasting tool definitions between projects.
Why did Intuit rebuild its AI agent architecture twice?
Intuit VP of AI Nhung Ho said they went from specialist agents (v1) to a central orchestrator (v2) to a skills-and-tools model (v3) in about four months. V1 broke on coordination and shared state, v2 broke because the orchestrator became a bottleneck requiring surgery for every new capability, doubling latency and cost. V3 works because routing lives inside a single LLM call via function calling. Each rewrite was only obvious after shipping the previous version.
How do you prevent an AI agent from taking destructive actions autonomously?
Require an approval token as a mandatory input parameter on destructive tools like refunds, deletes, or payments. The LLM cannot generate valid tokens, so it must request human approval through a separate flow before the tool can execute. This gate is enforced at the tool schema level, not by prompt instructions. It prevents postmortems like an agent refunding hundreds of customers by hallucination.