> For the complete documentation index, see [llms.txt](https://docs.concurrence.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.concurrence.com/api-reference/change-logs/amigo-api/amigo-api-history-09.md).

# API History: Archive 9

Retained API history, archive 9, with original entry headings and links back to current integration guidance.

Historical entries retain their original release/source context. Use [Current Upgrade Guidance](/api-reference/change-logs/upgrade-guide.md) for current integration boundaries and [API](/api-reference/change-logs/amigo-api.md) for the recent history and archive index. An older entry does not establish current availability.

<details>

<summary>v0.9.431 - Platform API: Intake Pipeline - Full Analytical Catalog Row and PHI Filename Exclusion (July 2026)</summary>

#### Intake Pipeline - Full Analytical Catalog Row and PHI Filename Exclusion <a href="#intake-pipeline-full-analytical-catalog-row-and-phi-filename-exclusion" id="intake-pipeline-full-analytical-catalog-row-and-phi-filename-exclusion"></a>

The async intake processing job now writes a complete file metadata row to the analytical catalog and excludes the original filename from the analytical layer for PHI protection.

**What changed:**

* **Full file metadata in analytical catalog.** The intake processing job now appends a complete file metadata row to the analytical catalog, including content type, file hash, size, ingestion timestamp, contract details, and processing paths. Previously, the analytical row contained only a subset of metadata fields. The expanded row makes intake data fully queryable for downstream analytics without joining back to the platform record.
* **PHI filename excluded from analytical catalog.** The original filename is no longer passed to or stored in the analytical catalog. Filenames are treated as protected health information and remain exclusively in the access-controlled platform record. This applies to the job parameters as well - the filename is not included in job run parameters, which may be visible in run management interfaces.
* **Explicit schema on catalog writes.** The analytical catalog writes now use explicit column schemas rather than relying on type inference. This prevents intermittent failures when processing results contain all-null columns (for example, pure insert or delete batches with no old or new values), which previously caused the job to fail on type inference.
* **Additional file metadata parameters.** The processing job now receives content type, file hash, size, ingestion timestamp, and optional contract metadata as parameters from the platform when triggered. These parameters populate the analytical catalog row directly.

**What you need to do:**

* **No action required for most users.** The analytical catalog now contains richer file metadata automatically. If you consume the analytical intake tables, the files table now includes additional columns for content type, file hash, size, ingestion timestamp, contract ID, contract version, schema fingerprint, and landing path.
* **If you depend on filename in the analytical catalog**, note that filename is no longer available there. Use the platform file detail endpoint to retrieve the filename when needed.

</details>

<details>

<summary>v0.9.430 - Platform API: Atlas Voice Runtime - Unified Model Configuration and Tool-Use Directive (July 2026)</summary>

#### Atlas Voice Runtime - Unified Model Configuration and Tool-Use Directive <a href="#atlas-voice-runtime-unified-model-configuration-and-tool-use-directive" id="atlas-voice-runtime-unified-model-configuration-and-tool-use-directive"></a>

The Atlas voice runtime now reads its backing model from the same environment-driven configuration as the real-time speech-to-speech runtime, and every Atlas phase agent receives an explicit tool-use directive in its system preamble.

**What changed:**

* **Unified model configuration.** The Atlas voice runtime previously used its own hardcoded model while the real-time speech-to-speech runtime followed the deployment's selected model. Atlas now reads the same deployment-level selection, so supported model changes apply consistently to both realtime providers.
* **Tool-use directive in system preamble.** The Atlas runtime now prepends a tool-use directive to every phase agent's system preamble. The directive instructs the model to call its attached tools for any information they can supply - appointment availability, records, scheduling, account or clinical details - rather than guessing, answering from memory, or telling the caller it cannot access the data. This addresses observed behavior where the model would decline to use an attached tool and instead claim it could not see the relevant information. The directive is phrased defensively so it remains accurate even when no tools are attached.

**What you need to do:**

* **No action required.** Atlas calls now follow the deployment's selected realtime model and retain the prior default when no override is configured. The tool-use directive is applied automatically to Atlas voice sessions.

</details>

<details>

<summary>v0.9.429 - Platform API: Automatic Async Intake Processing (July 2026)</summary>

#### Automatic Async Intake Processing <a href="#automatic-async-intake-processing" id="automatic-async-intake-processing"></a>

For workspaces with optional asynchronous intake enabled, an uploaded file can now start processing automatically. The processing path uses short-lived, run-scoped authorization instead of a customer-managed long-lived secret.

**What changed:**

* **Automatic start attempt after upload.** In an enabled workspace, landing a file attempts to start its asynchronous validation and materialization path without a separate client request.
* **Short-lived authorization.** Processing writes status back with scoped, short-lived authorization. Customers do not provision or rotate a long-lived processing secret.
* **Best-effort start.** If asynchronous processing does not start, the upload can still succeed and remain in `received` status for reconciliation or manual recovery. Poll file status rather than treating upload success as proof of processing completion.
* **Synchronous mode unchanged.** Workspaces without the optional asynchronous mode continue to validate uploads synchronously and return `curated` or `rejected`.

**What you need to do:**

* **No action required for most users.** Enabled workspaces attempt to start processing on upload without additional credential provisioning. Contact Amigo to confirm whether asynchronous intake is enabled for your workspace.
* **If you were manually starting processing**, that separate step is no longer necessary in an enabled workspace.

</details>

<details>

<summary>v0.9.428 - Platform API: Optional Async Intake Processing (July 2026)</summary>

#### Optional Async Intake Processing <a href="#optional-async-intake-processing" id="optional-async-intake-processing"></a>

Console file uploads to Customer Data Intake now support an optional asynchronous processing mode that Amigo enables per workspace.

**What changed:**

* **New processing mode for file uploads.** In an enabled workspace, a file uploaded through Console is stored and returned with status `received` instead of being immediately validated. Asynchronous processing performs conformance checks, validation, and diffing before writing the final `curated` or `rejected` verdict.
* **New `received` status.** The file status field can now return `received` in addition to `curated` and `rejected`. A file in `received` status has been persisted and is awaiting async processing. Poll the file detail endpoint to observe the final verdict.
* **Synchronous mode remains available.** Workspaces without asynchronous intake continue to validate uploads synchronously and return a terminal `curated` or `rejected` status immediately.
* **Deduplication unchanged.** Byte-identical re-uploads for the same dataset still return the existing file record regardless of processing mode.

**What you need to do:**

* **No action required for most users.** If you want asynchronous intake enabled for a workspace, contact your Amigo account team.
* **If you consume file status values**, update your integration to handle the `received` status. A successfully processed file transitions to `curated` or `rejected`; continue polling or use the documented recovery path when it remains `received`.

</details>

<details>

<summary>v0.9.427 - Platform API: Configurable Realtime Voice Model (July 2026)</summary>

#### Configurable Realtime Voice Model <a href="#configurable-realtime-voice-model" id="configurable-realtime-voice-model"></a>

The real-time speech-to-speech voice runtime now supports deployment-level model selection instead of one hardcoded model.

**What changed:**

* **Deployment-level model selection.** The realtime voice provider now reads the model selected for its deployment and falls back to the prior default when no override is configured. This lets Amigo roll out supported realtime model versions without changing the public call contract.
* **No API contract change.** Request and response schemas are unchanged. Conversation behavior remains model-dependent and can vary when Amigo selects a different supported model for the deployment.

**What you need to do:**

* **No action required.** The provider retains the same default model unless Amigo configures a supported deployment override. Contact Amigo when a workflow requires a different realtime model family.

</details>

<details>

<summary>v0.9.426 - Platform API: Trigger Pause and Resume Now Correctly Toggle Activation State (July 2026)</summary>

#### Trigger Pause and Resume Now Correctly Toggle Activation State <a href="#trigger-pause-and-resume-now-correctly-toggle-activation-state" id="trigger-pause-and-resume-now-correctly-toggle-activation-state"></a>

The trigger pause and resume operations now correctly flip the trigger's active state. Previously, pausing or resuming a trigger could silently fail to change the activation state because the request was routed through the general field-edit path, which does not modify lifecycle fields.

**What changed:**

* **Pause and resume are now dedicated lifecycle operations.** Pausing a trigger sets it to inactive, and resuming sets it to active. These operations are handled as distinct lifecycle transitions rather than general field updates, so the activation state change is always applied.
* **Next fire time is recomputed on resume.** When a trigger with a cron schedule is resumed, its next fire time is recalculated from the current moment. This means a resumed trigger starts firing from now rather than back-firing for any scheduled slots it missed while paused.
* **No change to the update endpoint.** The general trigger update endpoint continues to handle user-editable fields (name, schedule, and so on). Activation state is not modifiable through the update endpoint - use the pause and resume operations instead.

**What you need to do:**

* **No action required.** If you were calling the pause or resume endpoints and observing that triggers remained in their previous state, that behavior is now fixed. Pause and resume work as expected.
* **If you were working around this bug** by directly updating trigger fields to change activation state, you can remove that workaround and use the standard pause and resume operations.

</details>

<details>

<summary>v0.9.425 - Platform API: Trace Export Now Includes Voice Infrastructure Spans (July 2026)</summary>

#### Trace Export Now Includes Voice Infrastructure Spans <a href="#trace-export-now-includes-voice-infrastructure-spans" id="trace-export-now-includes-voice-infrastructure-spans"></a>

The `POST /traces:export` endpoint now exports per-call voice infrastructure spans alongside the existing tool-call spans, giving you end-to-end observability over both agent tool execution and voice isolation lifecycle events.

**What changed:**

* **Voice infrastructure spans included.** The trace export now returns `voice.*` infrastructure spans - allocation, media attachment, and teardown events for per-call voice isolation - in addition to the existing `gen_ai.*` tool-call spans. Both span families are exported as OTLP/HTTP JSON and follow the same allowlist-based attribute filtering.
* **New exported attributes.** Six new attributes are included in the allowlist for voice infrastructure spans: the allocated media server identity, the node it landed on, allocation latency, which media leg attached, the teardown reason, and the server lifetime. These are operational infrastructure attributes and never contain patient data.
* **Span naming for voice spans.** Voice infrastructure spans use their operation type as the span name directly (e.g. the allocation, attach, or reap operation), rather than the `<operation> <tool>` convention used for tool-call spans.
* **Zero-duration point events.** Voice infrastructure spans represent instants (allocation, attachment, teardown) rather than intervals, so they render as zero-duration point events in your trace viewer. This accurately reflects that these are discrete lifecycle moments, not timed operations.

**What you need to do:**

* **No action required.** If you are already consuming the trace export endpoint, voice infrastructure spans will appear automatically in your OTLP collector alongside tool-call spans. The response shape and pagination behavior are unchanged.
* **Update span filters if needed.** If your trace pipeline filters spans by name or attributes, you may want to add rules for the new voice infrastructure span names and attributes to route them appropriately in your observability tooling.

</details>

<details>

<summary>v0.9.424 - Platform API: Conversation List Performance Improvements (July 2026)</summary>

#### Conversation List Performance Improvements <a href="#conversation-list-performance-improvements" id="conversation-list-performance-improvements"></a>

The `GET /v1/{workspace_id}/conversations` endpoint is now significantly faster for workspaces with large call volumes. Two changes reduce list latency from multi-second to sub-second for typical page sizes.

**What changed:**

* **Concurrent source fetches.** Text and voice conversation sources are now fetched concurrently instead of sequentially. Previously, the unfiltered conversation list paid text latency plus voice latency in series; now both run in parallel.
* **Batched entity resolution.** Per-call entity metadata is now resolved in a single indexed lookup scoped to the current page of results, rather than joining against the full workspace entity dataset in the main query. Resolution time now scales with page size, not workspace size.

**What you need to do:**

* **No action required.** These are transparent performance improvements. Response shape, pagination, and filtering behavior are unchanged. You should observe faster response times on the conversation list endpoint, especially in workspaces with large numbers of calls.

</details>

<details>

<summary>v0.9.423 - Platform API: Status Write-Back Route and Delta Metadata Catalog for Customer Data Intake (July 2026)</summary>

#### Status Write-Back Route and Delta Metadata Catalog for Customer Data Intake <a href="#status-write-back-route-and-delta-metadata-catalog-for-customer-data-intake" id="status-write-back-route-and-delta-metadata-catalog-for-customer-data-intake"></a>

The customer data intake pipeline now includes a status write-back route that lets the async processing job advance a file to its terminal status, and a Delta metadata catalog that tracks file lifecycle, row-level changes, and schema changes across intake datasets.

**What changed:**

* **New status write-back endpoint.** `POST /v1/{workspace_id}/intake/files/{file_id}/status` advances a file's status after processing completes. The request body accepts `status`, `error_reason` (max 2000 characters, must not contain patient data), `curated_path`, and `cdc_path`. The processing job authenticates with the workspace's API key (Bearer), so the update is scoped to the correct workspace. Returns the updated file row on success, or 404 if the file does not exist in the workspace.
* **Delta metadata catalog.** Three new catalog tables track intake file lifecycle, row-level changes per dataset version, and schema changes. These tables provide a durable audit trail of every file's processing outcome and the data changes it introduced.
* **Processing job updated.** The async processing job now references the write-back route and catalog tables. The actual write-back call is activated in a follow-up cutover alongside secret provisioning and file-arrival trigger wiring - until then, processing verdicts are logged for observability.

**What you need to do:**

* **No action required for existing integrations.** The new endpoint and catalog are additive. The processing job does not call the write-back route until the cutover is complete, so existing workflows are unaffected.
* **If you are building custom intake integrations**, you can use the new status write-back endpoint to advance file status programmatically. Authenticate with a workspace API key and include only the fields relevant to your verdict (`curated_path` and `cdc_path` are optional and should be omitted for failed or held verdicts).

</details>

<details>

<summary>v0.9.422 - Platform API: HMAC-Signed Inbound Webhooks for Channel Bindings (July 2026)</summary>

#### HMAC-Signed Inbound Webhooks for Channel Bindings <a href="#hmac-signed-inbound-webhooks-for-channel-bindings" id="hmac-signed-inbound-webhooks-for-channel-bindings"></a>

Inbound-turn webhooks for messaging channel bindings (SMS, email, and iMessage) are now HMAC-signed with per-use-case secrets. Each messaging use case receives a signing secret at creation time, and every inbound-turn webhook POST includes one or more signature headers so the receiving service can verify authenticity.

**What changed:**

* **Webhook signing on create.** When you create an SMS, email, or iMessage use case, the response now includes a `webhook_secret` field containing the signing secret for that binding. This secret is returned exactly once at creation time and is not retrievable afterward - store it securely when you receive it.
* **Signature header on inbound webhooks.** Every inbound-turn webhook POST from a messaging channel binding now includes an `X-AMIGO-CHANNEL-MANAGER-WEBHOOK-SIGNATURE` header containing an HMAC-SHA256 hex digest computed over the request body using the use case's signing secret. Your webhook receiver should verify this signature to confirm that the request originated from the platform.
* **Secret rotation endpoint.** A new `POST /v1/use-case/{id}/webhook-secret` endpoint rotates the signing secret for a messaging use case. The response includes the new `webhook_secret` (returned once, not re-readable) and an `old_secret_lasts_until` timestamp. During the 30-minute grace window after rotation, the platform sends two signature headers - one signed with the new secret and one with the old - so your receiver can verify against either while you reconfigure. After the grace window expires, only the new secret is used.
* **Automatic secret rotation on webhook URL change.** When you update a use case's `webhook_url` via the update endpoint, the signing secret is automatically rotated with no grace window (since the destination itself changed, in-flight requests to the old URL are moot). The new secret is returned in the update response's `webhook_secret` field.
* **Secret cleanup on delete.** When a messaging use case is deleted, its signing secret is also removed.
* **Voice channels excluded.** Voice use cases (outbound voice, inbound voice, ringless voicemail) do not have webhook secrets because they do not POST inbound turns. Calling the rotation endpoint on a voice use case returns a 400 error.
* **Create response shape change.** The create use case response for messaging channels now includes `webhook_secret` and no longer includes `updated_at` (which was redundant with `created_at` for a just-created resource). The update and get responses continue to include `updated_at`.

**What you need to do:**

* **Capture the webhook secret on use case creation.** The secret is returned once in the create response. Store it in your secrets management system so your inbound webhook receiver can verify signatures.
* **Verify inbound webhook signatures.** Update your webhook receiver to compute an HMAC-SHA256 hex digest of the raw request body using the stored secret and compare it against the `X-AMIGO-CHANNEL-MANAGER-WEBHOOK-SIGNATURE` header. Reject requests where no header matches.
* **Handle dual signatures during rotation.** After calling the rotation endpoint, your receiver may see two signature headers for up to 30 minutes. Verify against both - accept the request if either signature matches.
* **Capture the new secret when updating webhook URLs.** If you change a use case's `webhook_url`, the response includes a new `webhook_secret`. Update your receiver configuration with the new secret immediately (there is no grace window for URL changes).

</details>

<details>

<summary>v0.9.421 - Platform API: Update Use Case Endpoint for Channel Bindings (July 2026)</summary>

#### Update Use Case Endpoint for Channel Bindings <a href="#update-use-case-endpoint-for-channel-bindings" id="update-use-case-endpoint-for-channel-bindings"></a>

A new `PUT /v1/use-case/{id}` endpoint allows you to update mutable fields on an existing use case without recreating it. This is particularly useful for rotating inbound webhook URLs on channel bindings.

**What changed:**

* **New update endpoint.** `PUT /v1/use-case/{id}` accepts a partial update for a use case. The request body is a discriminated union on `channel` (matching the create request shape), so the correct set of updatable fields is determined by the channel type. The `channel` field in the body must match the use case's existing channel - a mismatch returns a 409 error.
* **Updatable fields by channel.** The `description` field is updatable on all channel types (supply `null` to clear it, omit to leave it unchanged). SMS, email, and iMessage bindings also support updating `webhook_url` to rotate the inbound turn destination. Email bindings additionally support updating `sender_email_alias` (the display name rendered before the sender address in outbound messages).
* **Validation.** At least one updatable field besides `channel` must be provided. Description is limited to 2000 characters. The `webhook_url` must be a valid HTTP URL. The `sender_email_alias` must be 4-40 characters after whitespace trimming, or `null` to clear. Invalid requests return a 422 error.
* **Voice channels.** Outbound voice, inbound voice, and ringless voicemail use cases support updating `description` only. Voice binding resources (such as telephony application identifiers and region configuration) are immutable.
* **Response.** The endpoint returns the full use case response (matching the GET response shape) with the updated fields reflected.

**What you need to do:**

* **Use this endpoint to rotate webhook URLs.** If you need to change where inbound messages are forwarded for an SMS, email, or iMessage binding, send a PUT request with the new `webhook_url` instead of deleting and recreating the use case.
* **Include the `channel` field in every update request.** The channel is required to select the correct request variant, even though it cannot be changed.

</details>

<details>

<summary>v0.9.420 - Platform API: Pre-Warmed Media Routes for Per-Call Isolation (July 2026)</summary>

#### Pre-Warmed Media Routes for Per-Call Isolation <a href="#pre-warmed-media-routes-for-per-call-isolation" id="pre-warmed-media-routes-for-per-call-isolation"></a>

Isolated media servers now pre-register their routing identity at startup - before entering the warm pool - so their network route is live before the platform assigns them to a call. This closes a race condition where the telephony provider could attempt to connect the media stream before the route was populated, causing silent no-audio on the affected call.

**What changed:**

* **Route pre-warming.** Each isolated media server publishes its per-server routing identity at startup, before it signals readiness. The routing layer maps the server's address into the live route table while it is still in the warm pool, so by the time the platform allocates it for a call the route already exists. Previously, the route was created as a side-effect of allocation, leaving a brief window where the telephony provider's media-stream connection could arrive before the route was live.
* **Caller-aware orphan protection.** The self-reap watchdog that reclaims unused allocated servers now recognizes when a caller's media stream is already connected (waiting on hold music during preparation). A server with a connected caller is never reaped, even if the agent leg has not attached yet. If the caller disconnects before the agent leg connects (for example, by hanging up during hold), the timer re-arms and the server is still reclaimed - so pre-warming does not leak idle servers.
* **No change to the allocation API contract.** Callers of the allocation path receive the same response shape. The routing token is now read back from the server's self-assigned identity rather than being stamped at allocation time, but the returned host and token fields are unchanged.
* **No change to warm-pool sizing or autoscaling behavior.** The only difference is when the route becomes live (at server startup rather than at allocation).

**What you need to do:**

* **No action required.** The change is fully internal to the per-call isolation path. Calls that use per-call isolation benefit automatically. Calls on the shared path are unaffected.

</details>

<details>

<summary>v0.9.419 - Platform API: Fix Double-Encoding of REST Integration Path Parameters (July 2026)</summary>

#### Fix Double-Encoding of REST Integration Path Parameters <a href="#fix-double-encoding-of-rest-integration-path-parameters" id="fix-double-encoding-of-rest-integration-path-parameters"></a>

REST integration endpoint path parameters that contain special characters (such as Auth0 user IDs with `|` separators) are no longer double-encoded when the platform constructs the upstream request URL.

**What changed:**

* **Path parameter encoding fix.** When a REST integration endpoint path template contains a parameter with reserved characters (for example, `auth0|abc123`), the platform now preserves the single round of percent-encoding applied by the URI template expansion. Previously, the URL construction step re-encoded already-encoded characters - turning `%7C` into `%257C` - which caused upstream services to receive the literal `%7C` string instead of the intended `|` character. This caused key lookups to fail on services like Auth0 that use pipe-delimited identifiers.
* **Path template validation on create and update.** REST integration endpoint path templates are now validated at creation and update time to reject RFC 6570 reserved-expansion operators (`{+var}`, `{#var}`, `{.var}`, `{/var}`, `{;var}`, `{?var}`, `{&var}`). Only simple `{var}` placeholders are permitted. Reserved-expansion operators bypass percent-encoding of model-supplied values, which could allow path traversal. This validation ensures that all parameter values in the expanded path are safely encoded.
* **No change to existing endpoints with simple placeholders.** Endpoints that use only simple `{var}` path placeholders continue to work without modification.

**What you need to do:**

* **No action required for most users.** If you have REST integration endpoints with path parameters containing special characters (such as Auth0 `|` keys) that were failing, they should now work correctly without any changes to your configuration.
* **Review any endpoints using reserved-expansion operators.** If you have endpoint path templates that use operators like `{+var}` or `{/var}`, these will now be rejected on update. Replace them with simple `{var}` placeholders.

</details>

<details>

<summary>v0.9.418 - Platform API: Per-Binding Inbound Webhook URL for Channel Bindings (July 2026)</summary>

#### Per-Binding Inbound Webhook URL for Channel Bindings <a href="#per-binding-inbound-webhook-url-for-channel-bindings" id="per-binding-inbound-webhook-url-for-channel-bindings"></a>

Channel bindings (SMS, email, and iMessage) now support a configurable per-binding webhook URL that controls where inbound messages are forwarded. Previously, all inbound turns were routed to a single platform-wide destination. Each binding can now target a different consumer endpoint, enabling multi-tenant and multi-service routing patterns.

**What changed:**

* **New `webhook_url` field on channel binding creation.** When creating a use case with an SMS, email, or iMessage channel binding, a `webhook_url` field is now required. This URL receives the inbound turn payload for that binding. The receiver must implement the platform's inbound turn contract.
* **Per-binding routing.** Each channel binding routes its inbound messages independently. Two bindings on different use cases can point to different consumer endpoints, so a single deployment can fan out inbound traffic to multiple downstream services.
* **`webhook_url` in responses.** The `webhook_url` is returned on all use case read endpoints (get and list), so callers can confirm where each binding's inbound turns are routed.
* **No change to outbound behavior.** Outbound message sending is unaffected. Only the inbound forwarding destination is configurable.
* **Voicemail status forwarding removed.** The voicemail webhook no longer forwards status events to the platform API. Voicemail status transitions are persisted locally and logged, but are no longer relayed to a central endpoint.

**What you need to do:**

* **Include `webhook_url` when creating channel bindings.** All new SMS, email, and iMessage use case creation requests must include a `webhook_url` field containing a valid HTTPS URL. Requests without this field will be rejected.
* **Existing bindings are unaffected.** Previously created bindings have been backfilled to the prior default destination. No action is needed for existing use cases.

</details>

<details>

<summary>v0.9.417 - Platform API: OTLP Trace Export Endpoint (July 2026)</summary>

#### OTLP Trace Export Endpoint <a href="#otlp-trace-export-endpoint" id="otlp-trace-export-endpoint"></a>

A new read-only endpoint allows workspaces to export durable tool-call trace spans as OpenTelemetry Protocol (OTLP/HTTP JSON) spans, enabling external observability collectors and partner monitoring stacks to pull trace data from the platform.

**What changed:**

* **New trace export endpoint.** A paginated pull endpoint exports the workspace's durable `gen_ai.*` tool-call trace spans over a configurable time window as OTLP/JSON-encoded spans. The response contains standard OTLP `resourceSpans` envelopes that can be forwarded directly to any OTLP-compatible collector. The endpoint is read-only and never writes data.
* **Dark launch behind feature flag.** The endpoint is gated behind the `OTEL_TRACE_EXPORT_ENABLED` environment flag. When the flag is off, the endpoint returns 404. The endpoint is always registered so the API contract remains stable across environments.
* **Admin or owner role required.** Trace spans carry tool-call metadata, so the endpoint requires admin or owner credentials for parity with other sensitive data access paths.
* **PHI-safe by construction.** Exported attributes use a fail-closed allowlist of tool-call metadata fields (operation name, tool name, integration, endpoint, protocol, latency, success status, and call ID). Raw error text and any non-allowlisted fields are excluded, so no patient data leaves the trust boundary through this endpoint.
* **Paginated pull API.** The request accepts a time window (`start_time`, `end_time`), a page size limit (1-1000, default 500), and an opaque continuation token for paging. The response includes `has_more` and `continuation_token` fields for cursor-based pagination.
* **OTLP/JSON encoding.** Spans follow the OTLP/HTTP JSON encoding conventions: 64-bit integers and timestamps are decimal strings, trace IDs are 32 lowercase hex characters, span IDs are 16 lowercase hex characters, and each attribute value uses the typed `AnyValue` oneof encoding.
* **Resource and scope metadata.** Each response groups spans under a single resource with `service.name` and `amigo.workspace.id` attributes, scoped under the `amigo.world.trace` instrumentation scope.

**What you need to do:**

* **No action required.** The endpoint is dark by default. Contact your account team to enable OTLP trace export for your workspace if you want to integrate with an external observability collector.

</details>

<details>

<summary>v0.9.416 - Platform API: HIPAA Audit Parity for MCP Surface Tools and REST Data Query Invoke (July 2026)</summary>

#### HIPAA Audit Parity for MCP Surface Tools and REST Data Query Invoke <a href="#hipaa-audit-parity-for-mcp-surface-tools-and-rest-data-query-invoke" id="hipaa-audit-parity-for-mcp-surface-tools-and-rest-data-query-invoke"></a>

Surface configuration tools on the MCP server and the REST workspace data query invoke endpoint now emit HIPAA audit events, closing audit gaps between transport surfaces.

**What changed:**

* **MCP surface tool audit rows.** The `create_surface`, `reshape_surface`, and `create_surface_from_template` MCP tools now emit a per-invocation HIPAA audit event carrying the real session credential and MCP transport indicator. Previously, these tools were audited only under the system surrogate credential, making MCP-originated surface writes indistinguishable from REST API-key writes in the audit log. The new audit row is in addition to the existing surrogate row, so no existing audit data is lost.
* **REST workspace data query invoke audit.** The REST endpoint for invoking a workspace data query now emits a HIPAA audit event on every invocation - successful executions, not-found responses, and execution errors are all audited. The audit event records the workspace, query ID, actor credential, and pass/fail status. This brings the REST invoke path to parity with the MCP invoke path, which was already audited.
* **Cross-entity surface creation documented.** Surface configuration tools (create, reshape, create from template) intentionally allow the caller to target any entity within the workspace, matching the behavior of the REST surface creation endpoint. Only the outbound-contact delivery tool restricts the target to the caller's own entity. This is not a behavioral change - the cross-entity posture was already in effect - but it is now explicitly documented in the tool behavior.

**What you need to do:**

* **No action required.** Audit events are emitted automatically. Audit log consumers will see additional rows for MCP surface tool invocations and REST data query invocations. No configuration changes are needed.

</details>

<details>

<summary>v0.9.415 - Platform API: Write-Event Provenance and Audit Action Labels for MCP Clinical Writes (July 2026)</summary>

#### Write-Event Provenance and Audit Action Labels for MCP Clinical Writes <a href="#write-event-provenance-and-audit-action-labels-for-mcp-clinical-writes" id="write-event-provenance-and-audit-action-labels-for-mcp-clinical-writes"></a>

Clinical and operational write tools invoked through the MCP surface now carry correct provenance attribution and per-tool HIPAA audit action labels, ensuring that MCP-originated writes are distinguishable from voice-originated writes in both the event history and the audit log.

**What changed:**

* **MCP write provenance.** Clinical write events created through the MCP surface are now attributed to the MCP channel rather than the voice channel. This means event history and downstream systems can distinguish whether a schedule, cancellation, refill, insurance write, or other clinical action originated from a partner agent (MCP) or the in-house voice agent. The voice path is unchanged.
* **Outbound EHR sync for MCP writes.** MCP-originated clinical writes are now eligible for outbound EHR sync. Previously, writes from the MCP surface could silently fail to propagate to the connected EHR. Schedule, cancel, refill, insurance, and other clinical writes through MCP now sync to the EHR through the same connector pipeline used by voice-originated writes.
* **Per-tool HIPAA audit action labels.** Each clinical write tool now emits a HIPAA audit event with a tool-specific action label (e.g., a scheduling write is audited as a clinical scheduling action rather than a generic enrichment write). Surface delivery is audited with its own distinct action label. This makes it easier to filter audit logs by clinical action type.
* **No behavioral change for voice path.** The in-house voice agent path continues to work identically. Provenance attribution, outbound sync eligibility, and audit labels for voice-originated writes are unchanged.

**What you need to do:**

* **No action required.** If you have MCP write tools enabled, provenance and audit labels are applied automatically. Audit log consumers that filter by action label will now see more specific labels for clinical writes and surface deliveries.

</details>

<details>

<summary>v0.9.414 - Platform API: Clinical and Operational Write Tools on MCP Surface (July 2026)</summary>

#### Clinical and Operational Write Tools on MCP Surface <a href="#clinical-and-operational-write-tools-on-mcp-surface" id="clinical-and-operational-write-tools-on-mcp-surface"></a>

The MCP world-tools surface now supports 12 clinical and operational write tools, enabling external and partner agents to perform scheduling, patient management, insurance, medication, and operational actions through the same MCP server used for read tools. This is a dark launch behind a feature flag, available only to provider-principal sessions.

**What changed:**

* **12 write tools added to the MCP surface.** The MCP server now registers write tools for patient creation, patient updates, unified patient save (create-or-update), appointment scheduling, appointment cancellation, appointment confirmation, appointment rescheduling, insurance creation, prescription refill requests, call logging, triage logging, and ticket creation. These tools are available alongside the existing read tools on the same MCP server.
* **Provider-principal only.** Write tools are restricted to provider-principal sessions. Non-provider sessions cannot discover or invoke write tools.
* **Dark launch behind feature flag.** Write tools are registered behind the existing MCP feature flag for write operations. No separate enablement is required beyond the write tools flag.
* **Shared write logic.** The write tools execute the same logic used by the voice agent path, ensuring consistent behavior across both surfaces. Patient creation includes duplicate detection by identifier. Appointment scheduling supports slot references from prior search results. Insurance creation fires outbound sync to the connected EHR. Prescription refills reference the original prescription.
* **Dual-entity writes for appointments.** Appointment lifecycle operations (book, cancel, confirm, reschedule) write events to both the appointment entity and the linked patient entity, keeping both projections in sync.
* **Outbound EHR sync.** Write tools that create or modify clinical data fire outbound sync events, so changes propagate to the connected EHR through the standard connector pipeline. Triage logging is an exception - it records the triage outcome without firing outbound sync.
* **Confirmation-gated confidence.** Write tools support an optional confirmation level (confirmed, mentioned, or inferred) that maps to a confidence score on the written event. This enables downstream systems to distinguish between data the patient explicitly confirmed versus data mentioned in passing.

**What you need to do:**

* **No action required.** If you have MCP write tools enabled and are using provider-principal sessions, the 12 write tools are automatically available. No configuration changes are needed.

</details>

<details>

<summary>v0.9.413 - Platform API: HIPAA Audit Logging for MCP Read Surface (July 2026)</summary>

#### HIPAA Audit Logging for MCP Read Surface <a href="#hipaa-audit-logging-for-mcp-read-surface" id="hipaa-audit-logging-for-mcp-read-surface"></a>

Every PHI-bearing read invocation on the MCP world-tools read surface is now HIPAA-audited, matching the audit coverage already in place for MCP write operations.

**What changed:**

* **Per-invoke audit on world-model reads.** Each call to a world-model entity read tool through the MCP server now emits a HIPAA audit event recording the workspace, actor, tool name, and whether the call succeeded or failed. Both successful reads and failed reads are audited.
* **Per-invoke audit on workspace data query reads.** Each invocation of a workspace data query through the MCP read surface now emits a HIPAA audit event. Rejected invocations - such as attempts to run a non-read-only query through the read surface - are also audited with a failure status.
* **Discovery is not audited.** Listing available tools or queries (discovery operations) does not touch PHI and is not audited. Only actual data-returning invocations are logged.
* **Same audit pattern as writes.** Read audit events follow the same structure and delivery path as the existing write-side audit events, recording the transport, tool name, pass/fail status, and credential identifier.
* **No change in local development.** When the audit subsystem is not configured (typical in local development), read invocations continue without audit logging, matching existing write-side behavior.

**What you need to do:**

* **No action required.** If you have the MCP world-tools feature flag enabled, read invocations are now automatically audited. No configuration changes are needed. Audit events appear in the same audit log used by MCP write operations.

</details>

<details>

<summary>v0.9.412 - Platform API: Batch Enrichment Write Tool on MCP Surface (July 2026)</summary>

#### Batch Enrichment Write Tool on MCP Surface <a href="#batch-enrichment-write-tool-on-mcp-surface" id="batch-enrichment-write-tool-on-mcp-surface"></a>

The MCP world-tools write surface now supports a batch enrichment tool that writes multiple enrichment values to a single entity in one call, with all-or-nothing validation.

**What changed:**

* **New `put_entity_enrichment_many` tool.** Entity-anchored MCP credentials can now set several enrichment values on their anchor entity in a single call. The tool accepts a list of key-value items and validates every item against the workspace's enrichment registry before writing any of them. If any item fails validation, nothing is written.
* **Same anchor and scope rules.** The batch tool enforces the same single-entity anchor constraint as the existing `put_entity_enrichment` tool - the batch targets only the caller's own anchor entity and cannot span multiple entities.
* **Per-item optional fields.** Each item in the batch can optionally include `source`, `source_system`, and `confidence` fields. Value type is resolved from the enrichment registry, matching the behavior of the single-item tool.
* **Idempotency with payload awareness.** The batch tool accepts an `idempotency_key` like the single-item tool, but folds the full batch payload into the dedup key. This means a changed batch under the same idempotency key re-applies rather than returning the prior result, while an identical retry is safely deduplicated.
* **Audit logging.** Each batch call is audit-logged with the tool name and a comma-separated list of enrichment keys, following the same HIPAA audit pattern as single-item writes. Both successful and failed writes are recorded.
* **Dark launch.** This tool is registered behind the same feature flag as the existing MCP write tools. No separate enablement is required.

**What you need to do:**

* **No action required.** If you have already enabled MCP write tools, the batch enrichment tool is automatically available. External agents can use it to reduce round trips when setting multiple enrichment values on the same entity.

</details>

<details>

<summary>v0.9.411 - Platform API: Workspace Data Queries on MCP Read Surface (July 2026)</summary>

#### Workspace Data Queries on MCP Read Surface <a href="#workspace-data-queries-on-mcp-read-surface" id="workspace-data-queries-on-mcp-read-surface"></a>

The MCP world-tools read surface now includes workspace data queries (`wsq_*`) alongside the existing world-model entity read tools. External and partner agents can discover and invoke a workspace's registered read-only data queries through the same MCP server.

**What changed:**

* **Two new MCP tools registered.** When the world-tools MCP feature flag is enabled, the MCP server now registers `list_workspace_data_queries` and `invoke_workspace_data_query` in addition to the existing world-model read tools. These tools let external agents discover available read-only queries and run them by name with typed parameters.
* **Read-only enforcement.** Only queries whose SQL is a single read-only statement (SELECT or WITH) are listed or runnable through this surface. Queries with write capabilities are excluded from discovery and rejected at invoke time even if called by name. Read-only access is also enforced at the database transaction level as a second safety layer, blocking any write that the static SQL analysis cannot detect.
* **Workspace-scoped execution.** Query execution is constrained to the authenticated workspace, matching the behavior of the REST invoke endpoint. The workspace is determined from the authenticated MCP context and is never caller-supplied.
* **Same feature flag.** These tools are registered behind the same `MCP_WORLD_TOOLS_ENABLED` feature flag that governs the world-model entity read tools. No separate enablement is required.

**What you need to do:**

* **No action required.** If you have already enabled the MCP world-tools feature flag, workspace data queries are automatically available on the read surface. Only read-only queries are exposed - no configuration changes are needed to protect write-capable queries.

</details>

<details>

<summary>v0.9.410 - Platform API: Per-Call Media Stream Host Routing (July 2026)</summary>

#### Per-Call Media Stream Host Routing <a href="#per-call-media-stream-host-routing" id="per-call-media-stream-host-routing"></a>

When a call uses the per-call media isolation path, the TwiML media stream endpoint now routes to the allocated per-call media server rather than the shared host. This is the activation step for the routing information stored during call setup (v0.9.409).

**What changed:**

* **Media stream host follows per-call allocation.** For calls on the per-call isolation path, the media stream URL in the generated TwiML now points to the allocated per-call media server. Previously, the allocated routing was stored but not consumed - this release activates consumption. All call legs (caller, operator, and agent) use the same resolution, so media streams for a given call are routed consistently.
* **No change for non-allowlisted workspaces.** Workspaces not on the per-call routing allowlist continue to use the default host derived from the incoming request. The generated TwiML is byte-identical to previous behavior when the per-call path is not active.
* **Dark launch.** This change is deployed behind the existing workspace allowlist gate. Only workspaces already enrolled in the per-call routing allowlist are affected. The routing change is transparent to API consumers - no changes to request or response formats.

**What you need to do:**

* **No action required.** This is an infrastructure change with no visible effect on API behavior. Workspaces on the per-call routing allowlist will begin routing media streams to the allocated per-call server. No API, SDK, or configuration changes are needed.

</details>

<details>

<summary>v0.9.409 - Platform API: Per-Call Media Server Allocation at Call Setup (July 2026)</summary>

#### Per-Call Media Server Allocation at Call Setup <a href="#per-call-media-server-allocation-at-call-setup" id="per-call-media-server-allocation-at-call-setup"></a>

The per-call media routing path now allocates and pins an isolated media server when the agent leg is created, rather than deferring allocation to a later stage. This ensures the call's media routing is determined before the agent leg joins the conference.

**What changed:**

* **Allocate-then-pin at agent leg creation.** When a call enters the per-call isolation path (workspace is allowlisted and per-call routing is enabled), the platform now allocates an isolated media server and pins its routing information during agent leg setup. The pinned routing is stored alongside the call's cached conference data and forwarded to downstream webhooks.
* **Idempotent across retries.** If the telephony provider retries the agent leg creation (for example, due to a timeout), the previously allocated server and routing are reused from the call's cached data. A retry never allocates a second server, preventing orphaned resources.
* **Graceful failure on pool exhaustion.** If the media server pool is exhausted or the allocation fails, the agent leg returns a retryable failure rather than a hard error. The call follows the existing retry contract, and callers experience a retry rather than a dropped call. A metric is emitted for observability.
* **No change for non-allowlisted workspaces.** Workspaces not on the per-call routing allowlist continue on the legacy path. The call setup parameters and cached conference data remain byte-identical to previous behavior when the per-call path is not active.
* **Dark launch.** This change is deployed as a dark feature. The allocated routing information is stored and forwarded but is not yet consumed by downstream media stream endpoints. A follow-up release will activate consumption.

**What you need to do:**

* **No action required.** This is a dark infrastructure change with no visible effect on API behavior or call quality. Workspaces on the per-call routing allowlist will begin allocating media servers at agent leg setup, but the allocation is not yet consumed downstream.

</details>

<details>

<summary>v0.9.408 - Platform API: Workspace-Scoped Voice Assignment Gate (July 2026)</summary>

#### Workspace-Scoped Voice Assignment Gate <a href="#workspace-scoped-voice-assignment-gate" id="workspace-scoped-voice-assignment-gate"></a>

The voice session assignment gate now supports workspace-level scoping, allowing per-call media routing to be enabled for a subset of workspaces rather than all-or-nothing.

**What changed:**

* **Workspace allowlist for voice assignments.** The per-call media routing gate can now be narrowed to a specific set of workspaces. When the allowlist is configured, only calls for workspaces in the allowlist take the per-call isolation path. Workspaces not in the allowlist continue on the legacy path. When the allowlist is empty or not configured, the global toggle governs all workspaces as before.
* **Graduated rollout support.** This enables graduated rollout of per-call media routing across your deployment. You can enable per-call routing for individual workspaces, validate behavior, and expand the allowlist incrementally before enabling it globally.
* **Startup validation.** If the workspace allowlist is configured but the per-call routing toggle is off, the service rejects the configuration at startup. The allowlist only narrows an already-enabled gate - it cannot enable routing on its own.
* **No change to default behavior.** If you are not using the workspace allowlist, per-call media routing behavior is unchanged. The global toggle continues to govern all workspaces.

**What you need to do:**

* **No action required for most deployments.** If you are not configuring workspace-scoped routing, behavior is unchanged.
* **For graduated rollouts:** Configure the workspace allowlist with the workspace IDs that should use per-call media routing. The global per-call routing toggle must also be enabled. Workspaces not in the allowlist will continue on the legacy path until they are added or the allowlist is cleared (at which point all workspaces use per-call routing).

</details>

<details>

<summary>v0.9.407 - Platform API: Atlas Call Intelligence Envelope Drops Quality Score (July 2026)</summary>

#### Atlas Call Intelligence Envelope Drops Quality Score <a href="#atlas-call-intelligence-envelope-drops-quality-score" id="atlas-call-intelligence-envelope-drops-quality-score"></a>

The lightweight call intelligence envelope emitted for Atlas voice calls no longer includes a quality score. Previously, the envelope carried a placeholder zero quality score, which could pollute aggregate quality metrics (such as average voice quality score) with a fake value. The quality score field is now omitted entirely, so envelope-only calls are excluded from quality score aggregations.

**What changed:**

* **Quality score omitted from envelope.** The call intelligence envelope emitted at the end of Atlas voice calls no longer includes a quality score. The field is left unset rather than carrying a placeholder zero. This means Atlas calls that have only an envelope record (no full post-call analysis) are excluded from quality score aggregations instead of dragging the average down with a fake zero.
* **No change to list membership.** Atlas voice calls continue to appear in conversation listings. The envelope still carries turn count, duration, completion reason, direction, service, and final state - all the fields needed for list membership.
* **No change to analysis summaries.** The envelope continues to carry empty analysis summaries, as before. Full post-call analysis for Atlas calls is planned as a follow-up.

**What you need to do:**

* **No action required.** The change is applied automatically. If you previously observed Atlas calls contributing a zero quality score to aggregate metrics, those calls are now excluded from quality score calculations.
* **Quality scores remain unavailable for Atlas envelope-only calls.** Atlas calls that have only an envelope record will show no quality score rather than a zero. Full call intelligence analysis for Atlas calls will be available in a future release.

</details>

<details>

<summary>v0.9.406 - Platform API: Atlas Voice Calls in Conversation Listings (July 2026)</summary>

#### Atlas Voice Calls in Conversation Listings <a href="#atlas-voice-calls-in-conversation-listings" id="atlas-voice-calls-in-conversation-listings"></a>

Atlas voice calls now emit a minimal call intelligence record at the end of each call, so they appear in conversation listings alongside in-house pipeline calls. Previously, Atlas calls emitted lifecycle events (start/end) but did not produce a call intelligence record, which meant they could be missing from views that derive call membership from intelligence data.

**What changed:**

* **Call intelligence envelope emitted for Atlas calls.** When an Atlas voice call ends, the platform now emits a lightweight call intelligence record containing the fields needed for conversation list membership: turn count, duration, completion reason, direction, service, and final state. This record is emitted independently of the call-ended event, so a failure in one does not block the other.
* **Calls appear in conversation listings.** Atlas voice calls now surface in conversation listings (including the Agent Forge `forge conversation list` command and Developer Console call logs) even when the call has no full post-call analysis. The listing entry includes turn count, duration, and completion reason.
* **No analysis data in the envelope.** The envelope record carries empty analysis summaries and omits quality scores, so envelope-only calls do not affect aggregate quality metrics. It is not a substitute for full call intelligence analysis - it exists solely to ensure list membership. Full post-call analysis for Atlas calls is planned as a follow-up.
* **Fail-open design.** If the call intelligence envelope cannot be emitted (for example, due to a transient service issue), the voice call completes normally. The envelope emission is best-effort and never blocks or drops a live call.

**What you need to do:**

* **No action required.** Atlas voice calls now automatically appear in conversation listings. No configuration changes are needed.
* **Quality scores are not available on envelope-only calls.** The envelope record does not include a quality score or analysis summaries. Do not expect quality assessments on Atlas calls until full call intelligence analysis is available in a future release.

</details>

<details>

<summary>v0.9.405 - Platform API: Atlas Per-State Tool Visibility and Reluctance Fix (July 2026)</summary>

#### Atlas Per-State Tool Visibility and Reluctance Fix <a href="#atlas-per-state-tool-visibility-and-reluctance-fix" id="atlas-per-state-tool-visibility-and-reluctance-fix"></a>

The Atlas runtime now surfaces each state's available tools by name in the compiled state-machine prompt and explicitly instructs the model that all listed tools are available and working. This eliminates a class of live-call reluctance where the model would decline to use an attached tool or claim it could not access a system the tool covers.

**What changed:**

* **Per-state tool lists in the prompt.** Each conversation state in the compiled Atlas prompt now includes a `tools` field listing the tool names available in that state. The model sees exactly which tools it can call at each point in the conversation, removing ambiguity about tool availability.
* **Explicit anti-reluctance instruction.** The state-machine prompt now instructs the model that all listed tools are genuinely available and working on the current call. The model is forbidden from telling the caller it cannot do something, cannot access a system, or does not have access to information that one of its tools provides. The model must call the tool instead.
* **No configuration changes.** The per-state tool visibility and anti-reluctance instruction are applied automatically to all Atlas voice sessions. No changes to context graphs, skills, or service configuration are needed.

**What you need to do:**

* **No action required.** The prompt changes are applied automatically. If you previously observed the model declining to use available tools or claiming it lacked access to systems during Atlas voice calls, those behaviors should no longer occur.

</details>

<details>

<summary>v0.9.404 - Platform API: Atlas In-Flight Write-Tool Deduplication (July 2026)</summary>

#### Atlas In-Flight Write-Tool Deduplication <a href="#atlas-in-flight-write-tool-deduplication" id="atlas-in-flight-write-tool-deduplication"></a>

Atlas voice sessions now guard against double-writes during live calls. If the model re-invokes an identical write tool (same tool name and arguments) while a previous invocation is still executing, the duplicate is short-circuited instead of executing a second time. This prevents life-critical double-writes for operations such as scheduling, insurance updates, and medication changes.

**What changed:**

* **In-flight write deduplication.** When the model calls a write tool during an Atlas voice session, the runtime tracks the call. If the model issues an identical write call (same name and arguments) before the first completes, the duplicate receives an immediate response indicating the operation is already in progress. The model is instructed not to retry.
* **Per-call scope.** The deduplication guard is scoped to each individual call. Each call tracks its own in-flight writes independently, so concurrent calls do not interfere with each other.
* **Automatic release.** Once the original write tool invocation completes (whether it succeeds or fails), the guard is released. A later identical write call will execute normally.
* **Write tool set from platform configuration.** The set of tools considered "write" tools is the same set used by the platform's existing tool execution safety controls. No additional configuration is needed.
* **No behavior change for read tools.** Tools not classified as write tools are unaffected and can be called concurrently without deduplication.

**What you need to do:**

* **No action required.** The in-flight write deduplication is applied automatically to all Atlas voice sessions. No configuration changes are needed.
* **Review write tool classifications.** If you have custom tools that perform writes but are not classified as write tools, ensure they are correctly classified so the deduplication guard applies to them.

</details>

<details>

<summary>v0.9.403 - Platform API: Atlas Voice Call Lifecycle (July 2026)</summary>

#### Atlas Voice Call Lifecycle <a href="#atlas-voice-call-lifecycle" id="atlas-voice-call-lifecycle"></a>

Atlas voice calls now participate in the full call lifecycle. Each Atlas voice call mints a call entity and emits start and end events, so Atlas calls appear in conversation listings, entity timelines, and duration reporting alongside in-house pipeline calls.

**What changed:**

* **Call entity created per call.** Every Atlas voice call now creates a call entity when the call begins, matching the behavior of the in-house voice pipeline. The call entity is projected to entity timelines and conversation listings.
* **Start and end events emitted.** Atlas voice calls emit call-started and call-ended events with duration, turn count, and completion reason. These events flow through the same world-model path as in-house calls, so Atlas calls have full duration accounting and completion tracking.
* **Calls appear in conversation listings.** Atlas voice calls now surface in conversation listings (including the Agent Forge `forge conversation list` command and Developer Console call logs) with the same metadata as in-house pipeline calls.
* **Fail-open design.** If the call entity or lifecycle event cannot be emitted (for example, due to a transient service issue), the voice call continues without interruption. Lifecycle events are best-effort and never block or drop a live call.
* **Completion reason tracking.** The call-ended event records whether the call completed normally, timed out, or ended due to an error, giving you clear diagnostics in call history.

**What you need to do:**

* **No action required.** Atlas voice calls now automatically appear in conversation listings and entity timelines. No configuration changes are needed.
* **Expect Atlas calls in conversation listings.** If you were previously running Atlas voice calls, those calls will now appear in conversation listings and entity timelines. Review your call history to confirm Atlas calls are surfacing as expected.

</details>

<details>

<summary>v0.9.402 - Platform API: Atlas Voice Billing Metering (July 2026)</summary>

#### Atlas Voice Billing Metering <a href="#atlas-voice-billing-metering" id="atlas-voice-billing-metering"></a>

Atlas voice sessions now emit billable token-usage events for every model response during a call. This brings Atlas voice billing to parity with the in-house voice pipeline - Atlas calls appear in standard usage reporting and are metered like any other conversation turn.

**What changed:**

* **Per-response billing events.** Every model response during an Atlas voice call now emits a billable audio token-usage event. The event captures input tokens, output tokens, and cached input tokens for the response, and is tagged with the call session and workspace.
* **Parity with in-house pipeline billing.** Atlas voice calls now flow through the same usage-metering path as in-house pipeline calls. Usage appears in the same reports and dashboards, so billing visibility is consistent across all voice runtimes.
* **No behavior change.** Call handling, audio output, and agent execution are unchanged. Billing events are emitted asynchronously and never block or interrupt the audio stream.

**What you need to do:**

* **No action required.** Atlas voice calls are now metered automatically. Usage will appear in your standard billing reports alongside other conversation turns.
* **Expect Atlas voice usage in reports.** If you were previously running Atlas voice calls in a dark or preview configuration, those calls will now generate billable usage events. Review your usage dashboards to confirm Atlas call volumes.

</details>

<details>

<summary>v0.9.401 - Platform API: Atlas Voice Tool Roster Logging (July 2026)</summary>

#### Atlas Voice Tool Roster Logging <a href="#atlas-voice-tool-roster-logging" id="atlas-voice-tool-roster-logging"></a>

Atlas voice sessions now log the full list of attached platform tools at the start of every session. This gives operators a clear signal to distinguish "the model chose not to use an available tool" from "the tool was never attached to the session" when reviewing live or historical calls.

**What changed:**

* **Tool roster logged at session start.** When an Atlas voice session begins, the platform logs the names and count of all platform tools (skills and surface tools) attached to the agent. Tool names are configuration data, not patient data, so the log entry is PHI-safe.
* **Debugging tool binding gaps.** If a call review shows a tool was never invoked, the roster log confirms whether the tool was present on the session. A missing tool in the roster indicates a binding or provisioning gap rather than model reluctance.
* **No behavior change.** Tool attachment and agent execution are unchanged. This is an observability improvement only.

**What you need to do:**

* **No action required.** The tool roster is logged automatically on every Atlas voice session. No configuration changes are needed.
* **Use the roster for debugging.** When investigating why a tool was not used during a call, check the session start log for the tool roster to confirm the tool was attached.

</details>

<details>

<summary>v0.9.400 - Platform API: Atlas Single State-Machine Agent for Voice (July 2026)</summary>

#### Atlas Single State-Machine Agent for Voice <a href="#atlas-single-state-machine-agent-for-voice" id="atlas-single-state-machine-agent-for-voice"></a>

Atlas voice now uses a single state-machine agent architecture instead of multi-agent handoffs. The context graph is compiled into one agent whose prompt embeds the conversation states and in-prompt transitions, and the model navigates them in-context without handoff tools. This eliminates the transfer-tool reluctance that caused voice calls to stall in the entry phase.

**What changed:**

* **Single agent with embedded states.** Atlas voice calls now run as a single agent whose system prompt contains all conversation states, their instructions, and transition conditions. The model moves between states naturally during the conversation without invoking transfer tools. This is the recommended architecture for single-task voice agents.
* **No handoff tools on voice.** Transfer tools are no longer generated for Atlas voice calls. The model navigates states in-context using the transition conditions embedded in its prompt, which removes the transfer-tool reluctance that left the model parked in the entry phase during live calls.
* **Full platform tool set attached.** The complete platform tool set (skills and surface tools) is attached directly to the single agent, consistent with previous behavior.
* **Multi-agent handoffs preserved for cross-specialist branching.** The multi-agent handoff architecture remains available for scenarios that require genuine cross-specialist branching (multiple independent agents with different capabilities). Single-task voice calls use the state-machine form.
* **State-machine prompt format.** The prompt follows a structured format: a persona/guidelines preamble, a conversation flow guide explaining how to navigate states, a start state identifier, and the states rendered as structured data with IDs, instructions, and transition conditions.

**What you need to do:**

* **No action required.** Atlas voice calls automatically use the single state-machine agent architecture. No configuration changes are needed.
* **Expect improved state navigation.** If you observed Atlas voice calls stalling in the entry phase because the model would not invoke transfer tools, this update addresses the root cause by removing the need for transfer tools entirely.

</details>

<details>

<summary>Current Platform API Contract Summary</summary>

#### Current Platform API Contract Summary <a href="#current-platform-api-contract-summary-1" id="current-platform-api-contract-summary-1"></a>

The current Platform API OpenAPI contract is the source of truth for exact routes and schemas.

* Text sessions use `WS /v1/{workspace_id}/sessions/connect` with `Sec-WebSocket-Protocol` authentication.
* SMS opt-in consent enforcement: US numbers with A2P campaigns require opt-in before sending, and opt-out (STOP/HELP) keywords are managed by the platform.
* US/CA toll-free numbers: STOP, START, and UNSTOP keywords are handled by the platform. STOP creates an opt-out; START/UNSTOP reverses it. Keyword messages are never forwarded to the agent.
* SMS opt-out enforcement applies to all number types (toll-free, long code, short code). If a recipient has opted out, the send endpoint returns 422.
* SMS opt-outs are permanent from the platform's perspective - an opt-in resend cannot reverse a STOP. Re-subscription requires a fresh, recipient-initiated consent path (or START/UNSTOP for toll-free). The full opt-out history is retained for audit.
* Ringless voicemail is configured through channel use cases, service bindings, and Amigo-managed channel infrastructure; there are no current public workspace-scoped voicemail send/list endpoints.
* Public integration management is REST integration CRUD plus child endpoint CRUD and per-endpoint test operations; endpoints are addressed by endpoint ID.
* Desktop integrations are system-provisioned and are not created, updated, or deleted through the public REST integrations CRUD surface.
* Unified run reads use `GET /v1/{workspace_id}/runs`, `GET /v1/{workspace_id}/runs/{run_id}`, and `GET /v1/{workspace_id}/runs/{run_id}/trajectory`; the former conversation-only and framework-only list endpoints are retired.
* Non-voice operator takeover can stage the next reply with `POST /v1/{workspace_id}/runs/{run_id}/authored-turn`.
* API-key creation clients can discover the current role and permission matrix from `GET /v1/{workspace_id}/api-keys/permission-catalog`.
* External-user identity is linked to a world entity through the external identity bindings API and resolved by stable subject key at conversation start.
* Active event-based triggers match live workspace events at most once, without replay or later reconciliation.
* Real-time voice controls live under `voice_config.realtime`; the older `realtime_voice` shortcut is deprecated.
* Scribe sessions support generated notes, summaries, and checklists, plus note finalization.
* Historical Classic conversation metadata can be imported through `POST /v1/{workspace_id}/world/migration/conversations`.
* Conversation detail supports `include_tool_calls=true` for per-turn tool-call details, including failure messages when available.
* Skill `input_schema` create/update validation enforces the supported LLM tool-schema subset. The same validation also applies to each static tool's `input_schema` on skill create and update.
* Skills support optional `temperature` (0-1) and `top_p` (0-1) sampling parameters. Model-gated; set at most one.
* `ChannelKind` includes `imessage`.
* Use case service bindings accept `sms` and `imessage` channels.
* Outbound text endpoint supports `channel_kind='imessage'` with required `use_case_id`.
* A2P campaign submit and response no longer include `subscriber_opt_in` - the platform always treats campaigns as having subscriber opt-in.

</details>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.concurrence.com/api-reference/change-logs/amigo-api/amigo-api-history-09.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
