Skip to content

Host Command API Reference ​

The extension host command dispatcher exposes platform commands through window.isaExtensionBridge.invoke(command, args). Browser helpers may wrap these commands, but extensions can always call the canonical command names directly.

Capability Discovery ​

Use get_app_info to discover the surfaces enabled for the extension.

js
const appInfo = await window.isaExtensionBridge.invoke('get_app_info', {});
console.log(appInfo.filesystem.commands);
console.log(appInfo.projects);
console.log(appInfo.audioCapture);
console.log(appInfo.transcription);

Do not infer capability support from the host version or from a manifest alone. Check enabled and the advertised command before showing an action.

This reference spans native and browser host adapters. A command listed below is not necessarily enabled in the browser gateway. The current verified launch's command arrays, manifest permissions, resource authorization and executor health remain authoritative.

Browser storage_* holds origin/account/extension-scoped JSON drafts independently of the chat-store lock. Browser filesystem capabilities report filesystem.persistence.mode = "dashboard-confirmed", offlineWrites = false, and authoritativeWrites only when upload is advertised. Atomic JSON capabilities report read and write separately. Browser uploads, deletes and atomic writes require dashboard acknowledgment, including for files whose server metadata is syncable. The native offline journal and indexed-cache events described below do not apply to the browser. Check implementation status for staged gateways and outstanding live verification.

The Filesystem API exposes workspace-file identity only as returned fileId metadata, always uses path for canonical filesystem selectors, and does not accept legacy storage-id aliases. Check the advertised command list for supported operations.

The public filesystem command list is:

  • filesystem_ensure_group_folder
  • filesystem_open_workspace_file
  • filesystem_open_workspace_folder
  • filesystem_list_dir
  • filesystem_get_files
  • filesystem_query_index
  • filesystem_upload_files
  • filesystem_delete_file
  • filesystem_discard_pending_file
  • filesystem_get_download_link_file

The public shared-project command list is:

  • projects_list
  • projects_create
  • projects_set_archived

The atomic JSON command list is:

  • atomic_json_get
  • atomic_json_apply

Implemented Host Commands ​

Common non-filesystem commands include:

  • get_app_info
  • get_extension_info
  • get_native_capabilities
  • get_settings
  • set_settings
  • open_file_dialog
  • get_thread_list
  • list_extension_threads
  • get_full_thread_object
  • new_thread
  • create_extension_thread
  • set_extension_thread_attachment
  • update_thread
  • storage_put
  • storage_get
  • storage_delete
  • storage_list
  • projects_list
  • projects_create
  • projects_set_archived
  • atomic_json_get
  • atomic_json_apply
  • upsert_document_snapshot
  • send_email
  • mcp_list_resources
  • mcp_invoke_tool
  • calculator
  • web_search
  • extract_webpage_text
  • browse_and_extract
  • documents_in_conversation
  • search_documents
  • read_document

Atomic JSON workspace files ​

Atomic JSON commands provide operation-based updates to any valid JSON workspace file covered by the extension's ordinary exact-file or folder grant. The extension must declare atomic_json_read or atomic_json_write; the host supplies and enforces the immutable workspace, group, and extension scope. The target is an absolute canonical path, and traversal or access outside the granted scope is rejected.

atomic_json_get is the typed companion to atomic_json_apply. For a syncable target it materializes the strictly committed RIBLT copy plus all durable unacknowledged operations without using generic pending whole-file bytes. For a non-syncable target it reads the dashboard immediately. Its result distinguishes found, absent, and unavailable; malformed JSON is an error rather than absence. Any valid JSON root is accepted, including objects, arrays, scalars, and null. When pending is true, value includes the local operation overlay while revision, hash, and byte size still describe the committed generation.

atomic_json_apply accepts the same canonical target plus ordered operations. The optional boolean syncable is only a creation hint: exact true opts a missing file into durable local/RIBLT synchronization, while omission or false creates dashboard-first. An existing file always retains its authoritative persisted mode, even when the hint differs. Non-syncable applies succeed only after dashboard acceptance; a provisioned syncable target, or a missing target requested with exact true, can be saved durably while offline. Operation paths are arrays of literal object-key segments, so dots and slashes inside one key are not separators.

