Start with self-hosted Actae (free)
Self-hosting is the default way to run Actae: one free, self-contained binary with the API, dashboard, and PostgreSQL embedded — no account, card, or control plane. Download it from actae.dev/download and run it.
$ tar -xzf actae-<version>-<platform>.tar.gz && chmod +x ./actae $ ./actae # the banner ends with: # Dashboard: http://127.0.0.1:8002 # API key: sk-… (shown once — store it now)
You still need an API key — a local key the binary generates and prints once on first boot, not an account or portal credential. There is no signup. Mint more with actae keys create <name>. (Anonymous access is off by default.) Point the SDK at http://127.0.0.1:8002 with that key (ACTAE_URL/ACTAE_API_KEY for newClientFromEnv()). Prefer not to operate it? Actae Cloud is the managed runtime.
Install
$ npm install @actae/sdk
Node 20+, ESM-only, single runtime dependency ws. newClientFromEnv() reads ACTAE_URL, ACTAE_WS_URL, ACTAE_API_KEY.
60-second start
typescriptimport { ActaeClient } from "@actae/sdk";
const client = new ActaeClient({ apiKey: "sk-…", endpoint: "http://localhost:8002"});
const ev = await client.record("my-channel", "agent.step", { input: "hello"}, { actor: "agent"});
const events = await client.replay("my-channel", { limit: 100});API surface
The SDK mirrors the Python ActaeClient 1:1 — every HTTP method is available directly and through namespaced facades (client.events.record(...) === client.record(...)).
record, replay, query, transitionclient.eventssaveState, latestState, listStates, getState, deleteStateclient.statefork, getForkReceipt, resolveStep, diffStates, decisionTrail, compareChannels, promoteChannel, …client.channelsclaimExecution, completeExecution, failExecution, heartbeatExecution, cancelExecutionclient.executionscreateGroup, joinGroup, claimWork, ackWork, heartbeat, groupOffsetsclient.groupsscheduleWakeup, listWakeups, getWakeup, cancelWakeupclient.wakeupsconnect, subscribe, subscribeAndWait, publish, streamclient.wsErrors
All errors extend ActaeError: AuthError (401), LockError (402), ConnectionError (transport), RateLimitError (429, with retryAfterSeconds), SnapshotBoundaryError/VersionConflictError/IdempotencyConflictError (409s), SessionError/SessionCompletedError/NoRestorableCheckpointError, ServerError (5xx). Fork with instanceof.
WebSocket realtime
typescriptawait client.connect();
client.onMessage((topic, event) => console.log(topic, event));
await client.subscribe("my-channel", 0); // cursor 0 = replay from start
const ev = await client.publish("my-channel", { note: "hi"});
client.disconnect();publishreturns the persisted event from the server ack; a stableoperationIdmakes retries idempotent.stream(topic, cursor?)is an async iterator of live events, ending on disconnect.- The server does not echo publishes back — set
echoSelf: truefor single-client demos. - Auto-reconnect (0.5s → 30s backoff) resubscribes all topics;
disconnect()disables it permanently.
int64 / bigint fidelity
Integers beyond Number.MAX_SAFE_INTEGER arrive as bigint — never silently rounded. The serializer emits bigint as raw JSON number tokens, so received payloads round-trip. Accessors asInt64, asBigInt, asFloat, asString, asMap, asList mirror the Go SDK.
AgentSession, StateManager, and adapters
AgentSession covers step/fork/resume with deterministic operation keys, boundaryMode (exact/approximate/lineage_only), and boundary provenance on the session (forkReceipt, sourceStateSha256, reproducibility). StateManager is the framework-agnostic versioned-state helper.
Adapters live behind subpath exports with lazy framework imports: @actae/sdk/adapters/langgraph (ActaeCheckpointSaver), /langchain, /claude, /openai (installActaeTracing), /codex (CodexOTLPReceiver), /copilot. No CrewAI adapter — CrewAI has no TypeScript port.