Cua Docs

SDK reference

Python and TypeScript packages, constructors, methods, results, and errors for the typed Cua Driver SDK.

Packages#

RuntimePackageImport
Pythoncua-driverfrom cua_driver import CuaDriver
Node.js / TypeScript@trycua/cua-driverimport { CuaDriver } from "@trycua/cua-driver"

Both packages are generated from the same Rust and UniFFI contract. Methods are asynchronous. Python uses snake_case; TypeScript uses camelCase.

Constructors#

PythonTypeScriptBehavior
CuaDriver.create(options=None)CuaDriver.create(options?)Creates the primary same-process runtime. No daemon, executable, or IPC is required.
CuaDriver.create_configured(options)CuaDriver.createConfigured(options)Trusted-host constructor with an immutable runtime ceiling and compatibility mode.
CuaDriver.create_configured_with_authorization_host(options, host)CuaDriver.createConfiguredWithAuthorizationHost(options, host)Adds a trusted host callback for residual authorization boundaries.
CuaDriver.create_configured_with_activity_observer(options, observer)CuaDriver.createConfiguredWithActivityObserver(options, observer)Adds content-free activity events without changing authorization.
CuaDriver.create_configured_with_host_integrations(options, host, observer)CuaDriver.createConfiguredWithHostIntegrations(options, host, observer)Installs both optional host integrations.
CuaDriver.create_private_worker(options)CuaDriver.createPrivateWorker(options)Spawns one supervised process-isolated runtime over inherited pipes; no reusable endpoint is created.
CuaDriver.connect(socket_path=None)CuaDriver.connect(socketPath?)Connects the same typed surface to a daemon. This is a compatibility and app-hosting path.

DriverOptions currently contains claude_code_compatibility / claudeCodeCompatibility, which defaults to false.

create() validates the immutable permission-mode, managed-policy, user-policy, and bounded-manifest startup configuration before constructing the native runtime. Every subsequent same-process call passes the same native authorization coordinator used by daemon-backed calls. An invalid configuration returns DriverError.Configuration; a denied generic call returns a tool error with stable code permission_denied.

create_configured() accepts ConfiguredDriverOptions, whose authorization field is RuntimeAuthorizationOptions: an allowed-mode set, the compatibility mode inherited by ordinary CuaDriver calls, bounded manifest path when that compatibility mode is bounded, maximum absolute and idle session TTLs, and the separate unrestricted-risk acknowledgement. Applications may create more than one same-process runtime. Each runtime owns an independent authorization ceiling, session registry, browser bindings, recording state, and shutdown lifecycle.

Trusted host code may call the top-level create_trusted_session(driver, …) / createTrustedSession(driver, …) factory and receive a CuaDriverSession. Keeping the factory separate preserves the released structural CuaDriverProtocol and CuaDriverLike interfaces. The returned object is already bound to one immutable authorization context. Its public session string remains only a lifecycle label: a tool argument cannot select, replay, or widen the context. Call close() at the host lifecycle boundary; dropping the object, ending the session, or shutting down the runtime also revokes it. PrivateWorkerOptions adds the absolute Cua Driver binary path, host identity, startup and shutdown timeouts, configured runtime options, a safe environment allowlist, and optional stderr inheritance. Worker configuration is sent after spawn on the inherited channel rather than in argv. Caller-provided environment entries cannot set authorization controls; process-admin managed policy and disablement variables are inherited by both private workers and embedded services so a child topology cannot relax its parent's ceiling. Closing the host channel terminates the worker; a worker cannot be discovered or reattached.

Daemon connect() clients retain the daemon compatibility mode. An embedded host may create a trusted session only over its original authenticated service connection; an ordinary or standalone daemon client cannot.

Authorization host#

Routine standard-mode automation does not call the authorization host. The callback currently handles the existing logged-in Chromium profile boundary. It receives an attested, expiring request and must return the same request_digest with Allow, Deny, or Cancel.

Python:

from cua_driver import (
    CuaDriver,
    DriverAuthorizationAction,
    DriverAuthorizationDecision,
    DriverAuthorizationHost,
)
 
class AppAuthorization(DriverAuthorizationHost):
    async def authorize(self, request):
        allowed = await app_ui.confirm(request.human_summary)
        return DriverAuthorizationDecision(
            action=(
                DriverAuthorizationAction.ALLOW
                if allowed
                else DriverAuthorizationAction.DENY
            ),
            request_digest=request.request_digest,
        )
 
driver = CuaDriver.create_configured_with_authorization_host(
    options,
    AppAuthorization(),
)

TypeScript:

import {
  CuaDriver,
  DriverAuthorizationAction,
  type DriverAuthorizationHost,
} from "@trycua/cua-driver";
 
const authorizationHost: DriverAuthorizationHost = {
  async authorize(request) {
    const allowed = await appUi.confirm(request.humanSummary);
    return {
      action: allowed
        ? DriverAuthorizationAction.Allow
        : DriverAuthorizationAction.Deny,
      requestDigest: request.requestDigest,
    };
  },
};
 
const driver = CuaDriver.createConfiguredWithAuthorizationHost(
  options,
  authorizationHost,
);

The callback is trusted application code. Do not expose it as a model tool, forward resource_json / resourceJson to an agent, or auto-accept every request. Cua Driver intentionally does not prescribe or render the host UI.

Activity observer#

DriverActivityObserver receives content-free events for authorized actions, authorization refusals, ordinary action failures, grant issue and revocation, and session start and end. Events include the tool name, risk class, adapter IDs, public session label, and stable refusal code. They never include tool arguments, text, images, URLs, file paths, or attested resource JSON.

