Rebyte TypeScript SDK

The Rebyte TypeScript SDK is split into three layers so an integration can use the Agent runtime without adopting a particular frontend:

PackageResponsibility
@rebyte/agent-sdkFramework-free Responses client, durable Conversations, SSE parsing, and response accumulation
@rebyte/agent-reactHeadless React chat state plus browser/server transports
@rebyte/agent-uiOptional App Kit-style chat UI and execution inspector

The source is available in ReByteAI/rebyte-agent-sdk. The packages are not yet published to the npm registry. Until the first registry release, consume them from that repository as a workspace or file dependency. The package boundaries and public names above are stable; npm installation commands will be added when the release is available.

Core SDK

Organization API keys belong only in trusted server runtimes. The Core SDK refuses browser construction by default.

import { Rebyte } from "@rebyte/agent-sdk";

const client = new Rebyte({
  apiKey: process.env.REBYTE_API_KEY,
  baseURL: "https://api.rebyte.ai/v1",
});

Stream one Response

const stream = await client.responses.create({
  model: process.env.REBYTE_AGENT_ID,
  input: "Inspect this repository and summarize it.",
  stream: true,
});

for await (const event of stream) {
  if (event.type === "response.output_text.delta") {
    process.stdout.write(event.delta);
  }
}

const response = await stream.finalResponse();
console.log(response.conversation.id);

The event stream keeps standard Responses events and Rebyte's additive response.rebyte_tool_call.* events in arrival order.

Keep one durable Conversation

Use the Conversation helper when your application wants a stateful object:

const conversation = client.conversation({
  model: process.env.REBYTE_AGENT_ID,
});

await conversation.send("Remember that the deployment color is blue.");
await conversation.send("What is the deployment color?");

console.log(conversation.id); // one stable conv_... ID

The helper sends no continuity field on the first turn. It binds the returned conversation.id immediately and sends that ID on every later turn. It does not maintain a client-side previous_response_id chain or Conversation snapshot.

To attach to an existing Conversation:

const conversation = client.conversation({
  model: process.env.REBYTE_AGENT_ID,
  id: "conv_...",
});

Manage Conversations

The Conversation resource wraps Rebyte's durable Session lifecycle:

const created = await client.conversations.create({
  model: process.env.REBYTE_AGENT_ID,
  title: "Competitive research",
});

const current = await client.conversations.retrieve(created.id);
const page = await client.conversations.list({ model: current.model });
await client.conversations.interrupt(current.id);
await client.conversations.delete(current.id);

interrupt stops the active turn without deleting the Conversation. Deletion removes the Session runtime.

Headless React

@rebyte/agent-react owns state and transport, not markup. In a browser, point it at endpoints in your application so the organization key remains on your server:

import { useMemo } from "react";
import {
  createFetchTransport,
  useRebyteChat,
} from "@rebyte/agent-react";

export function Chat() {
  const transport = useMemo(
    () => createFetchTransport({
      url: "/api/responses",
      interruptUrl: "/api/conversations/interrupt",
    }),
    [],
  );
  const chat = useRebyteChat({ transport });

  return (
    <form onSubmit={(event) => {
      event.preventDefault();
      void chat.send("Hello");
    }}>
      {chat.messages.map((message) => (
        <p key={message.id}>{message.content}</p>
      ))}
      <button disabled={chat.status === "streaming"}>Send</button>
      {chat.status === "streaming" && (
        <button type="button" onClick={() => void chat.stop()}>
          Stop
        </button>
      )}
    </form>
  );
}

useRebyteChat exposes conversationId, streamed messages, status, errors, send, stop, and reset. stop calls the server-side Conversation interrupt before aborting the browser stream.

Optional UI

@rebyte/agent-ui provides one UI implementation on top of the headless hook:

import { createFetchTransport } from "@rebyte/agent-react";
import { AgentChat } from "@rebyte/agent-ui";
import "@rebyte/agent-ui/styles.css";

const transport = createFetchTransport({
  url: "/api/responses",
  interruptUrl: "/api/conversations/interrupt",
});

export function App() {
  return (
    <AgentChat
      transport={transport}
      agentName="Research Agent"
      inspector
    />
  );
}

The UI package is optional. A product can use the Core SDK alone, combine Core with the React hook, or replace every visual component while keeping the same Conversation transport.

Server proxy contract

The browser-facing Responses endpoint accepts text and an optional stable Conversation ID:

{
  "input": "Compare it with the previous company.",
  "conversation": "conv_..."
}

Your server adds the Rebyte Agent ID and organization API key, calls client.responses.create({ stream: true }), and forwards the upstream SSE body without buffering it. The interrupt endpoint accepts the Conversation ID and calls client.conversations.interrupt(conversation).

Never put REBYTE_API_KEY in browser code, client bundles, local storage, or a public environment variable.

Current protocol boundary

The initial SDK intentionally exposes the Responses subset Rebyte executes today:

  • text input and user text-message arrays;
  • synchronous Responses and live SSE;
  • stable conversation continuity;
  • durable Response retrieval;
  • standard text and MCP call events;
  • additive Rebyte tool-progress events;
  • Conversation create, retrieve, list, interrupt, and delete.

The raw Responses resource still accepts previous_response_id for wire compatibility, but Rebyte's Conversation helper, React bindings, and UI do not use it as state. Request-level OpenAI tools, file/image inputs, structured output, background mode, and Responses-native HITL continuation are not part of this release.