› cavi-ai/
GitHub ↗

Choose a backend and keep workflows reusable

Construct clients at your application's configuration boundary. Pass the resulting CapabilityClient into your run, stream, or batch functions. Those functions should accept application input, not provider credentials.

This reference describes the selected documentation artifact. For the OpenCode v2 polling adapter, Hermes profile routing, Managed Agents observed completion, and OpenClaw normalization options, see the provider compatibility guide. That guide states the version requirements; the examples below retain existing defaults.

ProviderExecution lifecycleBatchRequired configuration
Claude MessagesSynchronous; terminal state remembered locallyYesAnthropic key and available model
Claude Managed AgentsServer-side sessionsNoBeta access and persisted agent ID
CodexStored background responsesYesOpenAI key and available model
AGYSynchronous; terminal state remembered locallyNoService URL, API key, agent ID as model
OpenCodeScoped server sessionsNoCompatible server and absolute project directory
HermesGateway runs; SSE stream bridgeNoGateway URL/token; session key for streaming
OpenClawGateway RPC; WebSocket stream bridgeNoGateway URL/authentication and granted scopes

Runtime-only modules must be registered explicitly. The default registry contains Hermes and OpenClaw. Credentials supplied to the facade do not register an adapter. Resolved capabilities and each call's result determine what an instance can actually do.

Claude Messages and Codex at one boundary

This factory chooses the adapter from server configuration. Both clients can be passed into the same stream handler or run retrieval helper.

ts
import { createApiClient, createRuntimeProviderRegistry } from "@cavi-ai/api-client";
import { createClaudeProviderModule } from "@cavi-ai/api-client/providers/claude/messages";
import { createCodexProviderModule } from "@cavi-ai/api-client/providers/codex/runtime";

export function createBackend(config: { provider: "claude" | "codex"; apiKey: string }) {
  const module = config.provider === "claude"
    ? createClaudeProviderModule({ apiKey: config.apiKey })
    : createCodexProviderModule({ apiKey: config.apiKey });
  const registry = createRuntimeProviderRegistry({ modules: [module] });
  return createApiClient(config.provider, { registry, defaultTimeoutMs: 30_000 });
}

The returned client belongs to its application owner. Reuse it within the selected credential/configuration scope; dispose when that owner shuts down. Supply a provider-compatible model and tools in your run body. Changing the adapter does not translate native tool schemas or grant model access.

Claude Messages

startRun returns a terminal response. getRun reads remembered state from this client rather than polling Anthropic; it is not durable across restarts. Use streamRun for incremental events. The answer service returns text and usage to a caller.

Messages operations

Codex

The adapter uses the OpenAI Responses API, not a local Codex CLI. startRun can return an active run. Persist its ID and retrieve it later, or use a bounded local wait. Decide explicitly whether a local timeout should request cancellation.

Older releases normalize the response's output_text field without flattening native output items. A completed response can have no normalized text. Check the repository changelog before relying on it.

Codex operations

Claude Managed Agents

Use this stateful beta adapter when you already have provider access and a persisted agent. Configure an optional environment at the same boundary.

ts
import { createApiClient, createRuntimeProviderRegistry } from "@cavi-ai/api-client";
import { createClaudeManagedAgentProviderModule } from "@cavi-ai/api-client/providers/claude/managed-agents";

export function createManagedBackend(config: {
  apiKey: string; agentId: string; environmentId?: string;
}) {
  const registry = createRuntimeProviderRegistry({
    modules: [createClaudeManagedAgentProviderModule(config)],
  });
  return createApiClient("claude-managed-agents", { registry });
}

The module declares runs and streaming, not batch. Use the concrete Managed Agents client for agent, environment, vault, and deployment administration. Those operations are not universal facade resources.

Managed Agents operations

AGY

Supply an application-provided HTTP orchestration service implementing the documented routes and authentication. This adapter does not launch the agy CLI or Antigravity SDK, and CLI JSON/NDJSON is not its wire format. Set the run's model to the service's configured agent ID, or configure a module defaultModel.

ts
import { createApiClient, createRuntimeProviderRegistry } from "@cavi-ai/api-client";
import { createAgyProviderModule } from "@cavi-ai/api-client/providers/agy";

export function createAgyBackend(config: { baseUrl: string; apiKey: string }) {
  const registry = createRuntimeProviderRegistry({
    modules: [createAgyProviderModule({ apiKey: config.apiKey })],
  });
  return createApiClient("agy", { registry, baseUrl: config.baseUrl });
}

Runs are synchronous; retrieval and cancellation use remembered terminal state. Streaming distinguishes upstream failed runs from transport errors and does not infer completion from premature EOF. The HTTP response contract exposes available output and upstream status, without normalized token usage.

AGY operations

OpenCode

Run the server separately. The default v1 adapter targets OPENCODE_SERVER_VERSION and the legacy-http-sse endpoint family. Supply an absolute HTTP(S) URL without embedded credentials, query, or fragment, and an absolute project directory.

ts
import { createApiClient, createRuntimeProviderRegistry } from "@cavi-ai/api-client";
import { createOpenCodeProviderModule } from "@cavi-ai/api-client/providers/opencode";

export function createOpenCodeBackend(config: {
  baseUrl: string; directory: string; workspace?: string;
  username?: string; password?: string;
}) {
  const registry = createRuntimeProviderRegistry({
    modules: [createOpenCodeProviderModule({
      baseUrl: config.baseUrl,
      scope: { directory: config.directory, workspace: config.workspace },
      username: config.username,
      password: config.password,
    })],
  });
  return createApiClient("opencode", { registry });
}

A password enables Basic authentication; username defaults to opencode. Username alone does not enable authentication. Scoping selects server resources; it is not a sandbox guarantee.

The v1 adapter provides runs and streaming, without batch or gateway resources. Streaming subscribes before submission and has no reconnect/replay. Cancellation requests a server session abort. The separate v2 adapter uses HTTP polling and does not support streaming; see the provider compatibility guide.

OpenCode operations

Hermes

ts
import { createApiClient } from "@cavi-ai/api-client";

export function createHermesBackend(baseUrl: string, token: string) {
  return createApiClient("hermes", { baseUrl, token });
}

Use your deployed gateway origin and accepted authentication. For streamRun, supply the gateway's sessionKey in the body. Without it, the call returns a request-invalid gap and starts no run. Resources depend on the instance; teams also need a manifest or explicit backend.

Gateway resources · Hermes operations

OpenClaw

ts
import { createApiClient } from "@cavi-ai/api-client";

export function createOpenClawBackend(baseUrl: string, token: string) {
  return createApiClient("openclaw", {
    baseUrl,
    token,
    clientMode: "cli",
    requestedScopes: ["operator.read", "operator.write"],
  });
}

This is a headless server configuration. The WebSocket URL is derived from baseUrl unless supplied. In CLI mode no origin is derived automatically; for origin-gated configurations supply an allowlisted clientOrigin. Requesting scopes does not grant them.

The facade bridges native events into streamRun. Media/wiki depend on native RPC and installed plugins. Browser applications need gateway-approved identity/origin settings and browser-user credentials.

OpenClaw operations