TypeScript SDK
The TypeScript SDK wraps the app-server JSON-RPC protocol for product surfaces, hosted workers, and test harnesses that want to start turns, stream events, run host tools, and connect either to a local app-server process or a remote WebSocket.
Hosted clients default to browser-safe bearer subprotocol auth, while native WebSocket transports can keep using authorization headers. The SDK never needs credentials in query strings.
Agent host
RoderAgent.create() accepts local process, remote WebSocket, or custom transport options. A host can set the workspace, provider/model preference, tool allowlist, developer instructions, approval callbacks, and external tools, then call send() to start a turn.
const agent = await RoderAgent.create({
local: {
cwd: process.cwd(),
inheritEnv: false,
env: {
HOME: "/tmp/roder-home",
PATH: process.env.PATH,
TMPDIR: process.env.TMPDIR,
OPENAI_API_KEY: process.env.OPENAI_API_KEY,
},
},
});
const run = await agent.send("Summarize this repo");Stream control
RoderRun.stream() and RoderRun.wait() now accept anAbortSignal. This gives UI clients and automation harnesses a clean way to bound a wedged notification stream without abandoning a parked read that can swallow a later event.
const signal = AbortSignal.timeout(30_000);
for await (const event of run.stream({ signal })) {
renderEvent(event);
}Display parts
createPartTransformer() derives display-ordered text, reasoning, and tool parts from raw SDK events. It gives each part a stable id and splits text around tool boundaries, so a UI can render pre-tool text, the tool row, and post-tool text in the order the user expects.
const parts = createPartTransformer();
for await (const event of run.stream()) {
for (const part of parts.push(event)) {
renderPart(part);
}
}
for (const part of parts.flush()) {
renderPart(part);
}Runner workspaces
SDK-created threads can bind coding tools to a remote-runner workspace. The runner config now supports readRoots, which lets file reads resolve under additional absolute runner paths while writes and the working directory stay confined to the main workspace.
const agent = await RoderAgent.create({
runner: {
providerId: "e2b",
workspace: "/workspace/project",
readRoots: ["/workspace/shared-docs"],
},
});PATH,TMPDIR, provider keys, and a managed HOME; avoid inheriting database URLs, service tokens, or a real $HOME/.codex/skills tree into hosted app-server sessions.