json
{
  "path": "/groups/_group_ids/.../extensions/isa-match-rsx-to-quote/suppliers/enrichments.json",
  "syncable": true,
  "operations": [
    { "kind": "upsert", "path": ["supplier.example/id"], "value": { "rating": 4 } },
    { "kind": "remove", "path": ["supplier-456"] }
  ]
}

For syncable files the host journals only unacknowledged operations, retries immutable batches through the ordinary file-sync worker, and emits scoped filesystem-index-changed events when pending or committed materialization changes. Dashboard acknowledgment durably removes the acknowledged batch immediately; until a later RIBLT generation arrives, a read can expose an older committed value or report unavailable with no accepted-operation overlay. There is no atomic tombstone or incarnation barrier: deletion removes the ordinary file, a later accepted apply recreates from {}, operations apply to the valid JSON present when they arrive, and the last dashboard write to arrive wins. The resulting JSON remains visible, downloadable, and manageable through normal dashboard file inventory.

Filesystem Authorization ​

Dashboard group links decide what a user can see in a workspace. Extension filesystem access is narrower and local to the running user profile.

  • filesystem_ensure_group_folder creates or finds extension-owned storage for the selected launch group.
  • filesystem_open_workspace_file and filesystem_open_workspace_folder require explicit user selection and persist a local grant.
  • Grants are scoped by extension id, workspace id, and launch group.
  • read grants allow listing, reading, sync-index inspection, and signed download links.
  • read_write grants also allow upload, replacement, and delete.
  • A read-only grant must reject upload, replacement, and delete.
  • The selected workspace and group are captured when the iframe starts and stay immutable until that iframe is deliberately reloaded.
  • The host overwrites workspaceId and groupId on every filesystem_* request. Extension-supplied scope cannot retarget a mounted extension.
  • Delayed responses from a previous iframe generation are discarded.

get_app_info().extensionRuntime.launchContextId is the stable serialized identity of (workspaceId, groupId) and may key durable context-local recovery state. It does not change merely because the iframe reloads. The host's per-iframe generation token is separate and is not exposed to extensions.

filesystem_ensure_group_folder ​

Creates or finds the extension's group folder. The command must fail clearly if the extension was launched without a selected group.

Request:

json
{}

Response:

json
{
  "status": "ok",
  "folderId": "workspace_file:...",
  "path": "/groups/id-67726f75702d616c706861/extensions/id-7273782d62657374656b616e616c79736572",
}

The host supplies the trusted workspace, group, and extension IDs to one atomic dashboard operation. Folder identity is link-backed and stable across group renames; the returned persisted path must be retained and must not be rebuilt from the display name. Concurrent ensure calls converge on the same real folder row. Structurally ambiguous legacy links fail closed with identifiers for administrator diagnosis.

filesystem_open_workspace_file ​

Opens a workspace-file picker and persists a local file grant if the user confirms.

Request:

json
{
  "workspaceId": "workspace:...",
  "access": "read",
  "mode": "file"
}

Response:

json
{
  "status": "ok",
  "fileId": "workspace_file:...",
  "path": "/models/model.gguf",
  "name": "model.gguf",
  "kind": "file",
  "access": "read"
}

Cancellation returns a documented canceled result or rejects consistently, depending on the host implementation.

filesystem_open_workspace_folder ​

Opens a workspace-folder picker and persists a local folder grant.

Request:

json
{
  "workspaceId": "workspace:...",
  "access": "read_write",
  "mode": "folder"
}

Response:

json
{
  "status": "ok",
  "folderId": "workspace_file:...",
  "path": "/project-inputs",
  "name": "project-inputs",
  "kind": "folder",
  "access": "read_write"
}

filesystem_list_dir ​

Lists files below one granted folder or extension group-folder path. Dashboard inventory and locally available syncable files share one response. Pending or otherwise locally newer syncable metadata replaces a dashboard entry at the same canonical path.

Request:

json
{
  "path": "/groups/id-67726f75702d616c706861/extensions/id-7273782d62657374656b616e616c79736572"
  "recursive": false
}

Response:

json
{
  "status": "ok",
  "source": "dashboard+cache",
  "authoritative": true,
  "files": [
    {
      "path": "/groups/id-67726f75702d616c706861/extensions/id-7273782d62657374656b616e616c79736572/state.json",
      "name": "state.json",
      "kind": "file",
      "fileId": "workspace_file:...",
      "contentType": "application/json",
      "fileSize": 1234,
      "canRead": true,
      "canWrite": true,
      "availabilityStatus": "online",
      "synced": true,
      "lastSyncedAt": null
    }
  ]
}

