For the complete documentation index, see llms.txt. This page is also available as Markdown.

Archive: v0.9.100 - v0.9.249

Archived Concurrence API release notes covering v0.9.100 - v0.9.249. For current releases, see the main Concurrence API changelog.

This archive includes integrations, simulations, data, and voice. Entries retain their original release context; they do not establish current availability. Use Current Upgrade Guidance before applying an older example.

v0.9.249 - Platform API: Call Trace Analysis Retry Guidance Updated (July 2026)

Call Trace Analysis Retry Guidance Updated

The call trace analysis endpoint now recommends a longer retry interval for calls in pending status.

What changed:

  • Retry guidance updated. The pending status description on the call trace analysis endpoint previously recommended retrying after 15 minutes. The recommended retry interval is now 30 minutes, reflecting updated processing cadence for the analysis pipeline.

What you need to do:

  • Update polling intervals. If your integration polls the call trace analysis endpoint for pending results on a 15-minute interval, increase it to 30 minutes. More frequent polling still works but will return pending for longer before results are available.

v0.9.248 - Platform API: Integration Model Simplified (July 2026)

Integration Model Simplified

The integration data model has been simplified. The previous two-layer structure (a parent integration record plus a separate child record for REST-specific fields) has been collapsed into a single integration resource. All integration fields - including base_url and auth - now live directly on the integration object.

What changed:

  • Flat integration model. Integration responses no longer use an internal parent/child structure. The base_url and auth fields are returned directly on the integration resource alongside name, display_name, enabled, and other existing fields. This is a structural simplification with no change to the response shape or field names visible to API consumers.

  • kind field removed from integration responses. The kind field is no longer returned in integration responses or accepted in create/update requests. All integrations are REST integrations. The kind filter has been removed from the list integrations endpoint.

  • kind field removed from internal integration payloads. Internal integration payloads used during session initialization no longer include a kind field. If your code consumes internal integration data and checks or filters by kind, remove that logic.

  • No changes to endpoint structure. Integration endpoints (the per-action definitions within an integration) are unchanged. They continue to reference the parent integration directly.

What you need to do:

  • Remove references to kind. If your code reads, filters, or sets the kind field on integrations, remove those references. The field is no longer present in responses or accepted in requests.

  • No other migration required. The visible response fields (id, workspace_id, name, display_name, base_url, auth, enabled, endpoint_count, created_at, updated_at) are unchanged. Existing API consumers that do not reference kind require no changes.

v0.9.247 - Platform API: Desktop Integration Type and Computer Use Skill Tier Removed (July 2026)

Desktop Integration Type and Computer Use Skill Tier Removed

The platform no longer supports desktop-type integrations or the computer use execution tier for skills. REST integrations remain the only supported integration kind. The desktop sidecar infrastructure for remote desktop connectivity is retained as a standalone component but is no longer managed through the platform API.

What changed:

  • Desktop integrations removed. The desktop integration kind has been removed. Integrations endpoints no longer accept or return desktop-type integrations. The kind filter on the list integrations endpoint no longer includes desktop as a valid value. Existing desktop integration records are archived but no longer accessible through the API.

  • Computer use execution tier removed from skills. Skills no longer support the computer_use execution tier. The execution_tier field has been removed from skill configuration. All skills now use the standard orchestrated execution model.

  • Desktop session endpoints removed. All desktop session management endpoints have been removed from the API. These endpoints previously handled creating, managing, and terminating desktop automation sessions.

  • Task queue endpoints removed. Task dispatch and task status endpoints associated with background skill execution have been removed.

  • Skill response model simplified. The execution_tier and desktop_integration fields are no longer returned in skill responses.

  • Integration response model simplified. The kind field is still present on integration responses but will always be rest. Desktop-specific fields (host, port, display dimensions, gateway configuration, remote app settings) are no longer returned.

What you need to do:

  • Remove references to desktop integrations. If your code creates or filters integrations by kind: desktop, remove those references. Only rest integrations are supported.

  • Remove references to execution_tier. If your code sets execution_tier on skill configurations, remove that field. The field is no longer accepted.

  • Remove references to desktop_integration. If your skill configurations reference a desktop_integration name, remove that field.

  • Remove calls to desktop session endpoints. If your code calls desktop session management endpoints, remove those calls.

  • Remove calls to task queue endpoints. If your code calls task dispatch or task status endpoints, remove those calls.

v0.9.246 - Platform API: Simulation Case Eval Execution (July 2026)

Simulation Case Eval Execution

Simulation runs now automatically execute evaluation criteria (evals) defined on saved cases when a run completes. Eval results are returned inline on the run detail endpoint.

What changed:

  • Automatic eval execution on run completion. When a simulation run finishes, the platform evaluates all eval definitions captured from the run's cases. Two eval types are supported: assertions (which validate conversation outcomes) and metric checks (which compare observed metric values against expectations).

  • Assertion eval kinds. Assertion evals support several kinds: transcript_contains and must_contain check whether a phrase appears in the conversation transcript; transcript_not_contains and must_not_contain verify a phrase does not appear; tool_called checks whether a specific tool was invoked during the conversation; final_state checks whether the conversation ended in an expected state; and llm_judge uses an AI evaluator to judge the transcript against a natural-language criterion.

  • Metric eval checks. Metric evals look up observed metric values for the run and compare them against configured expectations. Expectations can specify exact equality, numeric ranges (gte/min, lte/max), or string containment.

  • New fields on GET /runs/{run_id} response. The run detail response now includes eval_results (array of eval result objects), eval_result_count, eval_pass_count, eval_fail_count, and eval_error_count.

  • Eval result object. Each eval result includes id, run_id, case_id, session_id, eval_key, eval_type, assertion_kind, metric_key, status (passed, failed, pending, skipped, or error), passed, score, expected, actual, rationale, details, definition, and created_at.

  • Real-time events. Eval results emit events through the standard event pipeline, so dashboards and listeners can react to eval outcomes as they are produced.

What you need to do:

  • No action required. The new fields are additive. Existing integrations that do not read eval results are unaffected.

  • To use case evals, define evals on your simulation cases (assertion or metric type with the appropriate kind, expected values, and parameters). When runs complete, eval results will appear automatically on the run detail response.

  • To track eval progress, read the eval_result_count, eval_pass_count, eval_fail_count, and eval_error_count fields from the run detail to get summary counts without iterating the full results array.

v0.9.245 - Platform API: Context Graph State in Non-Streaming Turn Responses (July 2026)

Context Graph State in Non-Streaming Turn Responses

The non-streaming conversation turn endpoint now returns the current context graph state alongside the agent response, giving callers visibility into where the agent is in the conversation flow after each turn.

What changed:

  • New context_graph_state field on turn responses. Non-streaming turn responses now include a context_graph_state field (object or null). When available, this field contains the agent's current position in the context graph, including the active node, visited states, and state-specific metadata. The field is null when the context graph state cannot be determined.

  • No change to streaming responses. This field is only returned on non-streaming (REST) turn responses. Streaming turn interactions are not affected.

What you need to do:

  • No action required. The new field is additive. Existing integrations that do not read context_graph_state are unaffected.

  • To use context graph state, read the context_graph_state field from the turn response object. Use it to track conversation flow progression, render navigation indicators, or drive conditional logic based on the agent's current state.

v0.9.244 - Platform API: REST Integration Endpoints as Context Graph Tool IDs (July 2026)

REST Integration Endpoints as Context Graph Tool IDs

Context graph validation now accepts REST integration endpoints as valid tool references. Previously, tool IDs in context graph states could only reference built-in tools, platform functions (fn_*), workspace data queries (wsq_*), and skill slugs. Now, endpoints from enabled workspace REST integrations are also accepted.

What changed:

  • Integration endpoints accepted as tool IDs. Context graph tool references using the {integration_name}_{endpoint_name} format are validated against the workspace's enabled REST integrations. Each enabled integration's endpoints are resolved during context graph version creation, so references to disabled or nonexistent integrations are rejected.

  • Validation scoped to workspace. Integration endpoint resolution is scoped to the workspace that owns the context graph. Endpoints from integrations in other workspaces are not visible and will fail validation.

What you need to do:

  • No action required for existing context graphs. This change only adds a new category of accepted tool IDs. Existing context graphs that do not reference integration endpoints are unaffected.

  • To use integration endpoints in context graphs, ensure the target REST integration is enabled in your workspace and reference endpoints using the {integration_name}_{endpoint_name} format in your tool ID fields.

v0.9.243 - Platform API: API Key Name in Expiry Alerts (July 2026)

API Key Name in Expiry Alerts

API key expiration alerts now include the key name alongside the key ID, making it easier to identify which key is approaching expiry without looking it up manually.

What changed:

  • Key name included in expiry notifications. Expiration alert messages now display the API key name as a separate field before the key ID. If no name was set on the key, the alert displays "Unknown" as the key name.

  • Webhook payload updated. The API key expiry webhook payload now includes an optional api_key_name field (string or null). Existing webhook consumers are not affected - the field is additive and defaults to null when not present.

What you need to do:

  • No action required. Expiry alerts will automatically include the key name going forward. If you consume API key expiry webhooks programmatically, you can optionally read the new api_key_name field from the payload.

v0.9.242 - Platform API: Integration Auth Redesign (July 2026)

Integration Auth Redesign

Integration authentication types have been restructured into four clear variants with a unified secret storage model. The previous six auth types (api_key_header, bearer_token, oauth2_client_credentials, json_token_exchange, oauth2_jwt_bearer, bearer_token_exchange) are replaced by four types with cleaner configuration surfaces.

What changed:

  • New auth types. Four auth types replace the previous six:

    • static_header - Replaces api_key_header and bearer_token. A single secret value sent verbatim as one header. For bearer tokens, store the full Bearer <token> string as the secret value and set header_name to Authorization.

    • oauth2_client_credentials - RFC 6749 § 4.4 Client Credentials grant. Now supports a client_auth_method field (basic or body) to control how client credentials are sent to the token endpoint.

    • oauth2_jwt_bearer - RFC 7523 § 2.1 JWT Bearer Token grant. Now supports configurable signing algorithms (RS256 through ES512), explicit include_iat and include_jti toggles, required assertion_subject field, and an extra_claims object for vendor-specific JWT extensions.

    • custom_token_exchange - Replaces json_token_exchange and bearer_token_exchange. A general-purpose pre-flight exchange with configurable request encoding (json or form), static and parameter-sourced headers and body fields, and a JSON Pointer path for extracting the token from the exchange response.

  • Unified secret storage. All auth types now use a single secret_value field on the create/update request. The secret is stored at a single per-integration path. The previous per-type secret suffixes (api_key, bearer_token, client_secret, private_key, exchange_secret) are consolidated.

  • secret_value moved to top level. The secret_value field is now a top-level field on the integration create/update request body, not nested inside the auth object. It is required when auth is provided.

  • JSON Pointer keys for static body fields. Endpoint static_body_fields now use RFC 6901 JSON Pointer syntax (e.g. /meta/tool_name) instead of dot-notation (meta.tool_name).

  • RFC 6570 URI Templates for path parameters. Endpoint paths now use RFC 6570 Level 1 URI Templates (e.g. /patients/{patient_id}/appointments) instead of the previous {param} convention. Behavior is the same - matched parameters are URL-encoded and consumed from the request params.

  • Auto-merged input schemas for custom token exchange. When an integration uses custom_token_exchange auth with parameter mappings (param_headers or param_body_fields), the mapped parameters are automatically added to each endpoint's input schema. This ensures the agent knows to supply these values without manual schema duplication.

  • Error handling. Integration endpoint calls now raise a structured error on any failure (auth errors, transport failures, HTTP error responses, response processing errors) instead of returning an error envelope in the success response. LLM-facing callers receive a JSON error payload so the agent session continues running.

What you need to do:

  • If you use api_key_header auth: Change type to static_header. Move secret_value to the top-level request body.

  • If you use bearer_token auth: Change type to static_header, set header_name to Authorization, and prepend Bearer to your secret value. Move secret_value to the top-level request body.

  • If you use oauth2_client_credentials auth: Add client_auth_method (either basic or body). Move secret_value to the top-level request body.

  • If you use json_token_exchange auth: Migrate to custom_token_exchange. Map your token_request_client_id_field and token_request_client_secret_field to static_body_fields entries (use {secret} placeholder for the secret). Set response_token_path to a JSON Pointer equivalent of your token_response_path (e.g. access_token becomes /access_token). Move secret_value to the top-level request body.

  • If you use bearer_token_exchange auth: Migrate to custom_token_exchange. Map your exchange_secret_header and exchange_secret_format to static_headers entries. Map exchange_param_headers to param_headers. Set response_token_path to a JSON Pointer (e.g. token becomes /token). Move secret_value to the top-level request body.

  • If you use oauth2_jwt_bearer auth: Add the now-required fields: assertion_subject, assertion_algorithm, include_iat, include_jti, and extra_claims (empty object {} if not needed). The assertion_scopes_in_jwt field is removed - use extra_claims with key scope instead. Move secret_value to the top-level request body.

  • If you use dot-notation static_body_fields on endpoints: Convert to JSON Pointer syntax (e.g. meta.tool_name becomes /meta/tool_name).

v0.9.241 - Platform API: First-Class Simulation Suites (July 2026)

First-Class Simulation Suites

Simulation suites are now first-class resources with full CRUD support and a dedicated run endpoint. Previously, suites were derived dynamically from suite:* tags on saved cases. Suites are now independent, named collections that define an explicit case list and optional required tags for dynamic case matching.

What changed:

  • New suite endpoints. Five new endpoints for managing simulation suites:

    • POST /simulations/suites - Create a suite with a name, description, explicit case IDs (max 500), required tags for dynamic matching, suite-level tags, and metadata.

    • GET /simulations/suites - List all suites in the workspace, ordered by creation date (newest first). Each suite includes a case_count reflecting the total resolved cases.

    • GET /simulations/suites/{suite_id} - Get a single suite by ID.

    • PATCH /simulations/suites/{suite_id} - Partially update a suite. At least one field is required.

    • DELETE /simulations/suites/{suite_id} - Delete a suite (204 on success).

  • Dedicated suite run endpoint. POST /simulations/suites/{suite_id}/run executes all cases resolved by a suite as a benchmark batch. The suite's explicit case IDs and required tags are combined to select the case set. The required_tags field must not be provided in the request body for suite runs.

  • Suite support on benchmark endpoint. POST /simulations/benchmarks/run now accepts an optional suite_id field. When provided, the benchmark resolves cases from the suite definition instead of using required_tags. suite_id and required_tags are mutually exclusive - providing both returns HTTP 422.

  • Updated suite response shape. The suite list and detail responses now return full suite objects with id, workspace_id, name, description, case_ids, required_tags, tags, metadata, case_count, created_by, created_at, and updated_at. The previous tag-derived response shape (tag, name, service_ids, latest_updated_at) is replaced.

  • Updated benchmark response. The benchmark run response now includes an optional suite_id field indicating which suite triggered the run, if any.

  • Stricter request validation. Create and update request bodies for simulation cases and suites now reject extra fields (HTTP 422) instead of silently ignoring them.

What you need to do:

  • If you used the GET /simulations/suites endpoint: Update your client to handle the new response shape. The response now returns full suite objects instead of tag-derived summaries. The tag, service_ids, and latest_updated_at fields are no longer present.

  • If you created suites by tagging cases with suite:* tags: Existing suite:* tags on cases still work for filtering, but suites are now managed as independent resources. Create explicit suite resources to take advantage of the new suite management and run capabilities.

  • If you used the benchmark endpoint: The required_tags field is now optional (it was previously required for meaningful results). You can use suite_id instead to run a suite-based benchmark.

  • If you sent extra fields in case create/update requests: Review your request payloads. Extra fields that were previously ignored now cause a 422 validation error.

v0.9.240 - Platform API: Voice Conversation Turn Fallback to Durable Store (July 2026)

Voice Conversation Turn Fallback to Durable Store

Voice conversation detail now falls back to the durable analytical store when turn data is no longer available in the hot session cache. Previously, voice conversation detail only read turns from the hot cache, which meant conversations whose cache had expired returned an empty turns array even though turn data existed in the durable store.

What changed:

  • Automatic fallback for voice turns. The voice conversation detail endpoint now uses the same two-tier turn resolution as text conversations - the hot session cache is checked first, and if no turns are found, the endpoint reads from the durable analytical store. This ensures that historical voice conversations retain their full turn history regardless of cache expiration.

  • Consistent behavior across channels. Text and voice conversation detail endpoints now follow the same turn resolution path. Both channels check the hot cache first and fall back to the durable store, so turn availability is consistent regardless of conversation type.

  • No change to response shape. The voice conversation detail response schema is unchanged. Conversations that previously returned an empty turns array due to cache expiration will now return their full turn history.

What you need to do:

  • No action required. This is a backwards-compatible improvement. Voice conversation detail responses that previously returned empty turns for expired sessions will now include the full turn history. If your application handled empty turns arrays as a special case for older voice conversations, that workaround is no longer necessary.

v0.9.239 - Platform API: Simulation Case Scenario Backfill (July 2026)

Simulation Case Scenario Backfill

Simulation case responses now guarantee that the scenario.instructions field is always present and non-empty across all endpoints that return simulation cases.

What changed:

  • scenario.instructions always populated. The list, get, create, and update simulation case endpoints now ensure that every returned case includes a non-empty scenario.instructions value. Previously, legacy cases that were created before the schema restructuring could return an empty or missing instructions field inside the scenario object.

  • Fallback for legacy cases. Cases that have no scenario instructions - for example, cases created before the schema migration - now fall back to the case description. If neither is available, a default placeholder is returned. This prevents API consumers from receiving empty scenario content for older cases.

  • Database backfill included. Existing legacy cases with empty scenario data have been backfilled so that their stored scenario content is consistent with the new guarantee.

What you need to do:

  • No action required. This is a backwards-compatible fix. If your code already handles the scenario.instructions field from the v0.9.238 schema, it will continue to work. Cases that previously returned empty instructions now return meaningful content instead.

  • If you had workarounds for empty scenario.instructions: You can safely remove any client-side fallback logic that handled missing or empty instructions, as the API now guarantees a non-empty value.

v0.9.238 - Platform API: Simulation Case Schema Refactored (July 2026)

Simulation Case Schema Refactored

The simulation case schema has been restructured to use a nested, composable shape. Flat top-level fields for scenario content, grounding, evaluation criteria, and provenance have been replaced with structured objects. This is a breaking change to the simulation case create, update, and response shapes.

What changed:

  • scenario replaces scenario_instructions, initial_message, and temperament. These three fields are now nested inside a scenario object with keys instructions, initial_message, and temperament. The scenario.instructions field is required and must be non-empty. initial_message defaults to an empty string and temperament defaults to null.

  • grounding replaces fixtures. The fixtures object has been replaced by a grounding object. Currently supports one optional field: patient_entity_id (UUID). The previous fixtures.case_specific, fixtures.grounding_facts, and fixtures.schema sub-fields are no longer accepted.

  • evals replaces assertions. The assertions array has been replaced by an evals array. Each eval item is a discriminated union with a type field. Two types are supported: metric (with metric_key, expected, params, weight) and assertion (with key, assertion_kind, description, expected, params, weight). Maximum 100 items per case.

  • metadata replaces provenance. The provenance string field has been removed. A free-form metadata object is now available for arbitrary key-value data. Cases created by the scenario generator or bridge include a source key in metadata (e.g. "source": "bridge").

  • constraints and target_spec removed. These top-level fields are no longer part of the case schema. Target specifications and constraints are now managed through evals and metadata.

  • Per-case entity ID resolution updated. Benchmark runs that resolve a patient entity ID per case now read from grounding.patient_entity_id instead of fixtures.case_specific.entity_id or fixtures.entity_id.

  • Run tags updated. Cases with a source value in metadata produce a source:<value> run tag instead of the previous provenance:<value> tag.

What you need to do:

  • If you create simulation cases via the API: Restructure your request body. Move scenario_instructions, initial_message, and temperament into the scenario object. Move fixture data into grounding. Convert assertions to evals with the appropriate type discriminator. Replace provenance with a metadata object containing a source key if needed.

  • If you read simulation case responses: Update your parsing to read from the new nested fields (scenario.instructions, scenario.initial_message, scenario.temperament, grounding.patient_entity_id, evals, metadata) instead of the removed top-level fields.

  • If you update simulation cases via PATCH: Use the new field names (scenario, grounding, evals, metadata) in your update payloads. The old field names (scenario_instructions, initial_message, temperament, fixtures, constraints, target_spec, assertions, provenance) are no longer accepted.

  • If you rely on per-case entity IDs in benchmarks: Set grounding.patient_entity_id on each case instead of embedding the entity ID in fixtures.

v0.9.237 - Platform API: Integration Endpoint Addressing Changed to ID (July 2026)

Integration Endpoint Addressing Changed to ID

Integration endpoint routes now use the endpoint's stable id instead of the endpoint name as the path parameter. The create-integration endpoint no longer accepts inline endpoints - endpoints must be added individually after the integration is created. The list-endpoints endpoint now supports search, multi-axis sorting, and cursor-based pagination.

What changed:

  • Endpoint path parameter changed from endpoint_name to endpoint_id. The GET, PATCH, DELETE, and test routes for individual endpoints now use the endpoint's UUID (endpoint_id) instead of the endpoint name. The endpoint id is returned in the create and list responses.

  • Create integration no longer accepts inline endpoints. The endpoints array has been removed from the create-integration request body. To add endpoints, use POST /integrations/{integration_id}/endpoints after creating the integration.

  • Endpoint responses now include id. All endpoint responses (create, get, list, update) now include a stable id field (UUID) that uniquely identifies the endpoint.

  • retry_on_status is now a set. The retry_on_status field on endpoint create, update, and response objects is now a set of integers (no duplicates) instead of an array. Duplicate status codes in requests are automatically deduplicated.

  • List endpoints now supports search and sorting. The list-endpoints route accepts search (substring match on name or description), sort_by (repeated query param with +field or -field syntax; allowed fields: name, created_at, updated_at), limit (1-200, default 50), and continuation_token (opaque cursor for pagination).

  • Get integration returns endpoint_count instead of inline endpoints. The integration response body now includes an endpoint_count integer instead of the full endpoints array. Use the list-endpoints route to retrieve endpoint details.

  • Get integration returns both REST and desktop kinds. The get-integration route now returns a discriminated response that includes desktop integrations in addition to REST integrations.

  • Delete integration returns 409 when referenced by skills. Deleting an integration that is referenced by one or more skills now returns 409 Conflict with a message listing the referencing skill names, instead of silently succeeding.

