@operator-labs/sdk
v0.2.2
Published
TypeScript SDK for the Operator platform — manage agents, chat, instances, automations, and webhooks programmatically.
Readme
@operator-labs/sdk
TypeScript SDK for Operator.io.
Operator.io is the API for building, managing, and hosting OpenClaw agents using AI.
Use op.chat when you want 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
npm install @operator-labs/sdkQuick Start for Operator.io
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
const op = new Operator({
apiKey: "ck_live_...", // Required: Chat API key from the dashboard
});Getting an API Key
- Go to Settings > API Keys in the Operator.io dashboard
- Click Create Key
- Copy the key (starts with
ck_live_orck_dev_)
API Reference
Health
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 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.
// 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 to inspect or evolve an instance filesystem or state, use op.chat.send(...).
// 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
// 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
// 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)
// 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:
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