Use exactly one of path or pathPrefix. recursive defaults to true; set it to false for direct children only. When the dashboard is unavailable, a non-empty local sync inventory is returned with source: "cache" and authoritative: false.

filesystem_get_files ​

Reads one or a bounded batch of granted files by canonical path. File IDs are returned as record-identity metadata but are not accepted as content-read selectors. The default local-first policy reads a complete clean synced cache entry for each syncable file, then retrieves only unresolved items from the dashboard. Use cachePolicy: "dashboard-required" when a canonical dashboard read is necessary before a CAS write, canonical application, or an authoritative absence decision.

Each request item selects exactly one canonical path. File IDs, duplicate paths, paths outside the extension's immutable granted root, unsupported encodings, and oversized requests are rejected. expectedSyncRevision and expectedContentHash are optional preconditions. A missing, incomplete, pending, corrupt, or mismatched cache entry causes a dashboard retrieval unless the policy prohibits it; it is never proof of remote absence.

Request:

json
{
  "workspaceId": "workspace-alpha",
  "files": [
    {
      "path": "/groups/id-67726f75702d616c706861/extensions/id-7273782d62657374656b616e616c79736572/enrichment/acme.json",
      "expectedSyncRevision": "42",
      "expectedContentHash": "4d14...64-hex-sha-256...b2"
    }
  ]
}

The response includes bounded items. Each item has path, status, and optional error; a successful item additionally returns text and coupled sync revision/content-hash metadata. An unsuccessful item does not fail unrelated items.

Response:

json
{
  "status": "ok",
  "items": [
    {
      "status": "ok",
      "path": "/groups/id-67726f75702d616c706861/extensions/id-7273782d62657374656b616e616c79736572/state.json",
      "fileId": "workspace_file:...",
      "filename": "state.json",
      "contentType": "application/json",
      "fileSize": 1234,
      "text": "{\"status\":\"complete\"}",
      "bytesBase64": null
    }
  ]
}

filesystem_upload_files ​

Uploads one or more files to granted paths. This is the only upload command: uploading one file means sending a one-item files list. Each item's path includes its final filename, and each item independently selects dashboard-first behavior or the local sync queue through metadata.syncable.

Request:

json
{
  "files": [
    {
      "path": "/groups/id-67726f75702d616c706861/extensions/id-7273782d62657374656b616e616c79736572/state.json",
      "text": "{\"status\":\"complete\"}",
      "contentType": "application/json",
      "metadata": { "syncable": "true" },
      "progressId": "upload-1"
    }
  ]
}

For idempotent online writes, metadata.client_operation_id may contain a stable lowercase or uppercase 64-hex operation identity. Retrying the same logical operation must reuse the exact path, content, and operation identity; the host forwards the value unchanged and the dashboard rejects reuse for a different request.

Progress event:

json
{
  "event": "filesystem-upload-progress",
  "extensionId": "rsx-bestekanalyser",
  "workspaceId": "workspace-alpha",
  "groupId": "group-alpha",
  "progressId": "upload-1",
  "filename": "state.json",
  "bytesReceived": 12345,
  "totalBytes": 50000,
  "progress": 24.69,
  "status": "uploading",
  "isComplete": false
}

An offline pending upload has the same shape but may return "fileId": null until the dashboard creates or resolves the real workspace-file row. fileId is never a backing object-storage ID and a path is never substituted as an ID.

Response:

json
{
  "status": "ok",
  "items": [
    {
      "status": "ok",
      "path": "/groups/id-67726f75702d616c706861/extensions/id-7273782d62657374656b616e616c79736572/state.json",
      "fileId": "workspace_file:...",
      "filename": "state.json"
    }
  ]
}

filesystem_delete_file ​

Deletes a granted file or folder by canonical path. File IDs are rejected as request selectors, and read-only grants reject this command.

Optional request fields are recursive, expectedSyncRevision, and expectedContentHash. Recursive deletion requires a path and cannot delete the root of a persisted folder grant.

filesystem_discard_pending_file ​

Discards a conflicted local pending version by path. The extension, workspace, launch group, grant, and path must all match. The host returns either restored_committed_cache or removed_pending_cache.