What you need to do:

  • If you call endpoint routes using endpoint_name in the URL path: Update to use the endpoint id (UUID) instead. Retrieve endpoint IDs from the create or list responses.

  • If you pass endpoints in the create-integration request body: Remove the endpoints field. Create the integration first, then add endpoints individually using the create-endpoint route.

  • If you read endpoints from integration responses: Use the endpoint_count field for summary information. Call the list-endpoints route to retrieve full endpoint details.

  • If you read retry_on_status as an ordered array: Treat the field as an unordered set. Duplicate values are no longer preserved.

  • If you paginate the list-endpoints route: The response shape now includes items, has_more, and continuation_token fields. Pass the continuation_token from the response back as a query parameter to retrieve the next page.

v0.9.236 - Platform API: Direct Execution Tier Removed (July 2026)

Direct Execution Tier Removed

The direct execution tier has been removed from the Skills API. Skills that previously used the direct tier - which executed a single integration endpoint call without a companion agent - should be reconfigured to use endpoint overrides or the orchestrated tier instead.

What changed:

  • direct removed from execution_tier. The execution_tier field on skill create, update, and response objects now accepts only orchestrated and computer_use. Requests that specify direct are rejected.

  • system_prompt now required for all skills. Previously, system_prompt was optional for direct-tier skills (since no companion agent was involved). With the direct tier removed, every skill requires a system_prompt.

  • Task state tier field no longer includes direct. The tier field on task state responses now accepts companion, desktop, and computer_use. Tasks default to companion when no tier is recorded.

  • Former direct-tier skills migrated automatically. Existing skills that used the direct tier have been migrated to use endpoint overrides. The underlying integration endpoint is now invoked directly by the agent as a tool rather than wrapped in a dedicated skill.

What you need to do:

  • If you create or update skills with execution_tier: "direct": Change to orchestrated (or computer_use if applicable) and provide a system_prompt. Alternatively, remove the skill and let the agent call the underlying integration endpoint directly.

  • If you read execution_tier from skill responses and handle direct: Remove handling for the direct value. Only orchestrated and computer_use are returned.

  • If you read the tier field from task state responses and handle direct: Remove handling for direct. The value is no longer returned.

v0.9.235 - Platform API: Integration Endpoint Config Reshaped (July 2026)

Integration Endpoint Config Reshaped

Integration endpoint configuration has been simplified. Response shaping now uses a single Jinja template instead of separate filter, key, and template fields. Request-side static injection uses a flat field map instead of a nested transform object. Retry and timeout settings are now direct fields instead of a nested config object.

What changed:

  • response_template replaces response_filter, result_key, and result_template. Response shaping is now a single Jinja template string rendered in a sandboxed environment. The template receives the parsed JSON response as top-level variables. Missing fields must be handled explicitly with | default("N/A") - unhandled missing fields raise an error. Set to null to fall back to the raw JSON response.

  • max_response_length replaces max_result_length. Same behavior (truncate rendered output to prevent token bloat, 0 = no limit), renamed for clarity.

  • static_body_fields replaces request_transform. Static fields are now a flat key-value map merged into POST/PUT/PATCH request bodies. Keys support dot-notation to build nested objects (e.g. meta.tool_name becomes {"meta": {"tool_name": ...}}). The inject map and wrap_params_key from the previous request_transform object are no longer accepted.

  • timeout_seconds added. Per-request HTTP timeout, configurable from 0 to 600 seconds. Default: 30.0. Previously this was a fixed internal default.

  • max_retries and retry_on_status replace retry_config. Retry settings are now direct fields on the endpoint instead of a nested object. Defaults are unchanged (max_retries: 2, retry_on_status: [429, 502, 503, 504]).

  • Test endpoint response reshaped. The after_filter and after_mapping fields have been removed from the test endpoint response. A new rendered field shows the output after Jinja template rendering. final_result now contains the rendered output after truncation.

What you need to do:

  • If you set response_filter, result_key, or result_template on endpoints: Replace these with a single response_template using Jinja syntax. For example, a template like {{name}} - {{birthDate}} replaces the old result_template with {{field.path}} placeholders. Add | default("N/A") to any field reference that might be missing.

  • If you set max_result_length on endpoints: Rename to max_response_length. The value and behavior are unchanged.

  • If you use request_transform with inject or wrap_params_key: Replace with static_body_fields. Move injected key-value pairs directly into the map. If you used wrap_params_key, restructure your endpoint configuration to use dot-notation keys in static_body_fields instead.

  • If you set retry_config on endpoints: Replace with max_retries and retry_on_status as direct fields.

  • If you read after_filter or after_mapping from test endpoint responses: Replace with rendered. The final_result field now matches rendered after truncation.

v0.9.234 - Platform API: Skill and Integration Delivery Fields Removed (July 2026)

Skill and Integration Delivery Fields Removed

The delivery and urgency_keywords fields have been removed from the Skill API. The result_delivery field has been removed from integration endpoint objects. Result delivery is now configured per state in the context graph rather than on individual skills or integration endpoints.

What changed:

  • delivery removed from skills. The delivery field (values: interrupt, queue) has been removed from skill create, update, and response objects. Skills no longer carry a delivery mode - delivery behavior is determined by the context graph state that binds the tool.

  • urgency_keywords removed from skills. The urgency_keywords field has been removed from skill create, update, and response objects. Urgency-based delivery escalation is no longer configured at the skill level.

  • result_delivery removed from integration endpoints. The result_delivery field (values: interrupt, queue) has been removed from endpoint create and response objects. Integration endpoints no longer carry a delivery mode.

  • Delivery configured on context graph state bindings. Result delivery is now a property of the context graph state's tool binding. The same tool can use different delivery modes in different states - for example, a tool can queue results silently during an intake state and interrupt immediately during a prescribing state. Existing configurations have been migrated automatically.

What you need to do:

  • If you set delivery or urgency_keywords when creating or updating skills: Remove these fields from your request bodies. They are no longer accepted.

  • If you read delivery or urgency_keywords from skill responses: Remove references to these fields. They are no longer included in responses.

  • If you set result_delivery when creating integration endpoints: Remove this field from your request bodies. It is no longer accepted.

  • If you read result_delivery from endpoint responses: Remove references to this field. It is no longer included in responses.

  • To configure delivery behavior: Set the delivery mode on the tool binding within each context graph state where the tool is used.

v0.9.233 - Platform API: Integration Schema Redesign - REST/Desktop Split, Update Endpoint, Per-Endpoint CRUD (July 2026)

Integration Schema Redesign

Integrations have been restructured into variant-specific types. The public API now exclusively manages REST integrations and exposes new endpoints for updating integrations and managing individual endpoints. Desktop integrations are system-provisioned and not accessible through the public CRUD surface.

What changed:

  • kind replaces protocol. Integration responses now include a kind field (value: rest) instead of the previous protocol field. The protocol query parameter has been removed from the list endpoint.

  • builtin field removed. The builtin field has been removed from integration responses. All integrations returned by the public API are workspace-scoped rows created through the standard create flow.

  • base_url is now required on create. The base_url field is required when creating an integration. Previously it defaulted to an empty string.

  • Update integration endpoint added. PATCH /integrations/{integration_id} is now available. You can update display_name, base_url, enabled, and auth individually without deleting and recreating the integration. Auth updates require setting auth_provided: true in the request body to distinguish between "leave auth unchanged" and "clear auth".

  • Per-endpoint CRUD added. Endpoints on a REST integration can now be managed individually:

    • POST /integrations/{integration_id}/endpoints - Add an endpoint

    • GET /integrations/{integration_id}/endpoints - List endpoints (paginated)

    • GET /integrations/{integration_id}/endpoints/{endpoint_name} - Get an endpoint

    • PATCH /integrations/{integration_id}/endpoints/{endpoint_name} - Update an endpoint

    • DELETE /integrations/{integration_id}/endpoints/{endpoint_name} - Delete an endpoint

    Endpoint names are immutable after creation. Adding, updating, or deleting endpoints updates the parent integration's updated_at timestamp.

  • List endpoint no longer accepts protocol filter. The protocol query parameter has been removed from GET /integrations. The list endpoint now returns only REST integrations.

What you need to do:

  • If you read the protocol field from integration responses: Replace references to protocol with kind. The value is rest for all integrations returned by the public API.

  • If you read the builtin field from integration responses: Remove references to this field. It is no longer included in responses.

  • If you filter by protocol on the list endpoint: Remove the protocol query parameter from your list requests. The endpoint now returns only REST integrations.

  • If you pass an empty base_url on create: Provide a valid base URL. The field is now required and must be non-empty.

  • If you delete and recreate integrations to change settings: Use the new PATCH /integrations/{integration_id} endpoint instead. This preserves the integration ID, endpoints, and associated secrets.

  • If you recreate integrations to add or remove endpoints: Use the per-endpoint CRUD endpoints to manage endpoints individually without affecting the parent integration or other endpoints.

v0.9.232 - Platform API: Test Connection and Health Check Endpoints Removed (July 2026)

Test Connection and Health Check Endpoints Removed

The POST /integrations/{integration_id}/test-connection and GET /integrations/health-check endpoints have been removed from the Platform API. Integration health metadata fields have also been removed from integration responses.

What changed:

  • Test connection endpoint removed. The POST /integrations/{integration_id}/test-connection endpoint has been removed. This endpoint previously probed an integration's auth resolution and upstream reachability without invoking a specific endpoint. Requests to this endpoint will return 404 Not Found.

  • Health check endpoint removed. The GET /integrations/health-check endpoint has been removed. This endpoint previously returned a bulk health summary of all enabled integrations in a workspace. Requests to this endpoint will return 404 Not Found.

  • Health metadata fields removed from integration responses. The last_tested_at and last_test_status fields have been removed from integration response objects. These fields previously reflected the most recent connection probe result. Integration list and get responses no longer include health metadata.

  • Stored health metadata cleared. Previously persisted health metadata from connection probes has been removed from integration records. This is a data cleanup with no behavioral effect - the fields that surfaced this data have been removed from the API.

What you need to do:

  • If you call POST /integrations/{integration_id}/test-connection: Remove these calls from your application. This endpoint no longer exists. Use the POST /integrations/{integration_id}/endpoints/{endpoint_name}/test endpoint to test specific integration endpoints instead.

  • If you call GET /integrations/health-check: Remove these calls from your application. This endpoint no longer exists.

  • If you read last_tested_at or last_test_status from integration responses: Remove references to these fields. They are no longer included in integration list or get responses.

v0.9.231 - Platform API: Integration Secrets Keyed by ID (July 2026)

Integration Secrets Keyed by ID

Integration auth secrets are now keyed by the integration's immutable ID rather than its user-supplied name. This means renaming an integration in a future release will not orphan its provisioned secrets.

What changed:

  • Secret paths use integration ID. The platform now derives auth secret storage paths from the integration's stable UUID instead of its name. This is an internal change - callers never supply or see secret paths - but it affects the lifecycle guarantee: secrets are now permanently tied to the integration ID and cannot be orphaned by a name change.

  • Integration ID assigned before secret provisioning. The integration ID is generated before any secrets are written, so the secret path and the database record always reference the same identifier. Previously, the ID was assigned at row insertion time, which could diverge from the path used during provisioning.

What you need to do:

  • No action required for most users. Secret provisioning and resolution are fully managed by the platform. If you supply inline secret values (api_key_value, bearer_token_value, client_secret_value, private_key_value, exchange_secret_value) at creation time, they continue to work exactly as before.

  • If you have integrations created before this release: Existing integrations created under the previous name-based scheme will be migrated automatically. No manual intervention is needed.

v0.9.230 - Platform API: Integration Secret Management Simplified, Update Endpoint Removed (July 2026)

Integration Secret Management Simplified, Update Endpoint Removed

Integration secret paths are now computed deterministically by the platform. The PUT update endpoint for integrations has been removed. Built-in integrations are no longer returned by the API - all integrations are workspace-scoped.

What changed:

  • Update integration endpoint removed. The PUT /integrations/{integration_id} endpoint has been removed. Integrations can no longer be updated in place. To change an integration's configuration, delete and recreate it. This simplifies the integration lifecycle and eliminates edge cases around secret rotation during partial updates.

  • Secret paths are now deterministic. Integration auth secrets are stored at platform-computed paths derived from the workspace, integration ID, and auth type. Callers no longer supply secret storage paths - the platform computes them automatically. The ssm_param_path, token_ssm_param_path, client_secret_ssm_param_path, private_key_ssm_param_path, and exchange_secret_ssm_param_path fields have been removed from the AuthConfig model. Inline secret values (api_key_value, bearer_token_value, client_secret_value, private_key_value, exchange_secret_value) remain the only way to supply secrets at creation time.

  • Built-in integrations removed from API responses. List and get endpoints no longer include platform-defined built-in integrations (Google Maps, Google Search, Stedi, athenahealth). All integrations returned by the API are workspace-scoped rows created through the standard create flow. If your application filtered on the builtin field, those entries will no longer appear.

  • Built-in integrations no longer block delete/update. Previously, attempting to delete or update a built-in integration returned 403 Forbidden. Since built-ins are no longer returned, this guard is removed. All integrations returned by the API can be deleted by their owner.

What you need to do:

  • If you use PUT /integrations/{integration_id}: This endpoint no longer exists. To modify an integration, delete the existing one and create a new one with the updated configuration. Requests to the old endpoint will return 405 Method Not Allowed.

  • If you supply *_ssm_param_path fields in AuthConfig: Remove these fields from your request bodies. The platform now rejects unknown fields on the auth config with 422 Unprocessable Entity. Supply secrets using the inline *_value fields only.

  • If you depend on built-in integrations in list responses: Built-in integrations are no longer returned. If your application relied on built-ins appearing in GET /integrations, you will need to create workspace-scoped equivalents through the standard create flow.

  • If you filter on the builtin field: This field will always be false for all returned integrations. You can remove any client-side filtering logic based on this field.

v0.9.229 - Platform API: List Endpoints Search by ID and Default Sort by Updated Date (July 2026)

List Endpoints Search by ID and Default Sort by Updated Date

List endpoints for agents, skills, services, integrations, and context graphs now support searching by ID and default to sorting by last updated date (newest first).

What changed:

  • Search by ID. The search parameter on list endpoints for agents, skills, services, integrations, and context graphs now matches against the resource ID in addition to the previously supported fields (name, description, slug, display name). This makes it easier to locate a specific resource when you have a partial or full ID.

  • Default sort changed to last updated. List endpoints for agents, skills, services, integrations, and context graphs now return results sorted by last updated date (newest first) by default. Previously, some endpoints defaulted to sorting by creation date or name. The sort parameter continues to work as before if you need a different ordering.

What you need to do:

  • If you rely on default list ordering: Be aware that results now appear in last-updated order by default. If your application depends on a specific sort order, pass the sort parameter explicitly.

  • If you search for resources by ID: You can now paste a full or partial ID into the search parameter and it will match. No API changes are needed to use this - existing search calls will also match IDs automatically.

  • No breaking changes. All existing query parameters and response shapes are unchanged.

v0.9.228 - Platform API: Simulation Case Management and Suites Endpoint (July 2026)

Simulation Case Management and Suites Endpoint

Simulation cases now support update, delete, and total count operations. A new suites listing endpoint returns all discoverable suites derived from suite:* case tags.

What changed:

  • Update simulation cases. PATCH /simulations/cases/{case_id} partially updates editable fields on a durable simulation case. Updatable fields include service assignment, persona, description, scenario instructions, initial message, temperament, fixtures, constraints, target specification, assertions, tags, and provenance. At least one field must be provided. Reserved tag prefixes are validated on update. Returns the updated case, or 404 if the case does not exist. Requires Service.update permission.

  • Delete simulation cases. DELETE /simulations/cases/{case_id} removes a simulation case. Returns 204 on success, or 404 if the case does not exist. Requires Service.update permission.

  • List simulation suites. GET /simulations/suites returns all suites discovered from cases tagged with the suite: prefix. Each suite includes a human-readable name derived from the tag, the number of matching cases, distinct service IDs, and the most recent update timestamp. Suites are dynamic - they are derived from case tags rather than requiring explicit registration.

  • Case list includes total count. The GET /simulations/cases endpoint now includes a total count in paginated responses, so clients can render pagination controls without issuing a separate count request.

What you need to do:

  • If you manage simulation cases programmatically: You can now update and delete individual cases through the API. Use PATCH for partial updates and DELETE for removal.

  • If you organize cases into suites: The new GET /simulations/suites endpoint provides suite discovery without needing to list and group cases client-side.

  • If you paginate case listings: The total field is now available in the list response to support accurate pagination UI.

  • No breaking changes. All existing endpoints continue to work as before. The new endpoints and fields are additive.

v0.9.227 - Platform API: Voice Sentiment Metric Removed (July 2026)

Voice Sentiment Metric Removed

The built-in voice_sentiment metric has been removed from the platform. This metric had zero active readers and is no longer computed or available in metric results.

What changed:

  • voice_sentiment metric removed. The built-in voice sentiment metric is no longer included in the default metric definitions. It will no longer appear in metric query results, workspace metric settings, or the MCP server's available metrics list.

  • Extraction mode simplified. The ai_sentiment extraction mode has been removed from the metric definition model. The supported extraction modes are now: static, ai_classify, ai_extract, ai_query, and sql_expr.

  • Custom metric validation updated. The validation error message for unsupported extraction modes on custom metrics now lists static, ai_query, ai_classify, and ai_extract as the allowed modes.

  • Built-in metric count reduced. The platform now ships 40 built-in metrics (previously 41).

What you need to do:

  • If you query voice_sentiment in dashboards or integrations: Remove references to this metric key. Queries for voice_sentiment will return no results.

  • If you use the ai_sentiment extraction mode in custom metric definitions: Migrate to ai_classify with appropriate labels, or use ai_query with a prompt that performs sentiment analysis. The ai_sentiment mode is no longer recognized.

  • If you reference voice sentiment in MCP tool calls: Update your queries to use other available voice metrics such as voice_quality_score, voice_escalation, or voice_completion_reason.

  • No data migration required. Historical metric values that were previously computed are unaffected, but no new values will be generated.

v0.9.226 - Platform API: Barge-In Events Preserved Individually in Call Intelligence (July 2026)

Barge-In Events Preserved Individually in Call Intelligence

Call intelligence now preserves individual barge-in event details instead of recording only an aggregate count. Each barge-in event includes the text that was interrupted and the timestamp of the interruption.

What changed:

  • Individual barge-in events in conversation summary. The conversation summary section of call intelligence now includes a barge_in_events array alongside the existing barge_in_count field. Each entry contains interrupted_text (the agent utterance that was interrupted) and timestamp (ISO 8601 timestamp of the interruption, or null if unavailable).

  • Aggregate count still present. The barge_in_count field continues to be populated and reflects the length of the barge_in_events array, so existing consumers that rely on the count are unaffected.

What you need to do:

  • If you consume call intelligence data: You can now access per-event barge-in details in the conversation summary. The barge_in_count field remains unchanged, so no migration is required.

  • No breaking changes. The barge_in_events array is additive. Existing integrations that read call intelligence data continue to work without modification.

v0.9.225 - Platform API: Call List Now Includes Intelligence-Only Calls (July 2026)

Call List Now Includes Intelligence-Only Calls

The call list endpoint now surfaces calls that have call intelligence data but no associated conversation record. Previously, the call list was driven exclusively by conversation records, so calls that were processed through the analytics pipeline but did not create a conversation were not visible in the list.

What changed:

  • Unified call list. The call list is now built from a unified view that joins call intelligence records with conversation records. Calls that exist only in call intelligence - for example, calls ingested from external sources or processed through analytics without following the standard conversation lifecycle - now appear alongside traditional conversation-based calls.

  • Field resolution across sources. Fields such as direction, duration, turn count, quality score, completion reason, final state, and source are resolved from whichever source has the most complete data. Call intelligence values take precedence where both sources provide a value, except for status and completion reason where conversation data takes precedence.

  • Detail endpoint supports intelligence-only calls. Retrieving detail for a call that exists only as a call intelligence record returns all available metadata and scoring fields with an empty turns array, rather than returning a not-found error.

  • No changes to filtering. Existing filters (status, direction, service, date range) continue to work. Status filtering considers the resolved status from both sources.

What you need to do:

  • If you consume the call list endpoint: You may see additional calls that were not previously visible. These calls have an id derived from the call intelligence record rather than a conversation ID. All other fields follow the same schema.

  • If you rely on the call_intelligence_batch_reader callback pattern (internal integrations): This callback has been removed. Intelligence data is now resolved directly in the list query. No action is needed if you use the public API.

  • No breaking changes to response schema. The response shape is unchanged. New calls include the same fields as conversation-based calls, with null values for conversation-specific fields (such as caller_id and phone_number) when no conversation record exists.

v0.9.224 - Platform API: Integration Auth Rejects Platform-Managed SSM Paths Without Inline Secrets (July 2026)

Integration Auth Rejects Platform-Managed SSM Paths Without Inline Secrets

The platform now rejects integration auth configurations that reference a platform-managed SSM path without providing the corresponding inline secret value. Previously, it was possible to copy a platform-managed SSM path from an API response (or another integration) into a create or update request without supplying the actual secret material. This would create an integration that appeared configured but could not authenticate, because the path was auto-generated and the secret was not actually provisioned for the new integration.