The observer cannot authorize, deny, or change a result. Return quickly and hand expensive work to an application queue.

execution_mode() / executionMode() reports the generated DriverExecutionMode value. The enum variants are Embedded, PrivateWorker, Daemon, and the Rust-only carrier-backed Remote.

Lifecycle and metadata#

PythonTypeScriptResult
metadata()metadata()Driver version, protocol version, and platform metadata
execution_mode()executionMode()DriverExecutionMode
is_available()isAvailable()Whether the runtime can serve calls
shutdown()shutdown()Stops admission and awaits admitted work

In TypeScript, shutdown() and uniffiDestroy() have separate jobs: shutdown() closes runtime admission and awaits admitted operations; uniffiDestroy() immediately frees the generated UniFFI object handle. JavaScript's FinalizationRegistry is only a nondeterministic fallback, so orderly applications call both, in that order. Python finalization releases its handle automatically, but applications must still await shutdown().

Session methods#

PythonTypeScriptInput
start_sessionstartSessionStartSessionInput
get_sessiongetSessionGetSessionInput
list_sessionslistSessionsListSessionsInput
end_sessionendSessionEndSessionInput
get_session_stategetSessionStateGetSessionStateInput (deprecated)
escalate_sessionescalateSessionEscalateSessionInput (deprecated)

start_session is optional. The first ordinary call creates an implicit session owned by the SDK transport, and later calls on that transport reuse it. The default idle TTL is five minutes. Shutdown, explicit end, and transport close run the same cleanup hooks. A call that is still in flight cannot expire, and only completed calls refresh the idle timer.

For multi-call work, prefer a short public session label and pass the same value on every call that accepts it. Passing it once is not sticky: a later call that omits the field uses the transport's implicit session instead. Use start_session to name or configure a run before acting, or to revive a public name after it has ended. For one-off or deliberately unlabeled work, omitting session is valid. get_session and list_sessions return content-free state only for sessions visible to that transport. The public label is a map key, never an authorization credential. A trusted host can inspect its wider runtime namespace through list_host_sessions_json() / listHostSessionsJson(); agent tools cannot use that operator view.

StartSessionInput.capture_scope / captureScope, get_session_state, and escalate_session remain available for legacy capture-scope sessions during the compatibility window. New code selects a target on each action. There is no deescalate_session method.

Typed desktop methods#

PythonTypeScriptInput
get_desktop_stategetDesktopStateGetDesktopStateInput
get_screen_sizegetScreenSizeGetScreenSizeInput
get_cursor_positiongetCursorPositionGetCursorPositionInput
move_cursormoveCursorMoveCursorInput
clickclickClickInput
dragdragDragInput
scrollscrollScrollInput
type_texttypeTextTypeTextInput
press_keypressKeyPressKeyInput
hotkeyhotkeyHotkeyInput

move_cursor, click, drag, scroll, type_text, press_key, and hotkey accept an ActionTarget / actionTarget on each call:

window:  { kind: "window",  pid, window_id }
desktop: { kind: "desktop", display_id: "primary" }

The desktop target uses screen coordinates and foreground delivery. The window target uses coordinates from that window's screenshot and keeps the existing background or foreground delivery ladder. Legacy flat scope, pid, and window_id fields remain accepted but cannot be combined with target.

Typed cursor methods#

PythonTypeScriptInput
set_agent_cursor_enabledsetAgentCursorEnabledSetAgentCursorEnabledInput
set_agent_cursor_motionsetAgentCursorMotionSetAgentCursorMotionInput
set_agent_cursor_themesetAgentCursorThemeSetAgentCursorThemeInput
get_agent_cursor_stategetAgentCursorStateGetAgentCursorStateInput

Cursor-bearing actions create or wake the transport's implicit session even when the caller does not supply a public session. Cursor configuration methods still take a public session label. cua.default is the only built-in theme. A trusted local operator may validate, compile, and install a custom theme with cua-driver cursor-theme; agent-facing tools may select an installed theme ID but cannot install source or compiled theme data. See Agent cursor themes for the semantic profile and authoring workflow.

Use list_tools_json() / listToolsJson() and call_tool() / callTool() for the generic, platform-extensible tool surface. Its top-level enforcement_adapters array distinguishes active, metadata-only, and not-exposed permission adapters. Prefer typed methods when one is available.

ToolResult#

Desktop methods return ToolResult.

Python fieldTypeScript fieldMeaning
texttextHuman-readable result text
imagesimagesReturned images and MIME types
structured_jsonstructuredJsonStructured platform result
is_errorisErrorWhether the tool reported failure
error_codeerrorCodeStable tool error code, when present
verifiedverifiedWhether post-action verification succeeded
degradeddegradedWhether a reduced-capability path was used
raw_jsonrawJsonComplete extensible result envelope

Errors#

The generated DriverError variants are:

  • Configuration
  • InvalidArguments
  • Transport
  • Protocol
  • Tool
  • Shutdown
  • RuntimeAlreadyExists
  • Worker
  • Remote
  • ActionInterrupted

Tool-level failures may also arrive as ToolResult.is_error / isError. Inspect the result before consuming images or structured fields. ActionInterrupted includes an ActionCompletion value: NotStarted, Completed, or Unknown. Do not automatically retry a non-idempotent action when completion is unknown.

RuntimeAlreadyExists remains in the stable error vocabulary for hosts or platform facilities that cannot safely establish another owner. Ordinary second-runtime creation no longer returns it.

See MCP tools for the agent-facing tool catalog and SDK, MCP, and process hosting for the architecture boundary.