Interview prep
SmellCouplers

Raw HTML Tool Output

Ferramenta que Cospe HTML

Raw HTML Tool Output is an AI code smell, a sign of trouble in LLM systems, in the Couplers group. The tool returns the whole page, menus and footer included, and the model gets lost.

Element
25/37
Level
Beginner
Read
4 min
Updated
On this page 7
  1. 01Signs and symptoms
  2. 02Reasons
  3. 03Cost of ignoring
  4. 04Treatment
  5. 05Payoff
  6. 06When to ignore
  7. 07Is it this smell?
  8. ··Quick answers

Signs and symptoms

A browser agent needs to find a product’s price on a store’s site. The fetch_page tool returns the page’s HTML. The trace (anonymized):

tool=fetch_page  url=store.example/product/123
result_tokens=31,840
result_preview="<!DOCTYPE html><html lang="en"><head><meta charset=...
  <nav class="main-menu">...[140 category links]...
  <script>window.__STATE__={...}</script>...
  <footer>...privacy policy, careers...</footer>"

To read one number, the agent paid for more than 30,000 tokens. By the second page, the context was above 60,000. By the fourth, the model quoted the price of the “related product” in the footer.

On a Brazilian marketplace the same pattern repeats: the listing page carries a menu, recommendations, other buyers’ questions, tracking scripts, and the price in three places (cash, installments, “was / now”). The model picks one. Sometimes the wrong one.

Signs of Raw HTML Tool Output:

  • Tools return HTML, API JSON, or logs in full, with no filtering.
  • Tool results run to tens of thousands of tokens.
  • The agent gets information wrong that was in the result, because there was too much noise.
  • The context fills up after a few calls.
  • The content includes scripts, menus, footers, and ads.
flowchart LR
  A(["1. Agent asks for the page"]):::llm --> T["2. fetch_page"]:::tool
  T --> H["3. Full HTML: menu, scripts, footer"]:::untrusted
  H --> A
  A --> X(["4. Wrong price, full context"]):::io
  1. The agent needs a small piece of data.
  2. The tool fetches the source.
  3. It returns everything, as it came.
  4. The model hunts for the data amid the noise and sometimes finds the wrong one.
Check +20 XP on first tryThe agent read four product pages. Context passed 120,000 tokens and the answer used the price of a 'related' item in the footer. Which design failure came first?

Reasons

  • The tool was written as a thin wrapper. requests.get(url).text is the fastest implementation. In ten minutes the agent “reads the web”. The cost of not filtering shows up in the trace, not in the first commit.
  • Trusting the model to filter. “It finds what it needs” is often true, at a high cost and with errors when the number appears several times.
  • Nobody looked at result sizes. Without traces that show tokens per tool, the weight is invisible. The bill arrives at month end, and the wrong price looks like a hallucination.
  • Converting HTML to markdown looks like enough. html2text strips the tags and leaves the menu, the footer, and the recommendations. Eight thousand tokens of prose still hide the price.

The paper “Lost in the Middle” (Liu et al., 2023) showed that models retrieve worse the information that sits in the middle of a long context, and better what sits at the start or the end. A 30,000-token page puts the product price exactly where the model misses most, in the middle, between <nav> and <footer>.

Cost of ignoring

  • Money. One tool call can cost more than the rest of the task. Four pages at 30,000 input tokens are already more than 100,000 tokens before the agent answers.
  • Quality. Too much noise leads to wrong data. Listing price, struck-through price, “customers also viewed” price.
  • Context. A few calls fill the window and degrade the decisions that follow. The agent forgets the original question because the HTML took the space.
  • Security. More outside text in the context means more room for hidden instructions. Greshake and colleagues (2023) showed indirect injection in content the agent fetches. A huge page is a larger billboard for the attack. See Instructions from Untrusted Data.

A bill for one price

The numbers below are illustrative. Suppose the agent compares 10 listings and each raw page is about 30,000 tokens.

Tool return Tokens per page For 10 listings (input only)
Raw HTML 30,000 300,000
Clean text, no menu or script 800 8,000
Fields title, price, installment, url about 40 400

Extraction in code (a selector, JSON-LD, an API field) turns the task from “find a number in a novel” into “read a record”. The model compares ten prices. It does not hunt for ten needles.

Treatment

Refactoring Choose it when
Normalize Tool Output Always. The tool returns only the useful fields, in a stable format: clean main text, or extracted fields. Also a target: MCP Adapter.

Three levels, from cheapest to most general:

  1. Deterministic filter. Strip script, style, nav, footer, ads. Convert the rest to text. That already cuts most of the tokens.
  2. Fields extracted in code. If you always want price, title, and availability, the tool returns those. CSS selector, JSON-LD, API endpoint. Failure becomes a tool error, not a model hallucination.
  3. Summary inside the tool. When the layout varies too much for a selector, a small model (no side-effect tools) reads the page and returns the record. The main agent never sees the HTML.

The trap: normalizing only the HTML and leaving the log tool returning 5,000 lines, the API tool returning nested JSON with 400 keys, the email tool returning the whole MIME. The smell is raw output, not the .html extension.

Check +20 XP on first tryYou already convert the page into clean text of about 800 tokens, without menus and scripts. The agent still quotes the installment price instead of the cash price. What is the most useful next step?

Payoff

  • Tool results of hundreds of tokens, not tens of thousands.
  • The model finds the right data.
  • Longer tasks fit in the context.
  • Less surface for malicious content.

When to ignore

  • The raw content is the task. An agent that inspects a page’s HTML for accessibility problems needs the HTML. Even then, strip scripts and styles, which do not enter the analysis and bloat the context.
  • Low volume and small pages. If the result is already short (an API that returns 80 tokens with the price), normalizing brings little. Measure size in the trace before you build a parser.

Is it this smell?

Check +20 XP on first tryA log search tool returns the service's last 5,000 lines, and the agent needs to know whether there were 500 errors in the last 10 minutes. Is this Raw HTML Tool Output?

Check +20 XP on first tryEach of the agent's tools returns a different format: one returns XML, another nested JSON, another plain text. The model gets confused combining results. Which smell is closest?

Check +20 XP on first tryThe fetch_page tool calls the store's API and returns the fields price, currency, and sku, about 30 tokens. The agent sometimes gets a two-store comparison wrong. Is this Raw HTML Tool Output?

Check +20 XP on first tryAn accessibility agent receives the page HTML, without script and without style, to list contrast and alt problems. The HTML is 4,000 tokens. Is this Raw HTML Tool Output?

Quick answers

What is Raw HTML Tool Output?

Raw HTML Tool Output is an AI code smell, a sign of trouble in LLM systems, in the Couplers group. The tool returns the whole page, menus and footer included, and the model gets lost.

How do you fix Raw HTML Tool Output?

With Normalize Tool Output. Each refactoring has safe step-by-step mechanics with an eval before and after.

Where does Raw HTML Tool Output show up in practice?

In the real-world scenarios On-call incident agent and Browser agent for repetitive tasks.

Go further

Relations

Refactorings that treat it 1
Search