What changed:

  • Platform-managed SSM paths require inline secrets. When creating or updating an integration, if an auth field (such as api_key_value, bearer_token_value, client_secret_value, private_key_value, or exchange_secret_value) references a platform-managed SSM path but does not include the inline secret value, the API returns a validation error. The error message indicates which field is affected and instructs you to pass the secret value directly.

  • External SSM paths are unaffected. If you manage your own SSM paths outside the platform, those paths continue to be accepted without an inline secret value.

  • Inline secret values work as before. Passing the actual secret value directly (e.g. api_key_value, bearer_token_value) continues to work. The platform auto-provisions the secret to SSM and returns the managed path in the response.

What you need to do:

  • If you copy SSM paths from API responses into new integration requests: Stop copying the ssm_param_path, token_ssm_param_path, client_secret_ssm_param_path, private_key_ssm_param_path, or exchange_secret_ssm_param_path values from responses. Instead, pass the original secret value in the inline field and let the platform provision it automatically.

  • If you use external (self-managed) SSM paths: No changes needed. External paths are accepted as before.

v0.9.223 - Platform API: Dynamic Simulation Suite Tags (July 2026)

Dynamic Simulation Suite Tags

Suite tags in the simulation framework are now fully dynamic. Previously, suite tags had to be pre-registered alongside capability and agent-type tags. Now, any tag with the suite: prefix is accepted as a valid suite tag without prior registration. This makes it easier to create and iterate on test suites - just tag your cases with a new suite: value and it becomes a runnable suite immediately.

What changed:

  • Suite tags are no longer validated against a fixed registry. Any suite:* tag is accepted on simulation cases. You can define new suites by tagging cases without updating a central registry.

  • Capability and agent-type tags are still validated. Tags with the capability: and agent_type: prefixes continue to be validated against known values. Unrecognized capability or agent-type tags are still rejected to prevent typos from silently excluding cases from benchmarks and rollups.

What you need to do:

  • No action is required. Existing suite: tags continue to work. You can now create new suites by applying any suite:* tag to your simulation cases.

v0.9.222 - Platform API: Conversation Turn Data Moved to Session Store, Call Analysis and Enrichment Fields Removed from API Responses (July 2026)

Conversation Turn Data Moved to Session Store

Per-turn conversation data is now served exclusively from the session store. The platform no longer reads turn data from the previous analytical table. This completes the migration to the session-based turn storage announced in earlier releases.

What changed:

  • Turn data served from session store only. Call detail and conversation detail endpoints now resolve turns exclusively from the session store. If the session store is unavailable, the response includes all conversation metadata and scoring fields with an empty turns array, rather than falling back to the previous analytical table. This matches the existing behavior documented for historical calls whose turn data was not preserved in current stores.

  • Historical calls unaffected. Calls whose turns were already in the session store continue to work identically. Calls whose turn data existed only in the previous analytical table will return an empty turns array in the detail response. All metadata, scoring, and summary fields remain available.

Call Analysis and Enrichment Fields Removed from API Responses

Several enrichment fields have been removed from call and conversation API responses. These fields were populated from analytical processing that has moved to the downstream analytics pipeline and are no longer written or returned by the platform API.

What changed:

  • call_analysis removed from call detail responses. The call_analysis object (containing outcome classification, transport close details, and post-call analysis) is no longer included in call detail API responses. If you consumed this field, use the analytics pipeline or metric store for equivalent data.

  • emotional_summary removed from call detail responses. The emotional_summary object is no longer included in call detail API responses.

  • forwarding removed from call detail responses. The forwarding object is no longer included in call detail API responses.

  • participants, states_visited, barge_in_events, and config removed from call detail responses. These enrichment arrays and objects are no longer included in call detail API responses.

  • escalation_status field type relaxed. The escalation_status field on call summary and operator escalation responses is now a free-form string (max 64 characters) instead of a fixed set of values. Existing status values continue to work. Client code that validated against a strict set of allowed values should be updated to accept any string.

What you need to do:

  • If you read call_analysis, emotional_summary, forwarding, participants, states_visited, barge_in_events, or config from call detail responses: These fields are no longer returned. Equivalent data is available through the analytics pipeline and metric store.

  • If you validate escalation_status against a fixed set of values: Update your validation to accept any string up to 64 characters.

  • If you depend on turn data for historical calls: Turns are now served exclusively from the session store. Historical calls that predate session store adoption will return an empty turns array with all other metadata intact.

v0.9.221 - Platform API: Endpoint-Level Overrides Removed, Google Maps Integration Split (July 2026)

Endpoint-Level Overrides Removed from Integrations

The base_url and auth fields on individual integration endpoints have been removed. All endpoints in an integration now inherit the integration-level base URL and auth configuration. This simplifies the integration model and removes ambiguity about which auth and URL apply to a given endpoint.

What changed:

  • base_url removed from endpoint configuration. Individual endpoints no longer accept a base_url override. The integration-level base_url is used for all endpoints. If you previously used per-endpoint base URL overrides, split those endpoints into separate integrations with their own base URLs.

  • auth removed from endpoint configuration. Individual endpoints no longer accept an auth override. The integration-level auth configuration is used for all endpoints. If you previously used per-endpoint auth overrides, split those endpoints into separate integrations with their own auth configurations.

Google Maps Built-in Integration Split into Two Integrations

The single google_maps built-in integration has been replaced by two separate built-in integrations: google_maps_places and google_maps_routes. This change reflects the removal of per-endpoint base URL overrides - the Places API and Routes API live at different hosts and now require separate integrations.

What changed:

  • google_maps integration replaced. The google_maps built-in integration no longer exists. It has been replaced by google_maps_places (Places API endpoints) and google_maps_routes (Routes API endpoints including directions).

  • google_maps_places integration. Contains all place search, geocoding, and place detail endpoints. Display name: "Google Maps - Places".

  • google_maps_routes integration. Contains the directions endpoint. Display name: "Google Maps - Routes".

  • Same authentication. Both integrations use the same API key authentication and the same GOOGLE_MAPS_API_KEY environment variable. No credential changes are needed.

What you need to do:

  • If you use per-endpoint base_url or auth overrides: Split those endpoints into separate integrations, each with its own integration-level base URL and auth configuration. These fields are no longer accepted on endpoint objects.

  • If you reference google_maps by name: Update references to use either google_maps_places or google_maps_routes depending on which endpoints you use. The google_maps integration name is no longer valid.

  • If you use the directions endpoint: This endpoint has moved from google_maps to google_maps_routes. Update any code that looks up the directions tool by integration name.

v0.9.220 - Platform API: Text Interact Turn Persistence Failures Now Surface Explicitly (July 2026)

Text Interact Turn Persistence Failures Now Surface Explicitly

The text interact endpoint now returns explicit error responses when turn persistence fails, instead of returning a silent success.

What changed:

  • Non-streaming text interact returns 502 on persistence failure. If the agent generates a response but the platform fails to persist the conversation turn, the endpoint now returns a 502 Bad Gateway with a message indicating that conversation history may be incomplete. Previously, this scenario returned a 200 OK, which masked the data loss.

  • Streaming text interact emits an error event on persistence failure. If turn persistence fails during a streaming interaction, the stream now emits an SSE error event with a message indicating that conversation history may be incomplete. Previously, the stream closed silently without signaling the failure.

  • Voice session persistence failures logged at error severity. Voice session sync failures are now logged at error severity instead of warning severity, improving observability for persistence issues across all channels.

What you need to do:

If you consume the text interact endpoint, update your error handling to account for 502 responses (non-streaming) or error SSE events (streaming) that indicate persistence failures. These responses mean the agent's reply was generated and delivered, but the turn may not appear in conversation history. You may want to retry the interaction or notify the user that the conversation state could be stale.

v0.9.219 - Platform API: SMART Backend Services Auth Type Removed from Integrations (July 2026)

SMART Backend Services Auth Type Removed from Integrations

The smart_backend_services authentication type has been removed from the integrations framework. This auth flow is now handled by the connector runner service. Integrations that previously used SMART Backend Services auth should migrate to use the connector runner for SMART-authenticated connections.

What changed:

  • smart_backend_services auth type removed. The smart_backend_services option is no longer accepted in the integration auth configuration type field. The supported auth types are now: api_key_header, bearer_token, oauth2_client_credentials, json_token_exchange, oauth2_jwt_bearer, and bearer_token_exchange.

  • assertion_algorithm field removed. The assertion_algorithm field on the auth configuration model has been removed. This field was only used with the smart_backend_services auth type.

  • assertion_kid field removed. The assertion_kid field on the auth configuration model has been removed. This field was only used with the smart_backend_services auth type.

What you need to do:

If you have integrations configured with smart_backend_services auth, migrate them to use the connector runner for SMART Backend Services authentication. The connector runner now owns this auth flow end-to-end. Contact support if you need guidance on migrating specific integrations.

v0.9.218 - Platform API: GCP WIF Auth Type Removed from Integrations (July 2026)

GCP WIF Auth Type Removed from Integrations

The gcp_wif authentication type has been removed from the integrations framework. Integrations that previously used GCP Workload Identity Federation auth should migrate to an alternative auth type.

What changed:

  • gcp_wif auth type removed. The gcp_wif option is no longer accepted in the integration auth configuration type field. The supported auth types are now: api_key_header, bearer_token, oauth2_client_credentials, json_token_exchange, oauth2_jwt_bearer, smart_backend_services, and bearer_token_exchange.

  • gcp_scopes field removed. The gcp_scopes field on the auth configuration model has been removed. This field was only used with the gcp_wif auth type.

What you need to do:

If you have integrations configured with gcp_wif auth, update them to use one of the remaining supported auth types before your next deployment. The supported auth types are now: api_key_header, bearer_token, oauth2_client_credentials, json_token_exchange, oauth2_jwt_bearer, and bearer_token_exchange. Contact support if you need guidance on migrating specific integrations.

v0.9.217 - Platform API: Agent Harness Approval Flag Update (July 2026)

Agent Harness Approval Flag Update

The non-interactive agent harness backend now uses a single consolidated flag for bypassing approval prompts and sandbox restrictions, replacing the previous separate flags.

What changed:

  • Consolidated approval and sandbox bypass. The non-interactive harness now passes a single combined flag to bypass both approval prompts and sandbox restrictions. Previously, these were configured as two separate flags (one for approval suppression and one for sandbox access). The new flag is functionally equivalent - agent behavior and execution results are unchanged.

What you need to do:

No action is required. This is an internal harness configuration change. Agent runs, audit events, and result formats are unaffected.

v0.9.216 - Platform API: Additional Agent Harness Backend (July 2026)

Additional Agent Harness Backend

The agent execution layer now supports a second harness backend for non-interactive batch execution, in addition to the existing interactive harness. The new harness can be selected per workspace and is fully integrated with the existing job scheduling and audit event pipeline.

What changed:

  • New harness option. Workspaces can now configure a second agent harness backend. The harness selection is set through workspace environment configuration and applies to all agent runs dispatched from that workspace. The new backend operates in non-interactive mode with full sandbox access, producing the same audit event structure and result format as the existing harness.

  • Audit events. Runs using the new harness emit audit events with harness-specific event types, following the same structure used by the existing harness. Each event carries a tool identifier, input summary, sequence number, and timestamp. The harness name is recorded on the run result so downstream systems can distinguish which backend produced the output.

  • Model selection. The new harness respects the same agent model configuration used by the existing harness. When an agent model is specified in workspace settings, it is passed through to the harness backend automatically.

  • Environment configuration. Two new optional environment variables control the API credentials for the new harness. These are only required when the new harness is selected and are ignored for workspaces using the existing harness.

What you need to do:

No changes are required for existing workspaces. To use the new harness backend, update your workspace agent harness configuration. If you consume audit events or run results, the harness_name field on the result now reflects which backend executed the run.

v0.9.215 - Platform API: Customer Data Zone and Catalog Reference Updates (June 2026)

Customer Data Zone and Catalog Reference Updates

The Data-MCP SQL query tool, the fallback SQL query tool used by the agent runtime, and the research query service now recognize the customer data zone catalogs. Catalog references across all LLM tool prompts have been updated to use fully qualified names.

What changed:

  • Customer data zone available in SQL queries. The read-only SQL query tools now accept queries against the customer data zone. These views use definer-rights access control and are automatically filtered to the caller's workspace, so queries return only data belonging to the authenticated workspace. Both production and staging catalogs are supported.

  • Fully qualified catalog references. All SQL tool descriptions presented to the agent now use fully qualified three-part catalog references instead of abbreviated names. This eliminates ambiguity when the agent constructs queries and ensures correct catalog resolution across environments.

  • Analytics catalog consolidation reflected in tool prompts. Tool descriptions now reference the consolidated analytics catalog for metrics, billing, memory, scheduling, and call trace data, replacing references to individual legacy catalogs that were retired in the May 2026 consolidation.

What you need to do:

No API changes are required. If you use Data-MCP or the agent's SQL query capabilities, the customer data zone is now queryable alongside existing catalogs. Queries against the customer data zone are workspace-scoped automatically - no manual filtering is needed.

v0.9.214 - Platform API: Call Intelligence Served from Session Artifacts (June 2026)

Call Intelligence Served from Session Artifacts

Call intelligence data on voice conversation endpoints is now resolved from the hot session cache first, with automatic fallback to the durable analytical store. This replaces the previous approach of joining against a dedicated database table on every read.

What changed:

  • Tiered call intelligence resolution. Single-call detail and conversation list endpoints now read call intelligence artifacts (quality scores, completion reasons, duration, direction, analytics summaries) from the fast session cache. When cached data is unavailable - for example, after cache expiration or for older conversations - the platform falls back to the durable analytical store automatically. No intelligence data is lost during the transition.

  • Batch intelligence lookups for conversation lists. The conversation list endpoint now resolves call intelligence for an entire page of results in a single batch lookup rather than issuing per-conversation queries. This reduces list endpoint latency, especially for pages with many voice conversations.

  • Consistent intelligence fields. The quality_score, completion_reason, final_state, duration_seconds, direction, source, service_id, and all analytics summary fields (risk_summary, latency_summary, conversation_metrics, tool_summary, safety_summary, operator_summary) continue to appear on conversation detail and list responses with the same types and semantics. Field precedence is unchanged: conversation-level values take priority where present, with intelligence artifacts filling in supplementary data.

  • Status and filter behavior. Conversation list status filters now evaluate against conversation header fields only, rather than joining intelligence data into the filter predicate. This makes total counts and pagination more predictable. The direction=playground filter continues to work but playground-originated conversations are no longer represented as voice conversation summaries.

What you need to do:

No API changes are required. Response shapes are unchanged. Conversation list and detail endpoints return the same fields with improved latency and consistency. If you filter conversations by status, results may differ slightly for edge cases where the intelligence record previously overrode the conversation header status.

v0.9.213 - Platform API: Generic Agent Harness Configuration (June 2026)

Generic Agent Harness Configuration

The platform now supports configuring which agent harness and model are used for agent task execution. Previously, the platform assumed a single hardcoded agent harness. You can now specify the harness type and model independently, enabling support for additional agent harness backends as they become available.

What changed:

  • agent_harness configuration field. A new agent_harness field controls which agent harness backend is used for task execution. The default value is claude-code, preserving existing behavior for current deployments.

  • agent_model configuration field. A new agent_model field specifies the model passed to the agent harness. This replaces the previous model configuration field and provides a harness-agnostic way to select models.

  • Backward compatibility. Existing model configuration continues to work. If only the previous model field is set, the platform uses it as the agent model automatically. The new fields take precedence when both are specified.

What you need to do:

No immediate action is required. Existing configurations continue to work without changes. To use a different agent harness or model, set the new agent_harness and agent_model configuration fields in your environment. The previous model configuration field remains supported for backward compatibility.

v0.9.212 - Platform API: Outbound Calls Require workspace_id and service_id (June 2026)

Outbound Calls Require workspace_id and service_id

The outbound call endpoint now requires workspace_id and service_id on every request. These fields were previously optional strings and are now required UUID values.

What changed:

  • workspace_id is required. The workspace_id field on the outbound call request body is now a required UUID. Previously it was an optional string that defaulted to null.

  • service_id is required. The service_id field on the outbound call request body is now a required UUID. Previously it was an optional string that defaulted to null.

  • Assignment always created. Outbound calls now always create a provisional assignment using the provided workspace and service identifiers. Previously, calls without workspace and service IDs skipped assignment creation silently.

What you need to do:

Update any outbound call integrations to include both workspace_id and service_id as valid UUIDs in every request. Requests that omit either field or provide non-UUID values will be rejected with a validation error.

v0.9.211 - Platform API: FHIR Protocol Coerced to REST (June 2026)

FHIR Protocol Coerced to REST

The FHIR integration protocol has been removed as a distinct protocol type. All existing FHIR integrations are automatically coerced to REST. FHIR integrations were already handled identically to REST integrations at runtime - this change removes the unnecessary distinction.

What changed:

  • FHIR protocol removed. The protocol field on integrations no longer accepts fhir as a value. Valid values are now rest and desktop. Existing integrations that were previously configured as fhir have been migrated to rest automatically.

  • Creatable protocol restricted to REST. The integration creation endpoint accepts only rest as the protocol value. The desktop protocol remains system-provisioned and cannot be created via the public API.

  • No behavioral change. FHIR integrations were already using the same HTTP-based integration path as REST integrations, including auth resolution, endpoint configuration, result templates, and connection probes. This change reflects that existing behavior in the data model.

What you need to do:

No action is required. If you have existing FHIR integrations, they have been migrated to REST automatically. If you have automation that creates integrations with protocol: "fhir", update it to use protocol: "rest" instead.

v0.9.210 - Platform API: Open Query Write Boundary and Function Delete Cleanup (June 2026)

Open Query Write Boundary and Function Delete Cleanup

The open query tool (fn_query) now delegates read/write enforcement to the data warehouse permission layer instead of applying a client-side keyword blocklist. Deleting a Python or UDTF function now also removes the corresponding warehouse artifact.

What changed:

  • Open query write boundary moved to warehouse permissions. The open query tool previously rejected SQL containing write keywords (INSERT, UPDATE, DELETE, MERGE, etc.) using a regex filter. This filter has been removed. Read/write enforcement is now handled by the warehouse permission layer - the agent's service identity has read access to the production catalog and full access only to the sandbox schema. Write statements against non-sandbox surfaces are denied by the warehouse with a permission error. This eliminates false positives from the old regex (e.g., column names containing "update") and provides a single, consistent enforcement point.

  • Open query tool description updated. The tool description presented to the agent now explains that writes succeed only against the sandbox schema and that the warehouse denies writes elsewhere. The previous "read-only" framing has been removed.

  • LIMIT injection scoped to SELECT/WITH. The automatic LIMIT 100 safety cap is now applied only to SELECT and WITH (CTE) queries. Write statements (INSERT, UPDATE, DELETE, MERGE) are no longer modified with a trailing LIMIT, which would have caused a syntax error.

  • Function delete removes warehouse artifact. Deleting a Python or UDTF function now drops the corresponding warehouse artifact before removing the registry row. The drop is idempotent - if the artifact is already gone (e.g., from a partial previous deploy), the delete still succeeds. If the warehouse is unavailable, the delete fails with a 503 error and the registry row is preserved so the operation can be retried. SQL and AI functions have no warehouse artifact, so their delete behavior is unchanged.

What you need to do:

No API changes are required. If you previously relied on the open query tool rejecting write keywords, note that write enforcement is now handled by warehouse permissions. Writes against the sandbox schema will now succeed through fn_query; writes against other schemas will return a permission error from the warehouse rather than a client-side validation error. Function deletes for Python and UDTF types are now fully clean - no orphan warehouse artifacts are left behind.

v0.9.208 - Platform API: Simulation Branch Isolation Removed (June 2026)

Simulation Branch Isolation Removed

The simulation API no longer supports database branch-based write isolation. Simulation sessions now write through the standard event pipeline with source tagging, and downstream consumers filter non-production sources automatically.

What changed:

  • branch_name field removed from session creation. The branch_name parameter on the create simulation session endpoint has been removed. Requests that previously included branch_name should omit it. The field is no longer accepted.

  • Branch management endpoints removed. The POST /simulations/branches, GET /simulations/branches, and DELETE /simulations/branches/{branch_name} endpoints have been removed. Branch lifecycle management is no longer part of the simulation API.

  • Simulation write isolation simplified. Simulation sessions continue to tag all writes with a simulation source, ensuring that simulation data is excluded from production sync, outbound EHR writes, gap detection, and billing. The tagging mechanism is unchanged - only the underlying isolation strategy has been simplified.

  • No changes to simulation session behavior. Creating sessions, stepping through conversations, forking sessions, and scoring all work exactly as before. The only difference is that branch_name is no longer a parameter and branch endpoints no longer exist.

What you need to do:

Remove any branch_name fields from simulation session creation requests. Remove any calls to the branch management endpoints (POST /simulations/branches, GET /simulations/branches, DELETE /simulations/branches/{branch_name}). No other changes are required - simulation sessions continue to be isolated from production data through source tagging.

v0.9.207 - Platform API: Enum Drift Fixes for Conversations, Metrics, Review Queue, and Channels (June 2026)

Enum Drift Fixes for Conversations, Metrics, Review Queue, and Channels

Several API surfaces now accept a wider set of valid values, fixing 500 errors caused by enum mismatches between stored data and API response schemas.

What changed:

  • SMS channel type added. The channel type enumeration now includes sms as a valid value. Surfaces and conversations using SMS channels are now correctly represented in API responses.

  • Review queue completed action values expanded. The completed_action field on review queue items now accepts both verb and past-tense forms: approve, reject, correct, approved, rejected, and corrected. Previously, only the past-tense forms were accepted, which caused errors when items stored with verb-form values were returned through the API.

  • Voice conversation status handling hardened. Voice conversation status resolution now maps unexpected status values to valid statuses instead of passing unrecognized values through. Conversations with statuses outside the expected set are mapped to a safe default, preventing serialization errors in conversation list and detail responses.

  • Categorical metric grouping simplified. Dashboard metric queries for categorical metrics now group by category value only, removing a dependency on a legacy grouping field. This fixes errors when the legacy field is absent from metric records.

What you need to do:

