Skip to content

Server-Side Examples

UClaw provides AppClient in @uclaw/sdk for Node.js, Next.js route handlers, Workers, and other trusted server environments.

WARNING

Always initialize AppClient with your UClaw API key on the server side. Never expose uc_live_ keys in browser bundles.

Installation

bash
npm install @uclaw/sdk
# or
bun add @uclaw/sdk

Create an Agent and Stream a Run

typescript
import { AppClient } from "@uclaw/sdk";

const app = new AppClient({
  apiKey: process.env.UCLAW_API_KEY,
  appId: "default",
});

const agent = await app.agents.create({
  title: "Programming assistant",
  config: {
    model: "anthropic/claude-sonnet-4",
    instructions: "You are a senior programming assistant.",
  },
});

const run = await agent.run("Write a simple quicksort implementation in TypeScript.");
await run.wait({ until: "running", timeoutMs: 60_000 });

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

Inspect Run State

Run state is held by the SDK process for the current invocation. You can read it while the stream is running or after it completes.

typescript
const run = await agent.run("Summarize the release notes.");

await run.wait({ until: "running", timeoutMs: 60_000 });
console.log(await run.getStatus());

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

const finalState = await run.getStatus();
console.log(finalState.status);
console.log(finalState.events.length);

Manage Agents

typescript
const agents = await app.agents.list();
for (const item of agents) {
  console.log(`${item.title}: ${item.id}`);
}

const existing = app.agents.get("agent-id");
await existing.rename("Renamed assistant");

await app.agents.delete(existing.id);

Update Agent Configuration

typescript
const agent = app.agents.get("agent-id");

const nextConfig = await agent.updateConfig({
  instructions: "Answer in concise bullet points.",
  maxSteps: 20,
});

console.log(nextConfig);
console.log(await agent.currentConfig());

App-Level Text Generation

Use generateText or streamText when you need a one-off model call without creating a persistent agent.

typescript
const text = await app.generateText("Write a product tagline.", {
  modelTier: "fast",
});

console.log(text);
typescript
for await (const delta of app.streamText("Draft a short announcement.", {
  modelTier: "fast",
})) {
  process.stdout.write(delta);
}

Client Token API Handler

React clients connect to the durable agent runtime using short-lived client tokens. Instead of manually invoking fetch and managing credentials on the server, you can delegate request handling to AppClient.handler (which accepts a standard Web Request and returns a standard Response).

Create a Next.js App Router catch-all route at app/api/uclaw/[...all]/route.ts:

typescript
import { AppClient } from "@uclaw/sdk";

const app = new AppClient({
  apiKey: process.env.UCLAW_API_KEY,
});

// Automatically handles POST requests to /api/uclaw/client-tokens
export const POST = (request: Request) => app.handler(request);