Creates a signed download URL for a granted file by canonical path. File IDs and legacy artifact-ID aliases are rejected as request selectors. A successful authoritative response may include fileId as record identity metadata. Syncable files do not require this operation: filesystem_get_files reads their complete local content directly when available.

Syncable Files ​

Set metadata.syncable = "true" for small files that should participate in the host sync queue. The host owns local caching, offline queueing, group-wide download, and conflict state. Extensions should not implement a second sync queue for these files.

The value must be the exact string "true". After the extension group folder and its read-write grant have been provisioned online, a syncable upload is first committed to the local synced-file store. A successful pending/local response means those bytes are durable and immediately available to offline filesystem_get_files and filesystem_list_dir calls, including after an app restart; it does not mean that the dashboard has accepted them yet. The host wakes its sync worker and uploads after reconnect. Pending state clears only after a reconciliation confirms the matching remote revision and hash.

The same contract applies to text, bytesBase64, and the snapshotted bytes from filePath, including empty content. Repeated local saves use the newest complete bytes. A conflict retains those bytes for resolution and is not silently retried. Invalid paths, missing authentication, read-only or revoked grants, and group-scope mismatches fail without creating a pending entry.

Creating the extension group folder and its initial grant remains online-only. Once provisioned, both replacements and new filenames below that folder can be queued offline. Uploads without the exact opt-in remain online-only.

The extension does not request or follow a dashboard download link for syncable files. filesystem_get_files reads complete local sync content first and the host obtains remote bytes only for unresolved items.

Shared Project Commands ​

These commands use the active launch group. Listing and creation require a dashboard advertising shared-projects-v1; archive and restore additionally require shared-projects-archive-v1. The host overwrites workspaceId and groupId; extensions cannot select another scope.

get_app_info().projects includes enabled, canRead, canWrite, and the available commands. projects_read enables projects_list; projects_write enables projects_create and projects_set_archived. Check the advertised command before rendering an archive or restore action.

projects_list ​

The extension sends no scope fields. includeArchived is optional and defaults to false:

js
const result = await window.isaExtensionBridge.invoke('projects_list', {});

const withArchive = await window.isaExtensionBridge.invoke('projects_list', {
  includeArchived: true
});

Response:

json
{
  "status": "ok",
  "projects": [
    {
      "id": "shared-projects-project-...",
      "name": "Renovatie West",
      "createdAt": "2026-07-22T19:00:00Z",
      "updatedAt": "2026-07-22T19:00:00Z",
      "canWrite": true,
      "archived": false,
      "archivedAt": null
    }
  ]
}

Results are sorted by most recent updatedAt, then name and id. Timestamps are RFC 3339/ISO-8601 strings. The default response omits archived projects; includeArchived: true returns active and archived projects so clients can offer restore without mistaking an archived id for a deleted or unknown project. archivedAt is null for an active project. canWrite is false when the extension lacks projects_write; it permits the dedicated project write commands and association of extension-owned data, but never raw mutation of the registry folder through the filesystem API.

projects_create ​

Request:

json
{
  "name": "Renovatie West"
}

Response:

json
{
  "status": "ok",
  "created": true,
  "project": {
    "id": "shared-projects-project-...",
    "name": "Renovatie West",
    "createdAt": "2026-07-22T19:00:00Z",
    "updatedAt": "2026-07-22T19:00:00Z",
    "canWrite": true,
    "archived": false,
    "archivedAt": null
  }
}

The name is trimmed, case-sensitive, and limited to 160 characters and 512 UTF-8 bytes. Empty names, traversal segments, separators, and control characters are rejected. Repeating the same canonical create returns the same project with created: false; no duplicate folder is made. A group supports at most 500 projects, including archived entries. Creating with the name of an archived project returns that same archived identity; use projects_set_archived to restore it explicitly.

projects_set_archived ​

This soft-archives or restores a project without deleting its registry identity or any extension-owned data.

Archive request:

json
{
  "projectId": "shared-projects-project-...",
  "archived": true
}

Response:

json
{
  "status": "ok",
  "changed": true,
  "project": {
    "id": "shared-projects-project-...",
    "name": "Renovatie West",
    "createdAt": "2026-07-22T19:00:00Z",
    "updatedAt": "2026-07-23T09:00:00Z",
    "canWrite": true,
    "archived": true,
    "archivedAt": "2026-07-23T09:00:00Z"
  }
}