No API changes are required. These fixes resolve intermittent 500 errors on conversation, review queue, metric, and channel endpoints. If you previously encountered server errors when listing or viewing conversations, review items, or dashboard metrics, those errors should now be resolved.

v0.9.206 - Platform API: Call Intelligence Artifact Contract Centralized (June 2026)

Call Intelligence Artifact Contract Centralized

The terminal call intelligence artifact - the payload emitted when a call or text session ends - now uses a single, validated contract across all channels and the metric projection endpoint. This replaces the previous pattern where each channel assembled its own payload dictionary with ad-hoc field sets.

What changed:

  • Strict artifact validation. The terminal call intelligence artifact is now validated against a single schema before it is emitted or projected. Missing required fields, out-of-range scores, and unknown extra fields are rejected at build time rather than silently stored. This applies to voice calls, text sessions, and simulation sessions equally.

  • Invalid direction and source values are now rejected. Previously, unrecognized call direction values fell back to "inbound" and unrecognized source values were silently dropped. Both fields now reject invalid values with an error. If you were relying on the fallback behavior for non-standard direction or source values, those calls will now fail to emit call intelligence until the values are corrected.

  • Workspace ID included in the artifact. The artifact now carries the workspace identifier as a required field. The metric projection endpoint validates that the workspace in the artifact matches the workspace in the request path, returning a 422 error on mismatch.

  • Metric projection accepts the shared artifact schema. The internal metric projection endpoint now accepts the same artifact schema used by the event pipeline. The previous endpoint-specific request model has been replaced by the shared contract. All fields, types, and constraints are identical.

  • Improved error handling for call intelligence persistence. When the event pipeline emits successfully but the hot cache write fails, the platform now distinguishes between the two failure modes. Metric projection proceeds if the durable event was emitted, even when the cache write fails. Previously, any persistence failure would skip metric projection entirely.

  • Playground calls excluded from metrics. Calls originating from the Developer Console playground are now explicitly excluded from metric projection. Previously, playground calls could be projected as production metrics depending on how the source value was interpreted.

What you need to do:

No API changes are required for standard integrations. If you consume call intelligence events downstream, the payload shape is unchanged - the same fields are present with the same types. If you were sending non-standard direction or source values through a custom integration, those values must now match the canonical set (direction: "inbound" or "outbound"; source: "real", "simulation", or "playground").

v0.9.204 - Platform API: Call Intelligence Enum Normalization (June 2026)

Call Intelligence Enum Normalization

Call intelligence data now normalizes call direction and call source values at write time, eliminating inconsistencies caused by legacy data or mismatched labels.

What changed:

  • Direction and source normalization at write time. Call intelligence events now normalize direction and source values before they are stored. Historical aliases and legacy labels are mapped to their canonical equivalents automatically. For example, calls that were previously recorded with inconsistent direction labels now resolve to the correct canonical value. Unrecognized direction values fall back to "inbound" to satisfy storage constraints; unrecognized source values are dropped rather than stored with an incorrect label.

  • Shared normalization across read and write paths. Both the call intelligence writer and the call listing read path now use the same normalization logic. Previously, the read path maintained its own alias mapping. This change ensures that direction and source values are consistent regardless of whether you are viewing a call in the Developer Console, querying the API, or consuming analytics events.

  • Legacy data cleanup. A data migration corrects historical rows that contained non-canonical direction or source values. Calls affected by the legacy labeling inconsistency will now display correct values in dashboards and API responses without any action required.

  • Monitoring for drift. The platform now tracks normalization events so the team can verify that no new sources of inconsistent values appear. Once the migration has been active long enough to confirm zero drift, the legacy fallback paths will be removed.

What you need to do:

No API changes are required. If you previously filtered or grouped calls by direction or source and noticed inconsistent labels, those values are now normalized. Dashboards and analytics that aggregate by direction or source will produce more accurate results.

v0.9.203 - Platform API: Frozen Conversation Status Removed (June 2026)

Frozen Conversation Status Removed

The frozen conversation status has been removed from the platform. Text conversations now use only active and terminal statuses (closed, completed, failed). Runtime session ownership is managed through the hot session cache rather than a persisted lifecycle status.

What changed:

  • frozen status removed. The frozen value is no longer returned in conversation status fields and is no longer accepted as a filter value when listing conversations. Conversations that would previously have been frozen now remain active in the durable store while releasing runtime resources through cache expiration.

  • resumed session status removed. The session_status field on text session creation responses no longer returns resumed. The field now returns either created or already_active.

  • reactivated field removed. The reactivated boolean field has been removed from conversation thread resolution and text session creation responses. Conversations no longer transition between frozen and active states.

  • Simplified conversation lifecycle. Active conversations release runtime resources through automatic cache expiration rather than explicit freeze/thaw transitions. When a new message arrives for a conversation whose session has expired, a new runtime session is created transparently. The conversation's durable identity and history are preserved across session boundaries.

What you need to do:

  • If you filter conversations by status=frozen, remove that filter. Active non-terminal conversations all have active status.

  • If you check for session_status: "resumed" in text session responses, update your code to handle only created and already_active.

  • If you read the reactivated field from conversation materialization or session responses, remove that dependency. The field is no longer present.

v0.9.202 - Platform API: MCP Integration Protocol Removed (June 2026)

MCP Integration Protocol Removed

The MCP (Model Context Protocol) integration protocol has been removed from the platform. Integrations now support rest, fhir, and desktop protocols only.

What changed:

  • mcp protocol removed. The mcp protocol option is no longer accepted when creating or updating integrations. The protocol field now accepts rest, fhir, or desktop (where desktop remains system-provisioned only).

  • MCP-specific fields removed. The mcp_transport, mcp_command, mcp_args, mcp_url, and mcp_headers fields have been removed from integration create, update, and response models. These fields are no longer accepted in requests or returned in responses.

  • Connection test simplified. The test-connection endpoint no longer includes MCP-specific probe logic. Connection probes exercise auth resolution and send a HEAD request to base_url for REST/FHIR integrations.

  • Creatable protocol set narrowed. The set of protocols available for user-created integrations is now rest and fhir. The desktop protocol continues to be system-provisioned only.

What you need to do:

  • If you have integrations using the mcp protocol, migrate them to rest or fhir before updating. Existing MCP integrations will no longer be recognized by the platform.

  • Remove any mcp_transport, mcp_command, mcp_args, mcp_url, or mcp_headers fields from your integration create and update requests.

v0.9.201 - Platform API: Strict Context Graph Tool Reference Validation (June 2026)

Strict Context Graph Tool Reference Validation

Context graph version creation now validates every tool reference against deployed workspace resources. Previously, tool references were checked against skill slugs and built-in tool IDs but did not verify that referenced platform functions or workspace data queries actually existed. This change catches misconfigured context graphs before they reach production.

What changed:

  • Platform function references validated at deploy time. Tool references using the fn_ prefix (e.g. fn_check_eligibility) are now verified against the workspace's deployed platform functions. If a referenced function does not exist, the context graph version creation request is rejected with a validation error listing the unresolved references.

  • Workspace data query references validated at deploy time. Tool references using the wsq_ prefix (e.g. wsq_recent_appointments) are now verified against the workspace's deployed workspace data queries. Missing queries cause the same validation rejection.

  • Skill references validated against enabled skills. Skill-based tool references continue to be validated against the workspace's skill registry, and now require the skill to be enabled. Disabled skills cause a validation error.

  • Built-in legacy functions removed. Five previously built-in function tools (fn_entity_confidence, fn_caller_history, fn_patient_summary, fn_patient_memory_snapshot, fn_patient_dimension_summary) have been removed from the platform. These functions are no longer auto-registered for every workspace. If your agent uses any of these, deploy equivalent platform functions in your workspace before updating your context graph. The open query (fn_query) and write (fn_write) tools remain available as built-in tools.

What you need to do:

  • If your context graphs reference fn_entity_confidence, fn_caller_history, fn_patient_summary, fn_patient_memory_snapshot, or fn_patient_dimension_summary, deploy these as platform functions in your workspace before creating new context graph versions. Existing deployed context graph versions continue to work, but new versions referencing these tools will fail validation.

  • Ensure all fn_* and wsq_* tool references in your context graphs correspond to deployed platform functions or workspace data queries in the same workspace.

  • Review any disabled skills referenced by context graphs - they must be enabled to pass validation.

v0.9.200 - Platform API: Call Intelligence Migrated to Session Store and Event Pipeline (June 2026)

Call Intelligence Migrated to Session Store and Event Pipeline

Call intelligence data now flows through the session store and event pipeline instead of being written directly to the analytical database. This change improves write latency for call intelligence, makes intelligence data available immediately after a call ends, and unifies the data path for voice, text, and simulation sessions.

What changed:

  • Session store is the primary call intelligence store. Call intelligence summaries are now written to the fast session cache and emitted through the durable event pipeline, replacing the previous direct database write. Intelligence data is available for API reads immediately after the call ends, without waiting for analytical pipeline ingestion.

  • Metric projection receives the full artifact. The internal metric projection endpoint now receives the complete call intelligence artifact directly from the agent engine, instead of reading it back from the database after a write. This eliminates a read-after-write dependency and removes the previous 404 response when the database row had not yet been committed. The projection endpoint no longer returns a not-found status.

  • Unified intelligence path for all session types. Voice calls, text sessions, and simulation sessions all emit call intelligence through the same session store boundary. Previously, each session type used a slightly different write path. The unified path ensures consistent data shape, timing, and event semantics across all channels.

  • Call intelligence reads from session store. The call intelligence detail endpoint now reads from the session store hot cache instead of querying the analytical database. This provides lower-latency reads and consistent data availability across all session types.

  • Simulation intelligence simplified. Simulation sessions no longer write intelligence data to the analytical database directly. Intelligence flows through the session store and event pipeline, then metric projection is requested through the standard platform API path. This matches the production call intelligence flow.

What you need to do:

No API changes are required. The call intelligence response shape is unchanged. If you consume call intelligence data through the API, you may notice improved availability - intelligence data appears immediately after a call ends rather than after analytical pipeline processing.

v0.9.199 - Platform API: Text Conversation Turns from Session Logs (June 2026)

Text Conversation Turns from Session Logs

Text conversation detail now reads turn data from the session log pipeline instead of inline conversation state. This aligns text conversations with the same turn resolution path used by voice conversations, providing consistent turn data across both channels.

What changed:

  • Turn resolution from session logs. The text conversation detail endpoint now reads turn history from the session store (hot path) with automatic fallback to the durable analytical store for historical conversations. Previously, text conversation turns were read from inline conversation state. This change means text conversations benefit from the same turn resolution pipeline that voice conversations already use.

  • Consistent turn format. Text and voice conversation detail responses now produce turns through the same rendering logic. Turn structure, timestamp formatting, and role mapping are identical across both channels.

  • Improved error handling. Turn read failures now return a 502 status with a descriptive error message ("Conversation turns unavailable" or "Conversation turns invalid") instead of failing silently or returning malformed data. Transient session store read failures are handled gracefully - the endpoint falls back to the durable store rather than returning an error.

What you need to do:

No API changes are required. The conversation detail response shape is unchanged. If you consume text conversation turns, you may notice improved turn availability for historical conversations that previously returned empty or incomplete turn data.

v0.9.198 - Platform API: Parallel Tool Registration During Session Initialization (June 2026)

Parallel Tool Registration During Session Initialization

Session initialization now registers workspace tools and data warehouse functions concurrently using a structured task group, replacing the previous sequential-then-deferred approach. This reduces session startup latency and simplifies error handling.

What changed:

  • Concurrent tool registration. Workspace tool registration and data warehouse function registration now run fully in parallel during session initialization. Previously, one registration path ran in the foreground while the other was deferred to a background task. Both paths now complete before the session proceeds, ensuring all tools are available to the agent from the first interaction.

  • Consistent error handling. Both registration paths now use the same non-fatal error handling. If either registration fails, the failure is logged as a warning and the session continues without those tools. Previously, the two paths used different error handling strategies, which could produce inconsistent behavior when one path failed.

  • Tool snapshot consistency. Because both registration paths complete before the session's tool list is finalized, all registered tools are guaranteed to be visible to the agent immediately. Previously, deferred registration could complete after the tool list snapshot was taken, causing some tools to be silently unavailable until the next session.

What you need to do:

No API changes are required. Sessions will initialize faster and all registered tools will be consistently available from the first turn. If you previously observed intermittent tool availability at session start, this change resolves that behavior.

v0.9.197 - Platform API: Fail-Fast Text Session Routing (June 2026)

Fail-Fast Text Session Routing

Text session routing and conversation directory operations now use strict fail-fast error handling. Previously, cache unavailability was silently absorbed and routing fell back to alternate lookup paths or returned empty results. Now, infrastructure errors propagate immediately so operators see one clear failure mode instead of silent behavior changes.

What changed:

  • Cache is a required dependency. Text session management and conversation routing now require the hot-path cache at initialization. Passing a missing or null cache reference raises an error at startup rather than being silently accepted.

  • No silent fallback on cache errors. Cache read and write errors (connection failures, timeouts) now propagate to the caller instead of being suppressed. Previously, errors were caught and the system returned empty results or skipped writes. This could mask infrastructure problems and cause sessions to silently stop routing. Errors are now surfaced so monitoring and alerting can catch them.

  • Consent lookup errors propagate. SMS consent cache lookups and writes follow the same fail-fast pattern. Infrastructure errors are no longer absorbed - callers see the failure and can handle it explicitly.

  • Deprecated compatibility wrapper removed. The legacy resolve_or_create conversation directory method has been removed. Callers should use the epoch-aware resolution method, which provides correct actor-epoch state for reactivated conversations.

  • Improved diagnostics for session engine cursor errors. When session load cursors are incoherent, the error now includes the specific cursor values and emits a metric, making diagnosis faster.

What you need to do:

No API changes are required. If you operate self-hosted infrastructure, ensure the active-session cache is healthy and monitored. Cache unavailability will now surface as explicit errors rather than degraded routing behavior. If you were using the deprecated resolve_or_create conversation directory method through internal tooling, migrate to the epoch-aware resolution method.

v0.9.196 - Platform API: Simplified Metrics Hot Path (June 2026)

Simplified Metrics Hot Path

The metrics pipeline has been simplified by removing the per-entity metric cache from the session store. Metric values now flow exclusively through the event pipeline and the realtime metric store, reducing write overhead on the session hot path.

What changed:

  • Per-entity metric caching removed from the session store. The session store no longer maintains a separate per-entity metric cache. Previously, per-entity metrics were written to both the session-level cache and the event pipeline. Now, metric values are written only to the event pipeline and served from the realtime metric store. This reduces per-session write volume and simplifies the data flow.

  • Session store scope narrowed. The session store now handles conversation turns and call intelligence data only. Metric storage and retrieval are handled entirely by the realtime metric store, which was introduced in v0.9.191.

What you need to do:

No API changes are required. If you consume metrics through dashboards, call detail views, or the metric catalog endpoint, behavior is unchanged - metrics continue to be available with the same low latency provided by the realtime metric store. The only difference is internal: the redundant session-level metric cache has been removed.

v0.9.195 - Platform API: Realtime Call Intelligence Metrics for Text Sessions (June 2026)

Realtime Call Intelligence Metrics for Text Sessions

Text sessions now project call intelligence metrics in realtime when a session ends, matching the behavior already in place for voice calls.

What changed:

  • Realtime metric projection for text sessions. When a text session completes, the platform now projects a terminal call intelligence row through the same realtime projection path used by voice calls. This means text session quality scores, conversation analytics, and custom metrics appear in dashboards and call detail views with the same low latency as voice call metrics. Previously, text session metrics relied on a separate path that could delay visibility.

  • Projection is best-effort. Metric projection for text sessions is secondary to the committed source data. If projection fails, the source call intelligence row is unaffected and metrics will be available once the analytical pipeline catches up. A failed projection does not cause the text session cleanup to fail.

What you need to do:

No API changes are required. Text session metrics now appear in dashboards and analytics with the same timeliness as voice call metrics. If you consume call intelligence data for text sessions, you may notice that metric values are available sooner after session completion.

v0.9.194 - Platform API: Resilient Call List Normalization (June 2026)

Resilient Call List Normalization

The call list endpoint now normalizes call direction and call source values before returning results, preventing unexpected values from causing errors in the response.

What changed:

  • Call direction normalization. Call direction values are now validated and normalized before inclusion in call list responses. Legacy or non-standard direction values are mapped to their canonical equivalents where a known alias exists. Unrecognized values are omitted rather than causing a server error.

  • Call source normalization. Call source values in the call list now pass through the same normalization already applied elsewhere in the API. Previously, raw values were returned directly, which could include non-standard entries. Unrecognized source values are now omitted from the response.

What you need to do:

No API changes are required. Call list responses now return consistent, validated values for direction and source fields. If you previously encountered errors when listing calls with unexpected direction or source values, those calls will now appear with normalized values or with those fields set to null.

v0.9.193 - Platform API: Deterministic Event Pipeline and Strict Session Journal Validation (June 2026)

Deterministic Event Pipeline and Strict Session Journal Validation

The session persistence engine now enforces strict journal metadata on all entries, emits deterministic event identifiers for downstream idempotency, and removes the request-path durable store fallback.

What changed:

  • Deterministic event identifiers. Turn and call intelligence events emitted to the analytics pipeline now carry stable, deterministic identifiers derived from each entry's journal position. If a retry re-emits the same event, downstream consumers deduplicate automatically. This makes the emission path at-least-once without risk of duplicate analytical records.

  • Flush-before-cache ordering. The event pipeline now confirms delivery before writing to the active-session cache. Previously, a cache write could succeed while the durable event delivery silently failed, leaving a gap in the analytical store. Flush failures now propagate to the caller so the synced cursor is not advanced prematurely.

  • Strict journal metadata validation. Session entries loaded from the active-session cache must carry canonical journal metadata - a journal kind, schema version, and index. Entries missing any of these fields are rejected at load time instead of being silently accepted with a fallback index. This eliminates an ambiguous migration-window code path where entries without journal metadata could produce inconsistent replay ordering.

  • Durable store replay removed from request path. The session engine no longer falls back to the analytical data store when the active-session cache is empty. Historical replay and bulk backfill are handled by offline data repair jobs and analytical projections, keeping per-request latency predictable. The session engine constructor no longer accepts optional data-store or replay parameters.

  • Unified turn-session identity for text and audio turns. Text and audio turn endpoints now derive session identifiers, cache keys, and conversation identifiers through a shared identity module. The derivation logic is unchanged - existing sessions continue without interruption - but the consolidation removes duplicated validation across the two endpoints.

  • Conversation detail read path simplified. The voice conversation detail endpoint no longer queries the analytical data store as a fallback when turn data is absent from the active-session cache. If turns are expected but not found, the response includes available metadata with an empty turns array and emits an observability breadcrumb. This matches the behavior already documented for historical calls in v0.9.192.

What you need to do:

No API changes are required. Session persistence, event emission, and conversation detail responses use the same schemas as before. The changes affect internal reliability and consistency guarantees:

  • Retry-safe event emission means analytics pipelines no longer need custom deduplication logic for turn and call intelligence events.

  • Calls where turn data has expired from the active-session cache now consistently return an empty turns array in the detail response, rather than attempting a slow fallback query.

v0.9.192 - Platform API: Listed Call Entity Fallback for Call Detail (June 2026)

Listed Call Entity Fallback for Call Detail

The call detail endpoint now resolves detail for all calls shown in the call list, even when turn-level data is not available in durable stores.

What changed:

  • Listed entity fallback. When a call appears in the call list but has no durable turn-level record (for example, older simulation or playground calls that predate the current session storage pipeline), the call detail endpoint now returns a minimal detail response built from the call's metadata and intelligence data. Previously, these calls returned a 404 from the detail endpoint despite being visible in the list. The response includes all available scalar fields (status, duration, direction, quality score, summaries, recording information) with an empty turns array.

  • Consistent list-to-detail resolution. Every call returned by the call list endpoint is now guaranteed to resolve through the call detail endpoint. This eliminates the inconsistency where some listed calls - particularly historical simulation and playground entries - could not be inspected.

  • Graceful degradation. If the metadata lookup encounters a transient error, the endpoint falls through to the existing 404 response rather than returning a 500. This keeps the fallback path safe for callers that retry on not-found responses.

What you need to do:

No API changes are required. Call detail responses use the same schema as before. Calls that previously returned 404 despite appearing in the call list will now return a valid detail response. The turns array will be empty for calls where turn-level data was not preserved, and recording information will be included when available.

v0.9.191 - Platform API: Realtime Metric Values and Catalog Metadata (June 2026)

Realtime Metric Values and Catalog Metadata

The metric store now makes recent values available with lower latency and returns additional public metadata from the metric catalog.

What changed:

  • Lower-latency metric reads. Recent metric values become available to dashboards and call detail views without waiting for a later batch refresh.

  • Expanded metric catalog fields. The metric catalog endpoint now returns source, custom_source_key, period_granularity, and latency_tier on each catalog entry. These fields were previously available only in workspace settings. The key field validation is also now explicit in the response schema (lowercase alphanumeric with underscores, 1-64 characters).

  • Renamed product surface. The metric store is now referred to as the "Realtime Metric Store" throughout the API and dashboard surfaces, replacing the previous "Universal Metric Store" name. The default metrics overview dashboard title has been updated accordingly.

What you need to do:

No request changes are required. If you consume the metric catalog endpoint, you can optionally use the new source, period_granularity, and latency_tier fields for filtering or display.

v0.9.190 - Platform API: Simplified Call Detail Source Resolution (June 2026)

Simplified Call Detail Source Resolution

The call detail endpoint now uses a simplified resolution path that removes redundant fallback layers and resolves call data from fewer, more predictable sources.

