Ground Truth

Build or Buy Your Agent Infrastructure

Mostafa DhouibMostafa Dhouib··7 min read
The short answer

Almost every agent platform sells the part that is easy and leaves you the part that is hard. The loop, the tool dispatch, and the trace viewer are commodity. Whether your system knows it made progress, what it does when it gives up, and what stops a call tree are yours regardless of what you buy.

Build or Buy Your Agent Infrastructure

The short answer. The build-or-buy line is not where vendors draw it. The loop, tool dispatch, streaming, retries, and a trace viewer are commodity and you should buy them. The measure of remaining work, the distinction between finishing and giving up, the budget across a call tree, and the gates on irreversible actions are all specific to your task, and no platform can supply them because they require knowing what done means for your work. Buy the plumbing, own the stopping conditions.

What is actually commodity

Genuinely solved, genuinely not worth your time, and improving faster than you would improve it.

The conversation loop and message assembly. Tool schema definition and dispatch. Streaming and partial output handling. Provider abstraction across model vendors. Retry and backoff on transport errors. Trace capture and a viewer. Token accounting.

If you are writing these, stop. The differentiation is zero and the maintenance is permanent.

What no platform can give you

Each of these requires knowing what your task means, which is exactly the knowledge a general platform does not have.

Buy: commodity
The conversation loop and message assembly
Tool schema definition and dispatch
Provider abstraction, streaming, transport retry
Trace capture and a viewer, token accounting
Build: yours regardless
The measure of remaining work
requires knowing what done means for your task
Done versus gave up, as different types to the caller
A budget carried across the whole call tree
Gates on irreversible actions, and grounded verification
If you are writing the left column, stop. If you are expecting a platform to supply the right column, it cannot.
FigureThe build-or-buy line is not where vendors draw it. Everything on the left is undifferentiated; everything on the right is the reason your system works or does not.

The measure of remaining work. A number your code computes from ground truth, shrinking as the task nears done: rows unmigrated, tests failing, records unmatched. A platform cannot know what counts as progress in your domain. Without it the loop can only stop because a model said so or a counter ran out, and neither is a completion signal.

The distinction between done and gave up. Whether a run finished or exhausted its budget must be different types to the caller. Platforms return a result object; making the two distinguishable, and forcing every caller to handle both, is your type system and your call sites.

The budget across the tree. Twenty capped agents each calling twenty capped agents is four hundred runs, all inside their limits. A platform bounds the loop it runs. Whether the tree has a budget carried through every nested call is your architecture.

The gates on irreversible actions. Which of your actions cannot be undone, and what stands in front of each, is a fact about your business. A framework can offer a hook; what goes in it is yours.

The verification that is grounded. A platform can call a second model for you. Whether the check compares against something the system did not generate depends on your domain having a checkable artifact.

The decision table

LayerBuyBuildWhy
Conversation loop, message assemblyYesNoCommodity, improving faster than you would
Tool schema and dispatchYesNoCommodity
Provider abstractionYesNoCommodity, and it hedges vendor risk
Transport retry and backoffYesNoCommodity
Trace capture and viewingYesSometimesBuy unless you need it in your own observability stack
Remaining-work measureNot availableYesRequires knowing what done means for your task
Done versus gave upPartlyYesPlatforms return a result; the distinction is your types and call sites
Task-level budget across a treeRarelyYesPlatforms bound their own loop, not your tree
Irreversible-action gatesHooks onlyYesWhich actions are irreversible is a fact about your business
Grounded verificationModel calls onlyYesNeeds a checkable artifact from your domain
Evaluation set and quality metricNoYesRequires your definition of correct

The pattern: everything above the line is undifferentiated and everything below it is the reason your system works or does not.

The trap in the middle

The uncomfortable case is a platform that appears to supply something below the line and supplies a shape of it.

A max-iteration setting looks like a stopping condition. It is a bound on spend, not on progress, and hitting it returns something the caller cannot distinguish from a completed answer. Configuring it feels like having solved stopping. Nine frameworks across nine organisations, different languages and years, all check the model's opinion and a counter, and none checks a measure of remaining work.

