Vercel AI SDK coupling
What we did
tapedeck targets only the Vercel AI SDK as a peer dependency
(ai >= 6.0.0 < 8), and specifically its language-model middleware
surface. It is a middleware, not a generic recorder. It records the SDK's
normalized request/response shape; it does not know, and deliberately
does not abstract over, any provider's raw wire format.
There is no "universal HTTP recorder" mode, no provider plugin system, no neutral cassette schema meant to outlive the SDK. A cassette is exactly as portable as the SDK abstraction it was recorded against.
Why bind tightly instead of staying generic
The honest framing: the SDK's request/response shape at the middleware layer is the structural ceiling on tapedeck's lifetime. If that shape changes incompatibly, tapedeck changes with it. We chose to accept that ceiling rather than paper over it, for two reasons.
Generic recording is what proxies already do — badly. A provider-agnostic HTTP recorder (nock/Polly) has to understand every provider's SSE envelope, auth scheme, and endpoint quirks, and it breaks every time one of them shifts. tapedeck's whole advantage is that it normalizes at the SDK's abstraction, which is precisely what makes it provider-agnostic within the SDK and stream-native by construction — see middleware, not a proxy. You can't get that benefit and also be SDK-agnostic; the benefit is the coupling.
A neutral cassette schema would lag both the SDK and reality. To record against the SDK and some other framework, the cassette would need a third, "neutral" shape that maps onto both. That shape would trail whichever upstream moved last, and every consumer would have to learn it. The SDK's own
content[]/ stream-part shape is already the lingua franca for AI SDK users; recording it directly means the cassette reads like the SDK and survives provider wire-format changes for free.
What the coupling buys, and how we manage its risk
Tight coupling is a real risk, so we make the boundary explicit rather than hide it behind an abstraction:
COMPATIBILITY.md— a public, dated record of everyaiversion tapedeck is tested against, what "pass" means (typecheck green, suite green, and a record→replay round-trip that stays byte-identical while a changed prompt misses), and the markers for⚠️ partialand❌ fail.A peer range that only widens on evidence.
peerDependencies: { "ai": ">=6.0.0 <8" }. A new SDK major joins it after the weekly compat cron proves it green, which is howai@7got in. What forces a tapedeck major is a spec shape change deep enough to break the fields tapedeck reads, not an SDK major that renumbers the spec: the middleware is typed structurally over those fields, so it satisfies spec v3 (ai@6) and spec v4 (ai@7) from one object, and a spec v5 would surface as a red type test rather than a silent consumer-side cast.The cassette
versionfield plus recorded provider/model. Every cassette carries"version": "tapedeck@0.1.0"and the recordedmodelProvider/modelId. If a future tapedeck or SDK changes the format, the version string makes the boundary visible at replay time instead of producing a confusing miss.
{
"version": "tapedeck@0.1.0",
"hash": "sha256:abc123…",
"request": { "modelProvider": "openai", "modelId": "gpt-4o", "prompt": [ … ] }
} ai release newer than the latest row there, you're ahead
of the tested matrix — a spec-shape change could surface as a CassetteCorruptError or an unexpected replay miss. Check
the table before bumping.What v2 might reconsider
The deferred list kept the first cut tight on purpose, and what has
landed since stayed inside the boundary: OTel span emission, the tapedeck CLI, cassette diff/merge tooling, and the edge-safe core in
0.2.0, multi-interaction named cassettes in 0.3.0, and drift detection in 0.4.0. None of them
weaken the coupling: they extend what tapedeck does within the SDK
abstraction. A genuinely SDK-agnostic recorder is not on the roadmap; it
would be a different, weaker product.
Consequences
- Sharp at one thing. tapedeck is the record/replay tool for AI SDK users, and every distribution surface — the README, the cassette shape, the peer range — reinforces that.
- The ceiling is visible.
COMPATIBILITY.md, the peer range, and the cassetteversionfield make SDK drift a documented, dated, loud event rather than a mystery. - The cost is reach. If you're not on the Vercel AI SDK, tapedeck is not for you — by design.
Related
- Compatibility table
- The middleware:
src/middleware.ts - The cassette format:
src/cassette.ts