What changed:

  • Simplified source chain. Call detail resolution now follows a shorter, deterministic path: the primary voice service, then durable conversation storage, then simulation records. Previously, the endpoint checked additional intermediate stores that duplicated data already available through the durable path. Removing these redundant layers reduces per-request latency and eliminates edge cases where stale intermediate data could shadow more complete records.

  • Legacy turn store removed. Historical conversation turns stored in an older per-turn format are no longer queried. Turn data is now served exclusively from the hot session cache or the durable session log. Calls that predate both stores may return without turn-level detail. This change has no effect on calls created after the session log pipeline was enabled.

  • Consistent detail dependencies. All call and conversation detail endpoints now share a single set of read-path dependencies initialized at startup, rather than constructing them per request. This ensures consistent behavior across the call detail, conversation detail, and turn-backfill paths.

  • Simulation calls resolved independently. Simulation session detail is now treated as a distinct source rather than a fallback in the real-call chain. If a call identifier matches a simulation session, it is resolved directly without first attempting voice or durable lookups. This avoids unnecessary queries for identifiers that were never real calls.

What you need to do:

No API changes are required. Call detail responses have the same schema and fields as before. If you have calls from before the durable session log was enabled, those calls may return without conversation turns - this was already the case for most of these calls in practice.

v0.9.189 - Platform API: Fail-Fast Startup Validation for Hot-Path Dependencies (June 2026)

Fail-Fast Startup Validation for Hot-Path Dependencies

The platform now validates all critical runtime dependencies at startup and refuses to serve traffic if any required dependency is unavailable. This applies to both the Platform API and the Connector Runner.

What changed:

  • Startup connection verification. Services that depend on a fast session cache now verify connectivity at startup with a bounded timeout. If the cache is unreachable, the service fails immediately with a clear error instead of starting and silently dropping writes or returning degraded responses during live conversations.

  • Required event pipeline validation. In deployed environments, services that emit world events now validate that the event pipeline is fully configured at startup. If the event pipeline endpoint or target is missing, the service refuses to start. This prevents silent data loss where events would be dropped because the pipeline was partially configured.

  • Conversation directory cache lookup. The conversation resolution path now checks the active-session cache before querying the durable store. When a conversation is found in the cache and is active, the system refreshes its time-to-live and returns immediately without hitting the database. This reduces per-message latency on the hot path for active conversations.

What you need to do:

No API changes are required. These are infrastructure-level reliability improvements. Services will now fail loudly at startup if dependencies are misconfigured, rather than degrading silently at runtime. If you manage your own deployment configuration, ensure that all required environment parameters for the session cache and event pipeline are set before deploying.

v0.9.188 - Platform API: Text Session Latency and Error Handling Improvements (June 2026)

Text Session Latency and Error Handling Improvements

Text sessions now load conversation history exclusively from the fast cache on the live interaction path, and the text interact endpoint returns clearer error responses when agent processing fails.

What changed:

  • Cache-only session loading on the live path. Text session turns no longer fall back to the durable analytics store when the fast cache is empty. The durable store query could add significant latency to individual turn requests. Live sessions now load from the fast cache only, keeping per-turn response times predictable. Durable store replay remains available for offline recovery and batch scenarios where latency constraints are relaxed.

  • Turn count in text interact response. The text interact response now includes a turn_count field reflecting how many turns have been completed in the session. The conversation turn count is reconciled between the session engine and the upstream response, using the higher value to ensure accuracy.

  • Explicit error responses. The text interact endpoint now returns structured HTTP error responses instead of silently producing empty results. Agent timeouts return a 504 (Gateway Timeout), agent processing failures return a 502 (Bad Gateway), and sessions where the agent produces no response also return a 502 with a descriptive message. Previously, some of these failure modes could result in a successful response with an empty message list.

  • Deferred terminal artifacts for text sessions. Conversation summaries and call intelligence data are now written only when a text session is finalized, not after every turn. Active turns still sync session state incrementally, but analytical artifacts are terminal - writing them mid-conversation was both slow and semantically incorrect. This reduces per-turn processing overhead.

  • Post-call metric projection authentication. The post-call metric projection pipeline now supports agent-scoped authentication tokens in addition to service account tokens. This allows metric projection to proceed using the session's existing credentials when available, reducing the need to mint additional service tokens.

  • Cleanup ordering for agent sessions. Agent session credentials are now revoked after all post-call processing is complete, rather than at the start of cleanup. This ensures that workspace-scoped cleanup operations (such as metric projection) can use the session's credentials through their completion.

What you need to do:

No API changes are required. Clients that consume the text interact response can optionally read the new turn_count field. Clients that previously treated empty message lists as a soft failure should be aware that these cases now return explicit HTTP errors (502 or 504). The response schema is otherwise unchanged.

v0.9.187 - Platform API: Restored Call Detail Turns from Durable Storage (June 2026)

Restored Call Detail Turns from Durable Storage

The call detail endpoint now recovers conversation turns from durable storage when the primary source returns a valid call record but its turn data has expired.

What changed:

  • Turn backfill from durable storage. When the call detail endpoint returns a call record that has metadata (status, duration, participants) but no conversation turns, the platform now checks durable conversation storage for turn data. If turns are found, they are merged into the call detail response. This addresses cases where short-lived caches expire before the call detail is requested, which previously resulted in structurally valid responses with empty turn lists.

  • Additional fallback for fully missing calls. Calls that are not found in the primary call store are now also looked up in durable conversation storage before falling back to the entity-only projection. This expands the window during which call details with full turn history remain available.

  • Conversation lookup by entity ID. When a call cannot be found by its call identifier in conversation storage, the platform now resolves the underlying call reference from the entity store and retries the conversation lookup. This handles cases where the call was recorded under a telephony-assigned identifier that differs from the entity ID used in the API.

What you need to do:

No API changes are required. The call detail endpoint returns the same response shape. Calls that previously returned empty turn lists may now return full conversation history. This is a backward-compatible improvement - clients that already handle turns will display richer data automatically.

v0.9.186 - Platform API: Metrics Pipeline Ordering and Transport Resilience (June 2026)

Metrics Pipeline Ordering and Transport Resilience

The realtime metrics pipeline now uses improved ordering rules when resolving duplicate metric values, and the event transport handles additional failure modes gracefully.

What changed:

  • Improved metric value ordering. When multiple metric value events arrive for the same metric, the pipeline now considers the metric's effective period as a secondary ordering signal after the computed timestamp. This ensures that a recomputed metric for a newer period takes precedence over an older-period retry, even if the retry arrived later. Previously, only the computed timestamp and arrival time were used for ordering.

  • Deterministic tiebreaker for retries. The final tiebreaker for metric value deduplication now uses ascending event identity order instead of descending. This produces stable, repeatable results during replay without relying on event identity as a freshness signal. The change only affects the rare case where all other ordering signals are identical.

  • Transport error handling. The event transport now catches timeout and connection failures during flush and converts them into structured send errors. Previously, these failure types could propagate as unhandled exceptions. Other unexpected errors still propagate normally. This is a fail-closed design - callers receive an explicit error rather than a silent retry.

  • Workspace-scoped query validation. Query validation for workspace-scoped analytical queries now uses stricter pattern matching to prevent false matches against similarly named catalog paths. This reduces the risk of an unscoped query accidentally bypassing workspace isolation.

What you need to do:

No API changes are required. Metric values are resolved using the same endpoints and response shapes. The ordering improvement may change which value is selected as the latest in rare cases where duplicate events with identical computed timestamps existed. Transport error handling changes are internal to the event pipeline and do not affect API callers.

v0.9.185 - Platform API: Canonical Session Replay for Text Sessions (June 2026)

Canonical Session Replay for Text Sessions

The session engine now replays text session history from a canonical journal projection, replacing the previous row-order-based fallback. Returning text sessions load interaction history from a cleaned, indexed projection that guarantees deterministic replay order regardless of how historical data was originally ingested.

What changed:

  • Journal-indexed replay. Each interaction log entry now carries a stable journal index that defines its absolute position in the session timeline. When a returning session is loaded from the durable store, entries are ordered by journal index rather than ingestion timestamp. This eliminates rare ordering inconsistencies that could occur when entries shared identical timestamps.

  • Canonical projection filtering. The durable store query now filters to only return entries that carry canonical journal metadata. Legacy entries without journal metadata are excluded from cold replay unless they have been explicitly migrated through a backfill process. This ensures the session engine always receives well-structured, typed entries.

  • Replay limit. Cold session replay is now capped at a defensive upper bound to prevent unbounded query results for abnormally large sessions. Normal text sessions are orders of magnitude smaller than this limit. If the limit is reached, the engine logs a warning and continues with the available entries.

  • Improved error classification for durable store failures. Failures when reading from the durable store are now classified as transient or permanent based on the error type. Transient failures (timeouts, temporary unavailability) return an empty result and allow the session to proceed without historical context. Permanent failures (authentication errors, missing resources, malformed queries) are raised immediately so they surface during development rather than silently degrading in production.

  • Session state derivation from full interaction log. Session state - including current navigation position, visited states, message count, and state group boundaries - is now derived from the complete interaction log after replay, rather than being accumulated incrementally during entry loading. This produces consistent state regardless of whether the session was loaded from cache or the durable store.

  • Journal metadata on sync writes. New interaction log entries written during session sync now include journal kind, schema version, and journal index metadata. This ensures that entries written by the current engine version are immediately readable by the canonical projection without requiring backfill.

What you need to do:

No API changes are required. The session engine continues to use the same two-tier storage model (fast cache for active sessions, durable store for recovery). Text sessions that were active before this change will continue to work - the engine falls back gracefully when journal metadata is not yet present. Historical sessions will gain canonical replay ordering as the backfill process runs.

v0.9.184 - Platform API: Deduplicated Voice Call List (June 2026)

Deduplicated Voice Call List

The voice conversation list endpoint now returns exactly one row per logical call, eliminating duplicate entries that could appear when multiple conversation records existed for the same call.

What changed:

  • One row per call. The voice conversation list now deduplicates records that share the same underlying call identity. When multiple records exist for a single call, the endpoint selects the most recently updated record. This prevents the call list from showing the same call multiple times.

  • Deterministic ordering. The deduplication uses a stable tiebreaker so results are consistent across repeated requests. Records are ranked by last-updated time, then creation time, then record identity.

What you need to do:

No API changes are required. The response shape is unchanged. If your call list previously showed duplicate rows for certain calls, those duplicates are now resolved automatically.

v0.9.183 - Platform API: Strict Session Persistence Validation (June 2026)

Strict Session Persistence Validation

The voice agent engine now validates all session persistence dependencies at startup and fails fast if any required backing service is unavailable. Previously, persistence operations used a best-effort strategy that silently swallowed errors during conversation writes, turn storage, and metric recording. This could mask configuration problems and lead to data loss that was only discovered after the fact.

What changed:

  • Startup validation for session persistence. The agent engine now verifies that all required session persistence services are reachable and healthy before accepting any sessions. If a required dependency is unavailable at startup, the engine fails immediately with a clear error rather than starting in a degraded state.

  • Errors propagate during conversation writes. Conversation persistence, turn storage, call intelligence writes, and session metric updates now propagate errors to the caller instead of catching and logging them silently. This ensures that write failures are visible and can trigger appropriate retry or alerting behavior.

  • Required dependency warmup with retry. The agent runtime now retries initial persistence and analytics dependency checks with backoff before accepting sessions. If a required dependency remains unavailable, startup fails instead of silently entering a degraded state.

  • Session cleanup runs unconditionally. Text session cleanup now runs in a finally block, ensuring session resources are released even when session log synchronization fails or times out.

  • Improved observability for sync failures. Session state synchronization failures now emit structured log fields and increment a dedicated metric counter, making it easier to detect and alert on persistence issues in monitoring dashboards.

What you need to do:

No API changes are required. If your deployment previously started successfully with misconfigured persistence backends, it may now fail at startup with a clear error message indicating which dependency is unreachable. Ensure all required backing services are available and healthy before starting the agent engine.

v0.9.182 - Platform API: Restored Voice Conversation Reads (June 2026)

Restored Voice Conversation Reads

Voice conversation detail now reads turn data from multiple sources to ensure complete transcript availability across all conversation ages.

What changed:

  • Lifecycle-aware turn resolution. The voice conversation detail endpoint now recovers turns across active, recently completed, and historical calls. This improves transcript availability without changing the response shape.

  • Consistent turn ordering for summaries. Voice conversation summary queries now return deterministic results when multiple analytical records exist for the same call. The endpoint selects the most recent record per call, eliminating duplicate rows that could inflate conversation lists.

  • Accurate turn counts. The voice conversation detail response now reports turn counts derived from the resolved turn data rather than relying solely on a stored counter. This fixes cases where the turn count could show zero for conversations whose turns had migrated between storage tiers.

What you need to do:

No changes required. The conversation detail endpoint returns the same response shape. Turn data is now more reliably populated for conversations across all lifecycle stages.

v0.9.181 - Platform API: Simplified Metrics Hot Path (June 2026)

Simplified Metrics Hot Path

The metric store now serves hot metric values from a low-latency cache instead of a federated database serving layer. Metric projection writes values to the cache with a TTL and simultaneously flushes durable metric events into the analytics pipeline for long-term history. This simplifies the metrics architecture and reduces read latency for dashboard and API consumers.

What changed:

  • Hot metric reads from cache. All metric value endpoints - list latest values, get values by key, get metric trend, and get subject metrics - now read from a fast in-memory cache instead of querying a federated serving table. Read latency is lower and no longer depends on the availability of the federated database layer.

  • Metric projection writes to cache and event pipeline. When a call-intelligence row is projected into metrics, the platform extracts metric samples, writes them to the hot cache with a time-to-live, and flushes durable metric events through the event pipeline into the analytics data warehouse. The cache is the bounded hot window; older values are available from the data warehouse.

  • Idempotent projection. Metric projection is idempotent based on deterministic metric value identifiers. Duplicate projections for the same source artifact are detected in the cache and skipped, so retries do not inflate metric counts.

  • Removed on-demand metric evaluation endpoint. The POST /{metric_key}/evaluate endpoint has been removed. On-demand metric preview was previously available for AI query metrics over call intelligence. This capability may return in a future release through a different surface.

  • Removed generic artifact projection endpoint. The internal POST /metrics/artifacts/project endpoint has been removed. Metric projection is now handled exclusively through the call-intelligence projection path.

  • queued_jobs field deprecated. The queued_jobs field in metric projection responses is now always 0 and is deprecated. It will be removed in a future version.

  • Dashboard metric queries updated. Dashboard templates that previously queried metric values and freshness from a federated serving table now query the analytics pipeline outputs directly. No dashboard configuration changes are required - templates are updated automatically.

What you need to do:

  • If you were using the POST /{metric_key}/evaluate endpoint for on-demand metric preview, remove those calls. This endpoint is no longer available.

  • If you were using the internal POST /metrics/artifacts/project endpoint, migrate to the call-intelligence projection path.

  • If you were reading queued_jobs from metric projection responses, stop relying on this field. It is deprecated and always returns 0.

  • No changes are needed for metric read endpoints. The same query parameters and response shapes are returned - only the underlying serving layer has changed.

v0.9.180 - Platform API: Simplified Session Journal Persistence (June 2026)

Simplified Session Journal Persistence

Session persistence has been simplified across all session types. The platform now treats the interaction log as the single source of truth for session state, removing redundant state checkpoints and mutable cursor records that were previously maintained alongside the log.

What changed:

  • Interaction log is the sole session record. Session state - including navigation position, visited states, and message history - is now derived entirely from the interaction log on load. The platform no longer maintains a separate mutable checkpoint record alongside the log. This eliminates a class of consistency issues where the checkpoint and log could diverge after partial write failures.

  • Text conversation state persistence simplified. Text sessions no longer perform a separate state-save step during session cleanup. Instead, new interaction log entries are flushed through the session store, and all downstream state is derived from the log on the next session load. This reduces the number of writes during session teardown and removes the version-conflict error path that could occur when two actors raced to save state.

  • Conversation reactivation simplified. Reactivating a frozen text conversation no longer requires reading or writing a version counter. The platform transitions the conversation status directly, and the next session load reconstructs state from the interaction log. If a reactivated session has no cached log entries available (for example, after cache expiry), the platform logs a warning so operators can monitor for sessions that may need durable journal replay.

  • Durable event emission failures now propagate. When the platform emits session journal entries to the durable event pipeline, failures are no longer silently swallowed. If the durable write fails, the error propagates so callers do not advance their sync cursor past unsent entries. This ensures at-least-once delivery to the durable store. Cache write failures after a successful durable emit are logged but do not cause errors, since the durable record is already safe.

  • Simulation trace derived from logs. Simulation trace data (turn counts, visited states) is now computed directly from the cached interaction log entries rather than read from a separate cursor record. This simplifies the trace endpoint and ensures trace data is always consistent with the actual interaction history.

What you need to do:

No changes required. The simplified persistence model applies automatically to all session types - text, voice, and simulation. Sessions resume correctly from the interaction log, and the behavioral improvement - fewer writes, no version conflicts during state save, stronger delivery guarantees for journal events - applies without configuration changes.

v0.9.179 - Platform API: Durable Session State Fallback (May 2026)

Durable Session State Fallback

The session state engine now supports a two-tier storage model. Session state is read from the hot cache first, and if no data is found (for example, after the cache entry expires), the engine falls back to a durable store populated by the platform's event pipeline. This ensures that returning sessions can always resume from where they left off, even after extended inactivity.

What changed:

  • Durable fallback for session state. When the fast cache does not contain session data for a conversation, the engine now queries a durable store that is continuously populated from conversation events. Previously, if the cache entry had expired, the session would start fresh with no prior interaction history. Now, interaction history is recovered from the durable store and the session resumes correctly.

  • Automatic state derivation on fallback load. When session state is loaded from the durable store, the engine derives the agent's navigation position - current state, message count, visited states, and returning-user status - directly from the interaction history. This removes the dependency on a separate cursor record when resuming from the durable store.

  • Cache-first performance. Active sessions continue to load from the fast cache with no additional latency. The durable store is only queried when the cache is empty, so the common case (resuming an active session) is unaffected.

What you need to do:

No changes required. The durable fallback applies automatically to all session types - text, voice, and simulation. Sessions that previously lost state after cache expiration will now resume correctly.

v0.9.178 - Platform API: Voice Session State Persistence (May 2026)

Voice Session State Persistence

Voice calls now use the same unified session state engine that was previously introduced for text sessions (v0.9.176) and simulations (v0.9.177). Session state for voice calls - including interaction history and navigation position - is now persisted incrementally through the shared state engine.

What changed:

  • Unified state persistence for voice calls. Voice sessions now persist their interaction state through the same incremental session state engine used by text sessions and simulations. Previously, voice sessions used a separate persistence path. The unified approach ensures that voice call data flows through the same analytical pipeline, and session state is stored and retrieved consistently across all session types.

  • Automatic state sync on call completion. When a voice call ends, the platform syncs the session state to the persistent store before flushing call intelligence data. This ensures that the full interaction history is available for post-call analytics, metric evaluation, and review queue processing.

  • Graceful error handling. If the state sync encounters an error during call teardown, the failure is logged and the rest of the call cleanup - including call intelligence emission and transcript persistence - continues without interruption. No call data is lost due to a state sync failure.

What you need to do:

No changes required. Voice calls automatically use the unified state engine. The behavioral improvement - consistent state persistence across all session types - applies automatically.

v0.9.177 - Platform API: Unified Session State Engine for Simulations (May 2026)

Unified Session State Engine for Simulations

Simulation sessions now use the same unified session state engine that was introduced for text sessions in v0.9.176. Session state for simulations - including interaction history, navigation position, write authorization, and state group tracking - is persisted incrementally rather than as a monolithic blob.

What changed:

  • Incremental state persistence for simulations. Simulation sessions (text playground, bridge runs, and forked sessions) now persist interaction log entries incrementally after each step, matching the behavior already in place for text sessions. Previously, simulation sessions serialized and replaced the entire session state on every step. The new approach reduces write volume and eliminates edge cases where concurrent fork branches could interfere with each other's state.

  • Session forking uses incremental copies. When a simulation session is forked into multiple branches, each branch receives an independent copy of the parent session's interaction history. Branches no longer share mutable references to the parent's state, preventing cross-branch contamination during concurrent execution.

  • Session cleanup removes all state. Destroying a simulation session now removes both the incremental interaction history and the session cursor, ensuring no orphaned state remains after cleanup.

  • Trace and prompt endpoints read from incremental store. The simulation trace and prompt log endpoints now read interaction history from the incremental session store rather than the legacy monolithic blob. The trace reconstruction logic also handles both the current and previous log entry type identifiers, so sessions that span a deployment boundary render correctly.

  • Lightweight session metadata. Simulation-specific metadata (workspace, service, branch, entity binding) is now stored separately from the interaction log. This reduces the payload size for metadata lookups that do not need the full interaction history.

What you need to do:

No changes required. Existing simulation sessions that were created before this update will continue to work - the platform handles both the previous and current persistence formats transparently. Active sessions will migrate to the new format on their next step. The behavioral improvement - faster step persistence, safer forking, and cleaner cleanup - applies automatically.

v0.9.176 - Platform API: Unified Session State Engine for Text Sessions (May 2026)

Unified Session State Engine for Text Sessions

Text sessions now use a unified session state engine that persists the authoritative interaction log incrementally after each turn, rather than reconstructing session state from durable conversation turns on every request.

What changed:

  • Incremental state persistence. After each agent turn, only the new interaction log entries are appended to the session store. Previously, the platform replayed the full conversation turn history into the engine on every request. The new approach reduces resume latency and eliminates state-reconstruction edge cases.

  • Cursor-based session resume. The agent's navigation position - active context graph state, wait condition, message index, and entity-level write scope - is persisted as a cursor alongside the interaction log. On resume, the cursor is restored directly rather than being inferred from turn metadata. If the persisted state name no longer exists in the current context graph (e.g., after a graph update between sessions), the agent falls back to the default state gracefully.

  • Returning user detection. Sessions that load prior interaction history are automatically marked as returning-user sessions, so prompt rendering skips first-time-meeting framing without requiring explicit flags.

  • Backward-compatible log deserialization. Sessions that were persisted under the previous turn-based format are automatically converted to the new interaction log format on load. No migration step is required.

What you need to do:

No changes required. Existing text sessions and conversations continue to work. Sessions persisted under the previous format are migrated transparently on next resume. The behavioral improvement - faster resumes and more reliable state continuity - applies automatically.

