Skip to content

CLI & SDK

openma is callable via two routes:

  • @openma/cli — a Node CLI for scripting against the API.
  • Anthropic’s official SDKs — TypeScript (@anthropic-ai/sdk), Python (anthropic), and Go (anthropic-sdk-go) — pointed at openma’s baseURL. The openma API is wire-compatible with the Claude Managed Agents API, so the same SDKs work against both.

The CLI lives in this repo (packages/cli).

Terminal window
npm i -g @openma/cli

The CLI reads two env vars:

Terminal window
export OMA_BASE_URL="https://app.openma.dev"
export OMA_API_KEY="oma_..."

For self-hosters, point OMA_BASE_URL at your own deployment.

Terminal window
# List agents
oma agents list
# Create an agent from a JSON file
oma agents create -f ./my-agent.json
# Start a session
oma sessions create --agent agent_abc123 --env env_abc123 --title "research"
# Chat — post a turn AND stream the reply token-by-token to your terminal
oma sessions chat sess_xyz "Summarize the openma docs."
# Fire-and-forget message (no streaming back; useful when something else is tailing)
oma sessions message sess_xyz "Now also include the integrations."
# Tail a session's full event stream (SSE under the hood)
oma sessions tail sess_xyz
# Replay a session's full event log
oma sessions logs sess_xyz
# Show your usage
oma usage

Run oma --help or oma <command> --help for the full surface.

The openma API is wire-compatible with the Claude Managed Agents API, so the recommended client is one of Anthropic’s official SDKs pointed at our baseURL. One SDK, two providers — moving between them is a config line.

Terminal window
npm i @anthropic-ai/sdk
# or: pnpm add @anthropic-ai/sdk
# or: bun add @anthropic-ai/sdk
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
baseURL: "https://app.openma.dev",
apiKey: process.env.OMA_API_KEY!,
});
// Create an environment.
const env = await client.beta.environments.create({
name: "my-env",
config: {
type: "cloud",
networking: { type: "unrestricted" },
packages: { type: "packages", pip: ["pandas"] },
},
});
// List sessions.
for await (const sess of client.beta.sessions.list({ limit: 10 })) {
console.log(sess.id, sess.title);
}

Every namespace in the official SDK works against openma:

NamespaceNotes
client.beta.environmentslist, create, retrieve, update, archive, delete
client.beta.agentslist, create, retrieve, update, archive, plus versions sub-resource
client.beta.sessionslist, create, retrieve, update, archive, delete, plus events, resources, threads sub-resources
client.beta.vaultslist, create, retrieve, update, archive, delete, plus credentials sub-resource
client.beta.memoryStoreslist, create, retrieve, archive, delete, plus memories, memoryVersions sub-resources (update not yet implemented server-side)
client.beta.filesfull list/upload/retrieve/delete
client.beta.skillsfull coverage
client.beta.modelsfull coverage

Endpoints that don’t exist in Anthropic’s API (tenants, OAuth, integrations, evals, cost reports, runtimes, …) live under /v1/oma/*. They aren’t typed in the official SDK — call them via the underlying client:

const usage = await client._client.get("/v1/oma/cost_report");

Or use plain fetch — every OMA endpoint is JSON, no extra runtime needed.

A small set of OMA-specific agent fields (auxiliary model, harness selector, sandbox runtime binding) are passed through under an _oma: body field on agent create / update calls. The server reads them; the upstream Claude Managed Agents backend would ignore them. They are optional — agents that omit _oma behave exactly like a vanilla Claude Managed Agents call.

FieldPurpose
aux_modelAuxiliary model used for tool-internal LLM work (e.g. web_fetch summarization). When unset, tools fall back to returning raw content.
harnessSelects the agent loop harness implementation. Reserved for OMA-managed runtimes.
runtime_bindingSelects which sandbox runtime services the agent’s sessions. Reserved for OMA-managed runtimes.

The Stainless-generated SDKs in every language pass unknown body fields through unchanged — there is no separate @openma/sdk to install. Use the SDK’s standard escape hatch:

import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
baseURL: "https://app.openma.dev",
apiKey: process.env.OMA_API_KEY!,
});
const agent = await client.beta.agents.create({
name: "researcher",
model: { id: "claude-opus-4-7" },
_oma: { aux_model: { id: "claude-haiku-4-5" } },
} as any); // SDK is strict-typed; extras pass through at runtime
// Response: cast to read the field back.
console.log((agent as any)._oma?.aux_model?.id);

The server returns Anthropic-standard error envelopes, so the SDK’s typed errors work as documented:

import Anthropic from "@anthropic-ai/sdk";
try {
await client.beta.sessions.retrieve("sess-bogus");
} catch (err) {
if (err instanceof Anthropic.APIError) {
console.error(err.status, err.error); // {error: {type, message}, request_id, type: "error"}
if (err.error?.error?.type === "not_found_error") { /* ... */ }
}
}