Skip to content

SDK

There is a first-party TypeScript client for this API. It is not on npm, so build against the HTTP contract, and read the versioning rule below before you pin anything.

@wamp/app-sdk is maintained in the WAMP repository. A registry check on September 8, 2026 returned 404 for the public npm package. Use the HTTP examples in this site, or obtain a packed package from your platform operator. Do not depend on an unpublished package name in deployment instructions.

Working without it costs little: every operation on this site is plain HTTPS against the OpenAPI contract, and the only part that is not a fetch call is signing the app assertion, which is about ten lines of jose. Authentication shows it.

The major version is the Cloud API generation the client speaks. 1.x speaks Cloud v1, the API this site documents; a Cloud v2 would ship as 2.x. Minor and patch releases are SDK-only — added methods, added exported types, fixes — and never move you to a different API generation.

So pin on the major (^1.0.0) if what you care about is the wire contract, and read a major bump as “the API generation moved”, not as “the client was rewritten”. The corollary is the useful part: a 1.x upgrade cannot change which endpoints you are calling.

Why the client is worth using when it ships

Section titled “Why the client is worth using when it ships”

Authenticated operations in the OpenAPI contract carry an x-wamp-sdk-method extension naming their client method. A test checks that mapping in both directions. The two without one are the unauthenticated discovery pair, GET /v1/openapi.json and GET /v1/docs. So the client cannot quietly fall behind the API, and the API cannot gain an operation the client silently lacks. That is the same reason the reference pages on this site are generated from the contract rather than written: the contract is the one artifact everything else is checked against.

The mapping is data, not just a test fixture: WAMP_CLOUD_V1_SDK_OPERATIONS is exported as a table of [method, path, client method] rows, so a backend that audits its own coverage can read it rather than transcribe it.

Three classes and two error types.

WampApp handles identity — the pieces you need before any Cloud call:

Member Purpose
generateAppKeypair() One-time Ed25519 key generation. Register the public half; the private half never leaves your backend
new WampApp(options) Holds your app slug and private key
issueUserToken(options) Sign an end-user session token for a client to send to the AI proxy
installationToken() Mint the tenant- and resource-exact backend token
createInstallationIntent() / getInstallationIntent() Drive the installation handshake
buildAssertion() Build the signed assertion the token exchange consumes

WampCloud is the API client. Its methods map onto the operations documented under Operations:

Area Methods
Discovery and input capabilities, transcribeAudio
Native identity me — first-party Desktop Cloud only; an installation credential cannot call it
Release probes activateRuntimeReleaseProbe, deactivateRuntimeReleaseProbe — requires wamp.cloud.runtime-releases:probe
Sessions createSession, getSession, updateSession, listSessions, archiveSession, restoreSessionWorkspace, inspectSessionExecution
Organization environments listEnvironments, getEnvironment, listEnvironmentRevisions, putEnvironment, restoreEnvironment, archiveEnvironment, unarchiveEnvironment, putEnvironmentSecret, deleteEnvironmentSecret, putEnvironmentArchive, setDefaultEnvironment
Turns and runs submitTurn, listTurns, getRun, cancelRun
Following work listSessionEvents, sessionEvents, streamSessionEvents, streamSessionChanges, listOpenInteractions, decideInteraction
Artifacts listArtifacts, getArtifact, getArtifactText, getArtifactContent
Repositories listRepositories, listRepositoryGrants, resolveRepositoryGrant, reviewRepository
Publications publishRepository, listPublications, getPublication, mergePublication, listPublicationMerges, getPublicationMerge

transcribeAudio accepts bounded audio bytes, MIME type, and duration (100 ms to 10 minutes, at most 20 MiB), and returns text. WAMP does not persist the source audio; treat the returned text as ordinary user input and apply your product’s normal review/send policy to it.

me exists on the Node client so the same class can serve the first-party native token. It is not an integration method.

CloudInteraction.request is typed as CloudInteractionRequest: questions for ask_user, plan for exit_plan_mode, and approval with the complete action for a live approval. The opened event carries approval metadata and deadline, without action arguments; fetch open interactions before presenting a decision. offeredApprovalChoices(request.approval) returns the choices Cloud accepts. Pass a caller-owned idempotencyKey to decideInteraction and reuse it on retry. When another answer already won, the cloud_interaction_conflict error’s outcome holds that answer; without outcome the request is no longer waiting. ACP questions expose stable field ids, typed option values, defaults and constraints; submit their answer as a JSON object in the reply Turn’s message. Each request member is optional, because a caller that renders only one kind still has to compile against an event carrying the other. Events has the payload.