v0.9.175 - Platform API: Workspace Data Queries CRUD Overhaul (May 2026)

Workspace Data Queries CRUD Overhaul

The workspace data queries REST surface has been redesigned around standard CRUD semantics with stable UUID-based addressing. Queries are now created with POST, partially updated with PATCH, and addressed by query_id (UUID) instead of name in all endpoints.

Breaking changes:

  • PUT /{name} replaced by POST (create) and PATCH /{query_id} (update). The upsert-by-name deploy endpoint has been removed. Create a query with POST /v1/{workspace_id}/data_queries (returns 201 Created with a server-generated id), then update it with PATCH /v1/{workspace_id}/data_queries/{query_id}.

  • All per-query endpoints now use query_id (UUID) instead of name. This includes GET, PATCH, DELETE, and invoke. The name field remains on the query object and is unique per workspace, but it is no longer part of the URL path.

  • POST /{name}/test removed. The test-invoke endpoint has been removed. Use the standard invoke endpoint for both testing and production execution.

  • input_schema removed from responses. The JSON Schema that was derived from parameters[] is no longer returned. Consumers can derive the schema locally from the parameter list if needed.

  • Test telemetry fields removed. The last_test_at, last_test_status, last_test_error, and last_test_duration_ms fields have been removed from query responses.

New behavior:

  • last_invoked_at field. Query responses now include last_invoked_at, which records the timestamp of the most recent successful invocation (whether via the HTTP invoke endpoint or the agent runtime). NULL until first invocation.

  • PATCH partial updates. The update endpoint accepts any subset of fields. Only fields present in the request body are changed; omitted fields retain their current values. When parameters is included, the entire parameter list is replaced. Validation runs against the post-update state, so placeholder/parameter parity is enforced even when only one side changes.

  • name is mutable. Queries can be renamed via PATCH. A rename that collides with an existing name returns 409 Conflict.

  • Create returns 409 Conflict for duplicate names. Previously, PUT would silently overwrite. Now, attempting to create a query with a name that already exists returns a conflict error.

  • Cascade delete. Deleting a query automatically removes its parameter rows. No separate cleanup is needed.

  • List endpoint returns parameter_count instead of full parameters. The list response now includes a parameter_count integer per query instead of the full parameter list. Use GET by ID to fetch full parameter details.

  • deployed_at and deployed_by are now non-nullable. These fields are always present on query responses.

What you need to do:

  • Update API clients to use POST for creation and PATCH /{query_id} for updates instead of PUT /{name}.

  • Update all per-query endpoint calls to use the query's UUID (id field from create/list responses) instead of name in the URL path.

  • Remove any references to the test-invoke endpoint or test telemetry fields.

  • If you were consuming input_schema from responses, derive it locally from the parameters array.

v0.9.174 - Platform API: Audit Events Emitted via Event Pipeline (May 2026)

Audit Events Emitted via Event Pipeline

Audit events are now emitted through the platform's unified event pipeline instead of being written directly to the data store. This aligns audit data with the same event infrastructure used by other platform subsystems, improving consistency and enabling downstream consumers to process audit events alongside other domain events.

What changed:

  • Unified event delivery. Audit events - including PHI access records, route-handler audit logs, and compliance-relevant actions - now flow through the platform event pipeline. Each audit event carries a domain, event type, entity reference, and source identifier, matching the structure used by other event types in the platform.

  • Buffered, best-effort delivery. The audit writer continues to buffer events in memory and flush them periodically or when the buffer reaches capacity. Fire-and-forget semantics are preserved - audit logging never blocks request processing. If an individual event fails to emit, the failure is logged and processing continues.

  • Pipeline flush after emit. After emitting buffered events, the writer explicitly flushes the event pipeline to ensure events are delivered before the buffer is cleared. This ordering guarantee is compliance-critical.

What you need to do:

No changes required. Audit events continue to be generated automatically by PHI access middleware and explicit audit calls in route handlers. Downstream consumers that read audit data from the event pipeline will begin receiving events in the new format.

v0.9.173 - Platform API: Python and UDTF Platform Functions Now Invoke User Code (May 2026)

Python and UDTF Platform Functions Now Invoke User Code

Python scalar and UDTF (table-valued) platform functions now correctly invoke the authored def main(...) entry point at execution time. Previously, deploying a Python or UDTF function would register the function successfully, but invoking it would return NULL (scalar) or raise a runtime error (UDTF) because the user-defined main function was never called.

With this release:

  • Python scalar functions - The platform appends a trampoline call that invokes main with the declared parameters and returns its result. Functions that previously returned NULL silently now execute as intended.

  • UDTF functions - The platform wraps the authored body inside a handler class with an eval method that calls main and yields its results. The HANDLER clause is now included in the generated DDL. Functions that previously raised a missing-name error now execute correctly.

  • UDTF invocation syntax - Table-valued functions are now invoked directly in the FROM clause rather than wrapped in a TABLE(...) expression, which resolves errors for registered table-valued functions.

Validation improvements:

  • Function bodies that do not declare a top-level def main(...) are now rejected at deploy time with a clear error, rather than being accepted and failing silently at invocation.

  • Parameter names are validated as legal identifiers at deploy time, preventing malformed names from producing invalid generated code.

What you need to do:

No changes required. Existing Python and UDTF functions that already declare def main(...) will begin executing correctly. Functions that were returning NULL or erroring will now produce the expected results. If you have functions deployed without a def main(...) entry point, redeploying them will surface a validation error prompting you to add one.

v0.9.172 - Platform API: Expanded Entity Fields in FHIR API Views (May 2026)

Expanded Entity Fields in FHIR API Views

The FHIR API views for patients, practitioners, appointments, and slots now expose additional entity fields that were previously only available through lower-level data access. These fields are returned directly in the standard FHIR entity views, so agents, integrations, and front-end applications can access them without extra lookups.

Patient view - new fields:

Field
Type
Description

address_state

string (nullable)

State from the patient's address

address_postal_code

string (nullable)

Postal/ZIP code from the patient's address

address_city

string (nullable)

City from the patient's address

primary_payer_name

string (nullable)

Name of the patient's primary insurance payer

practice_payer_id

string (nullable)

Practice-specific payer identifier

member_id

string (nullable)

Insurance member identifier

policyholder_name

string (nullable)

Name of the insurance policyholder

policyholder_relationship

string (nullable)

Relationship of the policyholder to the patient

policyholder_dob

string (nullable)

Date of birth of the policyholder

Practitioner view - new fields:

Field
Type
Description

member_id

string (nullable)

Provider member identifier

scheduling_eligible

boolean (nullable)

Whether the practitioner is eligible for scheduling

Appointment view - new fields:

Field
Type
Description

cancel_reason

string (nullable)

Reason for appointment cancellation

appointment_type

string (nullable)

Type or category of the appointment

duration_minutes

integer (nullable)

Duration of the appointment in minutes

modality

string (nullable)

Appointment modality (e.g., in-person, telehealth)

Slot view - new fields:

Field
Type
Description

provider_id

string (nullable)

Unique identifier for the provider associated with the slot

facility_id

string (nullable)

Unique identifier for the facility where the slot is offered

specialty

string (nullable)

Provider specialty for the slot

visit_type_ids

string (nullable)

Identifiers for visit types accepted in the slot

visit_type_names

string (nullable)

Display names for visit types accepted in the slot

All new fields are additive and nullable. Existing queries and integrations continue to work without changes. The slot view's provider_name field now also falls back to the practitioner display name when the previously used source is unavailable.

No client changes are required.

v0.9.171 - Platform API: Cross-Entity Appointment Patient Name Resolution (May 2026)

Cross-Entity Appointment Patient Name Resolution

Appointment entities in the world model now resolve the patient display name automatically when the source system does not include it in the appointment data. Previously, if the upstream system omitted the patient name from appointment records, the appointment_patient_display field remained empty even when the patient's name was available elsewhere in the world model.

With this release, the entity snapshot pipeline performs a cross-entity lookup: when an appointment references a patient but has no display name, the platform resolves the patient's identity through the entity linkage layer and populates the appointment's patient display name from the linked patient record. This happens automatically during entity processing with no configuration required.

Behavior:

  • If the appointment data already includes a patient display name, that value is preserved as-is.

  • If the patient display name is missing but the appointment references a patient, the platform resolves the name from the linked patient entity's demographic data.

  • If neither source provides a name, the field remains empty.

No client changes are required. Existing queries and integrations that read appointment_patient_display will see improved data completeness for appointments where the source system omits patient names.

v0.9.170 - Platform API: Slot Practitioner and Facility Identifiers (May 2026)

Slot Practitioner and Facility Identifiers

Slot entities in the world model now include practitioner and facility identifiers alongside the existing practitioner display name. These typed identifiers let agents and integrations match slots to specific providers and locations without relying on display-name string matching.

New fields on slot entities:

Field
Type
Description

slot_practitioner_id

string (nullable)

Unique identifier for the practitioner associated with the slot

slot_facility_id

string (nullable)

Unique identifier for the facility where the slot is offered

These fields are populated automatically during entity sync when the source system provides practitioner and facility references on availability data. Existing slots without this data will have null values for both fields.

Primary insurance projection. Insurance data for person entities is now also sourced from Coverage resources when available, with a fallback to inline insurance data on the patient resource. The fields returned are unchanged - patient_primary_payer_name, patient_practice_payer_id, patient_member_id, patient_policyholder_name, patient_policyholder_relationship, and patient_policyholder_dob - but coverage from dedicated insurance records takes precedence when both sources are present. Primary coverage (lowest order value) is preferred over secondary.

No client changes are required. Existing queries and integrations continue to work. The new slot fields are additive and nullable.

v0.9.169 - Platform API: On-Demand Forecast Computation for Population Health (May 2026)

On-Demand Forecast Computation

The population health forecast endpoints now compute forecast fan points on demand instead of reading from pre-materialized tables. Each request fits a statistical model to the current patient topology snapshot, generates 28 historical and 12 forecast data points with bootstrapped 95% confidence bands, and returns the same response shape as before.

What changed:

  • Territory and district forecast fan points are now computed at request time from the live patient topology. The response schema is unchanged - callers receive the same fields (run_id, scenario, t, ym, median, lower_95, upper_95, observed, is_historical) in the same structure.

  • Cluster forecast fan points are also computed on demand. Every (cluster, focus area) combination is generated dynamically, so new clusters or focus areas added to the topology are immediately available without a pipeline rerun.

  • Deterministic results. Forecasts for the same scope and target are deterministic across requests and across platform replicas. Two requests for the same view return identical data.

  • Tenant isolation. Topology data used for forecast computation is validated against the requesting workspace, with defense-in-depth checks that reject any rows not belonging to the authorized tenant.

Supported targets: T2D, Overall, BMI, HTN, CHF, Asthma, CKD, COPD.

Migration notes: No client changes are required. The forecast fan and cluster forecast endpoints return the same response shapes. Pre-materialized forecast tables are no longer read.

v0.9.168 - Platform API: Email Channel and SES Setup Management (May 2026)

Email Channel and SES Setup Management

The Channel Manager now supports email as a first-class channel alongside voice and ringless voicemail. Organizations can configure verified sending domains, create email use cases with reputation-isolated sending pools, and manage the full lifecycle through new API endpoints.

New: SES Setup endpoints

SES Setups represent a verified sending and receiving domain. Each setup provisions an isolated reputation boundary and domain identity for email delivery.

  • POST /v1/ses-setup - Create a new SES setup. Provisions the reputation isolation boundary and domain identity, then returns the DNS records the customer must publish (DKIM CNAMEs, MAIL FROM MX and SPF, DMARC TXT, and inbound MX). Returns 201 on success, 409 if the tenant name or domain already exists.

    • Request fields:

      • tenant_name (required, string, 1-64 chars, alphanumeric with hyphens and underscores) - Logical name for reputation and suppression isolation

      • domain_identity (required, string, 1-255 chars) - Domain to verify for sending and receiving (e.g. mail.customer.com)

    • Response includes id, tenant_name, domain_identity, dns_checked_at (null until first refresh), dns_records (array of records with address, record, type, and verified fields), and timestamps.

  • GET /v1/ses-setup - List all SES setups. Returns cached verification status per setup without triggering a live DNS check. Response includes items array with id, tenant_name, domain_identity, dns_verified, dns_checked_at, and timestamps.

  • GET /v1/ses-setup/{setup_id} - Get a single SES setup with a live DNS verification refresh. Checks DKIM, MAIL FROM, DMARC, and inbound MX status in real time and updates the cached verification state. Response includes the full DNS record list with per-record verified flags.

  • DELETE /v1/ses-setup/{setup_id} - Delete an SES setup and its associated domain identity and reputation boundary. Returns 204 on success. Refuses with 409 if any email use cases still reference the setup - those must be deleted first.

New: Email channel for use cases

The POST /v1/use-case endpoint now accepts "email" as a channel value. The request body is a discriminated union on channel - each channel variant carries only its own fields.

  • Email use case request fields:

    • channel (required, literal "email")

    • entity_name (required, string, 1-31 chars, letters/spaces/hyphens)

    • name (required, string, 1-31 chars, letters/spaces/hyphens)

    • description (optional, string, max 2000 chars)

    • ses_setup_id (required, UUID) - SES setup to bind to. Must have DNS fully verified.

    • sender_email_address (required, email) - From address for outbound sends. Domain part must match the setup's domain identity.

    • email_type (required, "transactional" or "marketing") - Outbound classification. Selects the reputation-isolated sending pool family. Immutable after creation.

  • Email use case response adds: ses_setup_id, configuration_set_name, sender_email_address, email_type, and tier.

  • tier represents the current reputation lane (onboarding, standard, premium, or suspended). New use cases always start at onboarding and are promoted based on send, bounce, and complaint performance.

  • Validation enforces that the sender email domain matches the setup's domain identity (422 with sender_domain_mismatch error if not), and that DNS is fully verified on the setup before use case creation (409 if not).

Updated: Use case list and delete

  • GET /v1/use-case now accepts an optional ses_setup_id query parameter to filter use cases bound to a specific SES setup. The response is a discriminated union - email use cases include SES-specific fields while voice use cases include Twilio-specific fields.

  • DELETE /v1/use-case/{use_case_id} now handles email use cases by tearing down the associated sending configuration and reputation pool binding before removing the database record.

Updated: Use case request field constraints

  • entity_name and name fields on use case creation are now constrained to 1-31 characters and must contain only letters, spaces, and hyphens (previously up to 256 characters with no pattern restriction). This ensures the combined identifier fits within downstream naming limits.

  • Use case responses are now a discriminated union on channel. Twilio-served use cases return twilio_setup_id; email use cases return ses_setup_id, configuration_set_name, sender_email_address, email_type, and tier. The previous flat response shape with an optional twilio_setup_id is replaced.

v0.9.167 - Platform API: Outbound Call Creation API (May 2026)

Outbound Call Creation API

The Platform API now exposes a public endpoint for initiating outbound voice calls from a workspace phone number. Previously, outbound calls could only be triggered through internal systems. With this release, API consumers can programmatically place outbound calls to any E.164 phone number using a caller ID registered in their workspace.

What changed:

  • New POST /calls/outbound endpoint. Creates an outbound voice call. The request specifies the destination number, the caller ID (which must belong to the workspace), and optional fields for service selection, system prompt override, and idempotency. The response includes the call identifier and initial call status.

  • Request fields:

    • phone_to (required, string) - Destination phone number in E.164 format (e.g. +18005551234)

    • phone_from (required, string) - Caller ID phone number in E.164 format. Must be registered in the workspace.

    • service_id (optional, string) - Service ID for the voice agent to use

    • system_prompt (optional, string) - System prompt override for this call

    • idempotency_key (optional, string) - Client-provided idempotency key. Auto-generated if omitted.

    • outbound_task_entity_id (optional, string) - Outbound task entity ID for completion feedback

  • Response fields:

    • call_sid (string) - Call identifier for the outbound call

    • status (string) - Initial call status (typically "queued")

  • Validation. Both phone_to and phone_from are validated as E.164 format. The phone_from number must belong to the requesting workspace or the request is rejected with a 403.

  • Idempotency. Clients can supply an idempotency_key to safely retry requests without creating duplicate calls. If omitted, the platform generates one automatically.

  • Rate limiting. The endpoint is subject to write rate limits.

  • Error responses: 400 (invalid phone format), 403 (caller ID not in workspace), 429 (rate limit), 502 (upstream error), 503 (outbound calls not configured).

v0.9.166 - Platform API: Slot Visit Types and Provider Specialty (May 2026)

Slot Visit Types and Provider Specialty

Slot entities in the world model now include the provider's specialty and the visit types accepted for that slot. This gives the voice agent and booking UI richer context when presenting available appointments - for example, "Dr. Chen (Cardiologist) - Tele Visit or In-Person Review at 10:00 AM" - without requiring additional lookups against practitioner or configuration entities.

What changed:

  • Slot specialty. Each slot now carries the provider's specialty (e.g., "Physician", "Cardiologist") when the connected EHR supplies it. The value is attached during availability sync and projected as a typed field on the slot entity.

  • Slot visit type IDs and names. Slots now include the list of visit types the provider accepts at the associated facility. Visit types are represented as two parallel pipe-delimited fields - one for IDs and one for human-readable names - so consumers can match on either. For example, IDs might be 100001000000008083|100001000000008085 with corresponding names Tele Visit|Review.

  • Enrichment from booking preferences. Visit type data is sourced from the provider's booking preferences, which the connector caches during its regular sync cycle. When cached data is not yet available, slots continue to emit without visit type fields (all new fields are nullable), preserving backward compatibility with existing consumers.

  • No breaking changes. All new fields are optional and nullable. Existing integrations continue to work without modification.

v0.9.165 - Platform API: Full Observer WebSocket Event Types for SDK Pipeline (May 2026)

Full Observer WebSocket Event Types for SDK Pipeline

The observer WebSocket event stream now includes typed payloads for all 20 real-time event types, up from the previous 6. SDKs and clients consuming the observer stream can now handle every event with compile-time type safety and discriminated unions.

New event types:

  • Session lifecycle. session_info, session_start, and session_end events provide session metadata at connect time, mark when a session begins (with initial state and trace context), and report final duration, turn count, and completion reason when a session ends.

  • State transitions. state_transition events fire when the agent moves between context graph states, including the previous and next state names, transition type, and optional annotation.

  • Streaming transcript deltas. agent_transcript_delta events deliver incremental agent speech tokens as they are generated, enabling real-time streaming displays.

  • Latency and timing. latency events report end-to-end time-to-first-byte, engine processing time, navigation time, render time, and audio time-to-first-byte. nav_timing events break down navigation and rendering durations with optional token counts, model identifier, and retry metadata.

  • Emotion and empathy. emotion events carry dominant emotion, valence, arousal, trend, coherence, per-segment scores, acoustic features, and language sentiment. compound_emotion events report blended emotion scores per turn. empathy_classified events indicate the selected empathy tier, whether the agent should pause, and filler suppression state.

  • Barge-in. barge_in events report caller interruptions, including the text that was interrupted, any discarded pending utterances, and cumulative barge-in count.

  • Participants. participant_joined and participant_left events track when callers, agents, or operators enter or leave a conference, with role and display information.

  • Voice context. voice_context_applied events indicate the current TTS emotion, speed, volume, filler state, emotion detection state, and reasoning behind the voice parameter selection.

No breaking changes. All existing event types (user_transcript, agent_transcript, tool_call_started, tool_call_completed, forward_call_resolved, speaker_muted) remain unchanged. The new types are additive. Clients that do not handle a particular event type can safely ignore it.

v0.9.163 - Platform API: Cluster Forecast Observed Values and Calendar Axis (May 2026)

Cluster Forecast Observed Values and Calendar Axis

The cluster forecast endpoint now returns observed values and calendar month labels alongside forecast data, enabling richer visualizations with actual-vs-predicted comparisons and human-readable time axes.

What changed:

  • Observed values. Each forecast data point can now include an observed field containing the actual measured value for that period. This allows clients to render scatter plots or overlay lines showing real data against the forecast fan.

  • Calendar month labels. Each forecast data point can now include a ym field containing a year-month string (e.g., "2026-05") for use as a human-readable x-axis label instead of a numeric time index.

  • Backward compatible. Both new fields are optional and nullable. Workspaces running older data pipelines that do not produce these fields continue to receive responses in the existing format with no disruption. The endpoint probes for field availability and adapts the response automatically.

v0.9.162 - Platform API: Desktop Integration Protocol (May 2026)

Desktop Integration Protocol

The integration protocol field now supports desktop as a valid value, alongside rest, fhir, and mcp. This allows integrations that connect to desktop applications to be represented with a dedicated protocol type rather than being mapped to a generic alternative.

What changed:

  • New protocol value. The protocol field on integration responses now includes desktop in its set of allowed values. Desktop integrations can be created and returned with protocol: "desktop" instead of requiring a workaround protocol assignment.

  • No breaking changes. Existing integrations using rest, fhir, or mcp protocols are unaffected. The new value is additive.

v0.9.161 - Platform API: Reliable Surface Creation (May 2026)

Reliable Surface Creation

Surface creation now writes to the primary data store before emitting downstream events, eliminating a race condition where newly created surfaces could briefly return 404 errors.

What changed:

  • Write-order fix. Previously, creating a surface emitted an event to the async pipeline first and wrote to the primary store second. If a client or the agent attempted to read the surface before the primary write completed, the request would fail with a 404. Surface creation now writes to the primary store first, so the surface is immediately queryable after the create call returns.

  • No API changes. The surface creation endpoint accepts and returns the same request and response shapes. Existing integrations require no changes.

v0.9.160 - Platform API: Dedicated Connector Configuration Storage (May 2026)

Dedicated Connector Configuration Storage

Connector definitions are now stored as individual records per connector instead of being embedded in workspace settings. This improves query performance, enables per-connector update timestamps, and supports future features like connector-level audit trails and granular access control.

