Concepts

Transports

How AI components send requests to your server and get answers back.

A transport is how an AI component sends a request and gets the answer back. Most apps use the fetch transport, which sends requests to a URL on your server. You create one and pass it to your component as the transport prop.

The transport does not care which AI provider you use. It only moves requests and answers.

Which one to use

OptionUse it forNetwork
createFetchTransportYour real app. Sends requests to your server routeYes
createMockTransportDemos and building UI without a server or API keyNo
mockGenerate + createFetchTransportTesting your server route without calling a modelYes
Your own transportSending requests some other way, such as WebSocketsDepends

Fetch transport (most apps)

import { createFetchTransport } from "@emend/ai/transport"

const transport = createFetchTransport({
  url: "/api/editor-ai",
})

It sends each request to your URL as a POST, and reads the answer as it streams back. If the server returns an error, such as 401 or 429, it turns it into an emend error your UI can show.

To add headers or change other options, see createFetchTransport.

Mock transport (no server needed)

import { createMockTransport } from "@emend/ai/transport"

const transport = createMockTransport({
  delayMs: 30,
})

It returns fake answers that match the action, so you can build and test your UI without a server or API key. Set failAfterDeltas to fake an error partway through an answer.

The demos on this site use a real model

The editors on this site use createFetchTransport with /api/editor-ai, which runs the Vercel AI Gateway recipe on OpenRouter's free models.

Build your own transport

If you do not want to send requests with fetch, you can write your own transport. It is an object with a run function that takes the request and returns the answer's events one at a time. emend does not include any other transports, so you write this part yourself. Its type is EmendTransport.

import type { EmendTransport } from "@emend/ai"

const transport: EmendTransport = {
  async *run(request, signal) {
    signal.throwIfAborted()

    for await (const event of readEvents(request, signal)) {
      yield event
    }
  },
}

Your transport must:

  • Stop when signal is aborted (for example, when the user clicks Stop), so you do not keep paying for an answer nobody will see.
  • Send back events with the same protocol version and request ID as the request. Events that do not match are ignored.

Next, read Supported Markdown and Compatibility to see which content the AI can edit and which versions emend supports.

On this page