A guardrails module looks like enforcement. Read what it does: if it is a model call classifying the output, it is an opinion with a policy-shaped name.

A human-in-the-loop hook looks like a gate. It is a place to put one. Which actions route through it is your decision, and the default is usually none.

A max-iteration setting
looks like a stopping condition. Bounds spend, not progress, and hitting it returns something indistinguishable from a completed answer
A guardrails module
looks like enforcement. If it is a model call classifying the output, it is an opinion with a policy-shaped name
A human-in-the-loop hook
looks like a gate. It is a place to put one, and the default is usually none
The failure point
The test for any feature that sounds like it covers a safety property: what does it compute, and from what?
If the answer is a model call or a counter, it is above the line wearing a name from below it.
FigureThe uncomfortable case is a platform feature that appears to supply something below the line and supplies a shape of it.

The test for any platform feature that sounds like it covers something below the line: what does it compute, and from what? If the answer is a model call or a counter, it is above the line wearing a name from below it.

How to actually choose a platform

Given that the important parts are yours regardless, the criteria change.

Can you get the remaining-work check into the loop? Not as a post-hoc callback, but as something the loop consults to decide whether to continue. Some frameworks make this awkward, which is a real cost.

Can a run return a type you define? If the exit shape is fixed and you cannot express three outcomes, you will be flattening them at your boundary forever.

Can a budget be carried through nested calls? Or does each sub-agent start fresh?

Can you get the trace out? Into your own systems, in a form you can compute on. A viewer you cannot query is a demo.

What happens on a partial success and a retry? Whether the framework re-executes tool calls it already made determines whether every non-idempotent tool you write needs its own protection.

How hard is it to leave? Assume you will. Lock-in on the commodity layer is the one kind you can afford, but only if the layer is actually thin.

The recommendation

Buy the plumbing. Insist on getting your own stopping conditions into it. Treat every platform feature that sounds like a safety property as unproven until you can say what it computes and from what.

Then run the five design-review questions against the result, because the framework will answer two of them and the other three are yours: what measures progress, what the caller gets when the budget runs out, what bounds the whole task, what the verifier has rejected, and which actions cannot be undone.

FAQ

Should we build or buy an AI agent platform? Buy the commodity layer: the loop, tool dispatch, provider abstraction, transport retry, and tracing. Build the parts that require knowing what your task means: the remaining-work measure, the distinction between finishing and giving up, the budget across nested calls, and the gates on irreversible actions.

Why can't a platform supply the stopping condition? Because a real stopping condition is a value computed from your domain's ground truth, and a general platform does not know what counts as progress in your work. What it can supply is an iteration cap, which bounds spend rather than progress.

Is a framework's max-iteration setting a stopping condition? No. It is a valid bound on effort, and hitting it returns something the caller cannot distinguish from a completed answer. Configuring it feels like having solved stopping, which is why it is the most common gap in production agents.

What should I check before choosing an agent framework? Whether you can get a remaining-work check into the loop itself, whether a run can return a type you define with three outcomes, whether a budget carries through nested calls, whether traces can leave in a computable form, what happens on retry after a partial success, and how hard it is to leave.

How do I evaluate a platform's guardrails feature? Ask what it computes and from what. If the answer is a model call classifying the output, it is an opinion with a policy-shaped name rather than an enforcement mechanism, and it belongs above the build-or-buy line rather than below it.

Free checklist
The Scale Readiness Check

Six sections that find the failures with no small-scale version: per-target limits and the feedback loop they cause, absence detection, the heterogeneity inventory, a load ramp that finds the knee rather than confirming today is fine, the degradation ladder, and cost per unit your customer buys.

One email, the resource, and nothing else unless you reply.
Carrying a program like this one?

Tell us the system, the stakes, and the date that matters. You get a straight technical reply from the person who would lead the work, within 24 hours.

Bring us the program