Model or dataset
moeru-ai/xsai avatar
moeru-ai/xsai

xsAI: a small OpenAI-compatible runtime for browser, edge and agent code

🤖💬 extra-small AI SDK.

658 stars60 forksTypeScriptMIT

At a glance

What is it?
xsAI is an ESM-only TypeScript SDK that keeps the OpenAI-compatible surface and drops the provider abstraction layer. It suits browser, edge and agent work where a full AI framework is more than the job needs.
Who is it for?
Adopt xsAI when your model endpoint already speaks the OpenAI wire format and you want a dependency that fits in a browser bundle or an edge worker, and when you are willing to own retries and provider quirks yourself. Skip it if you need one client that talks to Anthropic, Gemini and Bedrock through a single normalized API, or if you need a framework that manages agents, memory and tracing.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 28, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What xsAI is for, and what it refuses to be

The README states the project's position plainly: xsAI is built for cases where full-featured AI frameworks are too heavy, too broad, or simply unnecessary. It keeps three things in view, which the README lists as small size, runtime portability and a focused OpenAI-compatible surface. Everything else is deliberately out of scope. The README says there is no universal provider abstraction, no attempt to be a full AI application framework, and no unnecessary runtime baggage.

That framing tells you who this is for. If your application already talks to an OpenAI-compatible endpoint, whether that is OpenAI itself, a local Ollama server or any gateway that exposes the same shape, then a framework whose main value is normalizing many providers is mostly dead weight in your bundle. xsAI targets that gap. The audience is TypeScript developers building browser apps, edge functions, or agent tooling who want the request and response plumbing without an opinion about how their application is structured.

The trade-off is real and worth naming. A focused OpenAI-compatible surface means portability across runtimes, not portability across vendors. If a provider's API diverges from the OpenAI shape, xsAI does not smooth that over for you. The README does not document a compatibility shim or a translation layer, so the assumption is that your endpoint conforms.

How the Fetch API foundation shapes the architecture

The mechanism is stated in the README: xsAI builds directly on top of the Fetch API, stays ESM-only, and avoids extra dependencies unless they are strictly necessary. That single design decision explains most of the package's behaviour. Because Fetch is available in browsers, Deno, Bun and edge runtimes, xsAI does not need to import Node.js built-in modules, which the README confirms it does not. That is what makes the same package work in a Cloudflare Worker and in a Node script.

The repository layout reinforces the modular claim. There is a packages/ directory alongside packages-ext/ and packages-top/, and the README points out that you can install only some of the utils, naming @xsai/generate-text and @xsai/stream-text as examples. So the architecture is a set of small packages rather than one monolith with tree-shaking as an afterthought. Streaming lives in @xsai/stream-text, text generation in @xsai/generate-text, and tool definitions in @xsai/tool, based on the import lines in the README examples.

The README gives a size comparison table using packagephobia and bundlephobia figures: [email protected] at 142KB install size, 22.7KB bundled and 7.1KB gzipped, against [email protected] at 5740KB install, 301.5KB bundled and 74.3KB gzipped. The README attributes the difference to xsAI's narrower scope and notes that the larger figure includes dependencies for tool calls and structured output. Treat those numbers as the project's own measurement at a specific version, not a general law, but the order of magnitude is the point of the design.

Installing xsAI and making a first call

The README gives install commands for five package managers. Pick the one your project already uses. The package is published as xsai on npm.

bash
npm install xsai

The same section lists yarn add xsai, pnpm add xsai, bun install xsai and deno install npm:xsai as the equivalents. After installation, the quick example in the README is the shortest path to a working call. It imports generateText from the top-level package, reads the key from the environment, and passes messages and a model name.

ts
import { env } from 'node:process'
import { generateText } from 'xsai'

const { text } = await generateText({
  apiKey: env.OPENAI_API_KEY!,
  baseURL: 'https://api.openai.com/v1/',
  messages: [
    { content: 'You are a helpful assistant.', role: 'system' },
    { content: 'This is a test, so please answer \'YES\' and nothing else.', role: 'user' },
  ],
  model: 'gpt-4o',
})

What you should see is the string "YES" logged, assuming the key is valid and the model name is one your endpoint accepts. Note the trailing slash on baseURL in the README example. If you would rather not pull the whole package, the README says you can install individual utils, so a text-only project can depend on @xsai/generate-text instead. For streaming, the README's example imports streamText from @xsai/stream-text and iterates the returned textStream with a for await loop, pushing each part into an array.

Tool calling depends on valibot, and that is a coupling to accept

The README's tool-calling example is the most instructive part of the documentation because it shows where xsAI spends its dependency budget. The tool helper comes from @xsai/tool, and the parameter schema is built with valibot primitives: object, pipe, string and description. The tool is defined with a name, a description, an execute function and those parameters, then passed into generateText through the tools array.

ts
import { tool } from '@xsai/tool'
import { description, object, pipe, string } from 'valibot'

const weather = await tool({
  description: 'Get the weather in a location',
  execute: ({ location }) => JSON.stringify({ location, temperature: 42 }),
  name: 'weather',
  parameters: object({
    location: pipe(string(), description('The location to get the weather for')),
  }),
})

