Batch-ingest agent desktop screen recordings
Quality reviewers in retail branch offices, remote sites on weak links, and regulated windows-VDI fleets all share the same problem: agents capture their desktops locally and only upload when the network allows. Two read-side surfaces under/api/v1/recordings ingest those buffered artefacts after the fact — screen recordings of the agent’s desktop, and per-application usage segments — and bind them to the parent call recording so QA review, dispute evidence, and PCI attestation can replay what the agent saw.
Everything below uses POST /api/v1/recordings/:id/..., where :id accepts either the recording id or the call id of the interaction. That matters for batch upload: a desktop agent normally knows only the call id it captured during the live call, while a batch job reconciling new uploads on a schedule may hold either identifier. Both resolve to the same recording row.
Why the batch path exists
Live video sessions (browser video rooms) stream their screen share in real time and are not what this is for. Desktop capture on contact-center agents runs against screen-tool APIs that only work deployed into each agent’s workstation, and the upload is buffered on the agent’s hard drive until connectivity allows — in supporting poor-connectivity branch sites (retail chains, rural shared services desks, offshore BPO partners on asymmetric links) this is not optional. The ingest pipeline accepts artefacts post-hoc and resolves back to the interaction via the call id, so you can:- Capture locally with whatever tool you already deploy — the agent-side collector is in your hands.
- Upload to cloud storage (your own staging bucket) and hand only the object path over the ingest API.
- Buffer on the workstation during an outage and flush the queue once the link recovers.
1. Ingest screen recordings — sync evaluation + durable store
Screen recordings batch throughPOST /api/v1/recordings/:id/screen-sync. The endpoint evaluates whether the uploaded artefact actually covers the call it claims against a tolerance of 5 seconds on alignment and 90% on coverage, then persists the manifest, the verdict, and the consent/retention data onto the recording row under a dedicated slot.
The manifest the desktop collector posts:
synced— all checks pass: an artefact was actually uploaded, its duration exceeds the 2-second floor, it started within 5 seconds of the call start, it overlaps at least 90% of the call window, and every PCI redaction window stays inside the artefact’s own timeline.out_of_sync— one or more checks failed. The record is still persisted: “an agent uploaded a screen recording that did not line up” is itself dispute evidence, and the per-check report tells you exactly which clause broke.skipped— the call row has no finalized window yet (typically a still-open leg), so there is nothing to align against. The submission still persists, markedskipped.
screen_recordings key, re-submission of the same gcs_path updates in place (safe retry), and the per-recording array is capped at 20 — past that the API returns SCREEN_SYNC_LIMIT_REACHED. The full audit trail reads back with:
gcs_path once and rely on an in-place update rather than deduplicate client-side.
Scope and roles match the recording-QC surface: voice:read to list, voice:write to ingest, and the ingest route requires an owner, admin, or developer role because it emits an auditable QM verdict.
2. Desktop analytics — per-agent application usage (optional)
If your collector also watches which application sits in the foreground (a standard capability of workstation capture agents built on OS focus APIs), you can attach quantitative application-usage analytics as well. The data ships throughPOST /api/v1/recordings/:id/desktop-analytics, and is independent of whether your tenant also records screens — pick one pipeline, the other, or both per agent profile.
The collector orders the observed foreground spans and posts:
communication, crm, productivity, knowledge, idle, other. Labels decide which apps count as talk time vs. non-talk after-call work — idle spans drop out of the active-work totals entirely — so a bad label straight into crm or productivity skews your handle-time split upward rather than the report being wrong.
The report is derived entirely server-side from the segments; a client-sent report is ignored. The persisted record contains:
applications— per application: cumulative foreground time, visit count, share of active desktop time, mean dwell per visit, and whether it tripped the automation-candidate heuristic (at least 3 revisits and 30 seconds of accrued visited data-handling categories).top_transitions— the highest-frequency application→application hop pairs, ranked (max 5 entries).automation_opportunities— apps worth an RPA look, each with the dwell/visit evidence.non_talk_ratio— the fraction of handle time spent outside the communication surface. This is the after-call-work signal.
GET /api/v1/recordings/:id/desktop-analytics lists them, newest first.
Neither of these surfaces communicates with the carrier plane — these are read/QM/scoring artefacts over inbound interaction records, with no outbound contact.
3. Health and vitals reporting
Batch ingest failure modes surface in four predictable places, and the pattern for each:- Verdicts are evidence, not errors.
out_of_syncreturns200. Treat it as an analytic signal for the QA dashboard, not a retry trigger. Thereport.checksarray lists each clause (alignment over 5s, coverage under 90%, a PCI redaction window escaping the artefact’s timeline, a sub-2-second artefact signalling a crashed collector) and the measured value, so drift triage is one aggregation away. - Ingest flushes with strongly-typed failures. Invalid manifests return
400 SCREEN_SYNC_INVALID_BODY/400 DESKTOP_ANALYTICS_INVALID_BODY; unknown recording ids return404. The coverage monotonic thing to aggregate is a counter of non-2xx per flush, and contents-specific counters on a per-sync_statusbasis. - Collector-side vitals piggyback on your own observability. The agent workstation health signal (disk queue depth, oldest unsent artefact, consecutive sync-offset drift) belongs in whatever fleet health collector you already run — the ingest endpoints return enough to bind the flush’s outcome to a workstation and does not share telemetry centrally.
skippedis a race against the call finalize. Repeat the submission in the next batch window; the in-place upsert ongcs_pathkeeps replays safe, so the flush can be the naive “try unflushed records, then read back the list.”
4. Consent, retention, and the tenant-owned flag
Agent-side capture of a screen is workplace-monitoring data, and Orbit’s design preserves the tenant’s authority over it: we do not gate capture on behalf of the tenant and the platform ingest only acts when your account enables it. Concretely:- The capture flag is yours, not ours. Whether desktop capture runs at all is decided tenant-side on the workstation collector, typically behind a per-agent or per-team assignment flag. The ingest surfaces only receive what you enable them to receive; the flag lives with you. Orbit’s compliance posture is intentionally tenant-owned: the platform supplies the controls and leaves policy decisions in your tenant configuration rather than deciding on your behalf.
- Consent posture is recorded per artefact. Send
consent_method— the same closed vocabulary voice recordings use:verbal_attested,operator_attested,ivr_dtmf,ivr_speech,consent_announcement, ornone— and optionallyjurisdiction. Both carry through onto the audit record and the audit event. - Retention is explicit per artefact.
retention_daysaccepts 7–3650 (one week to ten years), matching the bounds voice recording configurations accept. Server-side this derives aretain_untiltimestamp on the record, so your retention sweep can expire desktop captures on the same schedule as audio. Leave it unset to inherit your tenant default. - PCI scope stays auditable. Every
redaction_windowsentry the collector asserts (card-entry screens blanked by pause/blank) is validated to fall inside the artefact’s own timeline — an invalid span will tripout_of_syncinstead of silently undermining the PCI claim. Track the redaction windows on the same compliance review where you review call-recording redaction. - Storage and lifecycle mirror voice recordings. Records travel with the parent recording row’s tombstone, so a GDPR erasure of the interaction removes the screen-capture and desktop-analytics audit trails along with the audio.
Record shape (GET /:id/screen-recordings)
Each item is a stable audit entry — id, artefact gcs_path, the timeline, agent_id, the consent/retention snapshot, the verdict snapshot (sync_status, coverage_ratio, sync_offset_seconds), and creation/update timestamps. Re-submission of the same gcs_path keeps the original id and created_at and moves updated_at forward — the audit identity is stable across retries.