Restore the project by sending the same projectId with archived: false. Both transitions are idempotent: requesting the current state returns changed: false. The project id, name, parent, and canonical path remain unchanged. Files and records stored by extensions under their own group folders are not moved or removed.

The project id is a stable foreign key shared by extensions. Project registry folders are system-owned, read-only metadata and cannot be used as raw extension storage. Persist extension-owned files under the extension's group folder and include the project id in their schema or metadata.

Audio Capture Commands ​

These commands require audio_capture and a frozen workspace/group context:

  • audio_list_input_devices
  • audio_get_active_recording
  • audio_get_recording
  • audio_list_recordings
  • audio_start_recording
  • audio_pause_recording
  • audio_resume_recording
  • audio_stop_recording
  • audio_cancel_recording
  • audio_delete_recording

The browser bridge supplies the frozen workspaceId, groupId, and extensionId; iframe arguments for those fields are discarded. The extension only supplies the fields shown below.

audio_list_input_devices returns:

json
[
  {
    "deviceId": "opaque-device-id",
    "label": "Built-in Microphone",
    "isDefault": true
  }
]

Start request:

json
{
  "deviceId": "opaque-device-id",
  "maxDurationMs": 14400000
}

deviceId is optional and selects the host default when omitted. maxDurationMs is optional and is capped by the host. The response is an audio recording state:

json
{
  "recordingId": "recording-...",
  "status": "recording",
  "device": {
    "deviceId": "opaque-device-id",
    "label": "Built-in Microphone",
    "isDefault": true
  },
  "startedAt": "2026-07-22T19:00:00Z",
  "updatedAt": "2026-07-22T19:00:02Z",
  "durationMs": 2000,
  "bytesWritten": 64000,
  "mimeType": "audio/wav",
  "sampleRateHz": 48000,
  "channels": 1,
  "peakLevel": 0.42,
  "recovered": false,
  "expiresAt": "2026-07-23T19:00:00Z",
  "canPause": true,
  "canResume": false,
  "canStop": true,
  "canCancel": true,
  "errorCode": null,
  "errorMessage": null
}

Recording statuses are starting, recording, paused, stopped, cancelled, and failed. All recording-specific commands use { "recordingId": "..." }:

  • audio_get_recording, audio_pause_recording, audio_resume_recording, audio_stop_recording, and audio_cancel_recording return recording state.
  • audio_get_active_recording returns the scoped active state or null.
  • audio_list_recordings returns all recording states in the launch scope.
  • audio_delete_recording returns { "recordingId": "...", "deleted": true }. An active recording must first be stopped or cancelled, and a recording leased by a transcription job cannot be deleted yet.

The response never includes audio bytes or a local path. Only one recording can be active in the app. A global host control remains available if the extension iframe is minimized. State changes arrive through audio-capture-state-changed; its payload contains sequence, the scoped IDs, and the latest state object.

Transcription Commands ​

These commands require transcribe_audio:

  • transcription_list_providers
  • transcription_start
  • transcription_get
  • transcription_cancel
  • transcription_delete

transcription_list_providers returns only speech-to-text models linked to the exact launch group. Provider credentials and local model paths are removed:

json
[
  {
    "id": "model:...",
    "name": "ggerganov/whisper.cpp · ggml-small",
    "providerKind": "localWhisper",
    "location": "local",
    "modelType": "speechToText",
    "supportsSpeakerLabels": false
  }
]

providerKind is localWhisper or openAiCompatible. A listed local provider is authorized for the group, but its model asset may still be downloading or not yet downloaded. supportsSpeakerLabels describes that exact model configuration; it is not implied by providerKind.

Start request:

json
{
  "recordingId": "opaque-recording-id",
  "modelId": "model:...",
  "language": "nl",
  "prompt": "Optional vocabulary hint"
}

recordingId and modelId are required. Empty optional values are removed; language is limited to 32 characters and prompt to 16,000 characters. The recording must be stopped and belong to the same extension, workspace, and group.

Start response:

json
{
  "jobId": "transcription-...",
  "status": "queued"
}

Persist jobId immediately. There is no command that lists transcription jobs, so it is required to recover state after the extension iframe is remounted.

Local model download handshake ​

The first transcription_start for a local provider also verifies the model asset. When the host starts downloading it, the bridge rejects before creating a job with the plain error message transcription_model_downloading. Keep the recording, show a waiting state, and retry that same request after a short delay. There is currently no public download-progress event.

