API
The Action agent WebSocket protocol over authenticated private action.sock
The Action agent is a local WebSocket server inside Action.app. This page
documents its raw RPC protocol. Most agents use the Action MCP server instead
(see Agent setup). The MCP server adds sessions,
target resolution, recording status, stage, and private layers on top of this
protocol.
Source of truth:
ActionAgentProtocol.swift
and
ActionAgentRuntime.swift.
Transport
| Property | Value |
|---|---|
| Protocol | WebSocket, text frames, JSON |
| Address | ~/.lattices/run/action.sock |
| Protocol version | 2, reported by status |
| Authentication | Connection token for every WebSocket; additional capability token for privileged methods |
status reports authentication: "capability-token" and authTokenFile, the
path of a token file that the agent writes at each launch. The file is
user-only (0600) in a user-only directory (0700).
Privileged requests must include protocolVersion and authToken in their
params. The privileged requests are:
drive.beginwithmode: "attention";workspace.dragFile;workspace.cancelOperation.
Every method requires an authenticated connection.
Private connection
Action 0.4.0 uses the private connection below. Install its matching runtime and Lattices CLI 0.15.1. Earlier TCP clients do not automatically fall back.
| Property | Value |
|---|---|
| Address | Unix socket ~/.lattices/run/action.sock (override with ACTION_SOCKET_PATH) |
| Connection token | ~/.lattices/run/action.token, sent as x-lattices-token on the WebSocket upgrade with Host: localhost and no Origin |
| Local access | User-owned directory mode 0700, socket and token mode 0600, plus the connection token. The server does not perform a separate peer-UID check. |
| TCP | 127.0.0.1:4319 opens only with ACTION_ALLOW_TCP=1, and still requires the connection token |
Every connection now needs the token, not only the privileged methods. The
privileged methods above still check authToken in their params as well. The
Action runtime and lats action call read the token for you.
Remote machines cannot reach this socket. A paired tailnet client can call a
reviewed subset of Action methods through the Lattices gateway, one exact grant
per method, for example --grant action:status. The gateway opens one Action
connection per call. It therefore denies drive.begin, drive.touch,
drive.release, workspace.dragFile and workspace.cancelOperation, which
create or use a lease owned by a persistent connection. drive.status remains
available with its own read grant. See
Private IPC and the gateway.
The receive side stays armed while a request runs, so a cancellation can arrive
during a gesture. Responses are serialized and correlated by request id.
Request
{
"id": "4f2c9b1e",
"method": "capture.screenshotScreen",
"params": { "output": "/tmp/screen.png" }
}id: request id. Native clients default to a UUID.method: a method name from the table below.params: a flat map of string keys to string values. Send numbers and booleans as strings ("1440","true").
Response
{
"id": "4f2c9b1e",
"ok": true,
"result": { "outputPath": "/tmp/screen.png", "status": "screenshot" },
"error": null
}ok: success flag.result: a flat string map. Structured values, such as a drive lease, arrive as JSON strings inside this map.error: an error string whenokisfalse.
Methods
Runtime and permissions
| Method | Purpose | Params |
|---|---|---|
ping |
Liveness check | none |
status |
Service metadata, method list, protocol version, build provenance, token path | none |
permissions.snapshot |
Accessibility and Screen Recording state | none |
permissions.request |
Prompt for both permissions | none |
permissions.requestAccessibility |
Prompt for Accessibility | none |
settings.openAccessibility |
Open the Accessibility settings pane | none |
settings.openScreenRecording |
Open the Screen Recording settings pane | none |
Apps, windows, and input
| Method | Purpose | Params |
|---|---|---|
app.launch |
Launch an app | bundleId |
app.activate |
Bring an app forward | bundleId |
window.setFrame |
Move and resize the app's window | bundleId, x, y, width, height |
window.getFrame |
Read the app's window frame | bundleId |
input.typeText |
Type text into the focused element | text |
input.drag |
Pointer drag | fromX, fromY, toX, toY, optional durationMs (default 300), optional filePath |
accessibility.pressElement |
Press an element by label | bundleId, label, optional role |
accessibility.setValue |
Set an element's value | bundleId, label, value, optional role |
calculator.buttons, calculator.clickButton, and calculator.displayValue
exist for the Calculator demo scenario. They are not a general API.
Drive leases
A drive lease tells other clients that an agent is acting on the desktop. The lease belongs to the connection that created it. Closing the connection cancels that connection's leases only.
| Method | Purpose | Params |
|---|---|---|
drive.begin |
Acquire a lease | agent, task, optional mode, sessionId; attention mode also needs approval, run and workspace ids, capability, resource, protocolVersion, authToken |
drive.touch |
Renew a lease | leaseId, optional axTier, actionKind |
drive.release |
Release a lease | leaseId, optional outcome, summary |
drive.status |
Snapshot of current leases | none |
sessions.prune |
Remove stale drive sessions | none |
sessions.clear |
Remove all drive sessions | none |
Workspace drag
| Method | Purpose | Params |
|---|---|---|
workspace.dragFile |
Drag one exact run fixture from Finder into one exact Scout drop zone | lease, run, and workspace ids; fixture URL; Finder and Scout window identities; destination AX identifier; display bounds; protocolVersion; authToken |
workspace.cancelOperation |
Cancel one in-flight operation | leaseId, operationId, protocolVersion, authToken |
workspace.dragFile is not a generic coordinate drag. It rejects unknown
params and accepts no source point, destination point, duration, command, or
executable. Action resolves exactly one Finder item by AXURL inside exactly one
titled Finder window. Action resolves exactly one run-scoped AX drop-zone
identifier inside exactly one titled app.openscout.scout window. All resolved
frames and points must be inside the supplied display bounds.
An approved attention drive.begin acquires the global system-pointer
resource and grants one workspace.drag-file capability. The capability is
bound to the connection, run, and workspace, and is consumed before the
gesture. During the drag, Action checks the lease and operation stop signals
on every step. Cleanup always attempts mouse-up and restores the saved pointer
position.
Capture
| Method | Purpose | Params |
|---|---|---|
capture.screenshotScreen |
Screenshot the main display | output |
capture.screenshotRegion |
Screenshot a region | x, y, width, height, output |
capture.screenshotAppWindow |
Screenshot an app window | output, bundleId or pid |
capture.recordRegion |
Record a region | x, y, width, height, output, optional fps, scale, stopFile, finishedFile, debugLog, includeSupervisionOverlay |
capture.recordAppWindow |
Record an app window | bundleId, output, optional stopFile, finishedFile, debugLog |
Recording contract
The agent does not record in its own process. A record method launches a fresh
Action.app instance in recording-probe mode, and that probe performs the
ScreenCaptureKit capture.
- A successful reply means the probe started.
- The recording ends when the
stopFileappears. - Completion is the movie at
outputplus thefinishedFilemarker. The marker can also contain a recording error. - Pass
debugLogto collect probe logs.
See Recording.
What is not in this protocol
- Private layers (
layer_*), stage, observation, target resolution, and session artifacts are MCP and runtime features. The raw agent does not orchestrate them. See Agent layer. - The
browser_*tools belong to the Lattices MCP. See Browser. computer.*methods belong to the Lattices core daemon onlattices.sock, not to this agent. See the Lattices API.
From the Lattices CLI
lats action call <method> [params-json] sends one request and prints the
result. In released builds it does not attach a capability token, so it cannot
call privileged methods. The matching runtime reads and attaches the token automatically;
see Private connection.
lats action call status
lats action call window.getFrame '{"bundleId":"com.apple.calculator"}'Remote Linux hosts
The raw agent protocol is local to the Mac. For a Linux desktop, the Action
runtime connects to lattices-host instead. See
Remote engine.