sessionEvents is the exception in that table: it is an async generator over the event log rather than a single operation, so it drives the cursor loop for you instead of returning one page. Three things stay yours, deliberately, and each is one line:

  • The cursor is event.sequence. The generator holds no state between calls, because only your code knows when an event became durable on your side. Persist the last sequence you handled and pass it back as after.
  • The bound is break. A generator fetches only what is pulled, so leaving the for await stops paging. There is no maxEvents option: a page cap makes “I stopped early” and “I reached the tail” indistinguishable, and a caller’s own break does not.
  • A hole throws WampCloudEventGapError. Sequences are gapless per session, and nothing prunes an event, so a page that does not start at after + 1 is a server-side invariant violation rather than a slow write or expired retention. The generator throws and your cursor stays where it was, so retrying asks for the same range again. error.after is the cursor you came from and error.firstSequence is what the server actually served — report the pair, do not invent a cursor past it. There is deliberately no resumeAfter: every cursor on the far side of a hole discards the missing events permanently, and that is an operator’s decision to take with the facts in hand, never a client fallback.

restoreSessionWorkspace brings back an expired sandbox, and inspectSessionExecution is an operational inspection aid, not part of the normal follow loop.

streamSessionEvents(sessionId, { after, signal }) follows the same log live as an AsyncIterable<CloudSessionEvent>. It checks sequence contiguity, resumes with Last-Event-ID, refreshes an App-mode token after 401, and spreads reconnects after server-side ends over 0–30 seconds. Save the last sequence your handler committed; the iterator’s in-memory cursor cannot replace that durable record. Abort its signal or break the loop to stop following. isTerminalRunEvent(event, runId) recognizes the four terminal Run types.

streamSessionChanges({ after, signal }) follows every Session the installation created over one connection, as an AsyncIterable<{ change?: CloudSessionChange; watermark: number }>. A change names a Session and the sequence its log reached; page that Session from your own cursor. An item without change only moves the watermark; every stream opens with one, so the first item also says the stream is open. Save watermark after acting on change and pass it back as after; the iterator reconnects with the newest watermark it holds, under the same retry and spread rules as streamSessionEvents. It needs an installation credential. See Follow many Sessions.

For a multi-tenant backend, construct one App-mode WampCloud per customer installation and reuse it across that customer’s calls. Each client caches its installation token, coalesces exchanges, and refreshes after a rejected token.

WampCloudError carries the API’s error code and status, so the handling described in Errors applies unchanged.

WampCloudEventGapError is the second error type and it is not an API error: no request failed, and it carries no code and no status. It is the SDK reporting that the event page is not contiguous with the cursor you supplied. Events are not pruned by a retention window; this is an invariant violation, not an expected expiration outcome. Handle it where you handle your cursor, not where you handle HTTP failures — instanceof WampCloudEventGapError before a generic WampCloudError branch, since neither is a subclass of the other.

WampApp and WampCloud both apply a 30-second deadline to every network request. Override it once with requestTimeoutMs, which must be an integer from 1 to 3 600 000 milliseconds — anything outside that range throws at construction rather than failing later. Provide a constructor-level AbortSignal to cancel all in-flight requests when your backend shuts down. Event-page reads also accept a per-call signal.

Two audience constants are exported for callers that validate tokens themselves: END_USER_TOKEN_AUDIENCE and WAMP_CLOUD_RESOURCE_AUDIENCE.

Every public Cloud declaration is exported from the package root, including CloudSessionContinuation, the retained timeline event types, KnownCloudSessionEvent, and CloudSafeTimelineEvent.

Five value sets are exported as as const arrays, so they are enumerable at runtime and not only in the type system:

Export Union Additive?
CLOUD_RUN_STOP_REASONS CloudRunStopReason yes
KNOWN_CLOUD_RUN_ERROR_CODES KnownCloudRunErrorCode yes
CLOUD_CONTINUATION_REASONS CloudContinuationReason yes
CLOUD_SESSION_PHASES CloudSessionPhase no — closed
THINKING_LEVELS ThinkingLevel no — closed

Each native model’s thinkingLevels lists the levels its route accepts. When the list is absent, that model has no reasoning-level control.

For the additive ones, treat an unrecognized value as unknown rather than invalid: use isKnownCloudSessionEvent before an exhaustive switch over known event members, and isKnownCloudRunErrorCode before branching on a terminal run’s errorCode. Both let you safely ignore a value newer than your installed SDK.

phase is the exception. CLOUD_SESSION_PHASES is the complete set the server can serve — three producers write it and nothing else does — so an exhaustive switch over it is legal, and a new value would be a contract change rather than an additive one. It stays advisory for a different reason: phase may lag a run’s terminal transition, so derive your state machine from run.status and use phase to label what a session is doing between runs.