What changed:

  • Per-connector records. Each connector definition is now stored as its own record with individual created_at and updated_at timestamps. Previously, all connectors for a workspace were stored together in the workspace settings payload, meaning any single connector change required rewriting the entire collection.

  • Simplified connector-runner refresh. The connector sync engine now reads from the derived data source index directly, removing a fallback code path that handled workspaces that had not yet been migrated to the structured connector format. All workspaces now use the same read path.

  • No API changes. The connector settings endpoints (GET and PUT) continue to accept and return the same request and response shapes. Existing integrations, including Agent Forge workflows, require no changes.

  • Automatic migration. Existing connector configurations are migrated automatically. No manual steps are required.

v0.9.159 - Platform API: Incremental Sync for Charm EHR Connector (May 2026)

Incremental Sync for Charm EHR Connector

The Charm FHIR connector now supports incremental sync. Instead of fetching all records on every sync cycle, the connector tracks the last successful sync time per resource type and only requests records updated since that point.

What changed:

  • Cursor-based incremental fetch. After a successful sync, the connector stores a per-resource-type cursor representing the sync timestamp. On subsequent polls, only records updated after that timestamp are fetched from the Charm FHIR API. This significantly reduces data transfer volume and sync duration for workspaces with large patient populations.

  • Automatic full re-fetch safety net. Cursors expire after 7 days. If a connector is paused or disabled for longer than that window, the next sync automatically performs a full fetch to ensure no records are missed. Corrupt or invalid cursors are also detected and trigger a full fetch with a diagnostic warning.

  • No configuration required. Incremental sync is enabled automatically for all Charm FHIR connections. Existing connectors will perform one full fetch on their next sync cycle, then switch to incremental mode going forward.

This change reduces sync times and API usage for active Charm integrations without any changes to connector configuration or API usage.

v0.9.158 - Platform API: World Event Source Consistency and Connector Emission Cleanup (May 2026)

World Event Source Consistency and Connector Emission Cleanup

This release improves the consistency and accuracy of event attribution in the world model, and removes unnecessary data emission from the connector sync pipeline.

What changed:

  • Consistent event source attribution. Events written to the world model by the voice agent now use a standardized source identifier instead of a freeform string. This ensures that all voice-agent-originated events are correctly categorized and filterable in downstream analytics, dashboards, and audit logs. Previously, some events could be tagged with a generic label, making it harder to distinguish their origin.

  • Connector runner no longer emits raw records without unification rules. When a data source has no unification rules configured, the connector sync pipeline now skips event emission entirely instead of writing unprocessed records into the world model. This prevents accumulation of unstructured data that could not be meaningfully resolved or used by the platform. Data sources without unification rules still sync normally - records are fetched and logged - but no world events are created until rules are configured.

These changes improve data quality in the world model and reduce noise in event streams for workspaces with partially configured connectors. No API changes are required.

v0.9.157 - Platform API: Voice Engine Actor Semantics and Per-Utterance TTS (May 2026)

Voice Engine Actor Semantics and Per-Utterance TTS

The voice agent engine now enforces stricter actor semantics during conversations, eliminating a class of timing issues where filler audio could overlap or conflict with primary agent responses.

What changed:

  • Per-utterance voice parameters. TTS emotion and speed settings are now resolved per utterance rather than applied globally to the speaker. This prevents a race condition where a late-arriving emotion update from one response could bleed into a subsequent response. Each utterance carries its own voice parameters, and the speaker restores its baseline after playback completes.

  • Retry filler coordination. When the reasoning engine retries after producing unparseable output, filler audio is now coordinated through the same signal-based pipeline as all other conversation events. This replaces a separate filler path that could produce overlapping audio. The retry filler respects the same cooldown and muting rules as other filler types.

  • New retry signal type. The conversation orchestrator recognizes a new signal for reasoning retries, allowing it to manage filler timing during retries using the same priority and deadline logic applied to other transitions. This signal is treated as a phase boundary, meaning it cleanly ends the current processing quantum before starting the retry filler.

  • Queue drain without interruption. The speaker now supports draining queued utterances without cutting off the currently playing audio. This is used during call suspension to let in-progress speech finish naturally while clearing pending items from the queue.

These changes improve audio continuity during complex multi-step conversations, especially when the agent is processing tool results, handling retries, or transitioning between conversation phases. No API changes are required.

v0.9.155 - Platform API: Real-Time Surface Events in Text Sessions (May 2026)

Real-Time Surface Events in Text Sessions

Text sessions now receive surface lifecycle events - such as form submissions and review approvals - in real time via the workspace event stream. Previously, the agent could only detect surface completions by polling. With this release, the session automatically subscribes to relevant workspace events when a surface is created, and delivers matching events to the agent as soon as they occur.

This reduces the delay between a patient completing a surface and the agent reacting to it, improving responsiveness in multi-step workflows that depend on collected data.

The subscription is resilient to transient disconnections and reconnects automatically with backoff. Surface status polling remains available as a fallback. No API changes are required - existing text session and surface endpoints work as before.

v0.9.154 - Platform API: Inline Operator State for Immediate Visibility (May 2026)

Inline Operator State for Immediate Visibility

Newly created operators now appear in operator list queries immediately after creation. Previously, a new operator could be invisible in list results until background processing caught up, because the data used by list queries was populated asynchronously.

With this release, the platform writes operator state - including roles, profile, and availability - at creation time, so list and filter operations return the new operator right away. The same applies to operator updates: changes to availability status or profile fields are reflected in list queries immediately rather than after a processing delay.

No API changes are required. Existing create and update endpoints behave the same; the improvement is in how quickly results are reflected in read operations.

v0.9.153 - Platform API: PCA Coordinates on Patient Topology (May 2026)

PCA Coordinates on Patient Topology

The patient topology endpoint now returns three-dimensional PCA coordinates (pca_x, pca_y, pca_z) alongside the existing UMAP coordinates for each patient. PCA coordinates provide an alternative dimensionality-reduction projection that can be used for 3D visualization or analytical workflows where linear projections are preferred.

All three fields are optional and may be null if PCA data is not available for a given patient. Existing integrations are unaffected - the UMAP coordinates and all other fields remain unchanged.

New response fields on each patient topology row:

Field
Type
Description

pca_x

number or null

PCA x-coordinate

pca_y

number or null

PCA y-coordinate

pca_z

number or null

PCA z-coordinate

v0.9.152 - Platform API: Text Session Transport and Event-Driven Trigger Scheduler (May 2026)

Buffered Text Session Transport

Text sessions now use a buffered message transport instead of a subscription-based model. Messages sent before the session actor finishes initializing are preserved and processed once the actor starts consuming, eliminating the previous timing dependency where the first inbound message could be lost if it arrived during session setup.

This also improves resilience to transient infrastructure errors during message consumption. The actor retries on transient failures with backoff and terminates the session gracefully after repeated consecutive errors, rather than silently dropping messages.

Additionally, the complete action now sends a final message (if present) and deactivates the session in a single step, ensuring the patient always receives the agent's closing message before the session ends.

Event-Driven Trigger Scheduler

The trigger scheduler now reacts to trigger mutations immediately instead of waiting for the next polling cycle. When a trigger is created, updated, paused, resumed, or deleted through the API, the scheduler wakes and re-evaluates due triggers right away. A periodic heartbeat remains as a safety net if the notification is missed.

No API changes are required. Existing trigger CRUD endpoints work as before - the scheduler simply picks up changes faster.

Workspace Event Signal Routing

The agent engine now recognizes workspace events (such as surface submissions and review approvals) as structured signals natively, without requiring a secondary reclassification step. This simplifies event routing and ensures workspace events are handled consistently with other signal types.

No changes to the workspace event format or API. Existing event payloads are handled transparently.

v0.9.151 - Platform API: Typed SSE Event Schemas (May 2026)

Typed Event Schemas for Real-Time Streaming

The Platform API SSE streaming endpoint now publishes fully typed event schemas in the OpenAPI specification. SDK consumers (including the TypeScript SDK generated via openapi-typescript) automatically receive discriminated union types for every workspace and observer event, enabling compile-time exhaustiveness checks when handling real-time events.

Workspace events are delivered over the SSE stream and cover the following domains:

Domain
Events

Call

call.started, call.ended, call.escalated

Surface

surface.created, surface.delivered, surface.updated, surface.archived, surface.reshaped, surface.submitted, surface.field_saved, surface.opened, surface.pending_review, surface.review_approved, surface.review_rejected

Operator

operator.registered, operator.status_changed, operator.profile_updated, operator.joined_call, operator.left_call, operator.mode_changed, operator.wrap_up

Pipeline

pipeline.sync_completed, pipeline.error

Observer events are delivered over the call observation WebSocket and include:

Event
Description

user_transcript

Caller speech transcription

agent_transcript

Agent speech output

tool_call_started

Tool execution began

tool_call_completed

Tool execution finished

forward_call_resolved

Call forwarding resolved

speaker_muted

Speaker mute state changed

Each event type has a fixed schema with domain-specific fields. The discriminator field (event_type for workspace events, type for observer events) lets clients switch on the event kind and access typed payloads without runtime parsing.

The publish_workspace_event interface now accepts typed event models in addition to the existing dictionary format. Both produce identical wire format. Existing integrations using the dictionary format continue to work without changes.

No existing events were removed or renamed. Clients that do not use the new typed schemas are unaffected.

v0.9.150 - Platform API: Population Health Forecast Fan Enhancements (May 2026)

Observed Values and Period Labels on Forecast Fan Points

The population health forecast fan endpoint now returns two additional fields on each data point:

Field
Type
Description

observed

number or null

Actual observed value for the period (populated on historical rows)

ym

string or null

Year-month label for the data point (populated on historical rows)

These fields let dashboard consumers distinguish historical observations from forecasted values and display period labels without deriving them from timestamps. When present, frontends can render historical data points as distinct markers on the forecast fan chart.

No existing fields were removed or renamed. Clients that do not use the new fields are unaffected.

v0.9.148 - Platform API: Population Health Stratified Fits and Notes Rollup Endpoints (May 2026)

Stratified Fits Endpoint

A new endpoint returns per-cohort, per-region model fits that drive the dashboard's outcome-by-segment comparison view. Each row includes outcome identifiers, cohort and region labels, sample size, base rate, AUROC, intercept, model coefficients, and whether the fit is a pooled fallback. Results can be filtered by outcome key.

Method
Path
Description

GET

/v1/{workspace_id}/population-health/stratified-fits

List stratified model fits by cohort and region

Query parameters:

Parameter
Type
Description

outcome_key

string (optional)

Filter to a single outcome (1-64 characters)

Response fields (per item):

Field
Type
Description

workspace_id

string

Workspace identifier

outcome_key

string

Outcome identifier

outcome_name

string or null

Human-readable outcome name

cohort

string

Cohort label

region

string

Region label

n

integer or null

Sample size

base_rate

number or null

Base rate for the cohort-region segment

auroc

number or null

Area under the ROC curve

intercept

number or null

Model intercept

coefficients_json

string or null

Serialized model coefficients

is_pooled_fallback

boolean or null

Whether this fit is a pooled fallback

Notes Rollup Endpoint

A new endpoint provides a cohort-wide (or per-cluster / per-district) rollup of NLP note extractions joined onto patient risk predictions. The rollup surfaces which narrative signals - symptoms, concerns, medications, sentiment, and social determinants of health - correlate with higher predicted risk.

Method
Path
Description

GET

/v1/{workspace_id}/population-health/notes/rollup

Get cohort-wide NLP extraction rollup

Query parameters:

Parameter
Type
Description

cluster

string (optional)

Filter to a specific cluster (1-64 characters)

district

string (optional)

Filter to a specific district (1-64 characters)

Response fields:

Field
Type
Description

workspace_id

string

Workspace identifier

total_notes

integer

Total notes included in the rollup

cohort_mean_risk

number

Mean predicted risk across the cohort

sentiment_distribution

array

Distribution of sentiment categories with counts, percentages, mean risk, and risk lift

top_symptoms

array

Most frequent symptoms with counts, percentages, mean risk, and risk lift

top_concerns

array

Most frequent concerns with counts, percentages, mean risk, and risk lift

top_medications

array

Most frequent medications with counts, percentages, mean risk, and risk lift

sdoh

object

Social determinants of health distributions (activity, smoking, diet)

Each category entry includes:

Field
Type
Description

value

string

Category label

n

integer

Number of patients in this category

pct

number

Percentage of total

mean_risk

number

Mean predicted risk for this category

risk_lift

number

Difference between category mean risk and cohort mean risk

v0.9.147 - Platform API: Signal-Driven Text Conversations (May 2026)

Signal-Driven Text Session Architecture

Text conversations (SMS) now use a signal-driven architecture that matches the model used for voice calls. All external events - inbound messages, delivery status updates, form submissions, review approvals, and timeouts - are processed sequentially through a single event loop per session. This eliminates race conditions that could occur when multiple events arrived concurrently under the previous model.

Delivery status tracking - Outbound SMS messages now include a delivery status callback. The platform receives delivery confirmations (sent, delivered) and failure notifications (failed, undelivered) from the telephony provider and routes them into the active session. Failed deliveries are logged and surfaced in session metrics.

New SMS status webhook - A new endpoint receives delivery status callbacks from the telephony provider and publishes them as structured events to the active text session. Status updates include delivery confirmation, failure notifications with error codes, and intermediate states. The endpoint validates provider signatures before processing.

Form and review event handling - Text sessions now natively handle form submission and review approval events. When a patient completes a form or a review is approved, the event is routed directly into the text session's event loop, clearing any pending wait conditions and continuing the conversation without polling.

Entity resolution for outbound sessions - Outbound text sessions can now resolve patient context by entity ID in addition to phone number lookup. This means outbound conversations initiated with a known patient ID load the full patient context immediately, rather than relying solely on phone number matching.

Session lifecycle events - Text sessions now emit structured workspace events at session start and session end, including session duration, turn count, completion reason, and final state. These events are available through the existing workspace event infrastructure.

Call intelligence for text - Text session analytics records now include a channel indicator distinguishing text sessions from voice sessions, enabling filtered reporting across conversation types.

v0.9.146 - Platform API: Signal-Driven Operator Lifecycle (May 2026)

Operator Takeover and Transfer Lifecycle

The operator escalation system now uses a signal-driven lifecycle model that processes all operator state changes sequentially, eliminating race conditions from concurrent events such as duplicate disconnect callbacks or simultaneous transfer and hangup signals.

Operator modes - Operators can join a call in takeover mode (agent is suspended, operator speaks directly with the caller) or listen mode (agent continues running, operator monitors silently). Mode can be switched at any time during the call.

Warm transfer - Operators can initiate warm transfers to bring a third party onto the call. The transfer follows a structured hold-dial-briefing-handoff sequence with automatic timeout handling at each stage. If the transfer target does not answer or disconnects during briefing, the caller is automatically taken off hold and the call resumes.

Handback context - When an operator in takeover mode leaves, the conversation that occurred during the human segment is summarized and injected into the agent's context so the agent resumes with full awareness of what was discussed.

Crash recovery - Operator state is persisted on every transition. If the hosting infrastructure restarts mid-escalation, the operator session recovers from the last known state and re-applies timeouts, ensuring in-progress calls are not disrupted.

Automatic timeout safety - Every non-terminal operator state has a deadline. If the expected next event does not arrive within the window, the system transitions to a safe state automatically - resuming the agent, releasing holds, or cleaning up partial transfers.

Idempotent signal handling - Duplicate signals (such as disconnect notifications arriving from both a webhook and a WebSocket) are handled idempotently. The system checks the current state before transitioning, so duplicate events are safely ignored.

v0.9.144 - Platform API: Admin Workspace Access Endpoint (May 2026)

List Workspaces With Admin or Owner Access

A new endpoint returns only the workspaces where the authenticated user holds an admin or owner role, filtering out workspaces where they have lower-level access.

Method
Path
Description

GET

/v1/workspaces/admin-access

List workspaces with admin or owner access

The response uses the same shape as the existing /v1/workspaces/access endpoint - a list of workspace access records including role, scopes, and workspace summary. Results are sorted alphabetically by workspace name.

This is useful for building admin-only views such as workspace management dashboards, where you need to show only the workspaces the current user can administer.

v0.9.143 - Platform API: Workspace Environment Conversion (May 2026)

Convert Workspaces Between Staging and Production

Two new workspace endpoints let you convert a workspace between staging and production environments after creation.

Method
Path
Description

GET

/v1/workspace/{workspace_id}/environment-check

Pre-check environment conversion

POST

/v1/workspace/{workspace_id}/convert-environment

Convert workspace environment

The pre-check endpoint returns compliance warnings for the target environment without making any changes. Converting from staging to production warns about stricter idle session timeouts, HITRUST compliance controls, enhanced audit retention, and production credential handling. Converting from production to staging warns about relaxed compliance controls and reduced audit retention.

The convert endpoint performs the actual conversion. It requires a target field (production or staging) and a confirm_slug field that must match the workspace slug, preventing accidental conversions. The workspace response includes metadata recording when the conversion occurred and the previous environment.

Both endpoints require Workspace.update permission (admin or owner).

v0.9.142 - Platform API: Default Staging Environment, Viewer Workspace Creation, and CSV Intake Support (May 2026)

Workspace Creation Defaults to Staging

The environment field on workspace creation is now optional and defaults to staging. Previously, the field was required and callers had to specify production, staging, or development explicitly. Existing integrations that already pass an environment value are unaffected.

Viewers Can Create Workspaces

The Viewer role now includes permission to create workspaces. Previously, only Editors and Admins could create workspaces. This lets read-only team members set up their own staging or development workspaces without requiring elevated access.

CSV Files Supported in Data Intake

Intake links now accept CSV file uploads (text/csv) in addition to the previously supported formats (PDF, JPEG, PNG, Word, and PowerPoint). The intake upload form also now filters the file picker to only show allowed file types, and displays human-readable labels for all supported formats including those not in the built-in label list.

v0.9.141 - Platform API: Use Cases, Outbound Voice, and Ringless Voicemail Restructured (May 2026)

Use Cases Are Now Top-Level Resources

Use cases have moved from being scoped under a Twilio setup to top-level resources with their own endpoints. Each use case now carries a channel type (outbound_voice, inbound_voice, or ringless_voicemail), a business entity name, and a descriptive name. For telephony channels, you supply the Twilio setup ID at creation time to bind the use case to that provider.

New endpoints:

Method
Path
Description

POST

/v1/use-case

Create a use case

GET

/v1/use-case

List use cases (filterable by entity, channel, or Twilio setup)

DELETE

/v1/use-case/{use_case_id}

Delete a use case

Removed endpoints:

Method
Path

POST

/v1/twilio-setup/{setup_id}/use-case

GET

/v1/twilio-setup/{setup_id}/use-case

DELETE

/v1/twilio-setup/{setup_id}/use-case/{use_case_id}

The use case response shape has changed: type is replaced by channel, the setup_id field is now twilio_setup_id (nullable), and new fields entity_name, description, and channel are included.

Outbound Voice Phone Number Selection Moved

Phone number selection for outbound calling has moved to a dedicated endpoint. The use case ID is now passed in the request body instead of the URL path, and only outbound_voice use cases are accepted.

Before
After

POST /v1/twilio-setup/{setup_id}/use-case/{use_case_id}/phone-number/select

POST /v1/outbound-voice/phone-number/select

Ringless Voicemail Endpoints Restructured

Ringless voicemail send and list endpoints have moved to top-level paths. The send endpoint now accepts use_case_id as a form field instead of a URL path parameter. A new list endpoint supports filtering by use case, setup, status, and recipient phone number.

Before
After

POST /v1/twilio-setup/{setup_id}/use-case/{use_case_id}/ringless-voicemail

POST /v1/ringless-voicemail

(none)

GET /v1/ringless-voicemail

Phone Number Assignment Changes

The assign endpoint (PUT .../use-case/{use_case_id}) now accepts the top-level use case ID and returns 204 No Content instead of the phone number object. The uniqueness constraint is now per-channel rather than per-use-case-type. The inbound_voice channel is now supported for assignment.

Webhook Paths Updated

Vendor webhook endpoints have moved to a consolidated /v1/webhook/ prefix:

Before
After

POST /twilio-setup/webhook

POST /v1/webhook/twilio/trust-hub

POST /v1/voicedrop/webhook/{voicemail_id}

POST /v1/webhook/voicedrop/ringless-voicemail/{voicemail_id}

Migration Notes

  • Update use case CRUD calls to use the new /v1/use-case paths

  • Update outbound voice phone number selection to use /v1/outbound-voice/phone-number/select with a request body

  • Update ringless voicemail sends to use /v1/ringless-voicemail with use_case_id as a form field

  • The assign phone number endpoint now returns 204 instead of 200 with a body

  • Webhook receiver URLs must be updated to the new /v1/webhook/ prefix paths

v0.9.139 - Appointment Reason in World Model (May 2026)

Appointment Reason Now Available as a First-Class Field

The world model now stores the patient-facing reason for an appointment as a dedicated field on appointment entities. Previously, the visit reason was only accessible by inspecting the raw FHIR resource. It is now surfaced directly, so the voice agent can reference why a patient is booked (for example, "you're scheduled for a follow-up") without additional data lookups.

This field is distinct from the cancellation reason, which only populates when an appointment is cancelled.

The new field is available through platform functions, world tools, and data access queries. No API request or response schema changes are required. Existing integrations continue to work without modification.

v0.9.135 - Global Provision Policy and Team Access Seeding (May 2026)

Global Viewer Baseline

The identity provisioning system now supports a global provision policy that automatically grants viewer-level access to all active workspaces for users in a specified domain. When a user signs in via SSO, the system evaluates global policies and provisions baseline workspace memberships before the user reaches any workspace. This means new team members see every workspace immediately on first login without manual invitation.

Team Access Seeding

A new operational script allows platform administrators to pre-seed workspace memberships from a configuration file. Team members can be assigned owner access across all workspaces or admin access on specific workspaces. The seeding process only upgrades roles - it never downgrades an existing membership. Every membership change is recorded in the audit log for compliance traceability.

Workspace names in the configuration must exactly match the workspace display name (case-insensitive). The script validates all names before applying changes and exits with an error on any mismatch.

