BROWSER-NATIVE AI · 0 RUNTIME DEPS · Open Source

web-ai-sdk

The TypeScript SDK for the Web AI surface.

Get startedView onGitHub
the question

Why not just use the APIs directly?

Link to the why-not-the-raw-APIs section

You can, and nothing here stops you. The Web AI surface is 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
coverage

Why one package per capability.

Link to the why one package per capability section

One model surface.

A single text-generation model abstraction reaches exactly one of these built-ins, LanguageModel (Prompt). Useful, but one surface, not the whole product.

  • Prompt / LanguageModel only
  • Text, tools, structured output

Seven surfaces beyond it.

The rest carry options a text-out contract cannot hold, so each gets its own thin package.

  • Translator (source + target language, pair-cached sessions)
  • Summarizer (type and length)
  • Writer (tone, format, length)
  • Rewriter (relative tone/length shifts)
  • Proofreader (per-issue offsets)
  • Detector (confidence scores, alternates)
  • WebMCP (an agent surface, not a model)
capability matrix

One lifecycle layer, eight surfaces.

The same guarantees, applied per API. Not every capability needs every feature; the matrix below tracks what each package actually does.

Link to Capability matrix section
PackageStreamingSession reuseResult cacheAbortSignal
@web-ai-sdk/prompt
@web-ai-sdk/webmcp
@web-ai-sdk/summarizer
@web-ai-sdk/translator
@web-ai-sdk/detector
@web-ai-sdk/writer
@web-ai-sdk/rewriter
@web-ai-sdk/proofreader
Streaming = AsyncIterable output. Session reuse = sessions cached by config so repeat calls skip model setup (conversation turns, language pairs, task options). Result cache = opt-in memoized results. AbortSignal = cleanup wiring on unmount and abort.
packages

Composable wrappers. One philosophy.

Link to Packages section
@web-ai-sdk/prompt
Talk to the on-device language model. Sessions, streaming, and AbortSignals; done.
  • 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/promptweb-ai-sdk Prompt API docs
ask() · streamingsession: cached · balanced
Output will stream here…
statusidletok0ms0tok/s0
model: on-device LM
support

Browser support.

Web AI support 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.

Link to Browser support section
PackageChromeEdgeSafariFirefox
@web-ai-sdk/prompt148+ stable138+ flag, Canary/Devno-op fallbackno-op fallback
@web-ai-sdk/summarizer138+ stable138+ stableno-op fallbackno-op fallback
@web-ai-sdk/translator138+ stable148+ stableno-op fallbackno-op fallback
@web-ai-sdk/detector138+ stable148+ stableno-op fallbackno-op fallback
@web-ai-sdk/writer137+ flag, OT138+ flag, Canary/Devno-op fallbackno-op fallback
@web-ai-sdk/rewriter137+ flag, OT138+ flag, Canary/Devno-op fallbackno-op fallback
@web-ai-sdk/proofreader141+ flag, OT142+ flag, Canary/Devno-op fallbackno-op fallback
@web-ai-sdk/webmcp146+ flag, OT 149+147+ flagno-op fallbackno-op fallback
Each version links to its source. stable = on by default; Canary/Dev = preview channel, needs the matching flag; flag = normal channel, behind a flag; OT = origin trial. WebMCP/Edge is empirical (no official page yet).
how it works

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.

Link to How it works section
// summarize.ts
import { 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,
})
philosophy

Why composable.

Link to Philosophy section

We handle the rough edges.

The Web 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

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 the design system.

  • Framework-agnostic core
  • Optional /react subpath
  • No global state, no providers required
  • Tree-shakable per package
  • Pick the layers you need
ArchitectureOwner
Browser Web AI
document.modelContext, Summarizer, Translator, LanguageModel, LanguageDetector, Writer, Rewriter, Proofreader
platform
@web-ai-sdk/X
ask(), createSession(), summarize(), translate(), detect(), write(), rewrite(), proofread(), registerTool(), AbortSignal, session cache
web-ai-sdk
@web-ai-sdk/X/react
usePrompt(), useSession(), useSummarizer(), useTranslator(), useDetector(), useWriter(), useRewriter(), useProofreader(), useWebMCP()
web-ai-sdk
Your application
Card, Button, Spinner, the design system
your code
ship it

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.