AI Components — Coding, Transcription, Voice & Semantic Search
Mockarty ships four optional self-hosted components that unlock AI-adjacent features. Each one runs next to the admin node. No Mockarty cloud account is required; for a fully air-gapped installation, mirror the component images and models and point the coding runner at a model endpoint inside the same environment.
| Component | Binary | Unlocks |
|---|---|---|
| Autonomous coding | mockarty-coder-runner |
Isolated implementation and verification work for autonomous missions |
| Speech-to-text | mockarty-whisper-runner |
Transcripts for voice messages and meeting recordings in Discussions, plus the AI meeting digest |
| Voice synthesis | mockarty-tts-runner |
The server-side Speak action — a shared voice reply posted into the thread for everyone |
| Semantic search | mockarty-rag-runner |
Semantic (meaning-based) search, “find similar” for test cases and wiki pages, and vector features across the Knowledge Base |
Speech, voice and semantic features degrade gracefully when their component is absent. Autonomous missions remain visible when no coder capacity is connected, so an operator can see and fix the missing runner instead of losing the mission.
How components connect
Every component authenticates to the admin node with an API token (create one in the UI: Settings → API Tokens, or ask your administrator) and identifies itself on start. Two environment variables are always required:
MOCKARTY_URL=http://your-mockarty:5770 # admin node base URL
MOCKARTY_API_TOKEN=<api-token>
Namespace scoping. By default a component with an administrator token serves the whole installation (a shared fleet). Set RUNNER_NAMESPACE=<name> to dedicate it to a single namespace — useful when one team’s traffic should not compete with others. A token that is pinned to a namespace automatically restricts the component to that namespace.
Components send a heartbeat every 30 seconds and deregister on clean shutdown, so the admin’s component lists always reflect reality.
How work reaches a component
By default a component asks the admin node for work: it holds a long request open and starts the job as soon as one appears. This needs no inbound network access, so it works behind NAT, in CI, and on a laptop.
If the admin node can reach the component over the network, you can additionally let it hand the job over directly, which removes the wait between “job created” and “component notices it”. Both ways stay active at the same time: a direct hand-over is tried first, and anything that cannot be delivered — the component is already busy, or unreachable — simply stays in the queue and is picked up the usual way. Nothing is ever lost, and you can turn it off at any time by removing the variables.
To enable it, give the component a port to listen on, a reachable host name, and a shared secret that the admin node also has:
| Variable | Where | Meaning |
|---|---|---|
RUNNER_PUSH_ADDR |
component | Port to accept jobs on, e.g. :8790. Empty = ask-only (the default) |
RUNNER_ADVERTISE_HOST |
component | Host name the admin node uses to reach it, e.g. tts-1. Empty = the component does not offer direct hand-over |
RUNNER_PUSH_SECRET |
component | Shared secret. Falls back to MOCKARTY_A2A_SECRET so one fleet-wide value is enough |
RUNNER_STATE_DIR |
component | Directory for the durable accepted-job journal. Mount it on persistent storage when direct hand-over is enabled |
RUNNER_STATE_ID |
component | Stable identity for that journal across process or pod replacement. It must identify exactly one advertised push endpoint |
MOCKARTY_A2A_SECRET |
admin node | The same secret. Unset = the admin node never hands jobs over directly |
The component also answers GET /healthz on that port — handy as a Kubernetes liveness probe. A component never accepts more jobs at once than its RUNNER_CONCURRENCY: extra hand-overs are declined and those jobs wait in the queue instead.
Before answering that it accepted a directly handed-over transcription or
synthesis job, the component records the job identity under RUNNER_STATE_DIR.
Keep that directory on a persistent volume: after a process restart the
component can then recognize the same job and will not perform paid work twice.
The first start creates an empty journal. A corrupt or unwritable journal makes
the push listener fail closed instead of accepting work without durable
evidence, so preserve the state volume across replacements. Pull-only mode does
not use this journal. Set RUNNER_STATE_ID to a stable value that survives pod
replacement. One advertised push address must lead to exactly one runner
journal; do not put multiple push replicas behind a load-balanced address. The
Helm chart enforces replicaCount: 1 while this push lane is enabled.
Autonomous coding runner
mockarty-coder-runner executes the coding steps of autonomous missions. Pull mode is the normal on-premises setup: the runner makes outbound requests to the admin node, advertises only the engine and sandbox selected for that process, accepts work only while it has capacity, and reports a durable terminal result before deregistering. Push mode is available for installations where the admin node can reach the runner.
Trust setup
The admin node signs short-lived task attestations and the runner verifies them with the paired public key. The two bindings must match exactly:
- set the admin node’s
MOCKARTY_CODER_ADMIN_URLto its stable public base URL; - start every runner with the same URL in
--admin-urland a stable--runner-id; - keep the admin signing seed/private key in a Kubernetes Secret or another secret manager as
MOCKARTY_CODER_ATTEST_KEY; - build the runner image with only the paired public key:
--build-arg CODER_ATTEST_PUBLIC_KEY_B64=<base64-ed25519-public-key>.
Never put the signing seed/private key into the runner image, a build argument, or runner environment. A source-only development build without an embedded public key fails closed. MOCKARTY_CODER_ALLOW_DEV_OPEN=1 opens it only for an isolated local development run and must never be used in a shared or production environment.
Without the key, a production node signs nothing. With ENV=production and no MOCKARTY_CODER_ATTEST_KEY, the coder routes still answer, but runner registration and heartbeat are refused with a message naming the variable. This is deliberate: a key generated on the fly would change on every restart, so attestations issued before one would stop verifying after it — and a runner built with a pinned public key would never accept them at all. An install that does not run a coder needs no key and is unaffected. On a development machine (ENV unset or anything other than production) a temporary key is generated so the fleet can be worked on locally.
For Helm, keep the admin URL in values and inject the signing seed from a Secret:
admin:
env:
MOCKARTY_CODER_ADMIN_URL: "https://mockarty.company.example"
extraEnvFrom:
- secretRef:
name: mockarty-coder-attestation # key: MOCKARTY_CODER_ATTEST_KEY
Pull-mode start
Create a namespace-scoped API token in Settings → API Tokens, choose a separate runner transport secret, and start the image:
docker run --rm \
-v mockarty-coder-state:/home/coder/.mockarty-coder \
-e MOCKARTY_CODER_TOKEN=<namespace-api-token> \
-e MOCKARTY_CODER_SECRET=<runner-transport-secret> \
-e DEEPSEEK_API_KEY=<model-key> \
ghcr.io/your-org/mockarty-coder-runner:version \
--pull --admin-url https://mockarty.company.example \
--namespace my-team --runner-id coder-01 \
--engine opencode --sandbox local
Keep the work-root volume across restarts: it contains pending result deliveries and bounded exact-replay receipts, not only temporary checkouts. Use --sandbox docker for untrusted tasks when the runner host provides Docker. The runner advertises only the selected sandbox and engine, so the admin does not dispatch work for capabilities that this process cannot execute. --max-concurrent is bounded by the process CPU budget.
Docker isolation also requires a pre-pulled engine image in --image and access to a dedicated or rootless Docker daemon. The runner image contains the Docker CLI but no daemon. Mount the daemon socket into the runner container (normally at /var/run/docker.sock) and add the socket’s group ID with Docker’s --group-add; the runner fails before registration if the CLI or daemon is unavailable. A host Docker socket grants broad control over that host, so do not share a general-purpose production daemon with untrusted autonomous workloads. Anyone who controls that daemon can inspect a workload container’s environment; treat the daemon and its operators as part of the trusted secret boundary. Prefer a dedicated runner host or rootless daemon and restrict its network separately. The --sandbox local example above is intentionally unsandboxed and is suitable only for an isolated development runner.
When a coder task declares original files, the runner redeems them before the
engine starts. Configure the exact HTTPS POST endpoint in
MOCKARTY_CODER_MATERIAL_BROKER_URL and inject its Bearer service credential
through MOCKARTY_CODER_MATERIAL_BROKER_TOKEN. Neither value may be named by a
task as a model, repository, or workspace credential. The runner verifies each
declared size, SHA-256 digest, MIME type, and response body, stages the complete
set under .mockarty-materials/, and does not expose one-time handles to the
coding engine or its report. The broker must bind redemption to the supplied
task, lease generation, logical attempt, design digest, and plan digest.
Push-mode start
Push mode suits installations where the admin node can reach the runner directly: the admin hands a job to the runner the moment it is queued, instead of waiting for the runner’s next poll.
The runner still registers with the admin, so it needs the same namespace token as a pull runner, plus the address the admin will dial:
docker run --rm -p 7480:7480 \
-v mockarty-coder-state:/home/coder/.mockarty-coder \
-e MOCKARTY_CODER_TOKEN=<namespace-api-token> \
-e MOCKARTY_CODER_SECRET=<runner-transport-secret> \
-e DEEPSEEK_API_KEY=<model-key> \
ghcr.io/your-org/mockarty-coder-runner:version \
--listen 0.0.0.0:7480 --callback-url http://coder-01.internal:7480 \
--admin-url https://mockarty.company.example \
--namespace my-team --runner-id coder-01 \
--engine opencode --sandbox local
--callback-url is the address the admin dials. When --listen already names a concrete host it is derived automatically; a wildcard bind such as 0.0.0.0:7480 has no dialable form, so the runner refuses to start without an explicit value rather than advertising an address nothing can reach.
The admin authenticates its outbound pushes with a credential it issues to this runner at registration; the runner adopts it automatically, and it is replaced on every re-registration. Nothing extra to configure.
A pushed job that the runner declines — it is at capacity, or the request never reached it — goes straight back to the queue, so a runner that also polls picks it up on its own. Results travel back over the same durable path pull mode uses, and SIGTERM still drains admitted work and deregisters the runner.
Repository credentials
A task may name a repository credential through repo.tokenEnv; it never carries the token value. The runner accepts that environment name only when MOCKARTY_CODER_REPO_TOKEN_BINDINGS binds the repository’s exact HTTPS origin to it:
MOCKARTY_CODER_REPO_TOKEN_BINDINGS="git.company.example=GITLAB_TOKEN,github.com=GH_TOKEN"
The format is host=ENV[,host=ENV]. For default HTTPS port 443, use only the host. For a non-default port, use host:port=ENV, for example git.company.example:8443=GITLAB_TOKEN. Matching is exact, repository URLs must use HTTPS, and one environment variable must not be rebound to another origin. Runner-internal credentials such as MOCKARTY_CODER_TOKEN, MOCKARTY_CODER_SECRET, the attestation signing key, and the Mockarty MCP key are never valid repository credentials.
The token is provided to Git through a private, short-lived askpass helper. It is not placed in process arguments or saved in .git/config.
Health and shutdown
Push mode exposes GET /healthz for liveness and GET /readyz for admission readiness. Readiness becomes unavailable as soon as draining starts, while liveness stays available until in-flight work has finished. Completed-task receipts are written atomically under the work root. If the same queue attempt is physically redelivered after a lost response or process restart, the runner sends the cached result instead of repeating the paid task; an explicit new retry remains a new execution even when its task text is unchanged. A result saved immediately before a crash is delivered before the restarted runner accepts more work, and push mode keeps retrying a durable pending result without requiring another restart. Pull mode also stops claiming work when heartbeat/lease safety or durable result delivery is uncertain. Shutdown budgets follow the longest admitted task timeout plus result-delivery time; the runner does not report a clean deregistration while paid work remains unresolved.
Speech-to-text (transcription)
When at least one transcription component is live, Discussions gain:
- automatic text transcripts under voice messages,
- transcripts + an AI digest (decisions, questions, action items) for meeting recordings.
Audio travels only between the component and the admin node.
Long recordings (meetings) are transcribed segment by segment, and the text
grows on the transcription job as each segment is recognised — you do not have
to wait for the whole file before reading the first minutes. The finished
transcript is still posted once, complete, under the recording.
Run with Docker Compose
A ready compose file ships with the distribution (deploy/compose/docker-compose.whisper-runner.yml). The image bakes in a small multilingual model, so the minimal start is two variables:
MOCKARTY_URL=http://admin:5770 MOCKARTY_API_TOKEN=<token> \
docker compose -f docker-compose.whisper-runner.yml up -d
Dedicate a pool to one namespace and scale it:
MOCKARTY_URL=... MOCKARTY_API_TOKEN=... RUNNER_NAMESPACE=my-team \
docker compose -f docker-compose.whisper-runner.yml up -d --scale whisper-runner=2
Use a different recognition model without rebuilding the image — mount a directory with a GGML model file:
WHISPER_MODEL_DIR=/srv/models WHISPER_MODEL_FILE=ggml-large-v3-turbo-q5_0.bin \
MOCKARTY_URL=... MOCKARTY_API_TOKEN=... \
docker compose -f docker-compose.whisper-runner.yml up -d
Run in Kubernetes (Helm)
The Mockarty Helm chart includes the component — enable it in your values:
whisperRunner:
enabled: true
namespace: "sandbox" # namespace it serves
apiToken: "" # inline for dev; use existingSecret in production
existingSecret: "" # Secret holding API_TOKEN
Run the binary directly
The component wraps a local whisper-server process (from the whisper.cpp project) — install it and point the runner at a GGML model:
| Variable | Required | Meaning |
|---|---|---|
MOCKARTY_URL |
yes | Admin node base URL |
MOCKARTY_API_TOKEN |
yes | API token |
WHISPER_MODEL_PATH |
yes | Path to the GGML model file |
WHISPER_SERVER_BIN |
no | Path to whisper-server (default: found on PATH) |
WHISPER_LANGUAGES |
no | Languages to advertise (default auto) |
RUNNER_NAME |
no | Display name (default whisper-<hostname>) |
RUNNER_NAMESPACE |
no | Serve only this namespace (empty = shared fleet) |
RUNNER_CONCURRENCY |
no | Parallel jobs (default 1) |
WHISPER_TRIM_SILENCE |
no | 1 = pre-trim silence with ffmpeg for faster jobs |
RUNNER_PUSH_ADDR |
no | Accept jobs handed over directly (see How work reaches a component) |
RUNNER_ADVERTISE_HOST |
no | Host name the admin node uses to reach this component |
RUNNER_PUSH_SECRET |
no | Shared secret for direct hand-over (falls back to MOCKARTY_A2A_SECRET) |
MOCKARTY_URL=http://localhost:5770 MOCKARTY_API_TOKEN=<token> \
WHISPER_MODEL_PATH=/models/ggml-small-q5_1.bin \
./mockarty-whisper-runner
For CI-style ephemeral use, --once processes a single job and exits.
Alternative: external transcription API
If you already operate a speech-to-text service with an OpenAI-compatible audio endpoint, skip the component and point the admin node at it:
MOCKARTY_TRANSCRIBE_URL=https://stt.internal/v1/audio/transcriptions
MOCKARTY_TRANSCRIBE_KEY=<key> # optional
MOCKARTY_TRANSCRIBE_MODEL=whisper-1 # optional
When both are present, live components take priority; the external API handles namespaces no component covers.
Voice synthesis (server-side Speak)
Text messages in Discussions always offer browser-side read-aloud (each person hears it locally). With a voice-synthesis component installed, the Speak action can also produce a shared voice reply — an audio message posted into the thread that everyone can play.
Run with Docker Compose
A ready compose file ships with the distribution (deploy/compose/docker-compose.tts-runner.yml). The image bakes in a Russian voice by default, so the minimal start is two variables:
MOCKARTY_URL=http://admin:5770 MOCKARTY_API_TOKEN=<token> \
docker compose -f docker-compose.tts-runner.yml up -d
Dedicate a pool to one namespace and scale it:
MOCKARTY_URL=... MOCKARTY_API_TOKEN=... RUNNER_NAMESPACE=my-team \
docker compose -f docker-compose.tts-runner.yml up -d --scale tts-runner=2
Use another voice without rebuilding the image — mount a directory with a Piper voice model (.onnx + its .onnx.json):
PIPER_VOICE_DIR=/srv/voices PIPER_VOICE_FILE=en_US-lessac-medium.onnx \
MOCKARTY_URL=... MOCKARTY_API_TOKEN=... \
docker compose -f docker-compose.tts-runner.yml up -d
Run in Kubernetes (Helm)
The Mockarty Helm chart includes the component — enable it in your values:
ttsRunner:
enabled: true
namespace: "sandbox" # namespace it serves
apiToken: "" # inline for dev; use existingSecret in production
existingSecret: "" # Secret holding API_TOKEN
Run the binary directly
The component wraps the Piper speech synthesizer — install piper and download a voice model (.onnx):
| Variable | Required | Meaning |
|---|---|---|
MOCKARTY_URL |
yes | Admin node base URL |
MOCKARTY_API_TOKEN |
yes | API token |
PIPER_MODEL |
yes | Path to the Piper voice model (.onnx) |
PIPER_BIN |
no | Path to piper (default: found on PATH) |
PIPER_VOICE_NAME |
no | Voice name to advertise (default: model file name) |
RUNNER_NAME |
no | Display name (default tts-<hostname>) |
RUNNER_NAMESPACE |
no | Serve only this namespace (empty = shared fleet) |
RUNNER_CONCURRENCY |
no | Parallel jobs (default 1) |
RUNNER_PUSH_ADDR |
no | Accept jobs handed over directly (see How work reaches a component) |
RUNNER_ADVERTISE_HOST |
no | Host name the admin node uses to reach this component |
RUNNER_PUSH_SECRET |
no | Shared secret for direct hand-over (falls back to MOCKARTY_A2A_SECRET) |
MOCKARTY_URL=http://localhost:5770 MOCKARTY_API_TOKEN=<token> \
PIPER_MODEL=/models/ru_RU-irina-medium.onnx \
./mockarty-tts-runner
--once is supported for ephemeral CI use. Without this component the shared-voice option is unavailable; local browser read-aloud keeps working.
Voice task defaults (per namespace)
A namespace can say two things about its automatic voice work — voice notes queued for transcription and replies queued for speech — in Settings → AI & Meetings:
- Voice language — the default language (BCP-47, e.g.
ru-RU) stamped on automatically queued voice tasks. A request that names its own language always wins. - Voice runner selector — comma-separated
key=valuelabels a runner must advertise (for exampleregion=eu,gpu=true). Leave empty to let any capable runner serve the namespace.
Both settings are constraints on where work goes: the queue skips a runner that does not match the selector (or the advertised language) and leaves the task for one that does. When no live runner matches, the task stays in the queue with a visible reason instead of being served by the wrong runner or hanging silently — add a runner whose advertised labels fit, and the queue picks it up.
The same settings are available over the API (GET/PUT /api/v1/namespaces/{namespace}/ai-settings, fields voiceLanguage and voiceRunnerSelector) and to agents through the namespace_voice_settings_get / namespace_voice_settings_update MCP tools.
Semantic search
With a semantic component registered, Mockarty adds meaning-based capabilities on top of regular keyword search:
- Semantic search across product entities (cases, wiki pages, mocks…),
- Find similar — near-duplicate detection for test cases, related wiki pages,
- vector-backed Knowledge Base features.
Vectors are stored in Mockarty’s own database — the component is stateless compute. Killing or scaling it loses nothing.
Unlike the two components above, the admin node calls this component, so it must be reachable from the admin at a URL you advertise:
| Variable | Required | Meaning |
|---|---|---|
MOCKARTY_URL |
yes | Admin node base URL |
MOCKARTY_API_TOKEN |
yes | API token |
ADVERTISE_URL |
yes | URL the admin uses to reach this component |
EMBED_MODEL_PATH |
yes | Path to the GGUF embedding model |
EMBED_SECRET |
yes for network listeners | Bearer secret the admin must present. It may be omitted only when LISTEN_ADDR is an explicit loopback IP |
LISTEN_ADDR |
no | Listen address (default :8090) |
RUNNER_NAME |
no | Display name (default rag-<hostname>) |
RUNNER_NAMESPACE |
no | Serve only this namespace (empty = shared fleet) |
LLAMA_ARG_THREADS |
no | llama.cpp worker threads (default: detected container CPU budget) |
LLAMA_ARG_CTX_SIZE |
no | Context size (default 2048) |
LLAMA_ARG_BATCH |
no | Physical batch size; must be at least the context size (default 2048) |
LLAMA_ARG_UBATCH |
no | Micro-batch size; must not exceed the physical batch (default 2048) |
LLAMA_ARG_N_PARALLEL |
no | Concurrent embedding slots (default: the smaller of 2 and the configured worker-thread budget) |
The component wraps a local llama-server (from the llama.cpp project) in embeddings mode. GET /healthz is the liveness endpoint. GET /readyz returns ready only after the model is available and the component is registered with the admin node. Embedding requests must use POST /v1/embeddings with JSON and the configured Bearer secret. Requests over 8 MiB are rejected; when all configured slots are busy, the component returns 429 with Retry-After so callers can retry without overloading the model.
Run with Docker Compose
MOCKARTY_URL=http://admin:5770 MOCKARTY_API_TOKEN=<token> \
ADVERTISE_URL=http://rag-runner:8090 EMBED_SECRET=<random-secret> \
docker compose -f docker-compose.rag-runner.yml up -d
Set RAG_RUNNER_IMAGE to the image mirrored into your registry. If Compose needs to build it locally, set RAG_MODEL_SHA256 to the verified SHA-256 of RAG_MODEL_URL; a missing or mismatched checksum stops the build. Set RAG_MODEL_MODE=NONE only when your own model is mounted at runtime: set EMBED_MODEL_DIR to its host directory and point EMBED_MODEL_PATH to /ext-models/<file>.
Run in Kubernetes (Helm)
ragRunner:
enabled: true
namespace: "" # empty = shared; set a namespace for dedicated compute
embedSecret: "" # bearer the admin presents on embedding calls
apiToken: "" # inline for dev; use existingSecret in production
existingSecret: "" # Secret holding API_TOKEN + EMBED_SECRET
The chart wires ADVERTISE_URL to the in-cluster service automatically.
Alternative: external embedding API
Any OpenAI/Ollama/TEI-compatible embedding server works — point the admin node at it instead of running the component:
MOCKARTY_EMBED_URL=https://embeddings.internal/v1/embeddings
MOCKARTY_EMBED_KEY=<key> # optional
MOCKARTY_EMBED_MODEL=<model-name> # optional
Without a component and without MOCKARTY_EMBED_URL, semantic features stay hidden and regular keyword search keeps working.
Monitoring
Registered components are visible over the API:
curl -H "Authorization: Bearer <token>" http://localhost:5770/api/v1/transcribe/runners
curl -H "Authorization: Bearer <token>" http://localhost:5770/api/v1/transcribe/jobs
curl -H "Authorization: Bearer <token>" http://localhost:5770/api/v1/tts/runners
curl -H "Authorization: Bearer <token>" http://localhost:5770/api/v1/semantic/endpoints
curl -H "Authorization: Bearer <token>" http://localhost:5770/api/v1/semantic/status
Each entry carries the component’s name, model, namespace, last heartbeat and job counters — a component that stops heartbeating drops out of dispatch automatically.
After an admin restart removes a speech runner’s registration, the runner
registers again on its next heartbeat. A temporary network or server error
does not create another registration; check the runner list once the admin
recovers.
Jobs waiting on an unanswered runner
When Mockarty pushes a job to a component and the response never comes back —
a dropped connection, a timeout, a component that died mid-answer — the job is
held, not retried. The component may already be doing the work, and
transcription and synthesis both cost real money, so handing the same job to a
second component would pay for it twice.
Held jobs are listed on their own. Listing requires read access to the target
namespace; a namespace outside the caller’s scope is hidden:
curl -H "Authorization: Bearer <token>" http://localhost:5770/api/v1/transcribe/jobs/fenced
curl -H "Authorization: Bearer <token>" http://localhost:5770/api/v1/tts/jobs/fenced
Each entry names the component the job is held under and how long it has been
waiting. Nothing moves it until you say what happened — check the component,
then record the answer. Reconciliation requires write access to the target
namespace; viewers and auditors cannot settle paid work.
curl -X POST -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
-d '{"runnerId":"<component id>","outcome":"not_started"}' \
http://localhost:5770/api/v1/transcribe/jobs/<job id>/reconcile-delivery
not_started— the component never began. The job goes back in the queue for
another component and the failed delivery is not counted against its retries.started— it did begin. The job is closed without being repeated.
An agent does the same through media_delivery_queue and
media_delivery_reconcile. Both record a fact you established; neither one
checks the component for you.
The CLI and all supported SDKs expose the same two operations:
mockarty-cli media-delivery queue --engine transcribe
mockarty-cli media-delivery reconcile <job-id> --engine transcribe \
--runner-id <component-id> --outcome not_started
page, err := client.MediaDelivery().ListFenced(ctx, "transcribe")
err = client.MediaDelivery().Reconcile(ctx, "transcribe", jobID, runnerID, "not_started")
page = client.media_delivery.list_fenced("transcribe")
client.media_delivery.reconcile("transcribe", job_id, runner_id, "not_started")
Map<String, Object> page = client.mediaDelivery().listFenced("transcribe");
client.mediaDelivery().reconcile("transcribe", jobId, runnerId, "not_started");
See also
- Discussions — voice messages, meetings, transcripts
- Knowledge Base (RAG) — what semantic search powers
- AI Features — the AI assistant and agent
- Installation & Deployment — deploying the platform itself