Usage supports both staging and production environments, with a dry-run mode for previewing changes before applying them.

Provisioning Capacity Increase

The provisioning system now supports users with access to a larger number of workspaces. The previous limits have been raised to accommodate global policies that expand to all active workspaces in a deployment. First-login provisioning performance remains within acceptable bounds - subsequent logins skip already-provisioned workspaces and complete quickly regardless of workspace count.

v0.9.134 - Patient Insurance and Provider Identifiers in World Model (May 2026)

Patient Primary Insurance

The world model now surfaces primary insurance information directly on patient entities. When a patient has primary insurance coverage on file, the agent's patient context includes:

Field
Description

payer_name

Name of the primary insurance payer

practice_payer_id

Practice-specific payer identifier

member_id

Member ID used for eligibility lookups

policyholder_name

Name of the policyholder on the plan

policyholder_relationship

Relationship of the policyholder to the patient

These fields appear as a primary_insurance block in the patient summary provided to the agent during conversations. If a patient has no insurance coverage on file, the block is omitted.

This removes the need for agents to query a separate coverage entity when handling insurance-related workflows such as eligibility checks, benefits verification, or appointment scheduling that requires payer information.

Practitioner Member ID

Practitioner entities now include a stable practice-level identifier. This identifier is used as the join key when resolving which provider is associated with an appointment or availability slot, enabling the agent to reliably link scheduling data to the correct practitioner without parsing reference strings.

v0.9.133 - Ringless Voicemail (May 2026)

Ringless Voicemail Delivery

The Channel Management API now supports sending ringless voicemails - pre-recorded audio messages deposited directly into a recipient's voicemail box without ringing their phone.

New use case type: ringless_voicemail is now a valid use case type when creating use cases for a Twilio setup. Phone numbers assigned to a ringless voicemail use case must have voice capability and must be US numbers.

New endpoint: POST /v1/twilio-setup/{setup_id}/use-case/{use_case_id}/ringless-voicemail

Send a ringless voicemail by submitting a multipart form with:

Field
Type
Description

recipient_phone_number

string

US E.164 phone number (+1XXXXXXXXXX)

audio

file

MP3 audio file, 10-60 seconds, max 8 MB

Returns 201 Created with:

Field
Type
Description

voicemail_id

string

Unique identifier for tracking delivery status

sender_phone_number

string

E.164 phone number the voicemail will be sent from

A sender phone number is selected randomly from all numbers assigned to the use case.

Delivery status lifecycle: Each voicemail starts as pending and transitions to one of four terminal states based on carrier feedback:

Status
Description

pending

Submitted, awaiting delivery confirmation

delivered

Successfully deposited in the recipient's voicemail box

not_delivered

Carrier reported non-delivery after attempt

skipped

Delivery skipped (e.g., recipient on a do-not-call list)

failed

Upstream failure during the send attempt

Validation:

  • Audio must be a valid MP3 between 10 and 60 seconds (returns 422 otherwise)

  • Audio must be under 8 MB (returns 413 otherwise)

  • Use case must be of type ringless_voicemail (returns 409 otherwise)

  • At least one phone number must be assigned to the use case (returns 404 otherwise)

Phone number assignment changes: Assigning a phone number to a ringless_voicemail use case now validates that the number has voice capability and is a US number. Non-US numbers return 409. The sender is automatically registered with the upstream delivery provider during assignment.

v0.9.127 - Download Intake Uploads (May 2026)

Operators can now download files that were submitted through intake links. A new endpoint on the intake links resource returns the raw file bytes with a Content-Disposition: attachment header, prompting the browser to save the file rather than render it.

The download is scoped through the intake link - an operator can only download uploads visible on the corresponding upload listing endpoint. If the upload row or the underlying file no longer exists (for example, after a right-to-be-forgotten deletion), the endpoint returns a 404 with the same detail as a missing upload, so callers cannot distinguish between the two cases.

Endpoint: GET /intake/links/{link_id}/uploads/{upload_id}/download

Parameter
Type
Description

link_id

path, UUID

Intake link identifier

upload_id

path, UUID

Upload identifier

Response: The raw file bytes with the original content type and filename. The response includes Cache-Control: private, no-store and X-Content-Type-Options: nosniff headers. Non-ASCII filenames are encoded per RFC 5987.

Error responses:

Status
Condition

404

Link, upload, or underlying file not found

502

Storage backend unavailable

Audit: Downloads are logged as PHI access events in the audit trail.

v0.9.125 - Caller ID for Simulation Sessions (May 2026)

Simulated Caller ID on Session Create

The simulation session creation endpoint now accepts an optional caller_id parameter. When provided, the platform forwards this phone number as the caller identity for the simulation session, enabling patient resolution during simulated conversations. This lets you test caller-specific behavior - such as greeting a known patient by name or loading their clinical context - without making a real phone call.

When caller_id is omitted or blank, the platform falls back to its default simulation identity, which produces no patient match. This matches the existing behavior before this change.

The parameter is available on both the create-session and create-test-conversation endpoints. Maximum length is 64 characters.

v0.9.123 - Manual Sync Trigger for Data Sources (May 2026)

On-Demand Data Source Sync

A new endpoint lets you manually trigger a sync for any data source in a workspace, bypassing the normal scheduling cadence. This is useful when you have just configured a new data source or pushed data to an upstream system and want the platform to pick up changes immediately rather than waiting for the next scheduled poll.

New endpoint:

POST /data-sources/{data_source_id}/sync

Returns 202 Accepted with the data source ID and a timestamp once the sync request is queued. The sync itself runs asynchronously - the response does not wait for the sync to complete.

Response body (202):

Field
Type
Description

status

string

Always "started"

data_source_id

string

The data source that was triggered

triggered_at

datetime

When the sync request was accepted

Error responses:

Status
Description

400

Invalid data source ID format

404

Data source not found in the workspace

409

Data source is already mid-sync. The response body includes last_poll_at and last_poll_duration_ms when available, so clients can display how long the current sync has been running.

429

Rate limit exceeded

503

The sync backend is temporarily unreachable - retry after a short delay

The 409 conflict check is best-effort. Because the status check and trigger are separate operations, a scheduled sync can start between them. Clients should treat 409 as a UX hint rather than a hard guarantee.

The endpoint requires write permissions and is subject to the standard write rate limit. A sync trigger is recorded in the workspace audit log.

v0.9.122 - Workspace Environment Session Idle Timeout (May 2026)

Per-Environment Session Idle Timeout

Session idle timeout is now determined by the workspace environment. Production workspaces use a stricter 15-minute default intended for regulated operating policies. Staging and development workspaces use a relaxed 8-hour default, reducing friction during development and testing workflows where sessions were previously expiring too quickly. Timeout configuration alone does not establish HIPAA compliance.

The idle timeout is resolved at token issuance time based on the workspace's environment setting. When a session is refreshed, the platform checks the stored timeout to determine whether the session has expired, then resolves a fresh timeout from the current workspace environment for the new token. This means environment changes take effect on the next token refresh rather than retroactively invalidating active sessions.

Bootstrap tokens (issued before workspace selection) use the production timeout by default. If the workspace environment cannot be determined, the platform fails safe to the stricter production timeout.

The idle timeout is set through deployment configuration with these validation constraints:

  • Production timeout must not exceed the configured ceiling of 900 seconds

  • Staging timeout must be greater than or equal to the production timeout

  • Both values must be between 1 and 86400 seconds (24 hours)

No changes to the token request or response shape. Existing integrations continue to work without modification. The Developer Console login reason banner (introduced in v2.60.0) continues to display the appropriate inactivity message when a session expires.

v0.9.120 - Async Simulation Bridge Generation (May 2026)

Async Generation Mode for Simulation Bridge

The simulation bridge endpoint now supports an async_generation flag. When set to true, the endpoint returns immediately with a run_id instead of blocking for the full duration of target-spec inference and scenario generation. The generation work - including optional target-spec inference, scenario generation, and bridge execution - runs as a tracked background task. Clients poll the run status via the existing GET endpoint to track progress.

This eliminates the long synchronous wait (typically 40-60 seconds) that could trip proxy and ingress read timeouts for browser-based clients and BFF proxies. CLI and script clients that prefer the synchronous flow can continue using the default behavior (async_generation: false).

If any step of the background pipeline fails - target-spec inference, scenario generation, run persistence, or bridge execution - the run is marked as failed with a descriptive reason visible through the GET endpoint. Clients polling for status will see a terminal failed state rather than a run stuck in progress.

Response Shape

When async_generation is true, the response returns with status: "running", an empty scenarios list, and no inferred target spec. The generated scenarios and effective target spec are available on the run row once the background task completes.

v0.9.116 - Tool Progress Orchestration (May 2026)

Intelligent Tool Progress Handling

The voice agent now uses a dedicated progress orchestration system during tool execution instead of the legacy filler loop. When a tool call starts, the platform resolves a progress hint for that specific tool - including the expected latency, progress style, and any custom phrasing configured for the tool - and passes it to the orchestrator. The orchestrator uses this information to deliver contextually appropriate progress responses while the tool runs, rather than falling back to generic filler audio.

This replaces the previous approach where a background monitor would periodically check on tool execution and emit filler responses on a fixed cadence. The new system is deadline-aware and adapts its progress behavior based on per-tool configuration, resulting in more natural conversations during tool calls that take varying amounts of time.

Tools that do not have explicit progress configuration continue to work without changes - the orchestrator falls back to default progress behavior.

v0.9.114 - DPoP Sender-Constrained Tokens (May 2026)

DPoP (Demonstration of Proof-of-Possession)

The token endpoint now supports DPoP sender-constrained tokens per RFC 9449. Clients can bind access tokens and refresh tokens to a cryptographic key pair, so stolen tokens cannot be used without the corresponding private key.

To opt in, generate an EC key pair (P-256, P-384, or P-521) and include a signed DPoP proof JWT in the DPoP header when requesting tokens. The proof must include the HTTP method, request URL, issued-at timestamp, and a unique identifier. The platform validates the proof signature, checks for replay, and binds the issued tokens to the client's public key.

When a token is DPoP-bound:

  • The token response returns token_type: "DPoP" instead of "Bearer".

  • The access token includes a confirmation claim (cnf) containing the key thumbprint.

  • Refresh token grants require a valid DPoP proof signed by the same key.

  • Refresh tokens are not rotated on use - sender-constraining eliminates the replay risk that rotation mitigates, which also eliminates race conditions when multiple tabs or clients refresh concurrently.

DPoP is supported on both credential-based and SSO (Google OAuth) token grants. Bootstrap tokens used during multi-workspace selection do not support DPoP binding.

Clients that do not send a DPoP header continue to receive standard Bearer tokens with the existing rotation behavior. No migration is required.

Supported algorithms: ES256, ES384, ES512

Key requirements:

  • DPoP proof typ must be dpop+jwt

  • Proofs must not contain an exp claim

  • Proofs are valid for up to 2 minutes from iat

  • Each proof jti can only be used once (replay protection)

v0.9.113 - Real-Time Event Emission for Conversations and Outbound Sync (May 2026)

Conversation Events

When a voice conversation is created, the platform now emits a real-time event to the analytics pipeline. This event includes metadata such as call direction, participant count, turn count, duration, and completion status. Downstream consumers - including dashboards, metric computations, and integrations - receive conversation data with lower latency than the previous polling-based approach.

This applies to all voice conversations regardless of direction (inbound and outbound). No API changes are required.

Outbound Sync Events

Outbound sync operations now emit completion and failure events to the analytics pipeline. When an outbound sync finishes successfully or encounters an error, the platform publishes an event that downstream analytics and monitoring systems can consume. This makes it easier to track sync health, detect persistent failures, and build alerting around data synchronization without polling the sync status endpoint.

Both event types are emitted asynchronously and do not affect the latency or reliability of the originating API call. If event emission fails, the primary operation still succeeds and the failure is logged internally.

v0.9.112 - Call Intelligence Events (May 2026)

Call Intelligence Event Emission

Call intelligence data is now emitted as a platform event at the end of every call session. Previously, call intelligence was written to the transactional store but was not available as an event for downstream analytics pipelines. Now, when a call completes and intelligence is generated, the platform emits a call.intelligence event that feeds the analytics pipeline, metric computations, and any downstream consumers.

This means standard metrics that depend on call intelligence data (such as quality scores, conversation summaries, and risk assessments) now receive data with lower latency and higher reliability.

v0.9.110 - Intake Upload Validation and Duplicate Detection (May 2026)

Magic Byte Validation

Files uploaded through intake links are now validated against their declared content type using magic byte detection. The platform reads the first bytes of the uploaded file and verifies that the actual file content matches the declared type. If the file content does not match an allowed type, or if the declared content type conflicts with the detected content, the upload is rejected with a 422 error.

This prevents scenarios where a file is renamed or mislabeled to bypass content type restrictions. Image uploads require valid magic bytes; document formats that share container signatures (such as Office XML formats) are handled correctly.

Duplicate Upload Detection

Intake upload responses now include a duplicate_of field. When an uploaded file has the same content hash as a previously uploaded file in the same workspace, the response includes the ID and timestamp of the original upload. The duplicate file is still accepted and stored - this is informational only, letting integrators and the upload UI surface duplicate warnings without blocking the upload.

The upload UI shows an "Uploaded (duplicate)" indicator when a duplicate is detected.

v0.9.106 - Session Tags in List and Graph Responses (May 2026)

Session Tags Surfaced in Simulation Responses

Simulation session listings and graph responses now include a tags array on each session object. Tags carry metadata such as the scenario index and temperament assigned to a session, letting consumers join a session back to its parent run scenario and display persona information without making a separate per-session detail request.

This applies to both the list-sessions endpoint and the session graph endpoint. Sessions without tags return an empty array.

v0.9.105 - Expanded Entity Data Model for Clinical Workflows (May 2026)

Richer Patient Demographics

Patient entities now surface structured address fields (line, city, state, postal code, country), marital status, preferred language, race, ethnicity, and emergency contact information (name, phone, relationship) as typed entity columns. These fields are available to platform functions, agent tools, and the world model API without parsing nested resource blobs.

US state values are normalized to two-letter USPS abbreviations during ingestion. Both patient addresses and location addresses use the same normalization, so licensed-state filters like state IN ('VA', 'MD', 'WV') match consistently.

Expanded Appointment Data

Appointment entities now include:

  • Participant references and display names for patient, practitioner, and location - the agent can show "Dr. Smith at Bristol" without additional lookups

  • Modality (in-person, telehealth, etc.) from the service type

  • Duration in minutes

  • Timezone for display in the patient's local time

  • Provider metadata including degree and specialization

  • Series and encounter identifiers for linking related appointments

  • Cancellation reason when an appointment is cancelled

Structured Location Data

Location (facility) entities now expose:

  • Typed address fields (line, city, state, postal code, country) for direct queries

  • Geographic coordinates (latitude and longitude) enabling proximity-based facility search without parsing nested resource data

  • Timezone for per-facility appointment display

  • Facility identifier used by availability and booking endpoints

Facility-Linked Availability Slots

Availability slots now carry a facility identifier, allowing the agent to filter provider availability by facility and match patients to nearby locations. Provider display names are resolved during availability polling so slot data includes the provider's name without a secondary lookup.

State Compatibility

The backward-compatible entity state structure now includes a place section for location entities alongside the existing demographics and scheduling sections. All new fields are also available in the flat entity state for consumers that read either format.

v0.9.104 - Simulation Bridge v2: Target Specs, Coverage-Driven Exploration, and Forking (May 2026)

Target Spec Support

The simulation bridge now accepts a structured target specification that defines what a simulation run should test. A target spec includes:

  • Desired states - conversation flow states the agent should reach during the simulation

  • Non-desired states - states the agent should avoid, with hard (fail) or soft (flag) severity

  • Ordered pathways - sequences of states the agent should walk through in order

  • Completion criteria - states that must be reached and tools that must be called for a scenario to pass

When a target spec is provided, each completed session is scored against it: 100 if all criteria passed, 0 if a hard-forbidden state was entered, 50 for partial completion with specific misses reported in the score rationale.

You can supply a target spec explicitly when calling the bridge, or set auto_target_spec to have the platform infer one from your natural-language objective. When inferred, the response includes the generated spec and a rationale explaining the inference.

Target Spec Planning Endpoint

A new /bridge/plan endpoint lets you preview what target spec the platform would infer from a natural-language objective before running a simulation. The response includes the inferred spec, a rationale, and the available states and tools on the service. This supports an edit-then-run workflow: review the inferred spec, adjust desired states or pathways, then POST the final spec to /bridge.

Detail
Value

Method

POST

Path

/simulations/bridge/plan

Auth

API key with write permission

Request body

service_id, objective (natural-language testing goal)

Response

target_spec, rationale, available_states, available_tools

Coverage-Driven Exploration

A new exploration parameter on the bridge endpoint enables coverage-driven turn selection. When coverage_driven_selection is enabled, the platform evaluates candidate caller utterances each turn and selects the one most likely to reach uncovered states or advance an ordered pathway. This produces higher state coverage without increasing the number of scenarios.

Session Forking

When exploration.enable_forking is enabled and the top two candidate utterances aim at different conversation states, the platform forks the session into parallel branches that explore both paths. Forking is bounded by a per-scenario budget (max_forks_per_scenario, default 2, max 5) and a maximum fork depth to prevent runaway branching.

Forked sessions inherit the parent's conversation history and state, and are scored independently on completion. The run's result now reports both root sessions and forked children, with forked sessions tagged for identification.

Run Replay Support

Bridge runs now persist the full request body, objective, and generated scenarios so runs can be replayed without regenerating scenarios. A new endpoint returns the full run payload including replay data:

Detail
Value

Method

GET

Path

/simulations/runs/{run_id}

Auth

API key with read permission

Response

Run metadata plus objective, bridge_request, scenarios

To replay a run, re-POST the bridge_request from the response to /bridge. The persisted request includes the effective target spec (inferred or explicit) so replays are deterministic - they reuse the same spec rather than re-inferring against potentially changed service configuration.

Run Tagging

Bridge runs are now automatically tagged based on their configuration:

  • bridge - all bridge runs (unchanged)

  • target_spec - runs with an explicit or inferred target spec

  • auto_plan - runs where the target spec was inferred from the objective

  • forking - runs with forking enabled

Session tags now include scenario_index:N linking each session to its scenario in the run's persisted scenario list, enabling the frontend to join sessions to personas without duplicating scenario data on every session.

Bridge Response Changes

The /bridge response now includes two additional fields when auto_target_spec was used:

  • inferred_target_spec - the target spec that was inferred from the objective

  • inferred_target_spec_rationale - explanation of the inference

Both are null when the target spec was explicit or absent.

Completion Event Changes

The bridge completion event emitted for observability now reports total_sessions (roots plus forked children), forked_sessions, and per-session metadata including scenario_index, is_fork_child, and recommend_degraded. The previous successful_scenarios field is renamed to successful_parent_scenarios for clarity.

Breaking changes: The bridge completion event field successful_scenarios is renamed to successful_parent_scenarios. Downstream consumers that parse this event should update their field references.

v0.9.102 - Upload Page Moved to Forms App (May 2026)

Upload Page Served from Forms App

The customer-facing file upload page is now served by the forms application instead of the API backend. Upload links now point to the forms app path (/s/upload/{token}) and the page is rendered as a modern React application with drag-and-drop support, upload progress indicators, and proper loading and error states.

The API backend retains the file upload endpoint and now exposes a new JSON info endpoint that the forms app consumes server-side to resolve link metadata (display name, allowed file types, size limits). The previous server-rendered HTML upload page has been removed from the API.

Upload URL Format Change

Upload URLs returned by the Create Link and List Links endpoints now use the forms app base URL with the /s/upload/{token} path pattern instead of the previous API-hosted /upload/{token} path. Existing unexpired links will continue to work, but newly generated links use the updated format. If you store or display upload URLs, update any URL pattern matching or validation logic accordingly.

Removed Environment Variable

The API_PUBLIC_URL environment variable is no longer used. Upload link URL generation now relies solely on FORMS_PUBLIC_URL. Deployments that previously set API_PUBLIC_URL can remove it.

New Info Endpoint

A new endpoint returns link metadata as JSON, replacing the previous HTML page render:

Detail
Value

Method

GET

Path

/upload/{link_token}/info

Auth

None (token-authenticated)

Response

JSON with display name, customer slug, max upload size, and allowed content types

Error codes

invalid_token (400), link_not_found (404), link_expired (410), link_exhausted (410)

Removed Endpoint

The GET /upload/{link_token} endpoint that returned the server-rendered HTML upload page has been removed. The upload file submission endpoint (POST /upload/{link_token}/files) remains unchanged.

Breaking changes:

  • Upload URLs now use a different base path. Integrations that parse or validate upload URLs should update their patterns.

  • The GET /upload/{link_token} HTML page endpoint no longer exists. Direct API consumers that rendered this page in iframes or webviews should point to the new forms app URL instead.

  • The API_PUBLIC_URL environment variable is no longer read.

v0.9.100 - Greeting Latency Optimization (May 2026)

Faster First-Message Delivery

The voice agent now delivers the greeting to the caller while speech-to-text initialization runs in the background. Previously, the greeting was blocked until the speech recognition pipeline was fully connected and configured, adding unnecessary delay before the caller heard anything.

With this change, the agent enqueues the greeting immediately after the caller joins, and speech recognition connects concurrently. Since callers typically take 3-5 seconds to respond after hearing the greeting, the speech pipeline is ready well before any caller speech arrives. This reduces first-message latency to under 2 seconds in typical conditions.

If the speech recognition pipeline fails to initialize within its timeout window, the session terminates cleanly rather than hanging indefinitely.

Greeting Latency Metric

A new voice_agent.greeting.ttfb_ms metric tracks time-to-first-byte specifically for the greeting message, separate from the general turn-level latency metric. The latency metadata sent to clients now includes an is_greeting field so integrators can distinguish greeting latency from subsequent turn latency.

Breaking change: None. The greeting behavior is unchanged from the caller's perspective - it just arrives faster. The new is_greeting field in latency metadata is additive.

Last updated

Was this helpful?