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);