July 13, 2026
Inline Markup Over Tool Calls: Make the Answer One Pass
Tool calling is the basic building block of agents - and also one of the most expensive things you do on the answer path. Each call is a round-trip: the model stops, asks for a result, the system runs the tool, the result comes back, the model continues. For things the model genuinely doesn't know - how many rows the table has, what today's value is - it's necessary. For a lot of what an agent renders at the end of its answer anyway, it's pure wasted time.
Here's the trick worth knowing: things that would normally call a rendering tool, let the model emit directly in the streamed answer as inline markup, and let the frontend render it natively. A human can't tell the difference. The model writes text and tagged bits in one pass. No extra round-trip.
The waste you save
Take follow-up suggestions - the little pills under an answer that hint where to go next. The instinct is to implement them as a tool call: the model calls suggest_followups, gets back a list, and only then begins writing the answer. It sounds clean. But notice what just happened: to show anything, you first had to produce the suggestions. That's a whole extra model-call before the first token reaches the screen. Time-to-first-token got longer by an entire step the user didn't want to see before the text anyway.
The trade: let the model generate the suggestions as text in inline tags - a block at the end of the answer that the frontend parses and renders as pills. The model writes answer and suggestions in one pass. Text starts streaming immediately. Pills arrive at the end, naturally, because that's where the model writes them anyway. You save a round-trip exactly where it would cost the most - at the start.
Entity links in the text
The same principle holds for entity links inside the answer. When the model writes "computer science" and you want it clickable, opening a detail panel, the instinct is to call a tool that resolves the entity and returns a rendering payload. The better path: let the model write an inline tag right in the text - here is an entity of type program with this id - and validate it on the backend only. The frontend renders the tag as a clickable link. The entity's detail arrives in parallel, in its own frame, before the user clicks - so the popover that opens has data already, no loading spinner.
There's a price tag here, and it's worth saying straight: you give up type-safe output. A tool call would return structured data; an inline tag is text the model could have botched - a nonexistent id, a wrong type, broken syntax. That's why the backend validator isn't optional: every inline tag is checked against the database before it's let through. Invalid links are silently dropped so a dead link never reaches the user. A strict tag whitelist plus validation is the cost of the round-trip you saved.
Self-heal for diagrams
A fun detail shows up here: the model sometimes generates an inline diagram that's broken - invalid syntax, malformed JSON. The naive system shows "broken diagram" and the user spots that something's off. The better path is a repair loop: send the broken block back to the model with an instruction to fix it, and render only the repaired result. It costs one extra step, but only on the narrow class of cases where something broke - not on every answer. The ordinary answer is still one pass.
When the tool call wins
This isn't evangelism for "tool calling is bad." For things the model doesn't know and must ask about - row counts, live data, expensive computations - the tool call stays what it should be: a necessary query out into the world. The trick is to tell them apart. Rendering steps - things whose only purpose is to show something the model already has in its head - belong in inline markup. Querying steps - things that must ask - belong in tool calls. Teams that mix this up watch their agent burn turns at the end of an answer on rendering calls that ascertain nothing.
What to take with you
Every tool call costs a round-trip. If that round-trip is there to ascertain something, it's the right price. If it's there to display something, it's a price you didn't need to pay - the answer should have been born in one pass. Move rendering steps into inline markup, validate them on the backend, and let the frontend render them natively. Time-to-first-token drops, because you're no longer computing up front what's meant to arrive at the end. And a model writing in one pass is, paradoxically, more accurate - it isn't dragged through structured handshakes that pull it away from what it meant to say.
Your agent spending its last turns calling tools that ascertain nothing? Most of those steps can move into inline markup and the answer collapses to one pass. Let's look at what your bot is rendering through a tool call when it shouldn't.
