npm package: @operator-labs/sdk
Description: TypeScript SDK for the Operator platform — manage agents, chat, instances, automations, and webhooks programmatically.
Latest version: 0.2.2

# @operator-labs/sdk

TypeScript SDK for [Operator.io](https://operator.io).

[Operator.io](https://operator.io) is the API for building, managing, and hosting [OpenClaw](https://openclaw.ai) agents using AI.

Use `op.chat` when you want [Operator.io](https://operator.io) to create agents, update files and skills, inspect instances, run web searches, or handle multi-step work. 

Use the typed methods for direct control over instances, config, automations, and webhooks.

## Installation

```bash
npm install @operator-labs/sdk
```

## Quick Start for [Operator.io](https://operator.io)

```ts
import { Operator } from "@operator-labs/sdk";

const op = new Operator({ apiKey: "ck_live_..." });

// Check auth
const status = await op.health();
console.log(status.planName, status.email);

// Ask Operator.io to build and manage agents for you
const { chatId, text } = await op.chat.send(
  "Create a new OpenClaw agent for outbound sales research and install the skills it needs."
);
console.log(text);

// Continue the conversation
const followUp = await op.chat.send(
  "Now update its state files so it posts a daily summary at 9am Bangkok time.",
  { chatId }
);
console.log(followUp.text);

// Ask Operator to do live web research through chat
const research = await op.chat.send(
  "Search the web for the title of https://example.com and answer with only the title text."
);
console.log(research.text);

// Structured multimodal input
const screenshot = await op.chat.send([
  { type: "text", text: "What is in this screenshot?" },
  {
    type: "image",
    mimeType: "image/png",
    path: "./screenshot.png",
  },
]);
console.log(screenshot.text);
```

## Configuration

```ts
const op = new Operator({
  apiKey: "ck_live_...", // Required: Chat API key from the dashboard
});
```

## Getting an API Key

1. Go to **Settings > API Keys** in the [Operator.io](https://operator.io) dashboard
2. Click **Create Key**
3. Copy the key (starts with `ck_live_` or `ck_dev_`)

## API Reference

### Health

```ts
const status = await op.health();
// { authenticated: true, userId: "...", planSlug: "pro", planName: "Pro", ... }
```

### Chat

`op.chat` is the main agent surface. Use it when you want [Operator.io](https://operator.io) to create agents, inspect an instance, read or mutate files, install or author skills, change agent behavior, run web research, or coordinate multi-step work. Use the typed resources below when you want direct control over common API objects.

Use natural language for web research. There is no separate SDK search method. Ask `op.chat` to search the web, inspect sources, or fetch a page.

```ts
// List all chats
const chats = await op.chat.list();

// Get a chat with messages
const detail = await op.chat.get("chat-uuid");

// Send a message and get the full response
const { chatId, text } = await op.chat.send("Create a new instance called my-agent");
console.log(text);

// Update agent files and skills through the agent
const edit = await op.chat.send(
  "Open the my-agent instance, update its core files for a stricter review style, install any missing skills, and summarize what changed."
);
console.log(edit.text);

// Continue a conversation
const followUp = await op.chat.send("Now check its logs", { chatId });
console.log(followUp.text);

// Web research through Operator chat
const research = await op.chat.send(
  "Search the web for https://example.com and answer with only the exact page title."
);
console.log(research.text); // "Example Domain"

// Send text plus one or more images
const vision = await op.chat.send([
  { type: "text", text: "Describe this image" },
  {
    type: "image",
    mimeType: "image/jpeg",
    dataUrl: "data:image/jpeg;base64,...",
  },
]);
console.log(vision.text);

// Stream a response token by token
const stream = await op.chat.stream("List my instances and their status");
for await (const event of stream) {
  if (event.type === "text-delta") process.stdout.write(event.text);
  if (event.type === "tool-call") console.log(`\n[Tool: ${event.toolName}]`);
}

// Collect the full streamed response as a string
const text = await (await op.chat.stream("Summarize my setup")).toText();

// Iterate over text chunks only
for await (const chunk of (await op.chat.stream("Hello")).textStream()) {
  process.stdout.write(chunk);
}

// Update title / delete
await op.chat.updateTitle("chat-uuid", "Deployment Chat");
await op.chat.delete("chat-uuid");
```

### Instances

Use `op.instances` for direct lifecycle and config management. If you want [Operator.io](https://operator.io) to inspect or evolve an instance filesystem or state, use `op.chat.send(...)`.

```ts
// List instances
const instances = await op.instances.list();

// Get instance details
const instance = await op.instances.get("instance-uuid");

// Create a new instance
const newInstance = await op.instances.create({ name: "my-agent" });

// Create from a checkpoint repo
const cloned = await op.instances.create({
  name: "from-checkpoint",
  checkpointRepo: "owner/repo",
});

// Update instance
await op.instances.update("instance-uuid", { name: "renamed-agent" });

// Restart (syncs config + secrets first)
await op.instances.restart("instance-uuid");

// Get logs
const logs = await op.instances.logs("instance-uuid");

// Config management
const config = await op.instances.getConfig("instance-uuid");
await op.instances.updateConfig("instance-uuid", { ...config, name: "updated" });

// Delete
await op.instances.delete("instance-uuid");
```

### Automations

```ts
// List automations
const automations = await op.automations.list();

// Create a scheduled automation
const automation = await op.automations.create({
  name: "Daily health check",
  prompt: "Check all instances and report any issues",
  cronExpression: "0 9 * * *",
  timezone: "America/New_York",
});

// Update
await op.automations.update(automation.id, {
  cronExpression: "0 */6 * * *",
  enabled: false,
});

// Delete
await op.automations.delete(automation.id);
```

### Webhooks

```ts
// List webhooks
const webhooks = await op.webhooks.list();

// Create a webhook
const webhook = await op.webhooks.create({
  name: "GitHub PR Handler",
  promptTemplate: "A new PR was opened: {{payload}}. Review and summarize it.",
});

// Update
await op.webhooks.update(webhook.id, { enabled: false });

// Delete
await op.webhooks.delete(webhook.id);
```

### Secrets (Environment Variables)

```ts
// List all secrets (metadata only, no raw values)
const secrets = await op.secrets.list();

// Create a new secret (raw value returned only here)
const secret = await op.secrets.create({
  name: "GITHUB_TOKEN",
  value: "ghp_xxxxxxxxxxxx",
  description: "GitHub personal access token",
});
console.log(secret.value); // only visible on create

// Get secret metadata
const meta = await op.secrets.get(secret.id);
console.log(meta.maskedPreview); // "ghp_****xxx"

// Update description (value cannot be changed, delete and recreate instead)
await op.secrets.update(secret.id, { description: "Updated description" });

// Toggle global access (available to all instances)
await op.secrets.setGlobal(secret.id, true);

// Grant/revoke access for a specific instance
await op.secrets.grantAccess(secret.id, "instance-uuid");
await op.secrets.revokeAccess(secret.id, "instance-uuid");

// List which instances have access
const { granted, available } = await op.secrets.listAccess(secret.id);

// Delete (removes from Key Vault and database)
await op.secrets.delete(secret.id);
```

## Error Handling

All API errors throw `OperatorApiError` with `status` and `body`:

```ts
import { Operator, OperatorApiError } from "@operator-labs/sdk";

try {
  await op.instances.get("nonexistent");
} catch (err) {
  if (err instanceof OperatorApiError) {
    console.error(`HTTP ${err.status}: ${err.message}`);
  }
}
```

## Requirements

- Node.js 18+ (uses native `fetch`)
- A valid API key from [Operator.io](https://operator.io)