The example also uses stopWhen: stepCountAtLeast(2), imported from @xsai/generate-text/shared-chat, and toolChoice: 'required'. That combination is what makes the model call the tool and then produce a final answer, which the README shows as "In San Francisco, it's currently 42°F." If you already use Zod or another schema library, this is a migration cost: the tool helper's parameter shape is valibot's, and the README does not present an adapter for other validators. That is a deliberate trade to keep one small schema dependency rather than many, but it is a decision your codebase inherits.

Where xsAI is the wrong choice

The clearest failure mode is provider diversity. If your product needs to call Anthropic, Google and a self-hosted model through one client with one normalized request shape, xsAI is the wrong tool, and the README says so by omission: no universal provider abstraction is a stated design goal, not a missing feature. You would end up writing the translation layer yourself, which is exactly the work a broader framework exists to do.

A second boundary is runtime. The README says xsAI does not depend on Node.js built-in modules and works in browsers, Deno, Bun and the Edge Runtime. That is a portability claim, not a guarantee for every environment. Any runtime without a global Fetch API is outside the design, and the README does not document a polyfill path.

Third, xsAI is not an application framework. There is no documented agent loop beyond the stopWhen and toolChoice parameters shown in the example, no memory store, no tracing or evaluation layer. If you need those, you are choosing to build them, and the README's community project list, which includes moeru-ai/airi, moeru-ai/arpk and GramSearch/telegram-search, suggests that is how the library is used in practice: as a small layer inside a larger application.

How xsAI differs from a full AI SDK

The natural comparison is the one the README itself draws: [email protected], the Vercel AI SDK. The difference is architectural, not cosmetic. A full SDK like ai invests in provider normalization, so your code names a provider and the library maps your request onto that provider's API, handling the differences in message formats, tool schemas and streaming encodings. xsAI declines that job. It sends an OpenAI-shaped request through Fetch and returns the parsed result.

The consequence is that xsAI's surface is smaller and its behaviour is more predictable if your endpoint is already OpenAI-compatible, but it gives you nothing when the endpoint is not. The README's size table quantifies the other side of the trade: 142KB install against 5740KB, and 7.1KB gzipped against 74.3KB. Those are the project's own figures for specific versions, and they measure the package, not your application's total cost. Still, for a browser extension or an edge worker with a bundle budget, the gap is the reason to care.

A second difference is the packaging model. xsAI publishes granular packages such as @xsai/generate-text and @xsai/stream-text, so a project that only needs one call shape can install one package. The README notes that @xsai/[email protected] is 22.6KB install size and 4KB bundled, 1.7KB gzipped. That granularity is the practical form of the small-size claim.

Maintenance, licence and what an upgrade costs

The repository is not archived, and the last push was on 2026-09-14, which is recent. The release history shows v0.5.0 "mirai" on 2026-08-29, preceded by v0.5.0-beta.8 on 2026-08-03 and v0.5.0-beta.7 on 2026-07-14, so the project moved through a beta series before the stable tag. The workspace package.json pins [email protected] and drives builds through turbo, with test and lint scripts defined at the root. That is a conventional monorepo setup, and it means contributing or building from source requires pnpm rather than npm.

On upgrades: the project is pre-1.0 and the version numbers show a beta cycle before each minor release. The README does not document a deprecation policy or a migration guide for breaking changes, so treat minor bumps as potentially breaking and read the release notes before moving. There is no documented rollback procedure either, which for a library means your lockfile is the rollback mechanism.

The licence is MIT, stated in the README and present as LICENSE.md in the repository root. MIT permits commercial use and modification with the copyright notice retained. That is a permissive arrangement, but this is not legal advice and you should confirm the terms against the LICENSE.md file itself, especially if your organisation has its own review process for dependencies.

Editorial conclusion

Adopt xsAI when your model endpoint already speaks the OpenAI wire format and you want a dependency that fits in a browser bundle or an edge worker, and when you are willing to own retries and provider quirks yourself. Skip it if you need one client that talks to Anthropic, Gemini and Bedrock through a single normalized API, or if you need a framework that manages agents, memory and tracing. Before committing, verify which subpackages you actually need, check that your target runtime has the Fetch API, and confirm the tool-calling path against your own model, since the README demonstrates tools with valibot schemas and the docs are the only place the full parameter list lives.

Frequently asked questions

Does xsAI work in the browser and in edge runtimes?

The README states that xsAI does not depend on Node.js built-in modules and works well in browsers, Deno, Bun and the Edge Runtime. It builds on the Fetch API, which is what makes that portability possible.

Can I install only part of xsAI instead of the whole package?

Yes. The README says you can install only some of the utils, naming @xsai/generate-text and @xsai/stream-text as examples, and it gives the size of @xsai/[email protected] separately from the full package.

Which schema library does xsAI use for tool parameters?

The README's tool-calling example builds parameters with valibot, importing object, pipe, string and description from that package and passing them to the tool helper from @xsai/tool. The README does not show an adapter for other schema libraries.

Official sources

  1. License: MIT
  2. moeru-ai/xsai on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/moeru-ai-xsai.svg)](https://hysenlabs.com/projects/moeru-ai-xsai)