Claude Haiku 5.5 vs 4.5 for classification, extraction and summaries
Compare Haiku 5.5 and 4.5 on real API classification, extraction and summary requests. Inspect JSON contracts, recorded usage and a safe migration workflow.
Claude Haiku 5.5 is worth evaluating for repetitive application tasks, but a model upgrade should pass your output contract before it replaces Haiku 4.5. In our small Ofox test, both versions returned the expected classification and extraction values. Their summary shapes differed, and both wrapped responses in Markdown fences despite requests for JSON. A correct-looking answer was not automatically valid input to a strict JSON parser.
This article compares three fabricated tasks sent to the real API, shows the recorded results, and provides a migration procedure for developers maintaining batch processing or application backends. It does not establish a general accuracy, latency or cost winner. There was one request per task per model, six requests in total, without a structured-output schema.
Anthropic announced Haiku 5.5 on October 7, positioning it for high-volume work including classification and summaries. Those product claims are separate from the narrow observations below.

Actual Ofox interface captured October 12, showing the model identifier and Anthropic SDK example. Our comparison below uses the separately specified Chat Completions route; this screenshot establishes the setup reference, not evaluation success.
The test contract
We used https://api.ofox.io/v1/chat/completions, max_tokens: 1800, and these exact Ofox IDs:
anthropic/claude-haiku-4.5
anthropic/claude-haiku-5.5
We did not explicitly set temperature or reasoning controls. Provider defaults, routing and token accounting can differ. The same user text therefore does not guarantee the same effective computation budget. Inputs contained no customer data, real orders or personal information.
The downloadable test kit includes the prompts, sanitized response evidence and scripts. Running the API scripts makes real requests and can incur usage charges; inspect them and set your own bounded test budget first. Original observations are dated to the batch, not regenerated each time this page is read.
| Task | Expected information | Acceptance boundary |
|---|---|---|
| Classify four tickets | A billing; B technical; C account; D billing | Exactly the expected ID-to-label mapping |
| Extract an order | BX-71; quantity 12; no delivery date; EUR | Preserve integer and null types; invent no date |
| Summarize a meeting | Maya; October 14 deadline; English-only pilot; price undecided | Preserve the approved decision and unresolved item; inspect shape separately |
The summary prompt requested named fields but did not provide a formal schema. This makes it useful for discovering an integration risk, not for asserting a model’s inability to follow an enforced schema.
Results: values and response shape are different checks
| Task | Haiku 4.5 | Haiku 5.5 |
|---|---|---|
| Ticket labels | Four expected labels returned | Four expected labels returned |
| Order extraction | Expected fields and values, including null delivery date | Expected fields and values, including null delivery date |
| Summary representation | A top-level tasks array with separate entries | Requested fields at the top level |
| Strict JSON directly from text | Markdown fences present | Markdown fences present |
For classification and extraction, the values matched after removing the single enclosing code fence. If your consumer does a direct json.loads(response_text), that same response is a parse failure. Choose and document whether the consumer accepts a single fence; do not silently “repair” arbitrary malformed output until it resembles your expected answer.
The Haiku 5.5 summary was a flat object:
{
"owner": "Maya",
"deadline": "2026-10-14",
"decision": "English-only pilot approved",
"unresolved": "Price undecided"
}
Haiku 4.5 instead grouped the draft email, pilot approval and undecided price into separate task entries. That representation contained useful information, but a consumer expecting top-level owner and deadline would not find them. With only one sample and an underspecified schema, the responsible conclusion is to test and enforce your integration contract—not that one version always summarizes better.
The flat object also leaves the email-drafting action implicit. If the business needs both action and decision, require separate fields. “Matches the schema” and “contains every operational fact” are two different acceptance tests.
Observed latency and tokens
These are client-observed request durations and API-reported token counts. They include the chosen gateway path and are not model-only inference measurements.
| Task | 4.5 seconds | 5.5 seconds | 4.5 input / output tokens | 5.5 input / output tokens |
|---|---|---|---|---|
| Classification | 1.833 | 1.791 | 64 / 43 | 89 / 45 |
| Extraction | 1.750 | 1.779 | 61 / 49 | 88 / 46 |
| Summary | 1.979 | 2.411 | 64 / 142 | 87 / 191 |
The summary request to 5.5 took longer in this run. That single observation neither refutes the vendor’s broader positioning nor predicts your production latency. Repeat representative cases, include failures and collect a latency distribution before changing a service-level expectation.
Do not count the visible answer’s words as billed output tokens. Record the returned usage fields and reconcile them with the provider’s request record. Our table reports what the API returned; it does not explain every difference in internal accounting or claim a settled dollar charge.
For budgeting, compare cost per accepted result, not just input and output rates. A practical worksheet is:
cost per accepted result =
reconciled spend across initial attempts, retries and fallbacks
/ number of results that pass your acceptance rules
Exclude neither rejected outputs nor fallback calls from the numerator. If there are no accepted results, the ratio is undefined; it is not zero. Look up the exact provider’s current rates and applicable cache or context tiers before calculating spend. This article intentionally makes no fixed Ofox savings claim.
Use a stricter extraction contract
Start with a prompt that spells out missing-value and type rules. This is an improved template, not the prompt used for the measurements above:
Extract only facts explicitly present in the input.
Return a single JSON object, without Markdown or commentary.
Keys must be exactly:
order_id: string
quantity: integer
delivery_date: ISO YYYY-MM-DD string, or null if not stated
currency: three-letter currency code, or null if not stated
Do not infer a delivery date from today's date.
Do not convert an unknown value to an empty string.
Input:
Order BX-71 contains 12 notebooks. Delivery is not scheduled.
Total: 48 EUR.
Validate the resulting object in code. If your chosen route supports schema-constrained output, validate that feature with the exact model and endpoint before adopting it; our prompt-only tests do not verify it.
import json
def validate_order(text):
value = json.loads(text) # Strict: intentionally rejects code fences.
expected = {"order_id", "quantity", "delivery_date", "currency"}
if not isinstance(value, dict) or set(value) != expected:
raise ValueError("Unexpected object shape")
if not isinstance(value["order_id"], str):
raise ValueError("order_id must be a string")
if type(value["quantity"]) is not int:
raise ValueError("quantity must be an integer")
# Fixture-specific assertions; replace with production business rules.
if value != {"order_id": "BX-71", "quantity": 12,
"delivery_date": None, "currency": "EUR"}:
raise ValueError("Fixture facts do not match")
return value
The exact-value assertion is appropriate to this synthetic fixture. A production validator also needs domain rules for allowed currency values, valid dates and record identifiers; it cannot compare every customer record with BX-71.
Migrate without losing failed records
Keep the model ID as an explicit configuration value and preserve the original until the replacement passes a representative evaluation. For each input, record a stable record ID, prompt version, model ID, attempt count, returned usage, validation status and output. Store errors as records instead of dropping those rows from a batch.
Begin with a small labeled set containing common cases and boundary cases: missing dates, contradictory information, unknown categories, empty input, unusually long text and instructions embedded in the input. Treat input documents as data. They should not be able to replace your extraction instructions or select arbitrary tools.
Compare semantic acceptance separately from JSON syntax and shape. Review disagreements before widening the rollout. During a limited rollout, maintain the old route as a controlled fallback, cap retries and track duplicate processing. If a request times out, it may still have reached the provider; avoid assuming no usage occurred.
For classification, define what happens when no allowed label fits. For summaries, define which facts may be omitted. For extraction, define whether ambiguous fields become null or enter human review. Those decisions usually matter more to application correctness than changing the model string alone.
If you also use Claude Code, validate its connection separately with the curl-versus-client diagnostic guide. Text API success is not a test of your coding client’s tools or configuration.
Frequently Asked Questions
- Did Haiku 5.5 win all three tests?
- No such overall ranking is justified. Both returned the expected classification and extraction values. The summary structures differed; every measured response included Markdown fencing, which our strict parsing contract would reject.
- Is Haiku 5.5 always cheaper per completed task?
- This test does not establish that. Compare actual accepted outputs, all retries and fallbacks, current provider rates and reconciled usage. A lower rate alone is not a complete task-cost measurement.
- Can I switch by changing only the model ID?
- That may be enough to send a request, but it is not enough to validate an application migration. Recheck output syntax, fields, semantic completeness, limits, latency and rollback behavior.


