ai-sdk-heal has 972 recorded weekly downloads on npm, a decrease of 30.3% over the past 30 days, ranking #1452 of 2,322 tracked listings.
About ai-sdk-heal
ai-sdk-heal

Keep your AI SDK conversations valid. ai-sdk-heal normalizes message arrays so they satisfy each provider's structural rules — pairing tool calls with results, coercing tool inputs to objects, preserving reasoning blocks correctly, and more.
One function. Pure. Idempotent. Safe on the hot path and on persisted history.
import { healMessages } from "ai-sdk-heal";
const { messages, repairs } = healMessages(rawMessages, { provider: "anthropic" });
await streamText({ model, messages });
What it does
Providers each have their own rules for what a valid message history looks like:
- Anthropic requires every
tool_useto be paired with a matchingtool_result, reasoning blocks to carry asignature, and rejects assistant messages that contain only reasoning. - OpenAI's Responses API expects reasoning items to be followed by a same-flow item.
- All of them require tool inputs to be objects and tool names to match
^[a-zA-Z0-9_-]{1,64}$.
Agents, retries, and persisted conversations make it easy to drift out of those rules — especially across long multi-turn flows with thinking models and parallel tool calls. ai-sdk-heal checks the whole history against the active provider's rules and returns a normalized copy, plus an audit trail of every change it made.
Rules
| Rule | What it does |
|---|---|
orphan-tool-use | Assistant tool-call with no matching tool-result: inserts a placeholder result (or drops the call) so the pairing invariant holds |
orphan-tool-result | tool-result referencing a call that isn't in history: drops it |
invalid-tool-input | Tool input stored as a raw string because JSON parsing failed upstream: coerces to { raw: "…" } so subsequent turns stay usable |
invalid-tool-name | Tool names with characters outside ^[a-zA-Z0-9_-]{1,64}$: sanitizes while keeping the call/result pair linked |
duplicate-tool-result | Same toolCallId appearing twice after a retry: dedupes |
empty-assistant-message | Assistant message with no substantive content: drops it |
orphan-reasoning-only-message (Anthropic) | After pruning, an assistant message contains only reasoning blocks: drops it |
missing-reasoning-signature (Anthropic) | Reasoning block with no providerOptions.anthropic.signature: drops it (Anthropic won't accept thinking without the signature on replay) |
reasoning-without-following-item (OpenAI) | Trailing reasoning part with no following item in the Responses flow: drops it |
Every change is captured in the repairs array so you can log it, alert on it, or surface it in admin tooling.
Each rule maps to a documented scenario tracked upstream: #8516, #9141, #11602, #13430, #13645, #14259, #8379, #7729, #12504.
Where this fits in the pipeline
ai-sdk-heal operates on ModelMessage[] — the array you pass to generateText / streamText. If you persist conversations as UIMessage[] (the React/UI shape) and call convertToModelMessages, that conversion sits before healMessages:
DB / state AI SDK ai-sdk-heal provider
────────── ────── ─────────── ────────
UIMessage[] ──convertToModelMessages──> ModelMessage[] ──healMessages──> ModelMessage[] ──> Anthropic / OpenAI / …
│ │
└─ pass `ignoreIncompleteToolCalls: true`
to drop UI-level orphans during conversion
The two layers solve different problems:
convertToModelMessages({ ignoreIncompleteToolCalls: true })filtersstate: "input-available"UI parts that haven't received a result yet. Use it for live UI message arrays where the user might have aborted mid-tool-call.healMessagesrepairs anything that survives conversion or that lives only inModelMessage[]form: missing reasoning signatures, invalid tool names, malformed tool inputs, duplicate tool results, OpenAI Responses ordering, persisted DB rows from older SDK versions, and the orphans thatpruneMessagescreates (#13430, #12504).
A defense-in-depth setup combines both:
const modelMessages = await convertToModelMessages(uiMessages, {
ignoreIncompleteToolCalls: true,
});
const { messages } = healMessages(modelMessages, { provider: "anthropic" });
await streamText({ model, messages });
Install
npm install ai-sdk-heal
Peer dependency: ai >= 5.0.
Usage
Heal before the provider call
import { healMessages } from "ai-sdk-heal";
import { anthropic } from "@ai-sdk/anthropic";
import { streamText } from "ai";
const { messages, repairs } = healMessages(rawMessages, {
provider: "anthropic",
onRepair: (r) => logger.info({ repair: r }, "message-normalized"),
});
const result = streamText({
model: anthropic("claude-sonnet-4-20250514"),
messages,
});
If you want to hard-fail during development instead:
healMessages(rawMessages, { provider: "anthropic", throwOnRepair: true });
Wrap your model once with withHealing
If you'd rather not remember to call healMessages on every request, wrap
the model itself. The wrapper heals the prompt as it passes through the AI
SDK middleware layer:
import { withHealing } from "ai-sdk-heal";
import { anthropic } from "@ai-sdk/anthropic";…
Description from the npm listing.
- ai
- ai-sdk
- vercel
- anthropic
- openai
- gemini
- tool-calls
- messages
- sanitize
- repair
- heal
- middleware
- llm
- agent
README badge
Show your rank in a README or on your website. The badge updates automatically.
Charts
Images: 30d · 1y · all time · 1600×900 dark
Adoption over time
7/30/90-day growth
Ranking history
Listing placement
Listing placement
Filled points are observed values; hollow points come from Internet Archive snapshots of the listing page. Dashed segments span periods with no observations — values between points are not interpolated.
Each band is one page of 20. Weekly downloads on a linear scale. Placement is projected from weekly downloads, so it can differ from the marketplace's own sort order. Hover a dot to see the listing.
Recent observations
Full history (544)Similar npm AI SDKs plugins
All 20 ai-sdk-heal alternativesData source
Weekly downloads (trailing 7 complete days) come from the official npm downloads API. Downloads include CI and mirrors and are not equivalent to installs or users. npm publishes no ratings.
Listing: https://www.npmjs.com/package/ai-sdk-heal. First seen Oct 16, 2026; last successful collection Oct 20, 2026. See the methodology.