Get started

Create your first session

Create a session with the SDK, wait for the turn to end, and read the model's answer

With the werft client from Install the SDK, create one session and follow it until the first turn ends. The examples assume the development server started with --fake-model. A GATE-SPEC {…} message is a script the fake model reads; on a server that runs the real Claude, send a plain sentence.

Pick a profile

A session runs on one of the profiles the server operator registered: the list you saw in Check the connection. The development server has claude-coding-local (a person answers permission requests) and claude-coding-auto (a classifier decides), which use a repository, and general, which runs without one. This page uses claude-coding-local.

Create a session

first-session.ts
import { waitForTurn } from "@werft-ai/sdk";
import { werft } from "./werft.ts";

const created = await werft.sessions.create({
  profile_id: "claude-coding-local",
  repository_id: "sample-app",
  message: 'GATE-SPEC {"id":"hello","steps":[],"final":"hello from Werft"}',
});
console.log(created);
{
  session_id: '…',
  turn_id: '1',
  receipt_id: '…',
  receipt_status: 'accepted',
  status: 'queued'
}
  • repository_id is the repository the session clones. The development server's read-only Git server provides sample-app.
  • message is the input of the first turn. This script calls no tool and ends with hello from Werft.
  • Creating a session only accepts it. Read the result after the turn ends.
  • A request that creates a session needs an Idempotency-Key. The SDK makes one per call and sends the same key when it retries that call.

Wait for the turn to end

The scheduler starts a worker, the worker clones the repository, and then it runs turn 1. The first time takes tens of seconds.

first-session.ts (continued)
const turn = await waitForTurn(werft, created.session_id, created.turn_id, {
  signal: AbortSignal.timeout(5 * 60_000),
});
console.log(`turn ${turn.turn_id}: ${turn.status}`);
turn 1: completed

waitForTurn checks every 2 seconds until the turn's status is a final value. completed, failed, interrupted, cancelled and outcome_unknown are final. failed is a status value, not an error, so judge whether the work got done from the events.

Read the model's answer

What happens in a session arrives on the event stream. The stream stays open after the turn ends, so end it yourself once you have the events you need.

first-session.ts (continued)
const stream = werft.sessions.events.stream(created.session_id);
for await (const event of stream) {
  if (event.kind === "assistant") {
    console.log((event.payload as { text?: string }).text);
  }
  if (event.kind === "result") break;
}
stream.close();
hello from Werft

The text of an assistant event is the text the model sent. Put the three pieces together in first-session.ts, run it with WERFT_API_KEY=csp_… node first-session.ts, and the output above appears in order.

Doing it with the HTTP API

The same flow is POST /v1/sessions (needs an Idempotency-Key header), polling GET /v1/sessions/{id}/turns/{turn_id}, and GET /v1/sessions/{id}/events (SSE).

Next steps

On this page