@xema/omni-protocol 0.1.95 → 0.1.96

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/guide.md CHANGED
@@ -19,18 +19,18 @@ are used precisely throughout and mean nothing looser here.
19
19
  | Word | What it means |
20
20
  | --- | --- |
21
21
  | **Omni** | The desktop application an agent works in. It composes several providers into one agent-facing experience and owns everything outside a provider's own system. |
22
- | **Host** | Omni, named that way where the contrast with a provider is the point — *the host carries the audio*, *host-side input*. |
22
+ | **Agent application** | The software the agent uses, such as Omni, whether web or desktop. It presents provider tasks and controls and manages local audio where supported. Existing API names use `Host` and `host` for this role. |
23
23
  | **Provider** | One independently connected external system: a voice platform, a chat platform, a mail platform. |
24
24
  | **Adapter** | The package implementing this contract for one provider. One adapter is one provider, so the words are often interchangeable; *provider* names the system, *adapter* the code speaking for it. |
25
25
  | **Agent** | The person signed in and taking work. On `onCall`, `agent` is a person on the call by user id; transfer destinations may include an agent when the provider publishes that directory item. |
26
26
  | **Lead** | An agent whose login declares `capabilities.team`. The provider publishes a `TeamMembers` object to them and to nobody else: **the login is the permission**. |
27
- | **Provisioning** | Omni-side policy about this agent, configured outside the protocol and never sent to a provider. It gates whether an offer may be rejected, whether the agent goes ready on login, and whether tasks are auto-accepted. Where a capability and provisioning disagree, the stricter wins. |
27
+ | **Local policy** | Rules configured by the agent application about this agent, outside the provider protocol and never sent to a provider. It gates whether an offer may be rejected, whether the agent goes ready on login, and whether tasks are auto-accepted. Where a capability and local policy disagree, the stricter wins. |
28
28
  | **Call** | The caller’s complete phone call, which may continue through IVRs, queues and several agents. |
29
29
  | **Interaction** | One agent’s part in the call or conversation. The same call may return to that agent for a new interaction. |
30
30
  | **Task** | The agent’s assigned work and its workspace, controls and completion work. A voice task represents one interaction, not the caller’s whole call. |
31
31
  | **Channel** | The kind of work a provider carries: `voice`, `chat`, or `email`. Fixed per provider by its manifest. |
32
32
  | **Task type** | The provider's own name for a category of work — a queue, a mailbox folder, a chat source. Free-form, and finer-grained than a channel. |
33
- | **Capability** | A provider's declaration that a control exists for a task or a session. It says *offer this*; the provider performs it, and the host only offers it — see **Where a command executes**. |
33
+ | **Capability** | A provider's declaration that a control exists for a task or a session. It says *offer this*; the provider performs it, and the agent application only offers it — see **Where a command executes**. |
34
34
  | **Login** | One authenticated sign-in to one provider, identified by `loginId`. A transport reconnect keeps it; signing in again replaces it, and nothing tied to the old `loginId` survives. |
35
35
  | **Transport** | The adapter's connection to its platform: a WebSocket or SignalR connection, required to be persistent and ordered. Which one and how it reconnects are the adapter's business; losing it does not end a login. |
36
36
  | **Connection** | The `Connection` object Omni holds for one login: the methods it can call and the events it receives. |
@@ -39,7 +39,7 @@ are used precisely throughout and mean nothing looser here.
39
39
  | **Event** | One completed transaction reported after a snapshot established the baseline. |
40
40
  | **Break** | A reported, supervised state in which the agent is not working — one with a reason, a decision behind it and a return. It covers what a platform may call *not-ready*, including equipment trouble. An agent who is merely at capacity is not on a break. |
41
41
  | **Workspace** | What Omni shows the agent. The **task workspace** holds the selected task, its controls and its browsers; the **idle workspace** holds what a provider contributes when no task is selected — dialpad, contacts, calendar, team member list. |
42
- | **Dial** | One outbound call the host asks a provider to place — from the idle dialpad, a cold or warm transfer, a conference add, or a connect-back. Identified by the host's `dialId`, accepted as `dialling`, and ended by exactly one `dial-outcome`. See **Every dial has an outcome**. |
42
+ | **Dial** | One outbound call the agent application asks a provider to place — from the idle dialpad, a cold or warm transfer, a conference add, or a connect-back. Identified by the agent application's `dialId`, accepted as `dialling`, and ended by exactly one `dial-outcome`. See **Every dial has an outcome**. |
43
43
  | **Listen** | A lead listening to a member's call unasked, from the team member list: `listen` in silence, `coach` heard by the agent alone, `join-call` heard by everyone. Nothing of it reaches the member's task, and there is no take-over in it. See **Listening to a call**. |
44
44
  | **On the call** | Who a voice task's audio joins, or is bringing in, as the provider states it on `Task.onCall`: the party, the agents, and anyone consulted or conferenced in from the moment their dial is placed. |
45
45
 
@@ -55,6 +55,11 @@ state use `status`; name the object when discussing them to avoid ambiguity.
55
55
  | `status` | The agent’s break lifecycle | `not-requested`, `awaiting-approval`, `granted`, `starting-after-task`, `on-break` |
56
56
  | `availability` | A team member | `ready`, `on-task`, `on-break`, `signed-out` |
57
57
 
58
+ Migration: describeUsers is now `getUserDetails`, and validateDescribedUsers is now
59
+ `validateUserDetails`. Related diagnostics use getUserDetails. Hosts and providers must
60
+ update together; the old method and validator have no compatibility aliases. The requested
61
+ user IDs, returned user details and directory requirements are unchanged.
62
+
58
63
  ## Versioning
59
64
 
60
65
  ### `OMNI_PROTOCOL_VERSION`
@@ -67,12 +72,12 @@ An adapter declares **every** version it can speak, not just the one it was comp
67
72
 
68
73
  ```ts
69
74
  supportedProtocolVersions: [1] // v1 only
70
- supportedProtocolVersions: [1, 2] // can serve either host
75
+ supportedProtocolVersions: [1, 2] // can serve either agent application
71
76
  ```
72
77
 
73
78
  A single pinned version would make migration impossible: recompiling against a newer package
74
79
  would silently move an adapter to the new version with no window in which both sides
75
- interoperate. Declaring a set lets an adapter support the old and new host at once, so the two
80
+ interoperate. Declaring a set lets an adapter support the old and new agent application at once, so the two
76
81
  can be deployed independently.
77
82
 
78
83
  ### `negotiateProtocolVersion(adapterVersions, hostVersions?)`
@@ -488,7 +493,7 @@ type Snapshot = {
488
493
  };
489
494
 
490
495
  type AgentCapacity = {
491
- count: number; // absolute ceiling, zero or more; zero is host-stopped
496
+ count: number; // absolute ceiling, zero or more; zero is agent application-stopped
492
497
  };
493
498
 
494
499
  type CapacityResult = { status: "applied" };
@@ -870,7 +875,7 @@ leaves out does not exist — a structure with no site level declares `org`, `te
870
875
  at: a label with no policy behind it decides nothing. A manifest that declares none has exactly
871
876
  the four. `lockedBy` is any level in force except `person`, who never locks their own value;
872
877
  `setBy` is any level in force, or `provider`, the protocol's word for "no level has said
873
- anything and the provider's own configuration supplied the value". A host renders "who decided" from the
878
+ anything and the provider's own configuration supplied the value". An agent application renders "who decided" from the
874
879
  declared labels and needs no others, and validates every republished `authenticated` state
875
880
  against them, not only the sign-in. What the wire carries is the resolution:
876
881
 
@@ -897,7 +902,7 @@ The adapter is the one that knows the value, so it is the one held to it: given
897
902
  queue locked, the validator refuses any other field carrying one, digits compared as digits so no
898
903
  formatting hides them (`task.locked.leak`), and a conformance run whose tasks lock a party's number
899
904
  or email states those values in `lockedValues`, since a run that cannot ask the question is not a
900
- pass. A host never has the value and never asks. A name is not locked. What the queue provides rather than permits — browsers, outcomes, custom
905
+ pass. An agent application never has the value and never asks. A name is not locked. What the queue provides rather than permits — browsers, outcomes, custom
901
906
  controls — is content, and is never locked.
902
907
 
903
908
  **A lead sets the team's policy from their team member list.** A login that declares
@@ -921,9 +926,9 @@ person's preference from their own screen, which arrives the same way. A prefere
921
926
  the capability's own name because it is the same capability at another level: effective in
922
927
  `Task.capabilities`, set for the team in `policies`, left to the person in `preferences`. The
923
928
  command `hold` acts on one call; the preference `hold` says whether the person wants the control
924
- at all, and a host renders it in its settings, never as the button on a call. Mute is in none of
925
- these ladders: the microphone is the host's, and nobody on the provider's side allows, locks or
926
- keeps a choice about it. See **The station is the host's**.
929
+ at all, and an agent application renders it in its settings, never as the button on a call. Mute is in none of
930
+ these ladders: the microphone is the agent application's, and nobody on the provider's side allows, locks or
931
+ keeps a choice about it. See **The station is the agent application's**.
927
932
 
928
933
  ## Breaks
929
934
 
@@ -1163,7 +1168,7 @@ type Connection<C extends Channel = Channel> = {
1163
1168
  execute(request: TaskCommandRequest<C>): Promise<TaskCommandResult>;
1164
1169
  disconnect(): Promise<void>;
1165
1170
 
1166
- describeUsers?(ids: UserId[]): Promise<User[]>;
1171
+ getUserDetails?(ids: UserId[]): Promise<User[]>;
1167
1172
  dial?(request: DialRequest): Promise<DialResult>;
1168
1173
 
1169
1174
  requestBreak?(request: BreakRequest): Promise<BreakRequestResult>;
@@ -1401,7 +1406,7 @@ fact.
1401
1406
 
1402
1407
  Omitting a field says *I cannot see this*. An empty value says *I looked, and there is nothing*.
1403
1408
 
1404
- Send whichever is true. A host renders them differently and cannot recover the distinction once
1409
+ Send whichever is true. An agent application renders them differently and cannot recover the distinction once
1405
1410
  it is lost.
1406
1411
 
1407
1412
  The same distinction applies to nested fields. Omit a nested field only when its value is unknown;
@@ -1500,7 +1505,7 @@ normative definition; matching names alone do not establish shared meaning.
1500
1505
  ### 10. Order on the wire is display order
1501
1506
 
1502
1507
  A list the provider publishes — a destination directory, outcome codes, a task's custom
1503
- controls, its browsers — is in the order the provider wants it shown, and a host keeps that order.
1508
+ controls, its browsers — is in the order the provider wants it shown, and an agent application keeps that order.
1504
1509
  A reader will find meaning in position unless something says there is none, so the provider
1505
1510
  decides: where it has an intention, an administrator's sequence, it lists in that order; where it
1506
1511
  has none, it orders by the label, so the order is visibly arbitrary and does not move under the
@@ -1537,9 +1542,9 @@ the login's store where the platform cannot hold it. Per offer, the `allocationI
1537
1542
  the offer itself states; per call, the media follows `task-media-started` and `task-media-ended`,
1538
1543
  never a flag set when the audio was opened; per session, the phone the agent holds is what the
1539
1544
  platform restates on activation, not a mapping read once over HTTP. What the platform cannot hold
1540
- -- a host's muted leg -- goes in `ConnectContext.store`, keyed by the task and gone with it.
1545
+ -- an agent application's muted leg -- goes in `ConnectContext.store`, keyed by the task and gone with it.
1541
1546
 
1542
- A fact read once over a connection and kept in the adapter object dies with the client. A host
1547
+ A fact read once over a connection and kept in the adapter object dies with the client. An agent application
1543
1548
  reload is the first client dying and a second coming up for the same login, and the second
1544
1549
  publishes the same truth about the same task as the first did, or the first was publishing
1545
1550
  something it made up: an allocation minted for the connection, media remembered as a boolean, a
@@ -1608,11 +1613,11 @@ compile time.
1608
1613
  | `phaseLabels` | Optional static adapter-defined display names for canonical `TaskPhase` values. They cannot vary at runtime. |
1609
1614
  | `taskTypePresentation` | Optional static adapter-defined presentation keyed by exact `taskType`. It names the item and its optional agent-facing reference. |
1610
1615
  | `orgLevels` | The organisation's whole ladder as the provider calls it, each level with the label a desk shows for "who decided". Stated outright, `person` included: what it leaves out does not exist. Omitted for the typical four, `DEFAULT_LEVELS`. See **Who decides what an agent may do**. |
