Getting Started

Connect Blazing Agents to your app

Add one backend endpoint that authorizes a product chat, calls Blazing Agents, and relays the response stream. Use this pattern when a browser or mobile application needs stateful chat without receiving a tenant API key or Session ID.

Before you begin

Complete the Quickstart, then set BLAZING_AGENTS_AGENT_ID in your backend environment to the printed ag_... Agent ID. You also need an authenticated backend endpoint and application storage that maps each authorized product user and chat to its Blazing Agents Session ID.

Keep credentials on the backend

The browser or mobile app must never receive the Blazing Agents API key. Authenticate and authorize the application chat before loading or accepting any Session mapping.

Put your backend between users and Blazing Agents

Browser or mobile app → your authenticated backend → Blazing Agents

Your backend authenticates the user, authorizes access to its own chat, selects the Agent, and calls Blazing Agents. Add the opaque tenant-chosen userId when you need end-user Attribution and metering; userId does not authorize access to a resource.

Add a chat endpoint

This framework-neutral handler keeps application-specific support in app.ts. Its authorize function authenticates the request and authorizes the chat; its Session lookup and save are scoped by both application user and chat; requireEnv throws for a missing or empty value; and reportIntegrationError surfaces failures to your application monitoring. The Build a chat endpoint guide covers the support wiring in depth.

import { BlazingAgentsError } from "@blazing-agents/sdk";
import { client } from "./client.ts";
import * as app from "./app.ts";
const agentId = app.requireEnv("BLAZING_AGENTS_AGENT_ID");
export async function handleChat(request: Request): Promise<Response> {
  const { chatId, userId, message } = await app.authorize(request);
  const existingSessionId = await app.loadSessionId(userId, chatId);
  const result = await client.chat({
    agentId, ...(existingSessionId ? { sessionId: existingSessionId } : {}),
    message, signal: request.signal, userId,
  });
  if (existingSessionId) return result.toResponse();
  const sessionId = await result.sessionId;
  const upstream = result.toResponse();
  const relay = new TransformStream<Uint8Array, Uint8Array>({
    async flush() {
      try {
        await client.sessions.messages(agentId, sessionId, { limit: 1 });
      } catch (error) {
        if (BlazingAgentsError.isInstance(error) && error.code === "not_found") return;
        throw error;
      }
      await app.saveSessionId(userId, chatId, sessionId);
    },
  });
  void upstream.body!.pipeTo(relay.writable).catch(app.reportIntegrationError);
  return new Response(relay.readable, { headers: upstream.headers, status: upstream.status });
}

Relay the stream

result.toResponse() provides an AI SDK UI-message SSE response. The handler preserves its bytes and headers, including Content-Type: text/event-stream, Cache-Control: no-cache, and X-Accel-Buffering: no; configure intervening proxies not to buffer or rewrite the response. See the streaming protocol for wire details.

Persist and resume the Session

The first call omits sessionId. The SDK reads the minted ID from response headers, and the handler commits its (userId, chatId) → sessionId mapping only after the stream finishes and the Session can be read.

A successful Turn commits its transcript. A failed or aborted first Turn does not materialize the Session, so the completion probe receives not_found and stores no mapping. Other probe failures and mapping-write failures error the relay and reach the application's error reporter instead of being discarded. Later calls load the server-owned mapping and pass its sessionId to client.chat().

Verify the integration

Send a first request that asks the Agent to remember a distinctive value. Confirm that the response streams incrementally and that your backend then stores an ss_... ID for the authorized user and chat.

Send a second request for the same application chat asking for that value. Confirm that the handler uses the mapped ID and the answer reflects the first Turn's stored context.

Production notes

  • Never trust a browser-supplied chat ID until your backend has authorized it for the authenticated user.
  • Forward the request AbortSignal so a disconnected caller can cancel the Turn.
  • Keep the API key and Session mapping in backend-only storage.
  • Alert on reported Session-mapping failures or enqueue them for durable retry.
  • Disable response buffering and preserve SSE headers across every proxy in the path.

Reference

On this page