Remote Tool Protocol
Implement or consume the shared Ansight tool discovery, catalog, call, batch, response, and compressed-payload protocol.
The local host player and CLI use one remote-tool protocol across the .NET, Android, iOS, React Native, Flutter, and Cordova/Capacitor SDKs. The native runtime carries the protocol over the authenticated live WebSocket session; cross-platform SDKs use the same native bridge and wire contract.
Applications normally work through their SDK’s registration APIs rather than constructing these messages. This page is the compatibility contract for host, SDK, bridge, and tooling authors.
Envelope
Every message is a JSON object with the following fields:
| Field | Meaning |
|---|---|
type | Message discriminator: tool.query, tool.catalog, tool.call, tool.batch, tool.result, tool.batch.result, or tool.error. |
id | Identifier for this message. |
replyTo | Request id being answered; present on responses. |
sessionId | Live session associated with the request or response. |
sentAt | UTC timestamp for the envelope. |
capability | tool.exec. |
payload | Message-specific JSON payload, or an encoded-payload wrapper described below. |
Use replyTo, not a response naming convention, to correlate a response with
its request.
Catalog Discovery
Request the current compact index with tool.query. When a caller already has
an index, pass both revisions:
{
"type": "tool.query",
"id": "tool_query_1",
"sessionId": "session_1",
"sentAt": "2026-08-25T00:00:00Z",
"capability": "tool.exec",
"payload": {
"detail": "index",
"ifRevision": "sha256:known-catalog-revision",
"ifAvailabilityRevision": "sha256:known-availability-revision"
}
}
The SDK responds with tool.catalog using schema
ansight.tool-catalog.v3:
{
"type": "tool.catalog",
"id": "tool_query_1.response",
"replyTo": "tool_query_1",
"sessionId": "session_1",
"sentAt": "2026-08-25T00:00:00.050Z",
"capability": "tool.exec",
"payload": {
"schema": "ansight.tool-catalog.v3",
"revision": "sha256:current-catalog-revision",
"availabilityRevision": "sha256:current-availability-revision",
"evaluatedAtUtc": "2026-08-25T00:00:00.050Z",
"detail": "index",
"tools": [
{
"id": "ui.perform_action",
"name": "Perform UI Action",
"description": "Performs a generic action against a current snapshot-scoped UI node.",
"category": "ui",
"policy": "write",
"definitionRevision": "sha256:tool-definition-revision",
"prerequisiteToolIds": ["ui.query_nodes"]
}
],
"count": 1,
"totalCount": 84,
"categories": { "ui": 12 }
}
}
revision is a deterministic SHA-256 value derived from the catalog schema,
guard, visible tool ids, and each tool’s definitionRevision. The separate
availabilityRevision changes when runtime executability changes.
When both supplied revisions match, the payload is exactly schema,
revision, and unchanged: true. When only availability changed, the response
also includes the new availabilityRevision, one evaluatedAtUtc, and a
changes object containing only non-default states. Treat changes as a
replacement snapshot: omitted tools are available and executable.
Index entries omit schemas. Request selected definitions with
detail: "definitions" and ids: [...]; cache each response by
definitionRevision. A request without detail remains compatible and returns
full definitions. ids, query, feature, policy, executableOnly, and
limit/maxResults are applied in the SDK before serialization.
JSON argument encoding, available/executable state, empty keywords, and
additionalProperties: false are protocol defaults and are omitted, as are
unchanged: false and the default detail: "full". Definition projections
omit index-level availability, timestamp, category, and total-count metadata. A
flattened-string tool declares argumentEncoding: "flattened-string".
Unavailable tools carry a compact runtime object with available: false and
optional code, reason, requiredState, remediation, and retryable.
Availability is evaluated again immediately before execution.
Calls and Results
Invoke one tool with tool.call:
{
"type": "tool.call",
"id": "tool_call_1",
"sessionId": "session_1",
"sentAt": "2026-08-25T00:01:00Z",
"capability": "tool.exec",
"payload": {
"toolId": "ui.perform_action",
"arguments": {
"reference": {
"source": "native",
"snapshotId": "native:42:example",
"revision": 42,
"nodeId": "root.0.save"
},
"action": "tap"
},
"after": {
"include": ["visualTree", "screenshot"],
"delayMilliseconds": 100
}
}
}
arguments must be a JSON object. Native JSON tools receive it without
flattening and validate both arguments and results against their published
schemas. Older tools that advertise flattened-string remain compatible.
Successful calls return tool.result. Its payload contains toolId,
success: true, optional message, result, and optional evidence.
Protocol, guard, availability, validation, and execution failures return
tool.error; its payload contains stable code, human-readable message,
retryable, and optional details.
An after request composes a call with post-call evidence. include accepts
visualTree and screenshot, and delayMilliseconds accepts 0 through
2000. Tool-specific visualTreeArguments and screenshotArguments can
refine those captures. Large binary artifacts use the separate ASFT
(ansight.file-transfer.v1) binary stream and are referenced from the JSON
result.
Batches
Use tool.batch to execute between 1 and 32 calls sequentially:
{
"type": "tool.batch",
"id": "tool_batch_1",
"sessionId": "session_1",
"sentAt": "2026-08-25T00:02:00Z",
"capability": "tool.exec",
"payload": {
"continueOnError": false,
"calls": [
{
"callId": "inspect-save",
"toolId": "ui.query_nodes",
"arguments": { "automationId": "save" }
},
{
"callId": "tap-save",
"toolId": "ui.perform_action",
"arguments": {
"reference": {
"source": "native",
"snapshotId": "native:42:example",
"revision": 42,
"nodeId": "root.0.save"
},
"action": "tap"
},
"after": { "include": ["visualTree"] }
}
]
}
}
The tool.batch.result payload preserves input order and reports success,
completed, requested, stoppedEarly, and results. Each result includes
its zero-based index, optional caller-provided callId, tool outcome, and any
post-call evidence. Execution stops after the first invalid or failed call
unless continueOnError is true.
Large JSON Payload Encoding
SDK responses may replace payload with a compressed wrapper when its compact
JSON representation is at least 32 KiB and gzip plus base64 is smaller than the
original. This applies to catalog, result, batch-result, and error responses.
Small or incompressible payloads remain ordinary JSON.
{
"type": "tool.catalog",
"id": "tool_query_1.response",
"replyTo": "tool_query_1",
"sessionId": "session_1",
"sentAt": "2026-08-25T00:00:00.050Z",
"capability": "tool.exec",
"payload": {
"$ansightEncoding": "gzip-base64-json",
"contentType": "application/json",
"originalByteCount": 65536,
"compressedByteCount": 2048,
"data": "H4sIAAAAA..."
}
}
Envelope fields are never compressed by this mechanism. A consumer must inspect the payload before interpreting message-specific fields:
- If
$ansightEncodingis absent, processpayloadas ordinary JSON. - For
gzip-base64-json, base64-decodedata, gunzip the bytes, decode them as UTF-8, and parse the result as the actual JSON payload. - Reject unsupported encodings, missing or invalid base64 data, gzip failures, and invalid decoded JSON as protocol errors.
originalByteCount and compressedByteCount describe the pre-base64 byte
counts. They are metadata for diagnostics and bounds checks, not replacement
payload lengths. Current resident hosts decode the wrapper before
catalog caching, authorization filtering, result normalization, or artifact
handling.
Authorization
Tool policy is one ordered value: read < write < critical. Read-only guards
permit read, read/write guards permit read and write, and full-access
guards permit all three. Use critical for destructive, secret-bearing, or
arbitrary code-invoking operations. The paired client’s maxToolPolicy can
lower the effective maximum but cannot raise the app’s local guard.
The guard affects both discovery and execution. Callers should discover the catalog before invoking tools, follow the published schemas exactly, and handle guard or runtime availability changes at call time.