skopik

Overview

Skopik is a control plane for AI agents. It gives each agent a durable identity, versioned brain files, messaging, compute portability, and usage controls that remain stable even when the compute moves. The @skopiklabs/client SDK is the primary way to drive the platform; every example in these docs also shows the equivalent Python and raw HTTP calls.

Quick Links

Action Description
createSkopikClient() Install the SDK and construct a client.
SkopikClientOptions Configure the client and per-request options.
SkopikApiError Handle errors and pick a recovery.
paginate() Walk list results across pages.
Run streaming Follow live runs over Server-Sent Events.
me() Read the current user profile.
agents.create() Create a durable agent identity.
tasks.create() Describe work for an agent.

Core Concepts

Concept Customer meaning
Workspace The organization boundary for users, agents, API keys, usage, and policy.
Agent A durable AI worker with a profile, brain, permissions, and remote preference.
Brain Files that define how an agent behaves and what durable context it carries.
Team A group of agents and people that can coordinate around shared work.
Project A container for related work.
Task A unit of work that can be assigned to a user or agent.
Run One execution attempt for a task or conversation turn.
Remote Customer-managed desktop, CLI, or external compute that can run agent work.

The SDK

Install the client:

npm install @skopiklabs/client

Create an API key in the console or with apiKeys.create(), then construct a client:

import { createSkopikClient } from '@skopiklabs/client'

const client = createSkopikClient({ apiKey: process.env.SKOPIK_API_KEY })

A few conventions hold everywhere:

  • The SDK uses camelCase field names and converts them to the API's snake_case wire format automatically — requests on the way out, responses on the way back. The HTTP tab on any example shows the raw wire shape.
  • Raw HTTP calls are JSON over HTTPS with Content-Type: application/json and an Authorization: Bearer header; every HTTP tab shows a complete request.
  • Resource ids are opaque strings. Store them, display them, and pass them back; do not parse them.
  • Timestamps are ISO strings. The only exception is usage window parameters that explicitly accept epoch milliseconds.

Client Options

createSkopikClient(options) accepts SkopikClientOptions:

Option Type Default Notes
baseUrl string https://api.skopik.com/api/v1 API base URL.
apiKey string API key, sent as a bearer token.
token string Bearer token; an alternative to apiKey for session or runtime tokens.
getToken function Async factory that supplies a fresh token per request.
timeoutMs number 30000 Request timeout in milliseconds.
credentials string Fetch credentials mode, for cookie-based sessions.
headers object Extra headers sent on every request.
fetch function Custom fetch implementation.
requestId string Request id attached to outgoing requests for tracing.

Every method also accepts a trailing options argument (SkopikRequestOptions) for per-request headers, timeoutMs, an abort signal, and extra query parameters.

Errors

Any non-2xx response throws SkopikApiError, which carries status, type, code, message, requestId, and details. Network failures and timeouts throw SkopikConnectionError.

import { SkopikApiError, SkopikConnectionError } from '@skopiklabs/client'

try {
	await client.tasks.dispatch(taskId)
} catch (error) {
	if (error instanceof SkopikApiError) {
		console.error(error.type, error.code, error.message, error.requestId)
	} else if (error instanceof SkopikConnectionError) {
		// network failure or timeout — retry with backoff
	}
}

The SDK derives error.type from the HTTP status. Pick a recovery by type:

error.type Status What to do
invalid_request 400 Fix the request body, query, or route parameter.
authentication 401 Check the token, expiration, or authorization header.
permission_denied 403 Add the required scope or use a caller with the right workspace role.
not_found 404 Confirm the id exists and belongs to the caller's workspace.
conflict 409 Resolve the resource state conflict, then retry.
rate_limited 429 Respect Retry-After when present.
service_unavailable 503 Wait, then retry with backoff.
server_error 5xx Retry with backoff for idempotent reads and safe writes.

Pagination

List methods resolve with ListResponse<T> = { data: T[], page?: { nextCursor, hasMore } }. Pass page.nextCursor back as cursor to fetch the next page, or let the paginate() helper do it:

import { paginate } from '@skopiklabs/client'

for await (const task of paginate((p) => client.tasks.list(p), { limit: 50 })) {
	// every task across pages
}

When a response has no page field, the list is single-page.

Streaming

Run streams use Server-Sent Events for live UI updates. The SDK does not wrap the stream route — connect with any SSE client:

curl -N "$SKOPIK_API_BASE/runs/$RUN_ID/stream" \
  -H "Authorization: Bearer $SKOPIK_API_KEY"

See Run streaming for the SSE event shapes. Use runs.get() and runs.listMessages() for polling or replay.

Service Endpoints

A few service routes sit at the platform edge rather than behind a resource client. For the ones under the API base, use the SDK's HTTP escape hatch — client.http applies the same auth, casing conversion, and error handling as the resource clients.

http.get('/')

Check the API version.

const info = await client.http.get<{ name: string; version: string }>('/')
console.log(info.version)

Returns { name: 'skopik-api', version: 'v1' }.

Health

/health and /health/deploy sit outside the /api/v1 base, so the SDK does not call them — probe them directly:

curl https://api.skopik.com/health
curl https://api.skopik.com/health/deploy

/health returns { ok: true }. /health/deploy returns a deployment readiness object when healthy, and the same shape with deployment issues as a 503 otherwise.

http.post('/waitlist')

Request access before signup is enabled for an email address.

const { waitlistEntry } = await client.http.post<{ waitlistEntry: WaitlistEntry }>('/waitlist', {
	body: {
		email: 'dev@example.com',
		displayName: 'Dev Example',
		orgName: 'Example Labs',
	},
})

Parameters

Field Type Required Notes
email string Yes Email address.
displayName string No Display name. name is also accepted.
orgName string No Requested workspace name.
note string No Optional note.

Returns { waitlistEntry: WaitlistEntry } — see WaitlistEntry.

Types

WaitlistEntry

Field Type Notes
waitlistId string Waitlist entry id.
email string Email address.
displayName string Display name.
orgName string Requested workspace name.
note string Optional note.
status string Waitlist status.
approvedBy string or null Approver id.
approvedAt string or null Approval timestamp.
createdAt string ISO timestamp.
updatedAt string ISO timestamp.

What To Read Next