web-ai-sdk
The TypeScript SDK for the Web's Built-in AI APIs.Composable building blocks, no runtime deps, just lifecycle, streaming, and AbortSignals.
See the same task: 15 lines with the SDK vs 37+ with the raw APIs →Why not just use the APIs directly?
You can, and nothing here stops you. The browser's built-in AI APIs are the foundation.
web-ai-sdk owns the thin, repetitive lifecycle layer you would otherwise rewrite in every app: capability checks, model downloads, session reuse, streaming with chunk smoothing, AbortSignal cleanup, opt-in result caching, and feature-detected fallbacks. Drop down to the raw APIs whenever you want.
See why it's composable →Composable wrappers. One philosophy.
- Session reuse. Cached by config so re-renders do not churn the model.
- Streaming first. AsyncIterable out of the box; React hook gives you a string.
- Clean lifecycle. AbortController on unmount, retry on session-lost.
$ npm install @web-ai-sdk/prompt web-ai-sdk Prompt API → - Declarative tools. Register from React; AbortSignal cleanup on unmount.
- Last writer wins. Re-registers on hot reload without duplicate errors.
- Spec aligned. Wraps document.modelContext verbatim.
$ npm install @web-ai-sdk/webmcp web-ai-sdk WebMCP → - Four shapes. key-points, tl;dr, teaser, headline.
- Three lengths. short, medium, long. Deterministic with the same seed.
- Streaming summaries. Pipe chunks straight into your UI.
$ npm install @web-ai-sdk/summarizer web-ai-sdk Summarizer API → - Pair caching. Sessions cached per source to target pair. Switching is instant.
- Block round-trip. Walks the DOM, swaps text, keeps the markup intact.
- Graceful fallback. No-op fallback when the API is missing.
$ npm install @web-ai-sdk/translator web-ai-sdk Translator API → - Top candidate or full list. Use the best guess, or inspect every alternate above your threshold.
- Bias hints. Pass expectedInputLanguages to break ties between similar languages.
- Wire the others. Detect first, then summarize, translate, or prompt with the result.
$ npm install @web-ai-sdk/detector web-ai-sdk Language Detector API → - Task in, prose out. Give it a prompt; get back a paragraph, email, or post.
- Tone and length. formal, neutral, casual, across short, medium, and long.
- Markdown safe. Trims edges only, so formatting and line breaks survive.
$ npm install @web-ai-sdk/writer web-ai-sdk Writer API → - Relative adjustments. more-formal, more-casual, shorter, longer, as-is.
- Streaming first. Pipe the revised text in as the model produces it.
- Same lifecycle. Session reuse, AbortSignals, opt-in caching; shared with Writer.
$ npm install @web-ai-sdk/rewriter web-ai-sdk Rewriter API → - Corrected text and diffs. Get the clean string and the list of edits with offsets.
- Highlight inline. Offsets index the original input, so you can mark each error in place.
- One-shot. No streaming; resolves once with the full result and optional caching.
$ npm install @web-ai-sdk/proofreader web-ai-sdk Proofreader API → Why composable.
01 We handle the rough edges.
The built-in AI surface is young. Capability checks, model downloads, abortable streams, session lifetimes, and DOM-rebuild safety are all things you would otherwise re-implement in every component.
- Feature detection per package
- Session cache keyed by config
- AsyncIterable streams plus AbortSignal cleanup
- Hot-reload and StrictMode safe
- Zero-runtime fallback when API missing
02 You compose the stack.
We ship the lifecycle layer: state machines, streams, abort signals. Framework adapters, polyfills, and UI primitives stay optional so they do not constrain your design system.
- Framework-agnostic core
- Optional
/reactsubpath - No global state, no providers required
- Tree-shakable per package
- Pick the layers you need
Same task. Three levels of abstraction.
All three tabs do the same thing: detect an article's language and summarize it into key-points. Same result, less to wire up.
// summarize.tsimport { detect } from "@web-ai-sdk/detector"import { summarize } from "@web-ai-sdk/summarizer"const article = document.querySelector("article")const text = article?.innerText ?? ""const detection = await detect({ input: text })const { output: summary } = await summarize({input: text,language: detection.output?.language ?? "en",type: "key-points", length: "short",onUpdate: render,})
Browser support.
Built-in AI lands engine by engine, and it is desktop-only for now: mobile browsers, including Chrome and Edge on iOS and Android, are not supported yet. Where it is not there yet, you get a feature-detected no-op so your code does not crash.
| Package | Chrome | Edge | Safari | Firefox |
|---|---|---|---|---|
| @web-ai-sdk/prompt | 148+ stable | 138+ flag, Canary/Dev | no-op fallback | no-op fallback |
| @web-ai-sdk/summarizer | 138+ stable | 138+ stable | no-op fallback | no-op fallback |
| @web-ai-sdk/translator | 138+ stable | 148+ stable | no-op fallback | no-op fallback |
| @web-ai-sdk/detector | 138+ stable | 148+ stable | no-op fallback | no-op fallback |
| @web-ai-sdk/writer | 137+ flag, OT | 138+ flag, Canary/Dev | no-op fallback | no-op fallback |
| @web-ai-sdk/rewriter | 137+ flag, OT | 138+ flag, Canary/Dev | no-op fallback | no-op fallback |
| @web-ai-sdk/proofreader | 141+ flag, OT | 142+ flag, Canary/Dev | no-op fallback | no-op fallback |
| @web-ai-sdk/webmcp | 146+ flag, OT 149+ | 147+ flag | no-op fallback | no-op fallback |
Try it in your project.
One install, all eight blocks. Or pick the individual @web-ai-sdk/* packages. Ships ESM, CJS, and types. Tree-shakable.