transcription_model_not_downloaded means the host could not establish a downloaded or downloadable model and should be surfaced as a terminal setup problem. transcription_model_unavailable means the model is no longer present in the frozen launch group's resources. Refresh the provider list after group or dashboard changes and when the extension becomes visible again.

An OpenAI-compatible provider opens a host confirmation for every start. If the user declines, the bridge rejects with external_transcription_cancelled and no job is created. Consent fields, provider endpoints, and API keys sent by an iframe are ignored. The host resolves credentials and binds its single-use consent token to the exact extension, scope, recording, and model.

Speaker-aware remote providers ​

Provider request behavior is host-owned. An extension selects an authorized modelId; it cannot inject a response format, chunking mode, endpoint, or provider-specific multipart field into transcription_start.

An OpenAI-compatible speech-to-text model can be configured by a workspace administrator with:

json
{
  "transcription": {
    "responseFormat": "diarized_json",
    "chunkingStrategy": "auto"
  }
}

The host then advertises supportsSpeakerLabels: true for that provider, asks for diarized output, and preserves each returned opaque speaker key on segments[].speaker. Extensions may display or explicitly map those keys, but must not infer a real identity from a label such as A.

When the host must divide one recording into independent provider uploads, it scopes returned speaker keys to their upload part before merging results. Provider-local labels are not assumed to identify the same person across separate uploads.

Query, cancel, and delete ​

All job commands use { "jobId": "transcription-..." }. transcription_get returns:

json
{
  "job": {
    "id": "transcription-...",
    "sourceId": "recording-...",
    "modelId": "model:...",
    "providerKind": "localWhisper",
    "status": "completed",
    "phase": "completed",
    "progressPct": 100,
    "segmentCount": 1,
    "requestedLanguage": "nl",
    "detectedLanguage": "nl",
    "errorCode": null,
    "errorMessage": null,
    "createdAt": "2026-07-22T19:01:00Z",
    "updatedAt": "2026-07-22T19:01:08Z",
    "completedAt": "2026-07-22T19:01:08Z"
  },
  "result": {
    "id": "transcription-result-...",
    "jobId": "transcription-...",
    "sourceId": "recording-...",
    "modelId": "model:...",
    "providerKind": "localWhisper",
    "text": "Welkom bij de vergadering.",
    "language": "nl",
    "durationMs": 8000,
    "segments": [
      {
        "index": 0,
        "startMs": 0,
        "endMs": 8000,
        "text": "Welkom bij de vergadering.",
        "speaker": null,
        "confidence": null
      }
    ],
    "createdAt": "2026-07-22T19:01:08Z"
  }
}

Job statuses are queued, running, completed, failed, cancelled, and interrupted. Phases are queued, openingRecording, preparingModel, transcribing, finalizing, completed, failed, and cancelled. A result is null until the job completes.

transcription_cancel is idempotent for terminal jobs and returns the job. transcription_delete accepts terminal jobs only and returns { "deleted": true, "jobId": "..." }. Cancel a running job before deleting it.

Transcription events and errors ​

The four browser events are transcription-progress, transcription-segment, transcription-completed, and transcription-failed. Their common payload is:

json
{
  "extensionId": "meeting-warden",
  "workspaceId": "workspace:...",
  "groupId": "group:...",
  "jobId": "transcription-...",
  "status": "running",
  "phase": "transcribing",
  "progressPct": 45,
  "segmentCount": 1,
  "errorCode": null,
  "errorMessage": null,
  "segment": null
}

Only transcription-segment carries a segment. Treat events as hints: an iframe can miss them while minimized, closed, or remounted, so reconcile each relevant event and restored jobId with transcription_get. Failed job views and events include a host-safe errorMessage in addition to the stable errorCode.

Host-command failures serialize { "code", "message", "retryable" } using snake_case codes. The current codes are cancelled, external_consent_required, group_required, internal, invalid_request, invalid_state, model_download_required, model_not_available, permission_denied, provider_error, provider_unavailable, scope_mismatch, source_not_found, and unsupported_audio.

The serialized object is normally carried inside the bridge Error.message. Bridge preflight failures described above are plain message sentinels, so robust code should normalize the message and must not assume every rejection has an error.code field.

ISA Warden extension specification