1611
- | `phones` | Voice only, and required there: the phones this platform can put an agent on, `softphone` (the call's audio lands in the host) and/or `deskPhone` (a handset the platform rings; the host shows the call and opens nothing). The host picks one per login. See **How the agent hears the call**. |
1616
+ | `phones` | Voice only, and required there: the phones this platform can put an agent on, `softphone` (the call's audio lands in the agent application) and/or `deskPhone` (a handset the platform rings; the agent application shows the call and opens nothing). The agent application picks one per login. See **How the agent hears the call**. |
1612
1617
  | `dialOutcomes` | Voice only. How a dial can end on this platform, as it distinguishes them: `answered` and at least one way of not reaching the destination. Required of a provider that dials at all — an idle dialpad, or tasks that transfer, conference or call back — and a `dial-outcome` carries only a declared member. See **Every dial has an outcome**. |
1613
- | `timeCheck` | Optional `true`: implements `checkTime` for fresh provider-clock samples; host polling is independently opt-in. |
1614
- | `timestampAuthority` | Optional `"provider"`: provider timestamps are final; host instants are advisory. Omission makes no trust promise. |
1615
- | `runningStepReports` | The provider takes running reports of a host-performed step — `recordStep` with `seconds` so far and no `ended`. Omitted, the host sends exactly two reports per leg, when it began and when it ended, and a running one is refused. See **The host records what it performs**. |
1618
+ | `timeCheck` | Optional `true`: implements `checkTime` for fresh provider-clock samples; agent application polling is independently opt-in. |
1619
+ | `timestampAuthority` | Optional `"provider"`: provider timestamps are final; agent application instants are advisory. Omission makes no trust promise. |
1620
+ | `runningStepReports` | The provider takes running reports of an agent application-performed step — `recordStep` with `seconds` so far and no `ended`. Omitted, the agent application sends exactly two reports per leg, when it began and when it ended, and a running one is refused. See **The agent application records what it performs**. |
1616
1621
  | `completionSettleMs` | Required. How long after an applied completion -- `complete`, or a lead's `take-over-call` -- the provider's `task-ended` is owed, a positive whole number of milliseconds (`manifest.completionSettleMs`). A warm transfer's `complete` is not final task completion: the agent's wrap runs after it. Stated per provider, since platforms settle at different speeds. See **`task-ended`**. |
1617
1622
 
1618
1623
  ### Authentication methods
@@ -1867,8 +1872,8 @@ Creates the provider-scoped authentication session.
1867
1872
  | --- | --- |
1868
1873
  | `protocolVersion` | The negotiated version, fixed for this login. |
1869
1874
  | `loginId` | Omni-generated identity for this login. The same value Omni later passes as `ConnectContext.loginId`, and how an adapter ties a connection back to the session that authenticated it. |
1870
- | `timeZone` | The zone the agent's day is reckoned in, as an IANA name from the host's clock, stated before any identity exists so the first `authenticated` state already carries it. The same value Omni later passes as `ConnectContext.timeZone`. See **The agent's day**. |
1871
- | `phone` | How this login hears its calls, chosen by the host from the manifest's `phones`: required for a voice provider, absent for any other. The same value Omni later passes as `ConnectContext.phone`. See **How the agent hears the call**. |
1875
+ | `timeZone` | The zone the agent's day is reckoned in, as an IANA name from the agent application's clock, stated before any identity exists so the first `authenticated` state already carries it. The same value Omni later passes as `ConnectContext.timeZone`. See **The agent's day**. |
1876
+ | `phone` | How this login hears its calls, chosen by the agent application from the manifest's `phones`: required for a voice provider, absent for any other. The same value Omni later passes as `ConnectContext.phone`. See **How the agent hears the call**. |
1872
1877
  | `secrets` | Omni-provided `SecretStore`, scoped to this provider's manifest id. |
1873
1878
  | `signal` | Optional cancellation signal. |
1874
1879
  | `log` | Optional structured logging callback. Never include credentials, tokens, or sensitive contact data. |
@@ -1930,7 +1935,7 @@ them from what arrives later.
1930
1935
  | `team.policyControl` | This lead sets the team's policy per capability — on, off, or the person's — within what the queue allows. Requires `executeTeamPolicy`; the team member list carries `policies`. |
1931
1936
  | `preferences` | What the team left to this person, with where each stands and who set it. Omitted when nothing was. Requires `setPreference`. See **Who decides what an agent may do**. |
1932
1937
 
1933
- A session action is available only when both the capability and Omni provisioning permit it.
1938
+ A session action is available only when both the capability and Omni local policy permit it.
1934
1939
 
1935
1940
  **Capabilities are current, not fixed.** They describe the login as of its latest `authenticated`
1936
1941
  state. A provider that reads roles live — a lead demoted mid-shift — republishes `authenticated`
@@ -2072,11 +2077,11 @@ Creates one live provider connection for the signed-in agent.
2072
2077
  | --- | --- |
2073
2078
  | `protocolVersion` | Version negotiated before authentication. Fixed for this login. |
2074
2079
  | `loginId` | Omni-generated identity for this login. It is the same value passed as `AuthenticationContext.loginId`, so an adapter can correlate this connection with the session that authenticated it. Stable across transport reconnects and changed only by a new login. |
2075
- | `autoAcceptTasks` | Agent provisioning policy relayed to the provider at login, stated by the host on every connection and never assumed from its absence. When `true`, a pending task states its `acceptance`; when `false`, every task requires agent acceptance. Fixed for this connection, like everything else here: the provider states or omits `acceptance` by the value it was sent, and Omni validates by that same value, not by a policy that has since moved — a change reaches the provider through a fresh `connect()`. |
2080
+ | `autoAcceptTasks` | Agent local policy policy relayed to the provider at login, stated by the agent application on every connection and never assumed from its absence. When `true`, a pending task states its `acceptance`; when `false`, every task requires agent acceptance. Fixed for this connection, like everything else here: the provider states or omits `acceptance` by the value it was sent, and Omni validates by that same value, not by a policy that has since moved — a change reaches the provider through a fresh `connect()`. |
2076
2081
  | `timeZone` | The same value passed as `AuthenticationContext.timeZone`. The provider stores it on the agent and carries it on the identity. See **The agent's day**. |
2077
- | `phone` | The same value passed as `AuthenticationContext.phone`: how this login hears its calls. The type ties `host.mute` to it: a `softphone` login's host states what its Mute does, and a desk-phone or conversation login's host cannot, so the omission is a compile error rather than a live seat's discovery. See **The station is the host's**. |
2078
- | `store` | The login's operational store, kept by the host for the life of the login, across a reload of the host, and cleared at sign-out: where an adapter that composes a record keeps what its platform cannot hold for it, such as the interaction legs a host reported. Three functions, by key. Never for anything sensitive, which is `AuthenticationContext.secrets`, a store a host may clear aggressively. **A task's keys carry the task id and go with the task**: a key written about a task names the task's id in the key, and is deleted before the task's end is published, because a platform retires a task id minutes after closing it and a requeue takes seconds, so a key that outlives its task is inherited by the next offer of the same id -- a record with legs the host never reported against it. A login-scoped key carries no task id and outlives any task. The harness requires the store of every connection (`store.shape`, `store.get`, `.set`, `.delete`), watches the one it hands over, and names a task's key still held after `task-ended` (`drive.store.retained`) or written about the task after its end -- a persist hung off a timer that saw the task as it was (`drive.store.late`). The ordinary late write is the host's, not the adapter's: a host reports a leg without waiting for the answer, so an unmute can follow `complete` by a tick, and the adapter answers a report about a task that has ended `failed` with `omni.task-not-found` and writes nothing -- the host ends its own open legs at the task's end, so such a report is the host's error to see, and a host reads every `recordStep` answer and awaits the one for the leg it closes at a task's end, the only moment a refusal is expected, since a report nobody waits for is an error nobody can see; an adapter that names no task in its keys gets no cleanup check, which is a gap rather than a pass, never an exemption: the obligation is that nothing of a closed task survives its ending, and an adapter that keeps every open task in one login-scoped value owes exactly that inside the value, where the harness cannot look. One key per task, named for it, is the shape the harness can hold, and the shape to reach for. The store lists nothing, so an adapter that needs to find its tasks keeps a login-scoped index of ids beside them; at the task's end it deletes the body first and reindexes after, since a crash between the two then leaves an index naming a task with no body, which a reader skips, where the other order leaves a body for a task that has ended, which is the hazard itself. A reader of the index tolerates an id with no body as an ending that was underway, not as corruption. |
2079
- | `host` | The host's report of the agent's station — devices, permissions, network — to consult before declaring the agent ready to the platform, and on every change. See **The host reports, the adapter decides**. |
2082
+ | `phone` | The same value passed as `AuthenticationContext.phone`: how this login hears its calls. The type ties `host.mute` to it: a `softphone` login's agent application states what its Mute does, and a desk-phone or conversation login's agent application cannot, so the omission is a compile error rather than a live seat's discovery. See **The station is the agent application's**. |
2083
+ | `store` | The login's operational store, kept by the agent application for the life of the login, across a reload of the agent application, and cleared at sign-out: where an adapter that composes a record keeps what its platform cannot hold for it, such as the interaction legs an agent application reported. Three functions, by key. Never for anything sensitive, which is `AuthenticationContext.secrets`, a store an agent application may clear aggressively. **A task's keys carry the task id and go with the task**: a key written about a task names the task's id in the key, and is deleted before the task's end is published, because a platform retires a task id minutes after closing it and a requeue takes seconds, so a key that outlives its task is inherited by the next offer of the same id -- a record with legs the agent application never reported against it. A login-scoped key carries no task id and outlives any task. The harness requires the store of every connection (`store.shape`, `store.get`, `.set`, `.delete`), watches the one it hands over, and names a task's key still held after `task-ended` (`drive.store.retained`) or written about the task after its end -- a persist hung off a timer that saw the task as it was (`drive.store.late`). The ordinary late write is the agent application's, not the adapter's: an agent application reports a leg without waiting for the answer, so an unmute can follow `complete` by a tick, and the adapter answers a report about a task that has ended `failed` with `omni.task-not-found` and writes nothing -- the agent application ends its own open legs at the task's end, so such a report is the agent application's error to see, and an agent application reads every `recordStep` answer and awaits the one for the leg it closes at a task's end, the only moment a refusal is expected, since a report nobody waits for is an error nobody can see; an adapter that names no task in its keys gets no cleanup check, which is a gap rather than a pass, never an exemption: the obligation is that nothing of a closed task survives its ending, and an adapter that keeps every open task in one login-scoped value owes exactly that inside the value, where the harness cannot look. One key per task, named for it, is the shape the harness can hold, and the shape to reach for. The store lists nothing, so an adapter that needs to find its tasks keeps a login-scoped index of ids beside them; at the task's end it deletes the body first and reindexes after, since a crash between the two then leaves an index naming a task with no body, which a reader skips, where the other order leaves a body for a task that has ended, which is the hazard itself. A reader of the index tolerates an id with no body as an ending that was underway, not as corruption. |
2084
+ | `host` | The agent application's report of the agent's station — devices, permissions, network — to consult before declaring the agent ready to the platform, and on every change. See **The agent application reports, the adapter decides**. |
2080
2085
  | `signal` | Optional cancellation signal. Stop startup promptly when aborted and do not begin new work. |
2081
2086
  | `log` | Optional structured logging callback. Never include credentials, tokens, or sensitive contact data. |
2082
2087
 
@@ -2088,12 +2093,12 @@ target, an answer streak, a per-queue count for today -- anything bucketed by da
2088
2093
  by somebody's day, and a platform that was never told whose uses its own. An agent in Chennai
2089
2094
  then finds their day rolling at 05:30, and a night shift in Chicago lands in two buckets.
2090
2095
 
2091
- So the host says whose day it is, and it says so first. `AuthenticationContext.timeZone` is the
2096
+ So the agent application says whose day it is, and it says so first. `AuthenticationContext.timeZone` is the
2092
2097
  agent's zone as an IANA name -- `Asia/Kolkata`, `America/Chicago` -- never an offset, since an
2093
2098
  offset cannot survive a daylight-saving boundary and a day boundary is exactly where that bites
2094
2099
  (`context.timeZone`). It is stated before any identity exists, and `ConnectContext.timeZone` is the
2095
2100
  same value again. The provider **stores it on the agent** and carries it as `identity.timeZone` on
2096
- every `authenticated` state and on every `User` it returns from `describeUsers()`, so a lead
2101
+ every `authenticated` state and on every `User` it returns from `getUserDetails()`, so a lead
2097
2102
  reading a colleague's yesterday sees the colleague's yesterday and a summary is bucketed by the
2098
2103
  right day after a session has ended. A roaming agent corrects it by signing in from where they are.
2099
2104
 
@@ -2102,12 +2107,12 @@ field to fill in later: an identity without one is refused (`authentication.iden
2102
2107
  so is a zone that is not an IANA name, wherever it appears. Nothing is ever assumed in its place --
2103
2108
  not the viewer's browser, which gives a different answer per reader for the same record, and not the
2104
2109
  provider's clock. The harness holds a provider to the round trip: the identity carries the zone the
2105
- host stated (`authentication.identity.timeZone.republished`), judged by what the name denotes:
2110
+ agent application stated (`authentication.identity.timeZone.republished`), judged by what the name denotes:
2106
2111
  `Asia/Kolkata` and `Asia/Calcutta` are one zone, and a provider that keeps the canonical name has
2107
2112
  kept the zone. **The round trip is not the store.**
2108
2113
  An adapter that echoes the stated zone back onto the identity passes that check with nothing kept,
2109
2114
  and a lead reading a colleague's day would still get the wrong one. What proves the store is a zone
2110
- the run never sent: a colleague's `User` from `describeUsers()` carrying theirs. A provider's own
2115
+ the run never sent: a colleague's `User` from `getUserDetails()` carrying theirs. A provider's own
2111
2116
  tests are where that is shown, with a second agent whose zone arrived through another session.
2112
2117
 
2113
2118
  ### Who the agent is
@@ -2150,10 +2155,10 @@ surface in one place, and what obliges an adapter to implement each one.
2150
2155
  | `checkTime(request)` | The manifest declares `timeCheck: true`. Read-only clock check; no task command or accuracy guarantee. |
2151
2156
  | `subscribe(listener)` | Always. |
2152
2157
  | `disconnect()` | Always. |
2153
- | `refused(report)` | Always. The host tells the adapter what it would not take -- a snapshot it did not replace its state with, an event it dropped -- with every rule broken, so a refusal is visible on both sides. See **What the host does with what it refuses**. |
2158
+ | `refused(report)` | Always. The agent application tells the adapter what it would not take -- a snapshot it did not replace its state with, an event it dropped -- with every rule broken, so a refusal is visible on both sides. See **What the agent application does with what it refuses**. |
2154
2159
  | `setCapacity(capacity)` | Always. Nothing may be allocated until a capacity is stated, so there is no connection that does not receive it. |
2155
2160
  | `execute(request)` | Always. Every channel has commands no capability gates — see **Which commands need a capability**. |
2156
- | `describeUsers(ids)` | The adapter publishes any `UserId`: on `ForcedBreak.by`, a team member list, or `interactionHistory[].by`. Each `User` carries its `timeZone`; a person whose zone the provider cannot name is omitted from the answer, as any unresolvable id is. |
2161
+ | `getUserDetails(ids)` | The adapter publishes any `UserId`: on `ForcedBreak.by`, a team member list, or `interactionHistory[].by`. Each `User` carries its `timeZone`; a person whose zone the provider cannot name is omitted from the answer, as any unresolvable id is. |
2157
2162
  | `dial(request)` | The manifest declares `idleCapabilities.dial`, and with it `dialOutcomes`. |
2158
2163
  | `requestBreak(request)` | The login declares `capabilities.breaks`. |
2159
2164
  | `commitBreak()` | The login declares `capabilities.breaks`. Commit and cancel are not optional halves of it. |
@@ -2163,7 +2168,7 @@ surface in one place, and what obliges an adapter to implement each one.
2163
2168
  | `executeTeamLeadAssist(command)` | The login declares `capabilities.team.leadAssistControl`. |
2164
2169
  | `executeTeamListen(command)` | The login declares `capabilities.team.listeningControl`. |
2165
2170
  | `setPreference(request)` | The login declares `capabilities.preferences`: the person's choice has to have somewhere to go. |
2166
- | `recordStep(report)` | The manifest lists `softphone` among its `phones`. On a softphone the host mutes its own microphone on any call, and the provider's record has to have somewhere to take that leg; a desk phone's microphone is the phone's. See **The host records what it performs**. |
2171
+ | `recordStep(report)` | The manifest lists `softphone` among its `phones`. On a softphone the agent application mutes its own microphone on any call, and the provider's record has to have somewhere to take that leg; a desk phone's microphone is the phone's. See **The agent application records what it performs**. |
2167
2172
  | `executeTeamPolicy(command)` | The login declares `capabilities.team.policyControl`. |
2168
2173
  | `openMedia(request)` | The manifest lists `softphone` among its `phones`. On a softphone the call's audio lands in Omni, so the adapter has to open it; a platform of desk phones alone never does. |
2169
2174
 
@@ -2203,12 +2208,12 @@ Registers a listener for provider changes and returns an idempotent unsubscribe
2203
2208
  while disconnected without requiring a durable event log.
2204
2209
  - After unsubscribe, the listener must receive no further events.
2205
2210
 
2206
- ### `Connection.describeUsers(ids)`
2211
+ ### `Connection.getUserDetails(ids)`
2207
2212
 
2208
2213
  Turns `UserId` values into something an agent can read.
2209
2214
 
2210
2215
  ```ts
2211
- describeUsers(ids: UserId[]): Promise<User[]>
2216
+ getUserDetails(ids: UserId[]): Promise<User[]>
2212
2217
  ```
2213
2218
 
2214
2219
  Required of any adapter that publishes a `UserId` — on `ForcedBreak.by`, a team member list, or
@@ -2243,14 +2248,14 @@ Stops the connection and releases adapter-owned resources.
2243
2248
  The task-allocation lifecycle has five ordered stages:
2244
2249
 
2245
2250
  **1. The agent signs in.** Nothing on the wire says ready or not-ready: the agent is not ready
2246
- until the host has stated a capacity, and ready once it has. A provider allocates nothing before a
2251
+ until the agent application has stated a capacity, and ready once it has. A provider allocates nothing before a
2247
2252
  capacity is stated, and needs no other word for it.
2248
2253
 
2249
- **2. The agent becomes ready.** The host states the capacity when its provisioning says: at once,
2254
+ **2. The agent becomes ready.** The agent application states the capacity when its local policy says: at once,
2250
2255
  or when the agent presses Ready. A successful connection, a healthy provider, or the absence of a
2251
2256
  break does not imply readiness. After that, the only way an agent stops taking work is a break,
2252
2257
  under `capabilities.breaks`; a login that declares no breaks cannot go not-ready once its capacity
2253
- is stated, and `count: 0` is the host's division of capacity, not the agent's choice.
2258
+ is stated, and `count: 0` is the agent application's division of capacity, not the agent's choice.
2254
2259
 
2255
2260
  **3. Omni states their concurrent capacity.** Only now does Omni ask providers for work, saying how
2256
2261
  much the agent can take at once. It is a standing declaration rather than a poll: Omni restates the
@@ -2271,13 +2276,13 @@ intent.
2271
2276
 
2272
2277
  During login, Omni sends the agent's `autoAcceptTasks` value to the provider. When it is `true`, the
2273
2278
  provider states `acceptance` on each pending task — on the task rather than the offer, so a
2274
- reconnect snapshot says it too and an offer the host never received is not accepted on the
2279
+ reconnect snapshot says it too and an offer the agent application never received is not accepted on the
2275
2280
  person's behalf for want of a word:
2276
2281
 
2277
2282
  | Directive | Contract |
2278
2283
  | --- | --- |
2279
2284
  | `no-preference` | The provider leaves acceptance to Omni; with `autoAcceptTasks: true`, Omni accepts automatically. |
2280
- | `consent` | The provider requires the person's explicit consent: Omni presents **Accept** and waits, whatever its own policy would have done. A host that declares `guarantees.personConsent` promises exactly this; a provider checks it before offering work only a person may take. |
2285
+ | `consent` | The provider requires the person's explicit consent: Omni presents **Accept** and waits, whatever its own policy would have done. An agent application that declares `guarantees.personConsent` promises exactly this; a provider checks it before offering work only a person may take. |
2281
2286
  | `automatic` | Omni accepts immediately without agent interaction. |
2282
2287
 
2283
2288
  When Omni sent `autoAcceptTasks: false`, the provider omits `acceptance` and every task the
@@ -2287,20 +2292,20 @@ no-auto-accept policy puts no word on the wire at all — the field is absent, a
2287
2292
  press is Omni's doing, not the provider's.
2288
2293
 
2289
2294
  **The value is stated, never assumed.** `autoAcceptTasks` is required of every connection: a
2290
- host says which policy the deployment provisioned, and a validator that is not told checks
2295
+ agent application says which policy the deployment provisioned, and a validator that is not told checks
2291
2296
  neither rule rather than guess the permissive one (`task.acceptance.required` and
2292
2297
  `.unexpected` fire only against a stated value). `acceptance` is the provider's own control and
2293
2298
  outranks the policy: `consent` puts the decision back in the agent's hands for any task where it
2294
- belongs, whatever the host was configured with.
2299
+ belongs, whatever the agent application was configured with.
2295
2300
 
2296
2301
  An automatically accepted task still arrives through `task-offered`.
2297
2302
 
2298
2303
  **Work the agent originated is accepted by the command that created it.** A task born of the
2299
- agent's own act — a dialpad call or a connect-back, recognisable by the host's `dialId` on
2304
+ agent's own act — a dialpad call or a connect-back, recognisable by the agent application's `dialId` on
2300
2305
  `onCall`; a lead's join, carrying `assisting`; a lead's listen, carrying `listening` — arrives
2301
2306
  through `task-offered` with `acceptance: "automatic"` whatever `autoAcceptTasks` says, and the
2302
- validator holds it there under either provisioning and under none (`task.acceptance.originated`):
2303
- the desk shows no **Accept** for a call the agent placed. The provisioning governs work the queue
2307
+ validator holds it there under either local policy and under none (`task.acceptance.originated`):
2308
+ the desk shows no **Accept** for a call the agent placed. The local policy governs work the queue
2304
2309
  routes to the agent, and nothing else.
2305
2310
 
2306
2311
  ### Pending
@@ -2321,7 +2326,7 @@ const allocation = {
2321
2326
  ```
2322
2327
 
2323
2328
  The rule the phase exists to express: **nothing is acquired on the agent's behalf while a task
2324
- is pending.** A host that carries media must not open the microphone until the task is
2329
+ is pending.** An agent application that carries media must not open the microphone until the task is
2325
2330
  accepted. Omni does not open the task's browsers either — a task that rings out costs nothing.
2326
2331
 
2327
2332
  When consent is required, Omni offers the agent an **Accept** control. The call is the
@@ -2374,25 +2379,25 @@ time. Runtime conformance checks also require the task channel to match its prov
2374
2379
  | Field | Contract |
2375
2380
  | --- | --- |
2376
2381
  | `id` | Required `TaskId`, the platform's own identity for the task. Unique among the tasks open at once; a platform retires an id minutes after closing it, so the same id comes back for another customer. Omni scopes it with the provider ID. |
2377
- | `allocationId` | Required `AllocationId`: this life of the task, minted once per offer and never reused for the life of the login, whatever the id does. Every event, command and report that names a task names its allocation too, so a late dial outcome or a late interaction report for the first customer never lands on the next under the same id. The stream refuses an offer reusing one (`stream.taskOffered.allocation`), an update restating another life of the id (`stream.taskUpdated.allocation`), and a media or ending event naming a life that has ended or that nobody has seen (`stream.allocation.ended`, `.unknown`); a `dial-outcome` may name an ended life, since a dial placed late routinely outlives its call, and the host routes it there. See **A task's life on the wire**. |
2382
+ | `allocationId` | Required `AllocationId`: this life of the task, minted once per offer and never reused for the life of the login, whatever the id does. Every event, command and report that names a task names its allocation too, so a late dial outcome or a late interaction report for the first customer never lands on the next under the same id. The stream refuses an offer reusing one (`stream.taskOffered.allocation`), an update restating another life of the id (`stream.taskUpdated.allocation`), and a media or ending event naming a life that has ended or that nobody has seen (`stream.allocation.ended`, `.unknown`); a `dial-outcome` may name an ended life, since a dial placed late routinely outlives its call, and the agent application routes it there. See **A task's life on the wire**. |
2378
2383
  | `title` | Agent-facing task title. |
2379
2384
  | `channel` | Channel used for this task. It must equal the source provider's manifest channel. |
2380
2385
  | `taskType` | Required provider-defined source or category of work, such as a voice `Queue Name`, `Mailbox Folder`, `Chat Source`, `Support`, `Billing`, or `Returns`. |
2381
2386
  | `capabilities` | Controls and workspace features available for this specific task. |
2382
- | `capabilitySource` | Required. Who chose the capabilities: `queue` when somebody configured these terms, `ungoverned` when nothing handed the work over -- an agent's own outbound -- and `undetermined` when a queue was named and its terms could not be read, in which case `capabilities` is what the provider will honour, not what the platform permits. A host shows `undetermined` where the agent works. See **Task capabilities**. |
2387
+ | `capabilitySource` | Required. Who chose the capabilities: `queue` when somebody configured these terms, `ungoverned` when nothing handed the work over -- an agent's own outbound -- and `undetermined` when a queue was named and its terms could not be read, in which case `capabilities` is what the provider will honour, not what the platform permits. An agent application shows `undetermined` where the agent works. See **Task capabilities**. |
2383
2388
  | `browsers` | Named browser definitions for the task workspace: at least one when the task declares the `browsers` capability, empty when it does not. |
2384
2389
  | `party` | The person or entity on the other end of this task, as a `Contact`: often a name and one address; a withheld caller ID may leave nothing to send at all. Optional. The party is who the task is *with*; `contacts` is the directory. |
2385
2390
  | `phase` | Current canonical task phase: `pending`, `confirmed`, `preview`, `in-progress`, `paused`, or `completing`. `preview` is voice only. |
2386
- | `media` | Voice only. The task's real-time audio as the provider holds it: `started` while audio is attached, `ended` once it ended, omitted while none is. The provider's word — see **`task-media-started`**. Media names a task whose work has begun, or whose party the host is dialling: on a `pending`, `confirmed` or `preview` task with nobody ringing it is refused (`task.media.beforeWork`), on a snapshot as on the event, since a host opens the microphone on it; with the party ringing by a host dial or provider-triggered preview dial, actual ring-back media may precede answer. |
2391
+ | `media` | Voice only. The task's real-time audio as the provider holds it: `started` while audio is attached, `ended` once it ended, omitted while none is. The provider's word — see **`task-media-started`**. Media names a task whose work has begun, or whose party the agent application is dialling: on a `pending`, `confirmed` or `preview` task with nobody ringing it is refused (`task.media.beforeWork`), on a snapshot as on the event, since an agent application opens the microphone on it; with the party ringing by an agent application dial or provider-triggered preview dial, actual ring-back media may precede answer. |
2387
2392
  | `acceptance` | How this offer is accepted — `no-preference`, `consent`, or `automatic` — stated on the pending task so a reconnect snapshot says it too. Required while `pending` when `autoAcceptTasks` was `true`, forbidden when it was `false`, and absent past `pending`. See **Acceptance modes**. |
2388
2393
  | `previewEndsAt` | Voice only, in `preview`: the preparation target instant. Absent, the agent has as long as they need without a preparation countdown. Always with `atDeadline`. See **Preview: the agent presses Call**. |
2389
- | `atDeadline` | Voice only, in `preview`, with `previewEndsAt`: what the system does at the deadline -- `calls` makes the provider initiate dialing, `host-calls` makes the host issue Call, `waits` keeps the task in preview awaiting the agent. |
2394
+ | `atDeadline` | Voice only, in `preview`, with `previewEndsAt`: what the system does at the deadline -- `calls` makes the provider initiate dialing, `host-calls` makes the agent application issue Call, `waits` keeps the task in preview awaiting the agent. |
2390
2395
  | `reference` | Optional agent-facing reference such as a case, call, conversation, ticket, or message number. It is distinct from the protocol `id`. |
2391
2396
  | `completionMode` | `agent-command` waits for the channel's `complete` command; `provider-automatic` completes without one. |
2392
2397
  | `wrapAllowance` | Fixed time allowed to complete the task after primary interaction ends. For real-time media, it begins after `task-media-ended`. Required under `provider-automatic`, where the provider acts on it. Optional under `agent-command`: omitted says the provider imposes no deadline, and Omni counts nothing down. |
2393
2398
  | `attributes` | Optional ordered, typed `TaskAttribute` entries with keys unique within the task. Each contact or timestamp is a separate array item; new attribute shapes require new union members. |
2394
2399
  | `interactionHistory` | The call record: `steps` — the ordered interaction history of this open task, one entry per occurrence, oldest first — and what they add up to before this agent, `interactionSeconds`, `holdSeconds`, `queueSeconds`, `transfers`, each present when the provider knows it. Live task data restated with the task, not a permanent archive. See **Interaction history**. |
2395
- | `onCall` | Voice only. Who is on the call, or being brought onto it, as the provider states it, replaced whole with the task: `party` is the customer -- carrying a `stage` while being dialled again on the same task, a connect-back with the host's `dialId` or a platform's callback without, ringing from the moment the dial is placed and joined on its answered outcome --, `agent` a person by user id, `consulted` and `conferenced` somebody a dial is bringing in, listed from the moment the dial is placed -- with the `destinationId` dialled, the `dialId` where a host placed it, the `stage` reached (`ringing` until answered, `joined` after), and `held: true` on anyone joined and parked. A `consulted` entry is what makes `transfer` `complete` and `cancel` issuable. `label` names a destination -- a person, a queue -- not a phrase; the host supplies the verb. Present when the provider knows the room, absent when it does not. See **Every dial has an outcome**. |
2400
+ | `onCall` | Voice only. Who is on the call, or being brought onto it, as the provider states it, replaced whole with the task: `party` is the customer -- carrying a `stage` while being dialled again on the same task, a connect-back with the agent application's `dialId` or a platform's callback without, ringing from the moment the dial is placed and joined on its answered outcome --, `agent` a person by user id, `consulted` and `conferenced` somebody a dial is bringing in, listed from the moment the dial is placed -- with the `destinationId` dialled, the `dialId` where an agent application placed it, the `stage` reached (`ringing` until answered, `joined` after), and `held: true` on anyone joined and parked. A `consulted` entry is what makes `transfer` `complete` and `cancel` issuable. `label` names a destination -- a person, a queue -- not a phrase; the agent application supplies the verb. Present when the provider knows the room, absent when it does not. See **Every dial has an outcome**. |
2396
2401
  | `leadAssist` | Voice only. Present from the agent's request for a lead until the lead leaves or the request ends: `requested` while nobody has joined, `joined` with the lead's `leadId` once somebody has. See **Lead assist**. |
2397
2402
  | `assisting` | Voice only, on the lead's own task for a call they joined: which member asked, with their note. Its presence is what makes `lead-assist` `take-over-call` and `leave` issuable. See **Lead assist**. |
2398
2403
  | `listening` | Voice only, on the lead's own task while they listen to a member's call: whose call, which call, and the `mode` they are heard in, restated on every change. Never on the member's task, and never together with `assisting`. See **Listening to a call**. |
@@ -2448,11 +2453,11 @@ requeue takes seconds, and on one platform a call was offered twice, thirteen se
2448
2453
  one id, through a close and a re-offer. Everything that names a task after the fact -- a dial
2449
2454
  outcome, a media event, an ending, an interaction report, a command -- would land on whichever life of
2450
2455
  the id is open when it arrives. So every offer mints an `allocationId`, unique for the life of the
2451
- login, and every one of those names it beside the `taskId`. The host keys its state on the pair, a
2456
+ login, and every one of those names it beside the `taskId`. The agent application keys its state on the pair, a
2452
2457
  late event finds the life it belongs to or is refused, and a task-scoped browser session
2453
2458
  (`PROVIDER_NAME__TASK_ID__TAB_NAME`) lives one allocation, never the next customer's cookies under
2454
- a reused id. A dial the host placed was already safe, since its outcome is placed by the host's own
2455
- `dialId`; where the allocation earns its place is everything the host does not mint --
2459
+ a reused id. A dial the agent application placed was already safe, since its outcome is placed by the agent application's own
2460
+ `dialId`; where the allocation earns its place is everything the agent application does not mint --
2456
2461
  `task-media-started`, `task-media-ended`, `task-ended`, a `recordStep` naming a task -- any of which
2457
2462
  would otherwise find the new task under the old id and act on it. The allocation is part of the task
2458
2463
  the adapter keeps, not a field held in memory beside it: a rebuilt adapter comes back with the same
@@ -2486,9 +2491,9 @@ const previewed = {
2486
2491
  const pressed: TaskCommand<"voice"> = { type: "call", dialId: "dial-7f2" };
2487
2492
  ```
2488
2493
 
2489
- **Call is a dial.** It carries the host's `dialId`, is answered `dialling`, and ends in exactly one
2494
+ **Call is a dial.** It carries the agent application's `dialId`, is answered `dialling`, and ends in exactly one
2490
2495
  `dial-outcome`; the phase is its gate and there is no capability, since a record put in front of an
2491
- agent is there to be called. Its media starts on `dialling`, as every host-placed dial's does --
2496
+ agent is there to be called. Its media starts on `dialling`, as every agent application-placed dial's does --
2492
2497
  ring-back is audio the agent hears -- so `task-media-started` arrives on the `preview` task with
2493
2498
  its party ringing. On `answered` the task is `in-progress`; on any other outcome the media ends,
2494
2499
  `task-media-ended` starts the wrap clock as on every voice task, and the task goes to
@@ -2503,8 +2508,8 @@ carries the provider's authoritative preparation-end instant and exactly one tri
2503
2508
 
2504
2509
  | Declaration | At preparation end |
2505
2510
  | --- | --- |
2506
- | `atDeadline: "calls"` | The provider initiates dialing. The host never sends a timer-triggered Call. |
2507
- | `atDeadline: "host-calls"` | The host sends the ordinary `call` command with a fresh host `dialId`. The provider does not independently auto-dial this task. |
2511
+ | `atDeadline: "calls"` | The provider initiates dialing. The agent application never sends a timer-triggered Call. |
2512
+ | `atDeadline: "host-calls"` | The agent application sends the ordinary `call` command with a fresh agent application `dialId`. The provider does not independently auto-dial this task. |
2508
2513
  | `atDeadline: "waits"` | Neither side auto-dials. The task remains in preview until the agent presses Call. |
2509
2514
 
2510
2515
  The agent may press Call early in either fixed-preparation dialing mode, or at any time in
@@ -2518,14 +2523,14 @@ answer at that exact instant. Scheduling/dispatch delay must remain visible, and
2518
2523
  prevented initiation must be reported rather than leaving a silently expired countdown.
2519
2524
  A source eligibility threshold that may never trigger an attempt is not this promise.
2520
2525
 
2521
- The two deadline fields travel together and only in preview. The host uses trusted provider-domain
2522
- time; clock estimation is allowed only under the explicit host-triggered preview exception below.
2526
+ The two deadline fields travel together and only in preview. The agent application uses trusted provider-domain
2527
+ time; clock estimation is allowed only under the explicit agent application-triggered preview exception below.
2523
2528
  Without usable provider-domain time
2524
2529
  it cannot safely auto-trigger and must expose the uncertainty and reconcile. No zero-duration,
2525
2530
  receipt-time or local-default deadline is inferred. Neither elapsed time nor submission changes
2526
2531
  the task phase: subsequent authoritative events state ringing, answer, media and completion.
2527
2532
 
2528
- A host must serialize manual clicks and its timer under the exact provider/login/task/allocation
2533
+ An agent application must serialize manual clicks and its timer under the exact provider/login/task/allocation
2529
2534
  scope, allowing at most one unresolved submission. Recheck the current phase, deadline owner,
2530
2535
  allocation and whether an attempt already exists before dispatch. A new snapshot or policy update
2531
2536
  cancels an obsolete timer; login loss, disconnect, task end and allocation replacement fence its
@@ -2534,28 +2539,28 @@ blindly submit again. An uncertain prior submission remains unresolved, without
2534
2539
  The provider atomically arbitrates any residual manual/timer race and does not accept a second
2535
2540
  command as ownership of an already-running independent attempt.
2536
2541
 
2537
- Host-triggered automatic dialing is an ordinary host dial: its result is `dialling` with the same
2538
- host `dialId`, followed by exactly one correlated terminal `dial-outcome`. A provider-triggered
2539
- dial has no invented host ID or host dial outcome. It reports source-evidenced party ringing,
2542
+ Agent application-triggered automatic dialing is an ordinary agent application dial: its result is `dialling` with the same
2543
+ agent application `dialId`, followed by exactly one correlated terminal `dial-outcome`. A provider-triggered
2544
+ dial has no invented agent application ID or agent application dial outcome. It reports source-evidenced party ringing,
2540
2545
  actual media and customer answer separately. In preview with `atDeadline: "calls"`, a ringing
2541
- party without a host ID may carry actual pre-answer media; the deadline alone permits no media.
2546
+ party without an agent application ID may carry actual pre-answer media; the deadline alone permits no media.
2542
2547
  Media is still introduced/ended by the corresponding events and must not imply customer answer.
2543
2548
  Submission acceptance is never an answered outcome or permission to publish `in-progress` early.
2544
2549
  Unsupported source correlation/outcome/media evidence remains an integration blocker.
2545
2550
 
2546
2551
  **Drop both fields when the phase moves.** A provider that builds the `in-progress` task by
2547
- spreading the `preview` one carries `previewEndsAt` and `atDeadline` with it, and the host refuses
2552
+ spreading the `preview` one carries `previewEndsAt` and `atDeadline` with it, and the agent application refuses
2548
2553
  the update (`task.preview.deadline.unexpected`): the desk keeps the task as it last stood, and the
2549
2554
  provider is told through `refused` exactly which rule, so the state that looked right on its side
2550
2555
  is named on its side. The task past preview has no deadline to wait for, so it carries neither
2551
2556
  field.
2552
2557
 
2553
- **Provider execution and host controls are distinct.** Answer, hold/resume, transfer (including
2558
+ **Provider execution and agent application controls are distinct.** Answer, hold/resume, transfer (including
2554
2559
  IVR routing), conference and interaction completion are executed by the provider
2555
2560
  through the adapter. The task's applicable capability, phase, completion mode and command-specific
2556
- prerequisites decide which controls are offered. Caller disconnect also executes at the provider. Microphone mute is host-owned, never a provider
2557
- TaskCommand or task capability. The separately declared host recording facility keeps its existing
2558
- recording contract; this distinction does not remove it or move provider call operations to the host.
2561
+ prerequisites decide which controls are offered. Caller disconnect also executes at the provider. Microphone mute is agent application-owned, never a provider
2562
+ TaskCommand or task capability. The separately declared agent application recording facility keeps its existing
2563
+ recording contract; this distinction does not remove it or move provider call operations to the agent application.
2559
2564
 
2560
2565
  A caller journey may revisit the same agent while an earlier interaction still wraps. Public task
2561
2566
  IDs must remain distinct for concurrently open interactions. For source-owned interaction IDs allocated
@@ -2615,7 +2620,7 @@ whether the channel carries real-time media:
2615
2620
  | Other non-media channels | The `task-updated` that moves the task to `completing` |
2616
2621
 
2617
2622
  **Off voice, `completing` is the provider's word that interaction ended.** There is no media event to
2618
- carry it, so the phase does; a host starts the wrap clock at that publication and nowhere else. It
2623
+ carry it, so the phase does; an agent application starts the wrap clock at that publication and nowhere else. It
2619
2624
  is optional: a conversation with nothing to wrap moves from `in-progress` to `task-ended` and
2620
2625
  `completing` is never published. Under `provider-automatic` with a non-zero `wrapAllowance` it is
2621
2626
  required, because the clock has to start somewhere: a chat or email task the provider completes
@@ -2661,7 +2666,7 @@ A task that declares `connectBack` lets the agent connect back to the party whil
2661
2666
  whoever placed the call in the first place. Most such calls came in, so this is not a redial: the
2662
2667
  agent rings a party who rang them. Omni issues `{ type: "connect-back", dialId }`; it is issuable
2663
2668
  only in `completing`, and only where the capability is declared. The provider knows who the party
2664
- is; the command carries no destination, and it is a dial like any other, so it carries the host's
2669
+ is; the command carries no destination, and it is a dial like any other, so it carries the agent application's
2665
2670
  `dialId`, is answered `dialling`, and ends in one `dial-outcome`.
2666
2671
 
2667
2672
  On `dialling` the provider is placing the call and the task returns to `in-progress`: the agent is
@@ -2672,15 +2677,15 @@ whose outcome says so and a call whose media ended: the task returns to `complet
2672
2677
  same event and the clock starts again from there. At no point is an agent dialling against a
2673
2678
  deadline.
2674
2679
 
2675
- **The room shows the party being dialled.** From the moment any host dial places the party -- a
2680
+ **The room shows the party being dialled.** From the moment any agent application dial places the party -- a
2676
2681
  dialpad call, a preview Call, a connect-back -- the `party` entry carries `stage: "ringing"` and
2677
- the host's `dialId`, exactly as a consulted or conferenced entry does from its dial; `joined` on
2682
+ the agent application's `dialId`, exactly as a consulted or conferenced entry does from its dial; `joined` on
2678
2683
  the publication that follows the answered `dial-outcome` and never before it
2679
2684
  (`stream.taskUpdated.stage`); and no stage from the next publication on, so `joined` is transient
2680
- and a later copy still carrying it is stale (`stream.taskUpdated.stage.lingering`). A host shows a
2685
+ and a later copy still carrying it is stale (`stream.taskUpdated.stage.lingering`). An agent application shows a
2681
2686
  call being placed, not a party it asserts is on a call that is still ringing. A callback the platform places itself on the same task -- the first
2682
2687
  call over, the platform dialling the party again without a command -- shows the same thing with no
2683
- host `dialId`, as any platform-placed dial does. A party with no stage is on the call, and a dial
2688
+ agent application `dialId`, as any platform-placed dial does. A party with no stage is on the call, and a dial
2684
2689
  with no stage is half a claim (`task.onCall.party.dial`). The stage is also what lets the stream
2685
2690
  tell a task coming back from one going backwards (`stream.taskUpdated.phase`).
2686
2691
 
@@ -2776,19 +2781,19 @@ task says whether a leg can still be running: a hold runs only while the task is
2776
2781
  only while its media is up, so a `held` entry without `seconds` on a task that is not paused, or a
2777
2782
  `muted` one on a call that is over, is a leg nobody closed and reads exactly like a leg running now
2778
2783
  (`task.interactionHistory.held.open`, `.muted.open`). Whoever performs the leg closes it — the
2779
- provider whose platform parks the caller, the host whose microphone it is — by restating the entry
2784
+ provider whose platform parks the caller, the agent application whose microphone it is — by restating the entry
2780
2785
  with its duration, and **an entry that cannot be closed is not written**: open for ever is a
2781
2786
  plausible nought one level down from a total. **A leg still open when the media ends is closed by
2782
2787
  the provider**, at that instant, in the same publication that says the media ended: the provider
2783
- is the one that knows the instant, and the host can only learn of it afterwards. Agents end calls
2784
- muted, so the host's leg is routinely open at media end; the provider closes it with the duration
2785
- from the leg's `at` to the media's end, and the host's own closing report for that leg, which
2788
+ is the one that knows the instant, and the agent application can only learn of it afterwards. Agents end calls
2789
+ muted, so the agent application's leg is routinely open at media end; the provider closes it with the duration
2790
+ from the leg's `at` to the media's end, and the agent application's own closing report for that leg, which
2786
2791
  follows what it hears, is answered `recorded` and changes nothing, the entry standing as the
2787
2792
  provider closed it. One publisher of the closed leg, and no order between them to get right. There is no resumed step; a resume is the end of a
2788
2793
  hold, at the entry's `at` plus its `seconds`, and nothing is lost by not naming it twice. The same goes for every step: two mutes are two
2789
2794
  `muted` entries, and a call that joined two queues -- a menu's, then this one -- has two `queued`
2790
2795
  entries, one per join. Order is enforced: an entry earlier than the one before it is refused
2791
- (`task.interactionHistory.order`). **Intervals between steps are the host's to subtract**, never a
2796
+ (`task.interactionHistory.order`). **Intervals between steps are the agent application's to subtract**, never a
2792
2797
  total the provider adds: *time to offer*, from the call's arrival to the agent's screen lighting
2793
2798
  up, is the `offered` entry's `at` minus the last `queued` entry's, and the ring is outside it.
2794
2799
  `queueSeconds` keeps the industry's meaning -- the whole wait until somebody answered -- and is not
@@ -2798,32 +2803,32 @@ grain: rounded to the nearest second, and a leg that rounds to nought is stated
2798
2803
  being under the contract's resolution, where dropping the entry would say the leg never happened.
2799
2804
 
2800
2805
  **A record once read is not unread.** Every restatement of a task's record -- on `task-updated`,
2801
- on a resync snapshot -- carries every entry the host has already read, by step and instant, and
2806
+ on a resync snapshot -- carries every entry the agent application has already read, by step and instant, and
2802
2807
  may add to them; it never has fewer, and never drops the record while the task is open. A fact
2803
- stated to the host and then withdrawn without an event is a record contradicting itself, exactly
2808
+ stated to the agent application and then withdrawn without an event is a record contradicting itself, exactly
2804
2809
  as a task that lost the terms it had read would be, and the stream refuses it the same way
2805
2810
  (`stream.taskUpdated.interactionHistory`, `stream.snapshot.interactionHistory`). A provider whose
2806
- platform cannot hold a leg the host reported keeps it in the login's `store` for the life of the
2807
- task, so a reload of the host restates the same record; the entry is keyed by `step` and `at`, so
2811
+ platform cannot hold a leg the agent application reported keeps it in the login's `store` for the life of the
2812
+ task, so a reload of the agent application restates the same record; the entry is keyed by `step` and `at`, so
2808
2813
  a running hold restated with its final `seconds` is the same entry.
2809
2814
 
2810
- **The provider owns the timestamps in its record.** Host timestamps are advisory. The provider
2811
- may retain a host instant it accepts or assign its own observation/receipt instant; it need not
2812
- copy the host clock. A provider declaring `timestampAuthority: "provider"` uses its own timestamps
2815
+ **The provider owns the timestamps in its record.** Agent application timestamps are advisory. The provider
2816
+ may retain an agent application instant it accepts or assign its own observation/receipt instant; it need not
2817
+ copy the agent application clock. A provider declaring `timestampAuthority: "provider"` uses its own timestamps
2813
2818
  for final records. Receipt time is an observation boundary, not a claim about when the physical
2814
- host action happened. Records are ordered by their published provider-selected instants, with no
2815
- rewriting of an already-published entry when a later host report arrives.
2819
+ agent application action happened. Records are ordered by their published provider-selected instants, with no
2820
+ rewriting of an already-published entry when a later agent application report arrives.
2816
2821
 
2817
- The incoming host `step` and `at`, scoped to the task and its current life, identify one reported
2822
+ The incoming agent application `step` and `at`, scoped to the task and its current life, identify one reported
2818
2823
  leg for correlation only. The provider retains a binding from that key to its chosen history
2819
2824
  `at`. Every successful `recordStep` returns `{ status: "recorded", at }` with that same canonical
2820
- history instant, even for subsequent duration/end reports. The host keeps sending the original
2821
- report key, never the returned history timestamp. A changed host timestamp is not a correction
2825
+ history instant, even for subsequent duration/end reports. The agent application keeps sending the original
2826
+ report key, never the returned history timestamp. A changed agent application timestamp is not a correction
2822
2827
  to the same report: it names a different leg. Bindings survive reconnect/reload for the retained
2823
- task lifetime. The host renders provider-published history unchanged. It never compares the
2828
+ task lifetime. The agent application renders provider-published history unchanged. It never compares the
2824
2829
  provider instant back to its own clock, substitutes its own timestamp, or adjusts later messages
2825
- to match an earlier host estimate. The acknowledgment identifies the provider record for
2826
- correlation/conformance only; it is not a host-side timestamp reconciliation instruction. Conflicting reuse is refused visibly, not paired by arrival time or nearest instant.
2830
+ to match an earlier agent application estimate. The acknowledgment identifies the provider record for
2831
+ correlation/conformance only; it is not an application-side timestamp reconciliation instruction. Conflicting reuse is refused visibly, not paired by arrival time or nearest instant.
2827
2832
  If two distinct entries would collide under the history's `(step, at)` key, do not invent a time
2828
2833
  or combine them: report the representation conflict. No ambiguous event is silently accepted.
2829
2834
 
@@ -2833,17 +2838,17 @@ history — until the task's media ends, and a hold neither pauses nor resets it
2833
2838
  duration is the `held` entry's `seconds`, and a desk that restarts its counter on resume is
2834
2839
  counting the wrong thing.
2835
2840
 
2836
- `muted` is there because the mute is the host's and never the provider's — see **The station is
2837
- the host's** — so without a step the provider, which alone keeps the task's record, would have no
2838
- account of a period the agent could not be heard. Each `muted` entry carries `mutedBy`, as the host
2839
- reported it: `host` for the agent's own Mute, `station` for a headset or system mute the host
2841
+ `muted` is there because the mute is the agent application's and never the provider's — see **The station is
2842
+ the agent application's** — so without a step the provider, which alone keeps the task's record, would have no
2843
+ account of a period the agent could not be heard. Each `muted` entry carries `mutedBy`, as the agent application
2844
+ reported it: `host` for the agent's own Mute, `station` for a headset or system mute the agent application
2840
2845
  observed. No other step has it (`task.interactionHistory.mutedBy`, `.mutedBy.unexpected`).
2841
2846
 
2842
2847
  **A step that dialled says which dial and where.** `transferred`, `conferenced` and `unanswered`
2843
- each end a dial, so the entry carries the `destinationId` it went to and, where a host placed it, the
2844
- `dialId` the host minted; no other step dialled, and either field on one is refused
2848
+ each end a dial, so the entry carries the `destinationId` it went to and, where an agent application placed it, the
2849
+ `dialId` the agent application minted; no other step dialled, and either field on one is refused
2845
2850
  (`task.interactionHistory.dialId.unexpected`). This is how a dial made before a transfer is placeable
2846
- by whoever holds the task now: a `dial-outcome` naming a `dialId` the host never minted is looked
2851
+ by whoever holds the task now: a `dial-outcome` naming a `dialId` the agent application never minted is looked
2847
2852
  up in the record, not discarded.
2848
2853
 
2849
2854
  Four rules a provider has to keep:
@@ -2859,7 +2864,7 @@ Four rules a provider has to keep:
2859
2864
  the same way `ForcedBreak.by` does. It comes from this provider's own directory, the same
2860
2865
  namespace as `AuthenticationState.identity.id` and the team member list, so entries pair
2861
2866
  within a provider and never across one.
2862
- - **A task carries no names.** Omni resolves what to display with `describeUsers()`. Two people
2867
+ - **A task carries no names.** Omni resolves what to display with `getUserDetails()`. Two people
2863
2868
  called Arun on one site is ordinary, and anything pairing entries on a display name pairs them
2864
2869
  wrongly; carrying the name here would also copy it into every task and leave it to go stale.
2865
2870
 
@@ -2867,7 +2872,7 @@ Four rules a provider has to keep:
2867
2872
  `queued` nobody takes part, so there is nothing to name. On every other step somebody did — see
2868
2873
  `INTERACTION_STEPS_WITH_A_PERSON` and `interactionStepExpectsAPerson()` — so an absent `by` there says
2869
2874
  *this was handled and the provider cannot say by whom*. The one step that is never unattributed is
2870
- `muted`: the host has exactly one agent and the provider knows who, so `by` is required there
2875
+ `muted`: the agent application has exactly one agent and the provider knows who, so `by` is required there
2871
2876
  (`task.interactionHistory.muted.by`).
2872
2877
 
2873
2878
  That case is ordinary rather than theoretical: a leg answered on a shared phone, a manager's
@@ -2876,7 +2881,7 @@ rather than dropping it.** A list missing a real handler looks complete and is w
2876
2881
  worse than one saying plainly it could not attribute a leg — and far better than publishing
2877
2882
  nothing because a single leg could not be named.
2878
2883
 
2879
- A host must render the two differently. Showing an unattributed `answered` the same way as
2884
+ An agent application must render the two differently. Showing an unattributed `answered` the same way as
2880
2885
  `queued` tells the agent nobody was involved, which is not what was said. Omni renders it as
2881
2886
  *"not recorded"* in the place the name would go.
2882
2887
 
@@ -2893,10 +2898,10 @@ zeros. The record is restated with the task on every `task-updated` and snapshot
2893
2898
  that arrives late corrects the sums. These four are what every platform reports; more will be
2894
2899
  added here as a need is shown, not invented ahead of one.
2895
2900
 
2896
- #### The host records what it performs
2901
+ #### The agent application records what it performs
2897
2902
 
2898
- `muted` is the one leg the host performs rather than the provider, and a record kept by the
2899
- provider would have a hole exactly there. So the host reports it, through `recordStep`, and the provider
2903
+ `muted` is the one leg the agent application performs rather than the provider, and a record kept by the
2904
+ provider would have a hole exactly there. So the agent application reports it, through `recordStep`, and the provider
2900
2905
  writes it into its record as it writes every other leg:
2901
2906
 
2902
2907
  ```ts
@@ -2906,12 +2911,12 @@ declare const allocationId: AllocationId;
2906
2911
  declare const at: IsoTimestamp;
2907
2912
 
2908
2913
  void connection.recordStep?.({ taskId, allocationId, step: "muted", at, mutedBy: "host" }); // the moment the agent mutes
2909
- void connection.recordStep?.({ taskId, allocationId, step: "muted", at, mutedBy: "host", seconds: 15 }); // still running, if the host chooses to say
2914
+ void connection.recordStep?.({ taskId, allocationId, step: "muted", at, mutedBy: "host", seconds: 15 }); // still running, if the agent application chooses to say
2910
2915
  void connection.recordStep?.({ taskId, allocationId, step: "muted", at, mutedBy: "host", seconds: 42, ended: true }); // the moment they unmute
2911
2916
  ```
2912
2917
 
2913
- Every report about one leg repeats its original `step` and host `at` as a correlation key;
2914
- the published history uses the provider-selected `at` returned by `recordStep`. The host reports
2918
+ Every report about one leg repeats its original `step` and agent application `at` as a correlation key;
2919
+ the published history uses the provider-selected `at` returned by `recordStep`. The agent application reports
2915
2920
  the action it performed and its measured duration, not an authoritative provider timestamp. It may say how long so far — `seconds` is
2916
2921
  elapsed while the leg runs and final once it has ended — and **the end is stated, never
2917
2922
  inferred**: `ended: true` marks the last report, and it carries the final duration. **What a
@@ -2922,16 +2927,16 @@ a running one it was never asked for (`interactionReport.running.unexpected`). W
2922
2927
  did ask for them forwards upstream, and how often, is its own business. The step appears in
2923
2928
  `interactionHistory` when the *provider* publishes it: Omni never writes the record itself.
2924
2929
  `recordStep` is required of every softphone login's connection, since every call on a softphone
2925
- can be muted by the host, and answers `recorded` with the canonical history `at`. A `muted` report says whose the silence was,
2930
+ can be muted by the agent application, and answers `recorded` with the canonical history `at`. A `muted` report says whose the silence was,
2926
2931
  `mutedBy: "host"` or `"station"`, and no other report has the word (`interactionReport.mutedBy`,
2927
2932
  `.mutedBy.unexpected`). On a desk phone the microphone is the phone's:
2928
- the host mutes nothing and records nothing.
2933
+ the agent application mutes nothing and records nothing.
2929
2934
 
2930
- **The provider's confirmed end is decisive.** The host keeps local state for interaction and
2935
+ **The provider's confirmed end is decisive.** The agent application keeps local state for interaction and
2931
2936
  reporting, but follows the provider's authoritative state. When the provider publishes the end
2932
- of the current mute leg, the host ends that local mute and releases its host-controlled mute
2937
+ of the current mute leg, the agent application ends that local mute and releases its agent application-controlled mute
2933
2938
  on the matching task's media. It does not wait for its own timer, reopen the leg, replace the
2934
- provider timestamp, or overwrite the provider's final duration with a later host report.
2939
+ provider timestamp, or overwrite the provider's final duration with a later agent application report.
2935
2940
  A later agent mute is a new leg, never a reopening of the ended one.
2936
2941
 
2937
2942
  Correlate the provider-published `muted` entry using the provider-selected `at` acknowledged
@@ -2939,15 +2944,15 @@ for the current report key; a final `seconds` closes that leg under the history
2939
2944
  This is identity matching, not reconciliation between clocks. An old closed entry, an unrelated
2940
2945
  task, or a stale connection cannot end a newer local mute. If publication precedes the acknowledgment,
2941
2946
  retain the current provider view and apply the matching closure once correlation is available;
2942
- never guess a match from arrival order or nearest timestamp. Failure to release a host-controlled
2947
+ never guess a match from arrival order or nearest timestamp. Failure to release an agent application-controlled
2943
2948
  mute is reported visibly; local device reports still describe the actual device state.
2944
2949
 
2945
- At a provider-confirmed task/media end, the host also stops the associated local mute and reports
2946
- its observed ending where the report is still accepted. A host closing report repeats its original
2950
+ At a provider-confirmed task/media end, the agent application also stops the associated local mute and reports
2951
+ its observed ending where the report is still accepted. An agent application closing report repeats its original
2947
2952
  key and may include its measured duration, but cannot reverse an already confirmed provider end.
2948
2953
  The provider acknowledges a known closed leg without rewriting its final record; after the task
2949
- has been completed, it may refuse the report as task-not-found. The host reads that response rather
2950
- than retrying or recreating the task. An observed host end before a provider closure is still
2954
+ has been completed, it may refuse the report as task-not-found. The agent application reads that response rather
2955
+ than retrying or recreating the task. An observed agent application end before a provider closure is still
2951
2956
  reported normally; the provider decides the final timestamp and publishes the record.
2952
2957
 
2953
2958
  ### Browser capability
@@ -2981,7 +2986,7 @@ Each `TaskBrowser` defines one named browser in the task workspace.
2981
2986
  | `url` | Initial URL. Must use `http:` or `https:`; see below. Later navigation comes from Chromium. |
2982
2987
  | `sharedSession` | Required. `false` creates a task-specific browser session. |
2983
2988
  | `isolationScheme` | **Required when `sharedSession` is `true`**, and rejected when it is `false`. There is no default: see below. |
2984
- | `urlVisibility` | What the agent sees of this tab's URL in Omni's chrome: `hidden`, `domain`, or `full`. Omitted, the URL shows as any browser's does; a provider says `hidden` where the URL carries what the agent may not read — a caller's number, a CRM token. Per browser, on the provider's word; a host that declares `guarantees.browserUrlVisibility` honours it tab by tab, and a provider checks that guarantee before it sends such a URL at all. |
2989
+ | `urlVisibility` | What the agent sees of this tab's URL in Omni's chrome: `hidden`, `domain`, or `full`. Omitted, the URL shows as any browser's does; a provider says `hidden` where the URL carries what the agent may not read — a caller's number, a CRM token. Per browser, on the provider's word; an agent application that declares `guarantees.browserUrlVisibility` honours it tab by tab, and a provider checks that guarantee before it sends such a URL at all. |
2985
2990
 
2986
2991
  ##### Choosing an isolation scheme
2987
2992
 
@@ -3072,8 +3077,8 @@ that produces two consumers disagreeing about one fact. The task is the one sour
3072
3077
  provider puts on the task what the platform permits for it -- and says, in `capabilitySource`, who
3073
3078
  chose those terms. `queue` says somebody configured them. `ungoverned` says nothing handed the work
3074
3079
  over: an agent's own outbound call has no queue behind it, and the provider states what it permits
3075
- for such a call. Neither changes where a host reads the capabilities from, which is the task; the
3076
- source is one more published fact about them, and the one that lets a host tell a fact from a fault
3080
+ for such a call. Neither changes where an agent application reads the capabilities from, which is the task; the
3081
+ source is one more published fact about them, and the one that lets an agent application tell a fact from a fault
3077
3082
  (see below).
3078
3083
 
3079
3084
  **Completing the task is not a capability, and no capability set withholds it.** `complete` is
@@ -3092,14 +3097,14 @@ task said so both times, at the moment it became true. A call moves queues the s
3092
3097
  identified as a priority customer is transferred to the priority queue, and the task arrives under
3093
3098
  that queue's terms -- a longer wrap allowance, a discount control the general queue never offered --
3094
3099
  restated on the task at the hand-over, not inferred from the queue it left. A capability stated
3095
- once at offer or answer and never corrected is a fact with a shelf life and no expiry, and a host
3100
+ once at offer or answer and never corrected is a fact with a shelf life and no expiry, and an agent application
3096
3101
  draws a control the provider will now refuse -- or withholds one the agent now has. So the provider republishes
3097
- the task, with its capabilities as they now stand, and a host treats the last statement as current
3102
+ the task, with its capabilities as they now stand, and an agent application treats the last statement as current
3098
3103
  rather than re-deriving anything. This is the same shape as a room left full after the call ends
3099
3104
  -- a field describing the present, carried past the moment it stopped being true -- carried past
3100
3105
  this time not by a spread but by nobody sending the correction. A provider whose platform can
3101
3106
  change a permission mid-task and does not republish is in breach, however conformant its offer was.
3102
- A capability set can shrink as well as grow, and a host that has only ever seen it grow meets a
3107
+ A capability set can shrink as well as grow, and an agent application that has only ever seen it grow meets a
3103
3108
  control that was there a moment ago and is gone; a command that arrives after its capability was
3104
3109
  withdrawn is refused with a reason, never acted on. The asymmetry decides which direction a
3105
3110
  provider gets right first: a control gained late is a nicety, a control withdrawn and not
@@ -3108,12 +3113,12 @@ direction: the task as offered and as republished, and one command that was issu
3108
3113
  first and is refused under the last for want of the capability withdrawn -- and nothing else.
3109
3114
 
3110
3115
  **An empty capability set is a statement, not a shrug.** `capabilities: {}` under `queue` or
3111
- `ungoverned` says the platform permits nothing capability-gated on this task, and a host draws
3116
+ `ungoverned` says the platform permits nothing capability-gated on this task, and an agent application draws
3112
3117
  nothing beyond what the phase and `completionMode` require. A provider that has not yet learned
3113
3118
  what the platform permits -- a queue's configuration that has not reached it -- knows nothing of
3114
3119
  the kind, and must not publish the task as if it did, neither as `{}` nor as every control it has.
3115
3120
  It publishes the task under `capabilitySource: "undetermined"`, with the capabilities it will
3116
- honour until it knows, and a host shows that where the agent works, beside the controls it draws
3121
+ honour until it knows, and an agent application shows that where the agent works, beside the controls it draws
3117
3122
  from them: "no queue governs this call" is a fact, "the configuration has not arrived" is a fault,
3118
3123
  and the set alone cannot tell them apart, so the provider says which. What a provider honours
3119
3124
  under undetermined terms is its own call -- a floor that would rather an agent briefly hold a
@@ -3158,9 +3163,9 @@ a message that shows and clears has said nothing about the buttons still on the
3158
3163
  words are close in English and far apart on the desk: `ungoverned` is silence, `undetermined` is a
3159
3164
  standing notice.
3160
3165
 
3161
- One consequence for whoever builds the host: because a conformance run fails on `undetermined`, a
3162
- conformant adapter never shows a host `undetermined` under test, and a clean `exerciseAdapter`
3163
- result says nothing about how the host renders it. That rendering is tested against a fixture --
3166
+ One consequence for whoever builds the agent application: because a conformance run fails on `undetermined`, a
3167
+ conformant adapter never shows an agent application `undetermined` under test, and a clean `exerciseAdapter`
3168
+ result says nothing about how the agent application renders it. That rendering is tested against a fixture --
3164
3169
  a task published under `undetermined` shows the notice, the same task under `queue` shows none --
3165
3170
  and never against an adapter, even in principle. `exerciseAdapter` treats a
3166
3171
  task published under `undetermined` as a violation (`capabilitySource.undetermined`), as it treats
@@ -3187,7 +3192,7 @@ See **Which commands need a capability**.
3187
3192
 
3188
3193
  | Capability | Omni UI | Contract |
3189
3194
  | --- | --- | --- |
3190
- | `decline` | Pending-task button: Decline | The provider can decline a pending voice offer. Omni shows it only when provisioning also permits declining. |
3195
+ | `decline` | Pending-task button: Decline | The provider can decline a pending voice offer. Omni shows it only when local policy also permits declining. |
3191
3196
  | `hold` | Primary toggle: Hold | Omni may issue voice-task `hold` and `resume` commands. |
3192
3197
  | `endCall` | Primary button: End call | The provider ends the caller connection and all owned/inherited agent-added channels; wrap/completion remain separate. See **Ending a call, and removing one person from it**. |
3193
3198
  | `connectBack` | Completing-task button: Connect back | Omni may have the provider connect the agent back to the task's party while the task is `completing`, returning it to `in-progress` on the same task. Not offered where there is no `completing` window: `provider-automatic` with a zero allowance completes the task at provider end. See **Connecting back during completion**. |
@@ -3195,7 +3200,7 @@ See **Which commands need a capability**.
3195
3200
  | `warmTransfer` | Secondary menu item: Warm transfer | Omni may park the customer and call a destination first, then hand the customer over or cancel back. See **Warm transfer**. |
3196
3201
  | `leadAssist` | Secondary menu item: Lead assist | Omni may ask a lead to join this call, with a note. The lead's decision reaches the agent on `Task.leadAssist`. See **Lead assist**. |
3197
3202
  | `conference` | Secondary button: Conference | Omni may dial a destination into the active call, and remove one person from it -- a conferenced entry, one still ringing included, which calls the dial off, or the party, leaving the agent with the colleague. See **Ending a call, and removing one person from it**. |
3198
- | `recording` | Overflow menu item: Recording | Per-task provider and host policies expose only their permitted recording actions; each has independent state and routing. |
3203
+ | `recording` | Overflow menu item: Recording | Per-task provider and agent application policies expose only their permitted recording actions; each has independent state and routing. |
3199
3204
  | `outcomes` | Primary button: Complete | Omni may request task completion with a provider outcome and notes. |
3200
3205
 
3201
3206
  ### Publishing codes and destinations
@@ -3277,7 +3282,7 @@ reason (`task.destinations.shape`): once nothing is typed, the directory is the
3277
3282
 
3278
3283
  **The provider chooses the supported destinations.** A published item may route to an IVR,
3279
3284
  queue, named agent or another configured destination. No destination kind is inferred from its
3280
- label. The host offers only the directory attached to this task's specific transfer capability,
3285
+ label. The agent application offers only the directory attached to this task's specific transfer capability,
3281
3286
  and sends the exact destination ID; it does not invent an agent picker or arbitrary dial target.
3282
3287
  The provider rechecks eligibility and executes the routing. Returning to an IVR or queue does not
3283
3288
  end the caller journey; a later assignment to the same agent is a new interaction.
@@ -3293,13 +3298,13 @@ provider.
3293
3298
  { type: "conference", action: "remove", destinationId: "tier2" } // the conferenced person leaves; ringing, this calls the dial off
3294
3299
  ```
3295
3300
 
3296
- The host sends the ordinary task-scoped `execute` request with `command: { type: "end-call" }`.
3301
+ The agent application sends the ordinary task-scoped `execute` request with `command: { type: "end-call" }`.
3297
3302
  The provider knows the caller and agent-added channel bindings; no channel list or owner details
3298
- are sent by the host. The task's `endCall` capability is permission, not an executor selection.
3303
+ are sent by the agent application. The task's `endCall` capability is permission, not an executor selection.
3299
3304
  `validateTaskCommandRequest` checks the exact interaction/allocation and delegates the command's
3300
3305
  policy/phase checks. The provider rechecks current ownership atomically; no client validator can
3301
- prove that its view is fresh. The host does not implement agent end-call; low-level removal of individual channels is not
3302
- this agent action. There is no host end-call execution API or fallback route.
3306
+ prove that its view is fresh. The agent application does not implement agent end-call; low-level removal of individual channels is not
3307
+ this agent action. There is no agent application end-call execution API or fallback route.
3303
3308
 
3304
3309
  `end-call` is gated by `endCall` on the current interaction. It ends the caller connection and
3305
3310
  all agent-added channels owned by that interaction, including channels originally added by previous
@@ -3351,7 +3356,7 @@ offer any of the three without the others, and each is declared on its own.
3351
3356
  ```
3352
3357
 
3353
3358
  `warm` is gated by the `warmTransfer` capability and names a directory item exactly as a cold
3354
- transfer does, from the same kind of directory. It is a dial, so it carries the host's `dialId`
3359
+ transfer does, from the same kind of directory. It is a dial, so it carries the agent application's `dialId`
3355
3360
  and is answered `dialling`, and its `dial-outcome` says whether the destination was reached. While
3356
3361
  the destination is on the line the task carries a `consulted` entry on `onCall`, and that presence
3357
3362
  is what makes `complete` and `cancel` issuable -- they name no destination because there is exactly
@@ -3377,7 +3382,7 @@ customer.
3377
3382
 
3378
3383
  | Capability | Omni UI | Contract |
3379
3384
  | --- | --- | --- |
3380
- | `decline` | Pending-task button: Decline | The provider can decline a pending chat offer. Omni shows it only when provisioning also permits declining. |
3385
+ | `decline` | Pending-task button: Decline | The provider can decline a pending chat offer. Omni shows it only when local policy also permits declining. |
3381
3386
  | `hold` | Primary toggle: Hold | Omni may pause and resume the agent’s interaction in the chat. |
3382
3387
  | `outcomes` | Primary button: Complete | Omni may request task completion with a provider outcome and notes. |
3383
3388
 
@@ -3385,7 +3390,7 @@ customer.
3385
3390
 
3386
3391
  | Capability | Omni UI | Contract |
3387
3392
  | --- | --- | --- |
3388
- | `decline` | Pending-task button: Decline | The provider can decline a pending email offer. Omni shows it only when provisioning also permits declining. |
3393
+ | `decline` | Pending-task button: Decline | The provider can decline a pending email offer. Omni shows it only when local policy also permits declining. |
3389
3394
  | `outcomes` | Primary button: Complete | Omni may request task completion with a provider outcome and notes. |
3390
3395
 
3391
3396
  ### Custom capabilities
@@ -3434,7 +3439,7 @@ Custom capabilities must not redefine the meaning of a standard channel capabili
3434
3439
  Starts one outbound call from the idle dialpad. It is present only when the voice provider
3435
3440
  declares `dial`.
3436
3441
 
3437
- - `dialId` is the host's identity for this dial, minted before the request leaves.
3442
+ - `dialId` is the agent application's identity for this dial, minted before the request leaves.
3438
3443
  - `destination` is the original number selected or entered by the agent.
3439
3444
  - The provider holds `destination` to its declared `destinations`: under `contacts-only`, a
3440
3445
  number that is not one of its contacts answers `failed` with `omni.destination-not-permitted`.
@@ -3454,7 +3459,7 @@ and apart from its answer -- the destination picks up, is busy, or never does --
3454
3459
  late in a call routinely outlives the call. Nothing in between is reported: the wire says
3455
3460
  `dialling`, then says how it ended, once.
3456
3461
 
3457
- **The host mints the identity.** Every command that dials carries a `dialId` the host made, unique
3462
+ **The agent application mints the identity.** Every command that dials carries a `dialId` the agent application made, unique
3458
3463
  across the installation, and it travels four ways so no leg is a lookup:
3459
3464
 
3460
3465
  ```ts
@@ -3462,10 +3467,10 @@ declare const connection: Connection<"voice">;
3462
3467
  declare const taskId: TaskId;
3463
3468
  declare const allocationId: AllocationId;
3464
3469
 
3465
- // 1. Out, minted by the host.
3470
+ // 1. Out, minted by the agent application.
3466
3471
  const result = await connection.execute({ taskId, allocationId, command: { type: "conference", action: "add", dialId: "dial-7f2", destinationId: "tier2" } });
3467
3472
 
3468
- // 2. Back on the result, restated, so the host compares and confirms.
3473
+ // 2. Back on the result, restated, so the agent application compares and confirms.
3469
3474
  expect(result).toEqual({ status: "dialling", dialId: "dial-7f2" });
3470
3475
 
3471
3476
  // 3. On the outcome, however late, against the task it belonged to.
@@ -3475,22 +3480,22 @@ const outcome: ProviderEvent<"voice"> = { type: "dial-outcome", dialId: "dial-7f
3475
3480
  const step: TaskInteractionStep = { step: "unanswered", at: "2026-08-21T09:15:30Z", by: "A-12", dialId: "dial-7f2", destinationId: "tier2" };
3476
3481
  ```
3477
3482
 
3478
- The identity is a correlation handle between host and provider and **is never shown to the
3479
- agent**. A host holding several tasks places an outcome by the `dialId` it minted; one it did not
3483
+ The identity is a correlation handle between agent application and provider and **is never shown to the
3484
+ agent**. An agent application holding several tasks places an outcome by the `dialId` it minted; one it did not
3480
3485
  mint -- a dial made by the previous agent before a transfer -- it finds on the task's `onCall` or in
3481
3486
  its `interactionHistory`, which is why the steps that dial carry it. The `dialId` is not a retry key:
3482
3487
  Omni never repeats a dial, and a command still carries no key for that purpose.
3483
3488
 
3484
3489
  **`dialling` is the answer to a dial, and `applied` is not.** A command that dials answers
3485
- `{ status: "dialling", dialId }`, restating the host's identity (`result.dialId`,
3490
+ `{ status: "dialling", dialId }`, restating the agent application's identity (`result.dialId`,
3486
3491
  `result.dialId.mismatch`); `applied` from such a command, or `dialling` from one that dialled
3487
3492
  nothing, is refused (`result.status`). `validateResult(result, method, path, dialId)` takes the
3488
- `dialId` the host sent for that reason.
3493
+ `dialId` the agent application sent for that reason.
3489
3494
 
3490
3495
  **The outcome is stated, once, either way.** A `dial-outcome` names the `dialId`, the task where
3491
3496
  there was one, the directory item it went to where there was one, and how the dial ended -- from a closed
3492
3497
  set: `answered`, `busy`, `no-answer`, `unreachable`, `rejected`, `cancelled`, `unexplained`.
3493
- `answered` is stated rather than read off somebody appearing on the call, because a host that infers
3498
+ `answered` is stated rather than read off somebody appearing on the call, because an agent application that infers
3494
3499
  success cannot tell "reached" from "still ringing". `cancelled` is the dialler calling the dial off
3495
3500
  before anyone answered -- the agent hanging up while a consult still rings -- which is not a
3496
3501
  `no-answer` the destination never gave. `unexplained` is the switch dropping the call with no cause among
@@ -3507,7 +3512,7 @@ and the harness places the outcome all the same (`TaskStream`, `stream.dialOutco
3507
3512
  `stream.dialOutcome.duplicate`); an agent who moved on still learns nobody was reached, against the
3508
3513
  call it belonged to and never against the next one.
3509
3514
 
3510
- The stream knows a dial from three places: `TaskStream.dialled(dialId)`, which a host calls when it
3515
+ The stream knows a dial from three places: `TaskStream.dialled(dialId)`, which an agent application calls when it
3511
3516
  places one; an entry on a task's `onCall`; and a step in its `interactionHistory`. Since a dialled entry
3512
3517
  is listed from placement, `dialled()` is load-bearing only for a dial that never has an entry -- a
3513
3518
  cold transfer, a connect-back, an idle dialpad call -- or whose entry has already left the room; an
@@ -3548,8 +3553,8 @@ const onCall: OnCall[] = [
3548
3553
 
3549
3554
  `party` is the customer and `agent` a person by user id; neither was dialled from anywhere, so
3550
3555
  neither carries a destination. `consulted` and `conferenced` were, so both carry the
3551
- `destinationId` of the directory item and, where a host's dial brought them, its `dialId`; a person
3552
- the platform added itself carries none. `held: true` is presence as claim. A snapshot establishes state, so a host that attaches
3556
+ `destinationId` of the directory item and, where an agent application's dial brought them, its `dialId`; a person
3557
+ the platform added itself carries none. `held: true` is presence as claim. A snapshot establishes state, so an agent application that attaches
3553
3558
  after a transfer reads the room from here rather than inferring it from a sequence of outcomes it
3554
3559
  never saw.
3555
3560
 
@@ -3564,7 +3569,7 @@ task may remain open for wrap. Completion is a separate task action, not the cal
3564
3569
  `previewEndsAt` and `atDeadline` are three instances of one shape, and there will be more: each
3565
3570
  describes a state that is true now, and each is carried past the moment it stops being true by the
3566
3571
  most natural implementation there is, building the next task by spreading the last one. The
3567
- provider's own state looks right, the claim on the wire is stale, and only the host sees it. An
3572
+ provider's own state looks right, the claim on the wire is stale, and only the agent application sees it. An
3568
3573
  adapter that builds each transition from what is true after it, rather than from what was true
3569
3574
  before, needs none of these rules named. Two agents were
3570
3575
  once shown on calls for the better part of an hour while callers queued, because the last message
@@ -3707,11 +3712,11 @@ thing as a break the platform forced on its own. Where a platform applies one au
3707
3712
  executing a preference somebody configured, and that person is the owner of the action — `by` names
3708
3713
  them, not the machinery that carried it out.
3709
3714
 
3710
- Omni resolves the name to show with `describeUsers()`, so a provider sends the identifier and never
3715
+ Omni resolves the name to show with `getUserDetails()`, so a provider sends the identifier and never
3711
3716
  a display name.
3712
3717
 
3713
3718
  **A forced break travels with `on-break` or `starting-after-task`, and nothing else.** It is a
3714
- break in progress or about to be; beside `granted` or `awaiting-approval` the host would read a
3719
+ break in progress or about to be; beside `granted` or `awaiting-approval` the agent application would read a
3715
3720
  request the agent never made and commit it (`break.forced.status`). Where the provider publishes
3716
3721
  `reasons`, the lead's `force-break` named one, and the member's state carries it as `activeReasonId`.
3717
3722
 
@@ -3724,18 +3729,18 @@ forced: {
3724
3729
  }
3725
3730
  ```
3726
3731
 
3727
- The host keeps **Resume** available for an agent on a forced break. The agent explicitly chooses
3728
- Resume; the host sends `endBreak()` and follows the provider-confirmed state before resuming
3732
+ The agent application keeps **Resume** available for an agent on a forced break. The agent explicitly chooses
3733
+ Resume; the agent application sends `endBreak()` and follows the provider-confirmed state before resuming
3729
3734
  work. An expected duration is a positive finite number of milliseconds, measured from actual
3730
3735
  entry into `on-break`, excluding any `starting-after-task` wait. Omission means no expected
3731
- duration was supplied. Neither duration expiry nor an overdue indication authorizes the host
3736
+ duration was supplied. Neither duration expiry nor an overdue indication authorizes the agent application
3732
3737
  or provider to end the break, restore availability, or route work to the agent.
3733
3738
 
3734
3739
  **A lead lifting the restriction does not resume the agent.** On an applied
3735
3740
  `end-forced-break`, the provider clears `BreakState.forced` while preserving the current
3736
3741
  `on-break` or `starting-after-task` status and `activeReasonId`. This command cannot publish
3737
3742
  `not-requested`, restore readiness, or start routing work. Ordinary progress from
3738
- `starting-after-task` to `on-break` still happens when work finishes. The host follows the
3743
+ `starting-after-task` to `on-break` still happens when work finishes. The agent application follows the
3739
3744
  published state and waits for the agent's explicit Resume, even after reconnect. Historical
3740
3745
  attribution is not rewritten by clearing the current forced marker.
3741
3746
 
@@ -3745,7 +3750,7 @@ must correlate resumption to the authenticated agent's action; a state-only orde
3745
3750
  cannot establish the cause of a transition. The usual multi-provider end/reconciliation flow
3746
3751
  still applies, and work resumes only on confirmed provider state.
3747
3752
 
3748
- A host may display the expected duration. A countdown requires an evidenced actual start;
3753
+ An agent application may display the expected duration. A countdown requires an evidenced actual start;
3749
3754
  a received snapshot, replay or reconnect is not a new start and cannot restart the duration.
3750
3755
  Without that evidence, show the duration without inventing a start or return time.
3751
3756
 
@@ -3789,7 +3794,7 @@ States how many tasks this provider may have allocated to the agent **at once**.
3789
3794
  `count` is an absolute ceiling, not an increment, a whole number of zero or more
3790
3795
  (`capacity.count`). An agent's capacity is a property of the agent, not of the moment: it is
3791
3796
  stated when the agent is set up and restated only when it genuinely changes, which is a
3792
- provisioning change rather than a task starting or ending -- with one exception below.
3797
+ local policy change rather than a task starting or ending -- with one exception below.
3793
3798
 
3794
3799
  **The provider counts its own outstanding tasks against it.** Allocate while you hold fewer than
3795
3800
  `count` tasks for this agent, and stop when you hold that many; when one of yours ends you have
@@ -3798,22 +3803,22 @@ go, and a provider that waits for it will stall.
3798
3803
 
3799
3804
  Your own tasks are the only ones you count. What the agent holds at other providers is not your
3800
3805
  concern — Omni set `count` knowing it, and this is how: the agent is one person on several
3801
- providers, and the host divides their capacity among them rather than telling each the whole. A
3802
- provider that has none of it for now is told **`count: 0`, host-stopped**: allocate nothing, show
3803
- the member as `reserved` on the team member list -- signed in here, capacity held by the host for elsewhere,
3806
+ providers, and the agent application divides their capacity among them rather than telling each the whole. A
3807
+ provider that has none of it for now is told **`count: 0`, agent application-stopped**: allocate nothing, show
3808
+ the member as `reserved` on the team member list -- signed in here, capacity held by the agent application for elsewhere,
3804
3809
  a fact this provider holds, where `on-task` would assert work it cannot see -- and take the next
3805
- count as any other when the host has capacity for this provider again. Zero is the one restatement
3806
- that follows work rather than provisioning.
3810
+ count as any other when the agent application has capacity for this provider again. Zero is the one restatement
3811
+ that follows work rather than local policy.
3807
3812
 
3808
3813
  **A capacity is taken, never refused.** `setCapacity` answers `applied` and nothing else: a
3809
- statement has no failure to report, and a `failed` arm gave four host-provider pairings four
3814
+ statement has no failure to report, and a `failed` arm gave four agent application-provider pairings four
3810
3815
  readings of which ceiling stood after it. A provider that cannot carry the count allocates within
3811
3816
  what it can and says so on a `diagnostic`, so the gap is visible and nothing is inferred from a
3812
3817
  refusal.
3813
3818
 
3814
3819
  Capacity supersedes rather than accumulates: the latest value is the ceiling, and a decrease is as
3815
3820
  ordinary as an increase. A provider whose ceiling can only rise -- one that keeps the highest count
3816
- it was ever told, or returns early on a small one -- cannot be told to take less work, and a host
3821
+ it was ever told, or returns early on a small one -- cannot be told to take less work, and an agent application
3817
3822
  taking capacity away is answered `applied` while the work keeps coming. The harness moves the axis
3818
3823
  both ways after the drive, two then one then nought, and an offer after a lower count is caught
3819
3824
  against it (`stream.taskOffered.overCapacity`).
@@ -3852,7 +3857,7 @@ These validators report violations without dispatching, rewriting state or provi
3852
3857
  Recheck prerequisites atomically at the provider; client validation cannot prevent a race.
3853
3858
  Continue to use `validateResult` for each method's response vocabulary. A request acknowledgment
3854
3859
  is not a grant, and no method response overwrites a newer state emission. Rejected promises
3855
- remain unknown and recover by snapshot, not automatic retry. The host's frozen provider set,
3860
+ remain unknown and recover by snapshot, not automatic retry. The agent application's frozen provider set,
3856
3861
  durable mutually exclusive commit/cancel decision and reconciliation obligations above remain
3857
3862
  required; per-provider validation does not implement the multi-provider coordinator.
3858
3863
 
@@ -3979,7 +3984,7 @@ request and is ready to stop the agent when Omni asks. It does not reveal that o
3979
3984
  or why Omni has not committed yet. While reporting `granted`, the provider remains available,
3980
3985
  continues to honour Omni's current capacity, and continues offering work normally.
3981
3986
 
3982
- Omni separately tracks the aggregate host states `working`, `requesting-break`, `committing-break`,
3987
+ Omni separately tracks the aggregate agent application states `working`, `requesting-break`, `committing-break`,
3983
3988
  `cancelling-break`, and `on-break`. While `requesting-break`, Omni shows which providers remain
3984
3989
  outstanding and offers **Cancel break request**, but does not tell the agent that their break has
3985
3990
  begun.
@@ -3996,7 +4001,7 @@ Omni coordinates one break attempt as follows:
3996
4001
  from and is not asked: nothing is asked of it, the break proceeds without it, and when the
3997
4002
  login is restored it is reconciled from its snapshot as a set-aside provider is, with no
3998
4003
  capacity until then. `refreshing` keeps a provider in — its identity and capabilities remain
3999
- available and work continues. `assertBreakAttemptProviders` holds a host to this set.
4004
+ available and work continues. `assertBreakAttemptProviders` holds an agent application to this set.
4000
4005
  2. Enter `requesting-break`. Keep the agent's normal capacity in place throughout this phase.
4001
4006
  3. Send one `requestBreak` to every asked provider. A provider reports `awaiting-approval` or
4002
4007
  `granted`; neither state stops work. A denial transitions directly to `not-requested` and
@@ -4128,7 +4133,7 @@ an absent `team` still means the login is not entitled to that contribution.
4128
4133
 
4129
4134
  | `TeamMember` field | Contract |
4130
4135
  | --- | --- |
4131
- | `id` | Required `UserId`. A task carries no names and neither does a team member list: Omni resolves what to display with `describeUsers()`. |
4136
+ | `id` | Required `UserId`. A task carries no names and neither does a team member list: Omni resolves what to display with `getUserDetails()`. |
4132
4137
  | `availability` | Required. What the member is doing now. |
4133
4138
  | `since` | Optional. When the current `availability` began — not when they signed in, and not when the team member list was read. |
4134
4139
  | `break` | Present only while the member has an outstanding break request. See **A member waiting for a break**. |
@@ -4140,7 +4145,7 @@ Each availability value means one thing:
4140
4145
  | `ready` | Signed in, able to take work, none assigned. |
4141
4146
  | `on-task` | Working on at least one task. It says nothing about how many, and nothing about whether more will fit. |
4142
4147
  | `on-break` | Stopped and not taking work, whether they asked or somebody stopped them. The reason lives on their own `BreakState`, not here. |
4143
- | `reserved` | Signed in here, and the host holds this agent's capacity for another provider (`count: 0`, host-stopped): not receiving this provider's work, and not on a break. See **Capacity**. |
4148
+ | `reserved` | Signed in here, and the agent application holds this agent's capacity for another provider (`count: 0`, agent application-stopped): not receiving this provider's work, and not on a break. See **Capacity**. |
4144
4149
  | `signed-out` | Known to this team but not signed in to this provider. |
4145
4150
 
4146
4151
  **Always publish the complete team member list, never a change to it.** Team presence typically reaches an
@@ -4183,7 +4188,7 @@ One method, `executeTeamBreak`, taking a discriminated command exactly as `execu
4183
4188
 
4184
4189
  `memberId` is this provider's own identifier for the member, as published on its team member list. It is
4185
4190
  never an identifier from another provider, and Omni does not translate between them; names come
4186
- from `describeUsers()`.
4191
+ from `getUserDetails()`.
4187
4192
 
4188
4193
  `requests-suspended` means requests are **rejected outright** rather than left pending — nobody is coming to
4189
4194
  approve them. A provider that suspends break requests must also publish `canRequestBreak: false` to the team's
@@ -4272,7 +4277,7 @@ const leadAssistCapable = {
4272
4277
  ```
4273
4278
 
4274
4279
  Lead and member alike are `UserId`s of this provider, so an adapter publishing them implements
4275
- `describeUsers()`; names never travel on a task or a team member list.
4280
+ `getUserDetails()`; names never travel on a task or a team member list.
4276
4281
 
4277
4282
  ### Listening to a call
4278
4283
 
@@ -4413,12 +4418,12 @@ decision or it is not.
4413
4418
  ## Real-time media
4414
4419
 
4415
4420
  Every voice provider has media: `channel: "voice"` says audio exists. Where the agent hears it
4416
- depends on the `phone` the host selected at authentication and connect from the manifest's
4421
+ depends on the `phone` the agent application selected at authentication and connect from the manifest's
4417
4422
  `phones`. On a softphone, audio lands in Omni; on a desk phone, it lands on the handset and Omni
4418
4423
  opens no audio. See **How the agent hears the call**. Media transitions are voice-only;
4419
4424
  chat and email publish none (`event.media.channel`, `stream.taskMedia.channel`).
4420
4425
 
4421
- The provider owns signalling and the platform's endpoint configuration. The host selects the
4426
+ The provider owns signalling and the platform's endpoint configuration. The agent application selects the
4422
4427
  declared phone mode; it does not enumerate or reconfigure the platform's devices. The selected
4423
4428
  mode stays with the login rather than being inferred from a snapshot or a device failure.
4424
4429
 
@@ -4427,11 +4432,11 @@ phase follow the provider's reports about the work, and the media — attaching,
4427
4432
  hold, a consult, a conference or a transfer, and ending — is transient beside it. See **A task is
4428
4433
  never its audio** under **Task allocation lifecycle**.
4429
4434
 
4430
- ### The host reports, the adapter decides
4435
+ ### The agent application reports, the adapter decides
4431
4436
 
4432
4437
  The adapter runs inside Omni and sees nothing of the station for itself: the devices, the
4433
- permissions, the audio element and the network are the host's, and only the host can tell. So
4434
- the host reports, and the adapter asks. **An adapter consults `ConnectContext.host` before it
4438
+ permissions, the audio element and the network are the agent application's, and only the agent application can tell. So
4439
+ the agent application reports, and the adapter asks. **An adapter consults `ConnectContext.host` before it
4435
4440
  declares the agent ready to its platform, and again whenever the report changes**, and it decides
4436
4441
  what any of it means and what to relay upstream — go not-ready, refuse calls, carry on because the
4437
4442
  platform's audio lands elsewhere. Omni facilitates and does not take responsibility: it captures
@@ -4439,29 +4444,29 @@ the microphone once as the voice connection opens, so the permission prompt land
4439
4444
  is signing in rather than over a contact, prompts, retries on the agent's request, tells the agent
4440
4445
  what failed, and reports. It never decides for the adapter what a missing microphone means.
4441
4446
 
4442
- **The host also guarantees, and a promise the provider cannot see is not one it can rely on.**
4443
- Two of this contract's obligations fall on the host rather than the provider — honouring a task
4447
+ **The agent application also guarantees, and a promise the provider cannot see is not one it can rely on.**
4448
+ Two of this contract's obligations fall on the agent application rather than the provider — honouring a task
4444
4449
  browser's `urlVisibility`, and taking a `consent` offer only on the person's own press — and more
4445
4450
  than one desk speaks this contract: a browser and a native application differ in what they can
4446
4451
  reach, and a provider never branches on which it is talking to, only on what it has declared —
4447
- here, and in `host.mute` (see **The station is the host's**). So `ConnectContext.host.guarantees` says which promises the
4448
- connected host makes, declared once per connection, presence being the guarantee exactly as it is
4452
+ here, and in `host.mute` (see **The station is the agent application's**). So `ConnectContext.host.guarantees` says which promises the
4453
+ connected agent application makes, declared once per connection, presence being the guarantee exactly as it is
4449
4454
  the permission everywhere else:
4450
4455
 
4451
4456
  | Guarantee | Contract |
4452
4457
  | --- | --- |
4453
- | `browserUrlVisibility` | Every task browser's `urlVisibility` is honoured in this host's chrome, tab by tab. A provider that would send a caller's number in a URL checks this first and tokenises where the promise is absent. |
4458
+ | `browserUrlVisibility` | Every task browser's `urlVisibility` is honoured in this agent application's chrome, tab by tab. A provider that would send a caller's number in a URL checks this first and tokenises where the promise is absent. |
4454
4459
  | `personConsent` | A `consent` offer is accepted only by the person's own explicit act, never on their behalf. A provider whose work may only be taken by a human checks this first and does not offer it where the promise is absent. |
4455
4460
 
4456
- A guarantee the host does not make is an absent key, never `false` — `validateHostGuarantees`
4461
+ A guarantee the agent application does not make is an absent key, never `false` — `validateHostGuarantees`
4457
4462
  refuses a false one, as it refuses a name this contract does not list.
4458
4463
 
4459
4464
  | Field | Contract |
4460
4465
  | --- | --- |
4461
- | `online` | Whether the host has a network interface up. Not a claim that anything is reachable — the adapter knows whether it can reach its own platform far better than the host does — so `false` is a reason not to go ready and `true` is not a reason to. |
4466
+ | `online` | Whether the agent application has a network interface up. Not a claim that anything is reachable — the adapter knows whether it can reach its own platform far better than the agent application does — so `false` is a reason not to go ready and `true` is not a reason to. |
4462
4467
  | `audio` | Present on a voice connection, absent where there is no audio. |
4463
- | `audio.input` | `available` with `localAudio` — the microphone as captured, the same stream `openMedia` receives — and `flowing`, false while no audio moves through it, when `mutedBy` says who stopped it: `host`, the host's own Mute on a host that mutes the station, or `station`, a slider on the headset or the operating system, which the host observed and did not do. An adapter treats `host` as the agent's act on a call and `station` as a condition of the station. `unavailable` with `reason`, since each wants a different fix from the agent: `no-device`; `denied`; `not-asked`, which a host that asks at connect never publishes; `in-use`, a device present and permitted that another application holds — on an agent desktop the commonest of all; `lost`, a capture that ended. A host decides the reason from the devices before the error name: a browser can report a permission error on a machine with no microphone at all, and "grant permission" is the wrong instruction for an agent who needs to plug one in. `failure` carries the words Omni showed them. |
4464
- | `audio.output` | `available`, with `flowing` where the host can know whether audio reaches the speaker — a browser mostly cannot, and omits it; a native host reads the endpoint — false while it is silenced, when `mutedBy` says who did it, as on input. Or `unavailable` with `reason` — `no-device`, or `lost` for one removed — and `failure`: an agent who cannot hear is as unable to take a call as one who cannot speak. |
4468
+ | `audio.input` | `available` with `localAudio` — the microphone as captured, the same stream `openMedia` receives — and `flowing`, false while no audio moves through it, when `mutedBy` says who stopped it: `host`, the agent application's own Mute on an agent application that mutes the station, or `station`, a slider on the headset or the operating system, which the agent application observed and did not do. An adapter treats `host` as the agent's act on a call and `station` as a condition of the station. `unavailable` with `reason`, since each wants a different fix from the agent: `no-device`; `denied`; `not-asked`, which an agent application that asks at connect never publishes; `in-use`, a device present and permitted that another application holds — on an agent desktop the commonest of all; `lost`, a capture that ended. An agent application decides the reason from the devices before the error name: a browser can report a permission error on a machine with no microphone at all, and "grant permission" is the wrong instruction for an agent who needs to plug one in. `failure` carries the words Omni showed them. |
4469
+ | `audio.output` | `available`, with `flowing` where the agent application can know whether audio reaches the speaker — a browser mostly cannot, and omits it; a native agent application reads the endpoint — false while it is silenced, when `mutedBy` says who did it, as on input. Or `unavailable` with `reason` — `no-device`, or `lost` for one removed — and `failure`: an agent who cannot hear is as unable to take a call as one who cannot speak. |
4465
4470
 
4466
4471
  Omni republishes the report whenever it changes — a permission granted late, a headset unplugged,
4467
4472
  a network gone — and it publishes a state, not a flicker: a change that resolves within moments is
@@ -4469,13 +4474,13 @@ not reported, so an adapter may act on what it reads without debouncing it again
4469
4474
  report is a task fact or a capacity fact; it is what the station can do, and the adapter's platform
4470
4475
  is the one that knows whether an agent without a microphone, or without a speaker, can work.
4471
4476
 
4472
- The host's own obligations here — asking at connect, never publishing `not-asked` when it does,
4477
+ The agent application's own obligations here — asking at connect, never publishing `not-asked` when it does,
4473
4478
  publishing a state and not a flicker — are Omni's tests' to hold. `exerciseAdapter` holds the
4474
- other side: it validates the shape of whatever host a test hands the adapter, requires `audio` on
4479
+ other side: it validates the shape of whatever agent application a test hands the adapter, requires `audio` on
4475
4480
  a softphone login and none elsewhere -- not on a desk phone, not off voice
4476
4481
  (`context.host.audio.required` / `.unexpected`), holds `host.mute` to the same line (`host.mute.required`
4477
4482
  / `.unexpected`, `host.mute` for a third word) -- and refuses a voice adapter that never asked the
4478
- host anything (`connection.host.consulted`), and one that subscribed to nothing will never hear of a
4483
+ agent application anything (`connection.host.consulted`), and one that subscribed to nothing will never hear of a
4479
4484
  change (`connection.host.subscribed`): the obligation has two halves, and each is held.
4480
4485
 
4481
4486
  ### Capacity around setup
@@ -4486,8 +4491,8 @@ set up — the adapter's own registration incomplete, its credentials not yet re
4486
4491
 
4487
4492
  Nothing closes that window, because nothing opens it: **Omni states no capacity until the
4488
4493
  connection is established**, and **Work is pulled, never pushed** makes an allocation with none
4489
- stated a violation. Capacity does not wait on the microphone: whether an agent without host audio
4490
- can take calls is the platform's question, answered by the adapter from the host's report, not by
4494
+ stated a violation. Capacity does not wait on the microphone: whether an agent without agent application audio
4495
+ can take calls is the platform's question, answered by the adapter from the agent application's report, not by
4491
4496
  Omni withholding capacity for every platform alike.
4492
4497
 
4493
4498
  Capacity follows **automatically** once the connection is established; the agent does not press
@@ -4496,7 +4501,7 @@ anything to become available.
4496
4501
  | Situation | What Omni sends |
4497
4502
  | --- | --- |
4498
4503
  | Connecting | Nothing. No capacity has been stated, so nothing may be allocated. |
4499
- | Connected and idle | `setCapacity({ count: n })`, with the host's report already available to consult. |
4504
+ | Connected and idle | `setCapacity({ count: n })`, with the agent application's report already available to consult. |
4500
4505
  | A task starts or ends | Nothing. The provider counts its own against the ceiling. |
4501
4506
  | The agent's provisioned capacity changes | `setCapacity({ count: n })` |
4502
4507
  | Agent asks for a break | `requestBreak`. Capacity is unchanged and work continues. |
@@ -4512,57 +4517,57 @@ a return.
4512
4517
 
4513
4518
  ### How the agent hears the call
4514
4519
 
4515
- A voice platform can put an agent on a **softphone**, where the call's audio lands in the host
4520
+ A voice platform can put an agent on a **softphone**, where the call's audio lands in the agent application
4516
4521
  and Omni owns the microphone and the playback, or on a **desk phone**, a handset on the platform's
4517
- switch that the platform rings, where the host owns no audio and only shows the call. Which of
4522
+ switch that the platform rings, where the agent application owns no audio and only shows the call. Which of
4518
4523
  these a platform can do is a fact about the platform, and which one a login is on is a choice the
4519
- host makes for that agent -- so the manifest declares and the host chooses.
4524
+ agent application makes for that agent -- so the manifest declares and the agent application chooses.
4520
4525
 
4521
4526
  ```ts
4522
4527
  // Manifest: what the platform can do
4523
4528
  phones: ["softphone", "deskPhone"]
4524
- // The host, at authentication and again at connect: which one this login is on
4529
+ // The agent application, at authentication and again at connect: which one this login is on
4525
4530
  { phone: "softphone" }
4526
4531
  ```
4527
4532
 
4528
4533
  A voice manifest lists its `phones` and any other channel lists none (`manifest.phones.required`,
4529
- `manifest.phones.channel`). The host's `phone` is required on a voice login, absent on any other,
4534
+ `manifest.phones.channel`). The agent application's `phone` is required on a voice login, absent on any other,
4530
4535
  and one the manifest listed (`context.phone.required`, `.unexpected`, `.unsupported`). Everything
4531
- about audio then follows the phone rather than the channel: on a softphone the host reports its
4536
+ about audio then follows the phone rather than the channel: on a softphone the agent application reports its
4532
4537
  audio, the adapter implements `openMedia`, and `task-media-started` is the word to open it; on a
4533
- desk phone the host reports no audio, opens nothing, and `task-media-started` still marks the
4538
+ desk phone the agent application reports no audio, opens nothing, and `task-media-started` still marks the
4534
4539
  moment the call is live so the desk shows it, with the sound on the handset. A platform that lists
4535
4540
  `deskPhone` alone never implements `openMedia`; one that lists `softphone` always does.
4536
4541
 
4537
- **The mode comes from the host; the status comes from the provider.** The host knows which kind
4542
+ **The mode comes from the agent application; the status comes from the provider.** The agent application knows which kind
4538
4543
  of station the agent signed in at, because the person chose it, and nothing else can know that.
4539
4544
  The provider knows whether that station can carry a call right now -- whether a handset is
4540
- registered -- which a host in a browser cannot see. So the host's `phone` selects the branch, and
4545
+ registered -- which an agent application in a browser cannot see. So the agent application's `phone` selects the branch, and
4541
4546
  the provider's own knowledge of the device decides readiness within it. A provider never overrides
4542
- the host's declaration from its device record: treating a desk-phone login as a softphone because
4547
+ the agent application's declaration from its device record: treating a desk-phone login as a softphone because
4543
4548
  the handset is momentarily unregistered, and demanding a microphone of it, is the reading this
4544
4549
  sentence exists to refuse. What the provider does when the handset is not registered is what it
4545
4550
  does for any station that cannot take a call -- hold the agent not-ready and say why.
4546
4551
 
4547
- **On a desk-phone login the host never calls `openMedia`.** There is no stream to hand over and
4548
- no audio to attach; a host that calls it anyway is in error, and an adapter that receives the call
4552
+ **On a desk-phone login the agent application never calls `openMedia`.** There is no stream to hand over and
4553
+ no audio to attach; an agent application that calls it anyway is in error, and an adapter that receives the call
4549
4554
  answers `unavailable` with a non-retryable failure, since waiting changes nothing about a station
4550
4555
  that is a telephone. The harness requires no `openMedia` of such an adapter and never calls it.
4551
4556
 
4552
4557
  **Which handset a desk-phone login rings is the platform's configuration for that agent**, and
4553
- this wire never asks the agent for it: a host declares `phone` and nothing more. What a platform
4558
+ this wire never asks the agent for it: an agent application declares `phone` and nothing more. What a platform
4554
4559
  asks on surfaces of its own is its own decision.
4555
4560
 
4556
4561
  **A declared phone the platform does not permit for this agent is a login that cannot be
4557
4562
  established.** The manifest says what the platform can do; the agent's record, kept by an
4558
- administrator, says what this agent is configured for, and the two can disagree with the host's
4563
+ administrator, says what this agent is configured for, and the two can disagree with the agent application's
4559
4564
  declaration -- a softphone declared for an agent whose record says desk phone. Honouring that
4560
4565
  declaration on a switch that allows one registration per endpoint would evict the handset: the
4561
4566
  agent's phone stops ringing and their calls land in a tab, and nobody is told. So the provider
4562
- refuses the login at authentication, with `omni.phone-not-permitted` and a message the host shows
4567
+ refuses the login at authentication, with `omni.phone-not-permitted` and a message the agent application shows
4563
4568
  -- "this agent is configured for a desk phone" -- and refusing is correct, not an override of the
4564
- host. It is a refusal, never a negotiation afterwards and never a quiet substitution, and it is
4565
- never retryable: trying again does not reconfigure the agent, and a host validating the answer
4569
+ agent application. It is a refusal, never a negotiation afterwards and never a quiet substitution, and it is
4570
+ never retryable: trying again does not reconfigure the agent, and an agent application validating the answer
4566
4571
  (`validateAuthenticationResult`) refuses a phone refusal marked otherwise
4567
4572
  (`authentication.failure.phone.retryable`). And **a
4568
4573
  provider never makes a declared phone true by changing the platform's configuration**: the record
@@ -4581,9 +4586,9 @@ openMedia({ taskId, localAudio }): Promise<OpenMediaResult>
4581
4586
  The adapter speaks whatever its platform speaks — SIP over WebSocket, a vendor SDK, plain
4582
4587
  WebRTC — and **none of that appears in this contract**. Registration, signalling, credential
4583
4588
  renewal and reconnect are the adapter's, exactly as its authentication and transport already
4584
- are. Omni owns what belongs to the host: the microphone, the output element, mute, and when a
4589
+ are. Omni owns what belongs to the agent application: the microphone, the output element, mute, and when a
4585
4590
  session ends — owning the microphone meaning capturing it, prompting, retrying and reporting how
4586
- it stands, never deciding for the adapter what a missing one means (see **The host reports, the
4591
+ it stands, never deciding for the adapter what a missing one means (see **The agent application reports, the
4587
4592
  adapter decides**).
4588
4593
 
4589
4594
  | Member | Contract |
@@ -4592,9 +4597,9 @@ adapter decides**).
4592
4597
  | `setMuted(muted)` | Mutes the agent's microphone on this session. |
4593
4598
  | `close()` | Releases the session. Omni calls it when the task ends. |
4594
4599
 
4595
- `localAudio` is the agent's microphone as Omni captured it, the same stream the host's report
4600
+ `localAudio` is the agent's microphone as Omni captured it, the same stream the agent application's report
4596
4601
  carries as `audio.input.localAudio`, and absent while that input is `unavailable`. A provider that
4597
- bridges audio without a host-side input may ignore it; one that needs it and finds it absent
4602
+ bridges audio without an application-side input may ignore it; one that needs it and finds it absent
4598
4603
  answers `unavailable` with a failure Omni shows the agent.
4599
4604
 
4600
4605
  **When to ask is the provider's word, not Omni's guess.** On a softphone login, Omni opens media on `task-media-started`,
@@ -4632,87 +4637,87 @@ command asks the provider to **perform** something: `hold`, `transfer`, `confere
4632
4637
  Provider-targeted `recording` commands and the rest act on the platform's own call leg, its bridge, or its record of the
4633
4638
  task. Nothing has happened until the provider applies them, and `failed` means nothing happened.
4634
4639
 
4635
- **The provider performs every action; the host only offers it.** A control drawn on the host is
4636
- an affordance, never the enforcement: the host asks, and the provider does or declines. A provider
4640
+ **The provider performs every action; the agent application only offers it.** A control drawn on the agent application is
4641
+ an affordance, never the enforcement: the agent application asks, and the provider does or declines. A provider
4637
4642
  answers `failed` for a command whose capability it did not publish, and that is the provider
4638
- honouring its own declaration, not the host deciding policy -- a host that refuses a command on
4643
+ honouring its own declaration, not the agent application deciding policy -- an agent application that refuses a command on
4639
4644
  its own reading of a queue's flag has decided something that was never its to decide. What a
4640
4645
  command means on the platform is the provider's to work out: `end-call` disconnects the caller channel, and
4641
- which legs on which bridge that touches is a fact about the switch, never a choice the host makes.
4642
- The one thing the host performs physically is the microphone, and that is not a command at all.
4646
+ which legs on which bridge that touches is a fact about the switch, never a choice the agent application makes.
4647
+ The one thing the agent application performs physically is the microphone, and that is not a command at all.
4643
4648
 
4644
- ### The station is the host's
4649
+ ### The station is the agent application's
4645
4650
 
4646
4651
  The microphone, the speaker, the headset and its buttons are the station's, and the station is the
4647
- host's. So mute is not a capability a provider declares, not a control a queue allows or a team
4652
+ agent application's. So mute is not a capability a provider declares, not a control a queue allows or a team
4648
4653
  locks, not a preference the person keeps with the provider, and not a command: nothing about the
4649
- station crosses to the provider except two things -- the station's condition, in the host report,
4650
- and the record of when the agent could not be heard, through `recordStep`. A host offers Mute on
4651
- every voice task with media open, under its own provisioning, in `in-progress` and `paused`
4654
+ station crosses to the provider except two things -- the station's condition, in the agent application report,
4655
+ and the record of when the agent could not be heard, through `recordStep`. An agent application offers Mute on
4656
+ every voice task with media open, under its own local policy, in `in-progress` and `paused`
4652
4657
  alone, and performs it through `VoiceMediaSession.setMuted()`. A task carrying
4653
4658
  `capabilities.mute` is refused (`task.capability.unknown`), and so is a `mute` command
4654
4659
  (`command.type`), a `mute` preference (`preference.id`) and a `mute` policy (`team.policy.key`).
4655
4660
 
4656
- **Two mutes, and the host states which its Mute performs.** A *stream* mute stops the audio the
4657
- host sends: the microphone keeps capturing, the party hears silence, nothing else on the machine
4658
- changes, and every softphone host can do it. A *station* mute silences the microphone itself at
4661
+ **Two mutes, and the agent application states which its Mute performs.** A *stream* mute stops the audio the
4662
+ agent application sends: the microphone keeps capturing, the party hears silence, nothing else on the machine
4663
+ changes, and every softphone agent application can do it. A *station* mute silences the microphone itself at
4659
4664
  the operating system: every application on the machine goes quiet, the system shows it, and a
4660
- headset that follows the system follows it. Only a native host can do it. `Host.mute` says which
4661
- this host does -- `stream` or `station` -- stated on a softphone login, where the host holds the
4665
+ headset that follows the system follows it. Only a native agent application can do it. `Host.mute` says which
4666
+ this agent application does -- `stream` or `station` -- stated on a softphone login, where the agent application holds the
4662
4667
  microphone, and absent on a desk phone and off voice (`host.mute.required` / `.unexpected`). A
4663
- browser says `stream`. A native host says whichever it does. Nothing on the wire says what kind of
4664
- application the host is; a provider reads only what the host declared.
4668
+ browser says `stream`. A native agent application says whichever it does. Nothing on the wire says what kind of
4669
+ application the agent application is; a provider reads only what the agent application declared.
4665
4670
 
4666
4671
  **A silenced device says who silenced it.** `audio.input.flowing: false` and
4667
- `audio.output.flowing: false` carry `mutedBy`: `host` when the host's own Mute did it -- which is
4668
- only ever true of a host whose mute is `station`, since a stream mute leaves the microphone
4669
- flowing -- and `station` when a slider on the headset or the operating system did, which the host
4670
- observed and did not do. Without the word, a station-muting host's own Mute would read as a fault
4672
+ `audio.output.flowing: false` carry `mutedBy`: `host` when the agent application's own Mute did it -- which is
4673
+ only ever true of an agent application whose mute is `station`, since a stream mute leaves the microphone
4674
+ flowing -- and `station` when a slider on the headset or the operating system did, which the agent application
4675
+ observed and did not do. Without the word, a station-muting agent application's own Mute would read as a fault
4671
4676
  and an adapter would take the agent out of ready in the middle of a call. A browser reads a station
4672
- mute through the capture track's muted state, read-only, and cannot lift it; a native host reads
4677
+ mute through the capture track's muted state, read-only, and cannot lift it; a native agent application reads
4673
4678
  the endpoint and can clear an operating-system mute. A hardware slider is nobody's to clear.
4674
4679
 
4675
4680
  **The record carries the same word.** A `muted` interaction leg is a period the agent could not be
4676
- heard, and the record exists so that period is not a hole. The host reports every such period
4681
+ heard, and the record exists so that period is not a hole. The agent application reports every such period
4677
4682
  through `recordStep` -- its own Mute, and a station mute it observed during a call -- with
4678
4683
  `mutedBy` saying whose the silence was, and the provider writes the word into the entry
4679
- (`task.interactionHistory.mutedBy`). The report names no agent because the host has exactly one, and
4684
+ (`task.interactionHistory.mutedBy`). The report names no agent because the agent application has exactly one, and
4680
4685
  the provider knows who that is: it attributes the leg to the login's agent in `by`, a fact it
4681
- holds and not an inference, for a station mute as much as for the host's own. An unattributed
4686
+ holds and not an inference, for a station mute as much as for the agent application's own. An unattributed
4682
4687
  `muted` entry is refused (`task.interactionHistory.muted.by`); a shared handset's unattributed hold
4683
4688
  is a different claim, and stands. A supervisor reading the record then sees "the agent muted for
4684
4689
  forty seconds" and "the agent's headset was muted for forty seconds" as the different things they
4685
- are. See **The host records what it performs**.
4690
+ are. See **The agent application records what it performs**.
4686
4691
 
4687
4692
  **Mute has a lifecycle, and none of it is inferred.** A call that starts while the station is
4688
4693
  already muted begins a `muted` leg the moment its media starts, `mutedBy: "station"`. Media that
4689
- ends while any leg is open ends the leg at that instant, as every host-performed leg ends. And the
4690
- host's own Mute starts off on every call, which is every `task-media-started` -- a connect-back
4694
+ ends while any leg is open ends the leg at that instant, as every agent application-performed leg ends. And the
4695
+ agent application's own Mute starts off on every call, which is every `task-media-started` -- a connect-back
4691
4696
  opens a second call on the same task with no offer -- so an agent is never muted by the call before.
4692
4697
 
4693
- **Every press on a headset is the agent's own press**, performed the host's way, and the lights
4694
- follow the host's state. The `personConsent` guarantee is honoured by a hook-switch press exactly
4698
+ **Every press on a headset is the agent's own press**, performed the agent application's way, and the lights
4699
+ follow the agent application's state. The `personConsent` guarantee is honoured by a hook-switch press exactly
4695
4700
  as by a click. What a call-control headset sends, and what becomes of it:
4696
4701
 
4697
- | Input | Where it comes from | What the host does | What crosses to the provider |
4702
+ | Input | Where it comes from | What the agent application does | What crosses to the provider |
4698
4703
  | --- | --- | --- | --- |
4699
- | Mute button | The headset, on the HID Telephony usage page: a Phone Mute report on the press, a Mute LED the host writes back | A press of the host's Mute, performed the host's way; the LED follows the host's state, so button, light and control are one state with one owner | The `muted` leg, `mutedBy: "host"` |
4700
- | Hook switch | The headset, HID Telephony | A press of the host's Answer or End call, only where the task is in a phase that has one; the off-hook and ring lights follow the task | The existing `answer` and `end-call` commands |
4704
+ | Mute button | The headset, on the HID Telephony usage page: a Phone Mute report on the press, a Mute LED the agent application writes back | A press of the agent application's Mute, performed the agent application's way; the LED follows the agent application's state, so button, light and control are one state with one owner | The `muted` leg, `mutedBy: "host"` |
4705
+ | Hook switch | The headset, HID Telephony | A press of the agent application's Answer or End call, only where the task is in a phase that has one; the off-hook and ring lights follow the task | The existing `answer` and `end-call` commands |
4701
4706
  | Flash, redial, speed dial | Older headsets and desk-phone style devices | Flash is Hold and Resume where the task offers `hold`; redial and speed dial map to nothing on a desk with no dial pad on a transfer, and are ignored | Nothing new |
4702
- | Volume up and down | The headset's own amplifier, or the operating system through the consumer-control keys | Nothing: the device and the system handle it | Nothing, except that a speaker at nought is `audio.output.flowing: false` where the host can know it |
4707
+ | Volume up and down | The headset's own amplifier, or the operating system through the consumer-control keys | Nothing: the device and the system handle it | Nothing, except that a speaker at nought is `audio.output.flowing: false` where the agent application can know it |
4703
4708
  | Microphone gain and level | The operating system, the headset's own boost | A level meter, so the agent can see they are heard | Nothing: a level is a flicker, not a state |
4704
- | Hardware or operating-system mute | A slider on the headset, the system's input mute | Observes it, publishes `flowing: false, mutedBy: "station"`, records the leg during a call, and tells the agent which it is where it knows -- headset or system -- and what to do; a host whose mute is `station` clears a system mute itself, a browser can only say so | The report and the leg |
4709
+ | Hardware or operating-system mute | A slider on the headset, the system's input mute | Observes it, publishes `flowing: false, mutedBy: "station"`, records the leg during a call, and tells the agent which it is where it knows -- headset or system -- and what to do; an agent application whose mute is `station` clears a system mute itself, a browser can only say so | The report and the leg |
4705
4710
  | Device changed, unplugged, permission revoked | The operating system | Re-capture, prompt, report | Already `audio.input` and `audio.output` with `lost`, `denied`, `no-device` |
4706
4711
 
4707
- **What the host shows.** Beside Mute, a standing line while the station is muted, saying which and
4708
- what to do, with a button that clears a system mute only on a host whose mute is `station`. The
4712
+ **What the agent application shows.** Beside Mute, a standing line while the station is muted, saying which and
4713
+ what to do, with a button that clears a system mute only on an agent application whose mute is `station`. The
4709
4714
  Mute control does not pretend: while the station is muted it shows the agent cannot be heard and
4710
- that pressing it will not change that, and a press still toggles the host's own mute, so the two
4715
+ that pressing it will not change that, and a press still toggles the agent application's own mute, so the two
4711
4716
  states stay separate and the agent is not unmuted by surprise when the slider moves back. Before a
4712
4717
  call, the same line in the ready state, so an agent does not learn of it from a silent customer;
4713
4718
  whether work is held back is the adapter's decision from the report, as it is for every station
4714
4719
  fact. Where a provider's own platform holds a mute of its own -- a bridge that silences a leg --
4715
- that is a fact about the switch, reported as the provider sees fit, and never the host's Mute.
4720
+ that is a fact about the switch, reported as the provider sees fit, and never the agent application's Mute.
4716
4721
 
4717
4722
  ### Which commands need a capability
4718
4723
 
@@ -4725,7 +4730,7 @@ declared:
4725
4730
  | `answer`, `accept` | Nothing. A task that was offered can be accepted, or offering it meant nothing. |
4726
4731
  | `end-call` | The `endCall` capability. |
4727
4732
  | `conference` with `action: "remove"` | The `conference` capability, and somebody else on the call: a remove that would leave the agent alone is `end-call`, and a provider answers it `failed`. |
4728
- | `decline` | The `decline` capability on any channel, **and** Omni provisioning permitting it. One word for refusing an offer, whatever the channel. |
4733
+ | `decline` | The `decline` capability on any channel, **and** Omni local policy permitting it. One word for refusing an offer, whatever the channel. |
4729
4734
  | `call` | The `preview` phase. A record put in front of an agent is there to be called, so the phase is the gate and there is no capability. It is a dial, with a `dialId` and a `dial-outcome`. |
4730
4735
  | `complete` | `completionMode: "agent-command"`. The `outcomes` capability decides whether a code travels with the command, never whether the command exists — a task Omni cannot complete never ends. What travels is what the capability published: a code from its list where it has one (`command.complete.outcome.unknown`), a code at all where it requires one (`.outcome.required`), notes as it said (`.notes.required`, `.notes.unexpected`), and neither where the task declares no outcomes (`.outcome.unexpected`). |
4731
4736
  | `connect-back` | The `connectBack` capability **and** the `completing` phase. It exists to reach the party again after the call, so it has no meaning while the call is up. |
@@ -4751,10 +4756,10 @@ The commands with a phase of their own -- `answer`, `accept` and `decline` in `p
4751
4756
 
4752
4757
  `validateTaskCommand(command, task)` holds a command to this table at runtime, both ways: the
4753
4758
  capability it needs, the phase it belongs to, and the state that has to stand. The task it wants
4754
- is the one the provider published, not a host's own mapping of it: a host that keeps only its
4759
+ is the one the provider published, not an agent application's own mapping of it: an agent application that keeps only its
4755
4760
  mapped shape has nothing honest to pass, and then checks shape alone, which is still worth doing
4756
4761
  -- it names a command the wire never had -- but is not the table. Keeping the published task
4757
- beside the mapped one is what the full check costs a host; an adapter has it for free. The
4762
+ beside the mapped one is what the full check costs an agent application; an adapter has it for free. The
4758
4763
  validator holds a command only to a task that stands: a task handed in that is not one the wire
4759
4764
  published is named (`command.task`) rather than checked against.
4760
4765
 
@@ -4806,7 +4811,7 @@ react rather than only display the message:
4806
4811
  | `omni.not-authenticated` | The provider session is no longer usable. The adapter has published `expired` at or before this answer — the state is what Omni surfaces reauthentication from; the code says why this action failed, and is never the only signal. |
4807
4812
  | `omni.capability-not-enabled` | The action targets a capability this task, manifest, or login did not declare — including a lead command from a login whose `capabilities` no longer carry it. |
4808
4813
  | `omni.task-not-found` | The provider-local task id is unknown, typically after the task already ended. |
4809
- | `omni.phone-not-permitted` | The host declared a `phone` the platform does not permit for this agent -- a softphone for an agent configured for a desk phone, or the reverse. The login is refused at authentication, and the provider never reconfigures the agent to make the declaration true. See **How the agent hears the call**. |
4814
+ | `omni.phone-not-permitted` | The agent application declared a `phone` the platform does not permit for this agent -- a softphone for an agent configured for a desk phone, or the reverse. The login is refused at authentication, and the provider never reconfigures the agent to make the declaration true. See **How the agent hears the call**. |
4810
4815
  | `omni.destination-not-permitted` | The dialled number, or the `destinationId` named, is not one the provider offers this agent. |
4811
4816
  | `omni.rate-limited` | The action was throttled. Pair with `retryAfterMs`. |
4812
4817
  | `omni.unavailable` | The provider is temporarily unable to serve the action, including any command sent while `transport-status` is not `active`. |
@@ -4820,7 +4825,7 @@ They are published as `OMNI_FAILURE_CODES`.
4820
4825
 
4821
4826
  | Field | Contract |
4822
4827
  | --- | --- |
4823
- | `id` | Required identifier for this event, unique within the login. Omni does not act on it; it exists so a host log line and an adapter log line can be matched when something has to be traced. |
4828
+ | `id` | Required identifier for this event, unique within the login. Omni does not act on it; it exists so an agent application log line and an adapter log line can be matched when something has to be traced. |
4824
4829
  | `loginId` | Login session that produced the event. Omni rejects any other value, which only reaches it if an adapter kept an old connection emitting after a re-login. |
4825
4830
  | `occurredAt` | Valid RFC-3339 timestamp with an explicit timezone, representing provider observation time. |
4826
4831
  | `event` | Typed `ProviderEvent` payload. |
@@ -4835,7 +4840,7 @@ instant that the source cannot establish makes that evidence unavailable, not pe
4835
4840
  invent a timestamp or silently omit a required field.
4836
4841
 
4837
4842
  Clock estimation is an exception, not the standard interpretation of events. An ISO timestamp
4838
- identifies an instant; it does not prove that the host and provider clocks are synchronized.
4843
+ identifies an instant; it does not prove that the agent application and provider clocks are synchronized.
4839
4844
  Use an explicitly trusted clock in the relevant domain. Do not infer a general clock offset
4840
4845
  from event arrivals, shift source timestamps, or use an estimate to order events or create history.
4841
4846
 
@@ -4843,29 +4848,29 @@ The current exceptions and their reasons are:
4843
4848
 
4844
4849
  | Case | Exception and reason |
4845
4850
  | --- | --- |
4846
- | Host display of provider deadlines (`allocationExpiresAt`, `previewEndsAt`, wrap deadline) | A countdown may use an explicitly bounded provider-clock estimate when a trusted direct clock is unavailable, because the deadline belongs to another clock domain. This estimates the display only; it does not establish that the provider acted. Without usable time, show timing uncertainty. |
4847
- | Host-triggered preview deadline | A bounded clock estimate with monotonic aging may schedule the host's Call command because the provider owns the deadline but the host owns the trigger. Do not trigger before the deadline is known to have passed; invalidate on clock discontinuity and reconcile when uncertain. |
4851
+ | Agent application display of provider deadlines (`allocationExpiresAt`, `previewEndsAt`, wrap deadline) | A countdown may use an explicitly bounded provider-clock estimate when a trusted direct clock is unavailable, because the deadline belongs to another clock domain. This estimates the display only; it does not establish that the provider acted. Without usable time, show timing uncertainty. |
4852
+ | Agent application-triggered preview deadline | A bounded clock estimate with monotonic aging may schedule the agent application's Call command because the provider owns the deadline but the agent application owns the trigger. Do not trigger before the deadline is known to have passed; invalidate on clock discontinuity and reconcile when uncertain. |
4848
4853
  | Recording evidence expiry | A bounded observer-domain clock estimate with monotonic aging may assess freshness because observation and expiry belong to the recorder's clock. If time cannot be trusted, recording state is unknown; never renew evidence from receipt or replay. |
4849
4854
  | Unknown recording state | `observedAt` and `validUntil` are absent because there is no confirmed observation. The containing provider event still has its own `occurredAt`; that publication is not a recorder observation. |
4850
4855
  | Direct snapshot reads and method requests/results | These are reads/operations, not event envelopes, and their current types have no general event timestamp. A snapshot event still carries `occurredAt`; embedded source instants remain unchanged. Do not treat a method result or read completion time as an occurrence boundary. |
4851
- | Host-provided provider-clock estimate | Best-effort ISO time may be supplied by the host for optional comparisons; it is not a source observation or accuracy guarantee. The reason is that the host does not own the provider clock. |
4852
- | Provider receipt timestamps | The provider may use its own receipt instant for final records of receipt/processing because host timestamps are untrusted advisory input. Receipt must not be presented as an earlier action or capture boundary. |
4853
- | Optional source instants and deadlines | Omit only where the declared type permits absence and the source has no evidence or the policy has no deadline (for example unlimited preview). Do not replace absence with host time. |
4856
+ | Agent application-provided provider-clock estimate | Best-effort ISO time may be supplied by the agent application for optional comparisons; it is not a source observation or accuracy guarantee. The reason is that the agent application does not own the provider clock. |
4857
+ | Provider receipt timestamps | The provider may use its own receipt instant for final records of receipt/processing because agent application timestamps are untrusted advisory input. Receipt must not be presented as an earlier action or capture boundary. |
4858
+ | Optional source instants and deadlines | Omit only where the declared type permits absence and the source has no evidence or the policy has no deadline (for example unlimited preview). Do not replace absence with agent application time. |
4854
4859
 
4855
4860
  Every additional exception must be listed with its scope and reason before adoption. Estimates
4856
4861
  must specify their uncertainty and validity; elapsed time should use monotonic aging, and a clock
4857
4862
  jump invalidates the estimate. The optional check below samples provider time without changing event timestamps. Report
4858
4863
  source-measured durations where required; timestamp subtraction is not a substitute.
4859
4864
 
4860
- #### Optional periodic provider time checks and host estimates
4865
+ #### Optional periodic provider time checks and agent application estimates
4861
4866
 
4862
4867
  A provider may declare `Manifest.timeCheck: true` and implement `Connection.checkTime(request)`.
4863
- Omission means unsupported. The host separately opts in with `ProviderTimeCheckPolicy`; these
4864
- host-local settings are not task policy or a guarantee. All four durations are explicit positive
4868
+ Omission means unsupported. The agent application separately opts in with `ProviderTimeCheckPolicy`; these
4869
+ agent application-local settings are not task policy or a guarantee. All four durations are explicit positive
4865
4870
  safe integer milliseconds, with `maxRoundTripMs <= timeoutMs <= intervalMs`. No default interval
4866
4871
  is assumed. Validate settings with `validateProviderTimeCheckPolicy`.
4867
4872
 
4868
- While the connection is active, the host checks immediately on opt-in and then at `intervalMs`
4873
+ While the connection is active, the agent application checks immediately on opt-in and then at `intervalMs`
4869
4874
  using a monotonic scheduler. Only one check may be outstanding. Missed ticks are skipped, never
4870
4875
  replayed in a burst. Each request has a fresh ID. The provider samples its own event/deadline
4871
4876
  clock after receiving the request and before returning `providerTime` as an ISO/RFC3339 instant,
@@ -4874,25 +4879,25 @@ may masquerade as provider time. A provider unable to sample that domain must no
4874
4879
  Clock authority replacement or a discontinuity changes `clockId`.
4875
4880
 
4876
4881
  Validate requests and responses with `validateProviderTimeCheckRequest` and
4877
- `validateProviderTimeCheckResult`. The host also checks the outstanding request, provider/connection
4882
+ `validateProviderTimeCheckResult`. The agent application also checks the outstanding request, provider/connection
4878
4883
  and login, monotonic elapsed time and cancellation after the await: a late successful response is
4879
4884
  still rejected. Reject samples at or beyond `timeoutMs`, or above `maxRoundTripMs`. Cancel local
4880
4885
  tracking and invalidate estimates on disconnect, logout, policy disable, clock change or clock
4881
4886
  jump; late results cannot restore them. Resume with a fresh check after reconnection. Expire a
4882
- sample at `maxSampleAgeMs` using monotonic elapsed time. Failure is visible through the host's
4887
+ sample at `maxSampleAgeMs` using monotonic elapsed time. Failure is visible through the agent application's
4883
4888
  existing diagnostic path, with the estimate unavailable; the next scheduled check can recover.
4884
4889
  Checking failure alone does not assert call/recording state or require a healthy connection to close.
4885
4890
  This read-only check is not a task command. Protocol supplies declarations and validators; the
4886
- host implements the scheduler and the provider implements the clock read.
4891
+ agent application implements the scheduler and the provider implements the clock read.
4887
4892
 
4888
- The host may also expose `Host.estimateProviderTime({ providerId, loginId })`. It returns an ISO
4893
+ The agent application may also expose `Host.estimateProviderTime({ providerId, loginId })`. It returns an ISO
4889
4894
  `at` in that provider's clock domain, the same explicit scope and `clockId`, or `undefined` when
4890
4895
  unavailable. Optional `uncertaintyMs` is an estimate, not a guaranteed bound. The method is optional
4891
- at the host level and is deliberately absent from `HostGuarantees`. A provider declaring time
4892
- checks does not require the host to expose estimates, and an estimate need not originate from
4893
- this check if the host has another explicitly configured source for that provider clock.
4896
+ at the agent application level and is deliberately absent from `HostGuarantees`. A provider declaring time
4897
+ checks does not require the agent application to expose estimates, and an estimate need not originate from
4898
+ this check if the agent application has another explicitly configured source for that provider clock.
4894
4899
 
4895
- To estimate the difference, the host brackets the request with local send/receive instants and
4900
+ To estimate the difference, the agent application brackets the request with local send/receive instants and
4896
4901
  measures elapsed time monotonically. For provider sample P and local bracketing instants H0/H1,
4897
4902
  the offset under stable clocks lies between P-H1 and P-H0, before clock error and timestamp
4898
4903
  precision are considered. A midpoint is only an estimate; one-way delays need not be symmetric.
@@ -4901,22 +4906,22 @@ sample with monotonic elapsed time, and return unavailable after its configured
4901
4906
  `validateProviderTimeEstimate` checks shape and scope, not actual accuracy or freshness.
4902
4907
 
4903
4908
  A provider may declare `Manifest.timestampAuthority: "provider"`: its own timestamps are
4904
- used for final records, and host-supplied timestamps are advisory. This declaration is independent
4905
- of time-check support and the optional host estimate; neither changes who owns the final record.
4906
- Omission makes no promise that host timestamps will be trusted. No host-authoritative default
4909
+ used for final records, and agent application-supplied timestamps are advisory. This declaration is independent
4910
+ of time-check support and the optional agent application estimate; neither changes who owns the final record.
4911
+ Omission makes no promise that agent application timestamps will be trusted. No agent application-authoritative default
4907
4912
  is inferred. Successful `recordStep` responses identify the provider-selected history instant;
4908
- see **The host records what it performs** for correlation and retained bindings.
4913
+ see **The agent application records what it performs** for correlation and retained bindings.
4909
4914
 
4910
- A provider need not trust or adopt any host-supplied timestamp. It may timestamp an incoming
4915
+ A provider need not trust or adopt any agent application-supplied timestamp. It may timestamp an incoming
4911
4916
  message using its own clock at receipt and use that for its own processing/accounting. The reason
4912
- for this exception is that host clocks and host estimates are not authoritative at the provider.
4913
- Receipt time must be described as receipt/observation time, not relabeled as the original host
4917
+ for this exception is that agent application clocks and agent application estimates are not authoritative at the provider.
4918
+ Receipt time must be described as receipt/observation time, not relabeled as the original agent application
4914
4919
  action, recorder capture boundary, or proof an operation applied. An existing field with a
4915
4920
  specific occurrence meaning still requires that evidence; this option does not silently redefine
4916
- it. Host-only instants remain advisory input; the provider owns its authoritative publication.
4921
+ it. Agent application-only instants remain advisory input; the provider owns its authoritative publication.
4917
4922
 
4918
- This host estimate is another explicit timestamp exception: it helps optional displays and
4919
- provider-clock comparisons when the host lacks that clock directly. It is not a source occurrence,
4923
+ This agent application estimate is another explicit timestamp exception: it helps optional displays and
4924
+ provider-clock comparisons when the agent application lacks that clock directly. It is not a source occurrence,
4920
4925
  may not replace event/history timestamps, and alone cannot authorize deadline actions or prove
4921
4926
  recording freshness. Uses requiring a trustworthy bound still need independently established
4922
4927
  clock accuracy/drift assumptions. It neither synchronizes the operating-system clock nor changes
@@ -4979,8 +4984,8 @@ safe for the agent to see.
4979
4984
  | `active` | The transport is up and the provider is serving this session. It is the only value under which work arrives. |
4980
4985
  | `error` | The adapter cannot serve the session and is not simply mid-reconnect. Say why in `message`, and say what revives it in `recovery` — required here, forbidden on any other status. It is not terminal: an adapter that recovers on its own still reports `connecting` and then `active`, and one that cannot is revived as `recovery` says. |
4981
4986
 
4982
- **An error names its recovery, and the host acts on that word.** The adapter knows why its session
4983
- died; the host knows how to run a login. `recovery` joins the two:
4987
+ **An error names its recovery, and the agent application acts on that word.** The adapter knows why its session
4988
+ died; the agent application knows how to run a login. `recovery` joins the two:
4984
4989
 
4985
4990
  - **`reconnect`** — the login is good and this connection is not: a backend restart, a session the
4986
4991
  platform no longer recognises. Omni calls `disconnect()` on the dead connection and then
@@ -4995,7 +5000,7 @@ died; the host knows how to run a login. `recovery` joins the two:
4995
5000
  `reconnect`, and the fresh snapshot re-establishes state. The adapter tears nothing down itself
4996
5001
  and expects nothing to carry on: the connection that reported `error` is finished.
4997
5002
 
4998
- **Patience is the host's.** An adapter in `connecting` retries for as long as it takes and never
5003
+ **Patience is the agent application's.** An adapter in `connecting` retries for as long as it takes and never
4999
5004
  has to decide when to stop. Omni owns giving up: after however long it chooses to wait, it may
5000
5005
  call `disconnect()` and either `connect()` afresh or surface the failure — so neither side waits
5001
5006
  for the other to blink.
@@ -5011,7 +5016,7 @@ authentication state, not here.
5011
5016
  adapter that leaves a stale `active` in place is telling Omni to keep waiting for work that cannot
5012
5017
  come — see **Liveness**.
5013
5018
 
5014
- **The status is seen, not merely known.** A host renders the transport's status where the agent
5019
+ **The status is seen, not merely known.** An agent application renders the transport's status where the agent
5015
5020
  works — `connecting` from the moment it is reported, `error` with what revives it — and never a
5016
5021
  healthy workspace over a transport that cannot serve it: an agent talking on a desk whose transport
5017
5022
  died was an incident, and it happened because the desk knew and did not say. The same obligation
@@ -5046,9 +5051,9 @@ snapshot. `seed(snapshot)` returns violations, which callers must check. This is
5046
5051
  tracker, not a complete production reducer: snapshot freshness, login/connection fencing and
5047
5052
  full task consistency remain separately required.
5048
5053
 
5049
- **Both sides must enforce the order.** The host validates immediately before dispatch; the
5054
+ **Both sides must enforce the order.** The agent application validates immediately before dispatch; the
5050
5055
  provider rechecks current permission and state atomically before acting. The provider validates
5051
- the resulting break/task state before publication and serializes those publications. The host
5056
+ the resulting break/task state before publication and serializes those publications. The agent application
5052
5057
  validates the envelope, transition and full task consistency before replacing local state. A
5053
5058
  request result does not optimistically advance break state, and a delayed command cannot apply
5054
5059
  to a later attempt merely because its status happens to look compatible. Keep at most one
@@ -5061,7 +5066,7 @@ Normal order is `not-requested` → `awaiting-approval` → `granted` →
5061
5066
  returns a precommit request to `not-requested`; an explicit agent end returns a committed
5062
5067
  break there. Same-state restatements are allowed. An evidenced forced break is the explicit
5063
5068
  exception to requesting/granting, and must carry its forced actor/state. Neither skipped
5064
- publication nor a host-local guess creates another exception. A later normal attempt starts
5069
+ publication nor an agent application-local guess creates another exception. A later normal attempt starts
5065
5070
  from `not-requested`, never by regressing an active break into a request.
5066
5071
 
5067
5072
  A fresh authoritative snapshot establishes a new baseline; do not run this event-transition
@@ -5102,8 +5107,8 @@ The provider's word that the task's audio should now attach. Omni calls `openMed
5102
5107
  a task carried with `media: "started"`, which is how a reconnect snapshot reattaches audio an
5103
5108
  earlier event brought — and renders the call as live from that word, never from its own senses. It
5104
5109
  precedes `openMedia` and is never a reply to it: a provider whose media state comes from the
5105
- platform, a station going in use the moment a call is answered, sends it then, before any host has
5106
- opened anything, and `openMedia` has its own answer for what the host did. It
5110
+ platform, a station going in use the moment a call is answered, sends it then, before any agent application has
5111
+ opened anything, and `openMedia` has its own answer for what the agent application did. It
5107
5112
  names a task whose work has begun, and it alternates with `task-media-ended`: media that never
5108
5113
  started cannot end, so a live call whose provider says nothing about its audio is a provider in
5109
5114
  breach, not a state a desk fills in from its own devices.
@@ -5138,7 +5143,7 @@ A successful `complete` or `transfer` command does not clear the task. Omni wait
5138
5143
  and not for ever: `applied` to a completion -- `complete`, or a lead's `take-over-call` -- says the
5139
5144
  provider has completed the task, and its `task-ended` follows within the
5140
5145
  manifest's `completionSettleMs`. A provider never answers `applied` for a completion it has not yet
5141
- performed. Past the bound the host calls `snapshot()`: a snapshot still carrying the task is a task
5146
+ performed. Past the bound the agent application calls `snapshot()`: a snapshot still carrying the task is a task
5142
5147
  held open by a provider that said it was done, and the desk shows it as unsettled -- "Completing...
5143
5148
  the provider has not confirmed" -- naming the command; a snapshot no longer carrying it clears the
5144
5149
  task, since the ending was owed and lost. The drive holds a provider to the same bound
@@ -5150,7 +5155,7 @@ recognised as the late event it is, never applied to the life now open under the
5150
5155
 
5151
5156
  ### `dial-outcome`
5152
5157
 
5153
- How a dial the host placed ended, once, either way, named by the `dialId` the host sent: `answered`,
5158
+ How a dial the agent application placed ended, once, either way, named by the `dialId` the agent application sent: `answered`,
5154
5159
  or one of the declared ways of not reaching the destination, with the switch's `reason` where it
5155
5160
  gave one. `taskId` names the task the dial was on, where there was one, and that task may already
5156
5161
  have ended. Omni shows it to the agent against the call it belonged to and does nothing else: no
@@ -5170,9 +5175,9 @@ state read that contradicted itself, a `task-ended` naming a task nobody held, a
5170
5175
  without a name. `expected` is the rule as a sentence, `observed` is what came instead, and
5171
5176
  `taskId` names the task where there is one. **Informational, never behavioural**: the provider has
5172
5177
  already done the safe thing before it speaks, and nothing in the task or break machinery reacts to
5173
- a diagnostic. It exists so that the loudness reaches a person — a host renders each one where the
5178
+ a diagnostic. It exists so that the loudness reaches a person — an agent application renders each one where the
5174
5179
  agent works and keeps a count an operator can read, because a healthy workspace over a shouting
5175
- console is the silence problem one layer up. One event per occurrence; the host counts, the
5180
+ console is the silence problem one layer up. One event per occurrence; the agent application counts, the
5176
5181
  provider does not batch. `exerciseAdapter` treats a diagnostic delivered during a run as a
5177
5182
  violation (`diagnostic.raised`): a conformance run against a platform that is breaking its rules
5178
5183
  fails loudly rather than passing with a note. A task published under `capabilitySource:
@@ -5252,18 +5257,18 @@ same exported checks are used by Omni and adapter tests so their interpretations
5252
5257
  | `validateEventEnvelope(envelope, manifest)` | Envelope identity, timestamp, and the payload for each event type. |
5253
5258
  | `validateContact(contact)` | Contact field shapes and attribute keys. Every field is optional, so this checks what is present rather than what is missing. |
5254
5259
  | `validateScheduledActivity(activity)` | Required activity fields and start/end ordering. |
5255
- | `validateHostGuarantees(guarantees)` | What a host promises: only the guarantees this contract names, each declared by presence and never `false`. The harness validates the guarantees of whatever host a test hands the adapter. |
5260
+ | `validateHostGuarantees(guarantees)` | What an agent application promises: only the guarantees this contract names, each declared by presence and never `false`. The harness validates the guarantees of whatever agent application a test hands the adapter. |
5256
5261
  | `validateProviderTimeCheckPolicy(policy)` | Explicit optional polling settings, positive safe-integer durations and round-trip/timeout/interval ordering. |
5257
- | `validateProviderTimeCheckRequest(request)` | Fresh-request shape; the host enforces actual uniqueness and outstanding-request lifetime. |
5262
+ | `validateProviderTimeCheckRequest(request)` | Fresh-request shape; the agent application enforces actual uniqueness and outstanding-request lifetime. |
5258
5263
  | `validateProviderTimeCheckResult(result, request, loginId)` | ISO timestamp, clock identity, exact request/login correlation; timing and source accuracy remain runtime checks. |
5259
- | `validateProviderTimeEstimate(estimate, scope)` | Optional host estimate shape and provider/login scope; no accuracy guarantee. |
5260
- | `validateInteractionReport(report, path?, manifest?)` | What the host reports of a leg it performed, for an adapter to check before forwarding: a task, a step, when it began, a positive `seconds` where stated, and an explicit `ended` that carries the final duration. Given the manifest, a running report is refused unless it declares `runningStepReports`. |
5261
- | `validateHostReport(report)` | The host's own report as published to an adapter: `online`, and where there is audio, an input that is `available` with the microphone and `flowing`, or `unavailable` with a reason and the failure that says why, and an output that is `available` or `unavailable` with its failure. The harness validates whatever host a test hands the adapter; `stillHost(report)` builds one that never changes. |
5262
- | `validateHostMute(mute, softphone)` | What the host's Mute does, stated on a softphone login and nowhere else: `stream` or `station` (`host.mute`), required where the host holds a microphone (`host.mute.required`) and refused where it does not (`host.mute.unexpected`). The harness holds `ConnectContext.host.mute` to it. |
5263
- | `validateLoginStore(store)` | The login's store the host hands every connection: an object with `get`, `set` and `delete` (`store.shape`, `store.get`, `.set`, `.delete`). The harness holds `ConnectContext.store` to it. |
5264
- | `validateCapacity(capacity)` | What the host states as capacity: a whole number of zero or more (`capacity.count`), zero being host-stopped. The harness states one on connect and two, one and zero after the drive, each answered `applied`, and holds any offer to the count in force (`stream.taskOffered.overCapacity`). |
5264
+ | `validateProviderTimeEstimate(estimate, scope)` | Optional agent application estimate shape and provider/login scope; no accuracy guarantee. |
5265
+ | `validateInteractionReport(report, path?, manifest?)` | What the agent application reports of a leg it performed, for an adapter to check before forwarding: a task, a step, when it began, a positive `seconds` where stated, and an explicit `ended` that carries the final duration. Given the manifest, a running report is refused unless it declares `runningStepReports`. |
5266
+ | `validateHostReport(report)` | The agent application's own report as published to an adapter: `online`, and where there is audio, an input that is `available` with the microphone and `flowing`, or `unavailable` with a reason and the failure that says why, and an output that is `available` or `unavailable` with its failure. The harness validates whatever agent application a test hands the adapter; `stillHost(report)` builds one that never changes. |
5267
+ | `validateHostMute(mute, softphone)` | What the agent application's Mute does, stated on a softphone login and nowhere else: `stream` or `station` (`host.mute`), required where the agent application holds a microphone (`host.mute.required`) and refused where it does not (`host.mute.unexpected`). The harness holds `ConnectContext.host.mute` to it. |
5268
+ | `validateLoginStore(store)` | The login's store the agent application hands every connection: an object with `get`, `set` and `delete` (`store.shape`, `store.get`, `.set`, `.delete`). The harness holds `ConnectContext.store` to it. |
5269
+ | `validateCapacity(capacity)` | What the agent application states as capacity: a whole number of zero or more (`capacity.count`), zero being agent application-stopped. The harness states one on connect and two, one and zero after the drive, each answered `applied`, and holds any offer to the count in force (`stream.taskOffered.overCapacity`). |
5265
5270
  | `validateAuthenticationResult(result, method)` | What `start()` or `complete()` answered: a challenge or a rejection, a login or a rejection. A rejection's failure is held to its rules -- an `omni.` code the contract lists, and `omni.phone-not-permitted` never retryable, since the agent's station is configuration. `validateAuthenticationFailure(failure)` is the same check on a failure alone. |
5266
- | `validateTaskCommand(command, task?)` | What a command needs to be issuable, against the task it names: its own shape -- a dial's `dialId`, a transfer's item, a remove naming exactly one person -- and, with the task, the capability the table above gates it on (`command.capability.<name>`, `.locked`), the phase it belongs to (`command.phase.*`, `command.phase.interaction` for every control on the call or the conversation), and the state that has to stand: a consulted entry, a lead requested, somebody else still on the call (`command.conference.remove.alone`). A host validates before sending and an adapter before acting. |
5271
+ | `validateTaskCommand(command, task?)` | What a command needs to be issuable, against the task it names: its own shape -- a dial's `dialId`, a transfer's item, a remove naming exactly one person -- and, with the task, the capability the table above gates it on (`command.capability.<name>`, `.locked`), the phase it belongs to (`command.phase.*`, `command.phase.interaction` for every control on the call or the conversation), and the state that has to stand: a consulted entry, a lead requested, somebody else still on the call (`command.conference.remove.alone`). An agent application validates before sending and an adapter before acting. |
5267
5272
  | `validateResult(result, method)` | What a connection method answered: the status it gives, a failure where the status says so and nowhere else, the failure's shape, and that an `omni.` code is one this contract names. |
5268
5273
  | `validateAuthenticationState(state)` | The identity each state must carry, the capabilities a usable login declares, and the expiry that only `authenticated` may. Omni applies it to every state a session publishes — the republished as much as the first. |
5269
5274
 
@@ -5289,25 +5294,25 @@ and may be compiled against a different protocol version, so its output is untru
5289
5294
  Validating a snapshot before it replaces provider state is what stops a malformed task from
5290
5295
  reaching the workspace.
5291
5296
 
5292
- ### What the host does with what it refuses
5297
+ ### What the agent application does with what it refuses
5293
5298
 
5294
5299
  A refusal has an aftermath on the desk and a report to the provider, and both are stated.
5295
5300
 
5296
- - **A refused snapshot replaces nothing.** The host keeps the last state it took from this
5301
+ - **A refused snapshot replaces nothing.** The agent application keeps the last state it took from this
5297
5302
  provider whole, and shows the provider as faulted -- the transport as it stands, and the words
5298
5303
  "last update refused" with the rule -- so the agent knows the view is standing still rather than
5299
5304
  believing it current. It does not adopt the good half of a snapshot: a task the agent is on would
5300
5305
  vanish from the desk while the call is up.
5301
- - **A refused event is dropped and counted.** The state the host holds does not move for it. The
5302
- provider is told, and may republish a corrected state or raise a `diagnostic`; the host retries
5306
+ - **A refused event is dropped and counted.** The state the agent application holds does not move for it. The
5307
+ provider is told, and may republish a corrected state or raise a `diagnostic`; the agent application retries
5303
5308
  nothing. The desk shows nothing for it: the view kept moving for every other event, so "last
5304
5309
  update refused" would be false of it, and a chip that said nothing would be right about the
5305
- transport. Counted, and the provider told, is all a host can truthfully do for one event.
5310
+ transport. Counted, and the provider told, is all an agent application can truthfully do for one event.
5306
5311
  - **The provider is told, every time.** `refused(report)` carries the artefact, the envelope id for
5307
5312
  an event, and every violation with its rule and path. An adapter logs it at error and treats it as
5308
- its own defect until shown otherwise: what the host refused never reached the agent, and a
5313
+ its own defect until shown otherwise: what the agent application refused never reached the agent, and a
5309
5314
  provider that hears nothing runs a whole shift beside a frozen desk with nothing wrong on its
5310
- side. The harness tells an adapter under test exactly as a host does
5315
+ side. The harness tells an adapter under test exactly as an agent application does
5311
5316
  (`connection.refused.required`, `connection.refused.rejected`).
5312
5317
 
5313
5318
  ## Conformance helpers
@@ -5352,18 +5357,18 @@ in each adopter's own tests. `{ drive: true }` closes that: the exercise takes t
5352
5357
  provider offers through one ordinary lifecycle -- accept it, wait for its media and open it on a
5353
5358
  softphone, hold and resume where the task offers `hold`, end the call where it offers `endCall`,
5354
5359
  complete it with an outcome where the agent completes -- and holds every step to the rules a
5355
- host holds a provider to. Each command is validated against the task as published
5360
+ agent application holds a provider to. Each command is validated against the task as published
5356
5361
  (`drive.command.*`), each answer for its method, a refusal of a control the task offered is a
5357
5362
  violation (`drive.command.failed`), and an event the provider owes and never sends is one too
5358
5363
  (`drive.timeout`, after `driveTimeoutMs`, 5000 by default). Around the drive the exercise holds
5359
- the run to what a host holds a provider to between commands: an offer before the host stated
5364
+ the run to what an agent application holds a provider to between commands: an offer before the agent application stated
5360
5365
  capacity, or beyond the count with nothing dialled on it, is named
5361
5366
  (`stream.taskOffered.beforeCapacity`, `.overCapacity`); every user the snapshot names is looked up
5362
- through `describeUsers` and the answer held to the shape, nobody unasked, nobody described as
5363
- nothing (`describeUsers.user.*`, `describeUsers.unasked`, `connection.describeUsers.empty`); and
5367
+ through `getUserDetails` and the answer held to the shape, nobody unasked, nobody described as
5368
+ nothing (`getUserDetails.user.*`, `getUserDetails.unasked`, `connection.getUserDetails.empty`); and
5364
5369
  the second adapter a `rebuild` gives comes up signed in as the same login from the secrets alone
5365
5370
  before it reads anything (`drive.reload.login`), and is then held to everything the first was on
5366
- connect: the methods its declarations call for, the host's report, a capacity stated to it, its
5371
+ connect: the methods its declarations call for, the agent application's report, a capacity stated to it, its
5367
5372
  snapshot read as the connect snapshot was, and its media opened afresh on a task carried with
5368
5373
  `media: "started"`, since the first client's session died with it. The result also says which rules the
5369
5374
  run evaluated, pass or fail, in `rulesEvaluated`: the validators' as each was applied, the stream's
@@ -5377,8 +5382,8 @@ in the completing publication or the open entry is refused (`task.interactionHis
5377
5382
  and the drive's closing report after the media ended is expected `recorded` and to change nothing:
5378
5383
  a record restated afterwards with that leg's duration altered is named (`drive.recordStep.overwritten`).
5379
5384
  Where the provider restates the task's record afterwards, each leg is in it or the hole is named
5380
- (`drive.recordStep.history`). Given `rebuild`, a way to build the adapter again as a host reload
5381
- does, the drive reloads the host as a reload happens: the first client is unsubscribed,
5385
+ (`drive.recordStep.history`). Given `rebuild`, a way to build the adapter again as an agent application reload
5386
+ does, the drive reloads the agent application as a reload happens: the first client is unsubscribed,
5382
5387
  disconnected and its session closed (`drive.reload.handover`), and only then is a second adapter
5383
5388
  built and connected for the same login with the same context and the same `store`; its snapshot
5384
5389
  must carry the task with that leg at its acknowledged provider timestamp and the reported actor, and the run goes on with the second as its
@@ -5397,8 +5402,8 @@ first client is gone before the second connects, there is no client for the plat
5397
5402
  open task back to, and nothing about the reload is exempt from any rule. The second adapter opens its session from the same
5398
5403
  `secrets`, so the reload is a restore before it is anything else: an adapter that holds a session
5399
5404
  has already put what would rebuild it into the secrets store, from the moment it was handed one,
5400
- not only when a flow completes -- the session is the adapter's, the store is the host's, and a
5401
- host reload is exactly when no flow will run. And once the task has ended, the store the drive
5405
+ not only when a flow completes -- the session is the adapter's, the store is the agent application's, and a
5406
+ agent application reload is exactly when no flow will run. And once the task has ended, the store the drive
5402
5407
  handed the adapter holds no key naming the task's id, delimited, never as a run of characters inside
5403
5408
  another id (`drive.store.retained`); an adapter whose keys never named the task leaves the rule
5404
5409
  unevaluated, and the result says so rather than passing it: a task's keys go
@@ -5456,8 +5461,8 @@ cannot be established from TypeScript structure alone.
5456
5461
  | `assertReached(result, subjects)` | The exercise met every subject named; throws listing those it did not. Pair it with a clean `exerciseAdapter` result. |
5457
5462
  | `assertAuthenticationRestoreAndExpiry(states)` | A restored authenticated session can refresh and ends in expiry. Every state is validated. |
5458
5463
  | `assertReconnectWithMissedAssignments(before, reconnect, ids)` | A reconnect snapshot restores assignments received while offline. |
5459
- | `stillHost(report?, guarantees?, mute?)` | A host that reports one thing and never changes, for a test context: `{ online: true }` by default, a report with audio for a softphone voice adapter, and never for a desk phone. |
5460
- | `TaskStream`, `BreakStream` | The cross-event models the harness applies after the connect snapshot, exported for a host that wants the same rules at its boundary: `seed(snapshot)`, then `apply(envelope)` returns the violations. |
5464
+ | `stillHost(report?, guarantees?, mute?)` | An agent application that reports one thing and never changes, for a test context: `{ online: true }` by default, a report with audio for a softphone voice adapter, and never for a desk phone. |
5465
+ | `TaskStream`, `BreakStream` | The cross-event models the harness applies after the connect snapshot, exported for an agent application that wants the same rules at its boundary: `seed(snapshot)`, then `apply(envelope)` returns the violations. |
5461
5466
  | `assertBreakFollowsItsRequests(envelopes, snapshot?)` | A break follows its requests: a commit's states only after a grant, never backwards, and a forced break arriving in effect with `forced`. The harness applies the same rules after the connect snapshot. |
5462
5467
  | `assertMediaFollowsTheTask(envelopes, snapshot?)` | The media follows the task and never decides it: every task is introduced once, `task-media-started` and `task-media-ended` alternate on work that has begun, media ends only where it arrived, and what follows the media ending is `completing` or `task-ended`. The harness applies the same rules to every event after the connect snapshot (`stream.*`). A sequence with no media satisfies it by never testing it — pair it with the assertion that the media end is present. |
5463
5468
  | `assertBreakAttemptProviders(candidates, asked)` | A break attempt asks every usable provider holding capacity, `refreshing` included, and nothing of a provider whose login is `expired`. |
@@ -5475,7 +5480,7 @@ Adapters should run the relevant scenarios against deterministic test state befo
5475
5480
 
5476
5481
  ## A provider does not style the workspace
5477
5482
 
5478
- How a deployment themes Omni is the host's concern and is specified with the host, not here. What
5483
+ How a deployment themes Omni is the agent application's concern and is specified with the agent application, not here. What
5479
5484
  belongs in this contract is the boundary. A provider says what a control **is** through its
5480
5485
  capabilities and what its work is **called** through `phaseLabels` and `taskTypePresentation`; how
5481
5486
  any of it is drawn is Omni's. A task cannot select a design language, inject a component, or
@@ -5485,21 +5490,21 @@ override the agent's theme and font preferences.
5485
5490
 
5486
5491
  Recording is voice-only. A task can arrive already recording, including while pending, and offer
5487
5492
  no recording controls. The provider publishes only its own current state on
5488
- the provider field of the task’s `recording` state. The host publishes its own full scoped view in `HostReport.recordings`.
5489
- A provider task update cannot replace host state. Neither a capability nor an accepted command
5493
+ the provider field of the task’s `recording` state. The agent application publishes its own full scoped view in `HostReport.recordings`.
5494
+ A provider task update cannot replace agent application state. Neither a capability nor an accepted command
5490
5495
  establishes recording. Missing state, lost recorder observation, transport loss and expired
5491
5496
  observation mean unknown; they never mean stopped. Paused means a recording remains open without
5492
5497
  capturing. Task hold, task pause and recording pause are independent.
5493
5498
 
5494
- The per-task policy is `Task.capabilities.recording`, with independently optional provider and host
5499
+ The per-task policy is `Task.capabilities.recording`, with independently optional provider and agent application
5495
5500
  action sets. The outer capability may be locked. Absence grants no permission, and a state may
5496
5501
  exist without any permission. A provider may offer only stop for a recording started automatically,
5497
5502
  or withdraw a control on a later task update. There is no global recording mode and no automatic
5498
- start from a capability declaration. Host support is declared on `ConnectContext.host.recording`,
5499
- not the provider-owned manifest. The task chooses an explicitly provisioned host destination;
5503
+ start from a capability declaration. Agent application support is declared on `ConnectContext.host.recording`,
5504
+ not the provider-owned manifest. The task chooses an explicitly provisioned agent application destination;
5500
5505
  unknown destinations or unsupported actions are refused visibly, never redirected to provider
5501
- recording or a default upload location. Initial host support requires voice softphone media and
5502
- capture of both local and remote audio; a host unable to capture either must refuse start/resume.
5506
+ recording or a default upload location. Initial agent application support requires voice softphone media and
5507
+ capture of both local and remote audio; an agent application unable to capture either must refuse start/resume.
5503
5508
  This package declares that contract; it supplies no recorder, media mixing, storage or upload.
5504
5509
 
5505
5510
  | Action | Required current recording state | Confirmed outcome |
@@ -5520,7 +5525,7 @@ Partial success (capture stopped but storage outcome unknown) cannot return fail
5520
5525
  of no effect. It rejects with unknown outcome, reports the failure visibly and publishes whatever
5521
5526
  current capture state is actually known. Retention is not a promise of sample-perfect audio.
5522
5527
 
5523
- Provider commands go exclusively to `Connection.execute`; host commands go exclusively to
5528
+ Provider commands go exclusively to `Connection.execute`; agent application commands go exclusively to
5524
5529
  `HostRecording.execute`. Both include task, allocation, request and observation identities; all
5525
5530
  non-start commands identify the particular recording. IDs are opaque and scoped by provider login,
5526
5531
  task and recorder owner. They are never inferred from filenames or current agent identity. A
@@ -5528,8 +5533,8 @@ recording ID survives pause/resume and reallocation only where the same recorder
5528
5533
  commands always name the current allocation. A later start gets a different ID. Reconnect does not
5529
5534
  create a new recording or fresh evidence. After lost continuity, use unknown until reconciled.
5530
5535
  There is no automatic restart, transfer to another recorder, or stop on task hold/disconnect.
5531
- Task removal does not prove recording stopped: outstanding host recorders remain tracked by the
5532
- host until its executor reconciles/finishes them, with visible unresolved cleanup failures.
5536
+ Task removal does not prove recording stopped: outstanding agent application recorders remain tracked by the
5537
+ agent application until its executor reconciles/finishes them, with visible unresolved cleanup failures.
5533
5538
 
5534
5539
  Only start/resume require an in-progress or paused task with started media. Pause/stop/cancel may
5535
5540
  also finish an independently observed recorder while the task is completing. A pending task may
@@ -5550,34 +5555,34 @@ identity or observation time publish unknown and offer no issuable controls.
5550
5555
 
5551
5556
  Use `validateTask` and `validateTaskCommand` for published shape and static permissions.
5552
5557
  Immediately before dispatch, additionally use `validateRecordingRequest` against the full current
5553
- task and explicit observer-domain time. For host commands also supply the current host declaration,
5554
- full host report and softphone context. The same checks must run at the executing boundary;
5558
+ task and explicit observer-domain time. For agent application commands also supply the current agent application declaration,
5559
+ full agent application report and softphone context. The same checks must run at the executing boundary;
5555
5560
  client validation alone is not authorization. The executor serializes operations on each recorder
5556
5561
  and durably correlates request identity with scope, action and outcome: an exact retry refers to the
5557
5562
  same operation; reuse with different contents is refused. It never silently retries an ambiguous
5558
5563
  operation. Implementations without reliable request correlation must refuse controls.
5559
5564
 
5560
- Keep command progress in host UI separately from authoritative state. Applied means the requested
5561
- recording transition and any retain/discard effect actually completed; publish the confirming task or host report before
5565
+ Keep command progress in agent application UI separately from authoritative state. Applied means the requested
5566
+ recording transition and any retain/discard effect actually completed; publish the confirming task or agent application report before
5562
5567
  resolving applied. Failed means confirmed no effect. Rejected promise means outcome unknown:
5563
5568
  show the failure, reconcile that path and do not automatically retry or pretend inactive. Authoritative
5564
- updates remain full current task/host views, not replayed provider events. These current-state fields
5569
+ updates remain full current task/agent application views, not replayed provider events. These current-state fields
5565
5570
  create no interaction-history entries and infer no actors, durations or historical capture boundaries.
5566
5571
 
5567
5572
  Migration is explicit: replace the old true recording capability with per-path action policies,
5568
5573
  replace untargeted commands with scoped commands, and retain protocol version 1. During pre-release
5569
5574
  development, hosts and adapters must align their recording contracts; negotiation does not detect
5570
5575
  differences between package revisions that share that protocol number. No legacy-shape fallback is provided.
5571
- This change does not publish a package or enable recording in any existing host/provider by itself.
5576
+ This change does not publish a package or enable recording in any existing agent application/provider by itself.
5572
5577
 
5573
5578
  `validateRecordingOutcome` checks confirming observations against recording-specific applied/failed
5574
5579
  semantics, including pause/resume identity and rejection of a dialling result. It cannot prove audio
5575
5580
  retention/completion or source truth from a status flag; those remain executor obligations.
5576
5581
 
5577
- Host destination selection binds storage when start actually creates a recording. Existing recordings
5582
+ Agent application destination selection binds storage when start actually creates a recording. Existing recordings
5578
5583
  keep that binding through pause/resume/stop/cancel; a later policy cannot redirect their stored audio.
5579
5584
  The executor rejects a mismatched destination rather than moving or discarding another binding.
5580
- Action permission does not authorize unattended invocation: host controls require the agent's explicit
5585
+ Action permission does not authorize unattended invocation: agent application controls require the agent's explicit
5581
5586
  act, and provider authorization remains enforced at its authenticated command boundary.
5582
5587
 
5583
5588
 
@@ -5589,31 +5594,31 @@ capability restrictions from disappearing at dispatch. The standalone `validateR
5589
5594
  requires an affirmative permission; false, malformed permission declarations and unknown actions grant nothing.
5590
5595
 
5591
5596
 
5592
- ### Host recording announcements to the caller
5597
+ ### Agent application recording announcements to the caller
5593
5598
 
5594
- `HostRecording.announcesToCaller`, when true, is a guarantee that the host delivers audible recording
5599
+ `HostRecording.announcesToCaller`, when true, is a guarantee that the agent application delivers audible recording
5595
5600
  status messages to the remote party over the call's outgoing audio. It belongs inside the optional
5596
- host recording capability: without that capability there is no such guarantee. Omission makes no
5601
+ agent application recording capability: without that capability there is no such guarantee. Omission makes no
5597
5602
  promise; false is invalid. It does not belong in the provider manifest, the task's recording policy
5598
- or the general `HostGuarantees` object. A provider can inspect this host guarantee when deciding
5599
- whether to permit host recording on a task.
5603
+ or the general `HostGuarantees` object. A provider can inspect this agent application guarantee when deciding
5604
+ whether to permit agent application recording on a task.
5600
5605
 
5601
- The guarantee applies only to host-owned recordings. Providers implement announcements for their
5602
- own recordings at their end; provider state updates must not cause the host to announce those
5606
+ The guarantee applies only to agent application-owned recordings. Providers implement announcements for their
5607
+ own recordings at their end; provider state updates must not cause the agent application to announce those
5603
5608
  recordings. Both recorders can operate independently on the same call.
5604
5609
 
5605
- On a confirmed host start, the remote party hears that recording started. On a confirmed stop or
5610
+ On a confirmed agent application start, the remote party hears that recording started. On a confirmed stop or
5606
5611
  cancel, they hear that recording stopped. If pause/resume is supported, say paused/resumed so a
5607
5612
  pause is not presented as a finished recording. Announcements follow actual capture transitions,
5608
5613
  not button clicks, accepted requests or task-policy changes. When attaching to an already-active
5609
- host recording, announce that recording is active, without inventing its original start time.
5614
+ agent application recording, announce that recording is active, without inventing its original start time.
5610
5615
  Repeated observations of the same state do not repeat announcements. Unknown or expired evidence
5611
5616
  must never produce a stopped announcement.
5612
5617
 
5613
5618
  A local sound, UI indicator, screen-reader message to the agent, or sound leaking through the
5614
- microphone does not fulfil this guarantee. The host must deliver the message directly in the audio
5619
+ microphone does not fulfil this guarantee. The agent application must deliver the message directly in the audio
5615
5620
  sent to the remote party, even when the agent microphone is muted. It may also notify the agent.
5616
- Only declare the guarantee when the host can provide that outgoing audio path. An announcement
5621
+ Only declare the guarantee when the agent application can provide that outgoing audio path. An announcement
5617
5622
  that cannot be delivered, including after the remote party has disconnected, is a visible failure;
5618
5623
  never claim delivery or replay the notice into a different call.
5619
5624
 
@@ -5623,4 +5628,4 @@ report the announcement failure visibly and reject with unknown command outcome.
5623
5628
  effect, automatically repeat the recording action or silently switch to an agent-only notice.
5624
5629
 
5625
5630
  `validateHostRecording` checks the declaration, including its true-or-absent guarantee. Actual audio
5626
- delivery remains the host implementation's responsibility and must be exercised in its own tests.
5631
+ delivery remains the agent application implementation's responsibility and must be exercised in its own tests.