serverAmigo API

Release history for the Amigo API backend. Classic API and Platform API changes, new endpoints, and migrations.

Release history for the Amigo API (backend services).

circle-info

Current Version: v0.9.522 | Requires: Agent Forge v0.3.0+

circle-exclamation
chevron-rightv0.9.522 - Platform API: Start Mode and Context for Text Conversations (July 2026)hashtag

Start Mode and Context for Text Conversations

Text conversations now support a start_mode parameter that controls whether the agent or the user speaks first, and a context parameter that injects caller or patient context into the agent's prompt for a conversation or turn.

What changed:

  • start_mode on create conversation - The create conversation endpoint (POST /conversations) now accepts a start_mode field with two possible values: user_first (default) and agent_first. When set to agent_first, the platform produces the agent's opening message during conversation creation and returns it in the turns array of the response. When set to user_first (or omitted), the conversation is created with no initial turns and the agent waits for the user to send the first message.

  • context on create conversation - The create conversation endpoint now accepts an optional context string (up to 5,000 characters). This text is injected into the agent's prompt as caller or patient context for the conversation. Useful for passing appointment details, patient identifiers, or other situational information that the agent should know before the conversation begins.

  • viewport_width and viewport_height on create conversation - The create conversation endpoint now accepts optional viewport_width (range 20-500) and viewport_height (range 5-500) integer fields. When provided alongside start_mode: agent_first, the agent uses these dimensions to format its opening message. These dimensions are also forwarded to subsequent turns in the conversation.

  • context on conversation turns - The create turn endpoint (POST /conversations/{id}/turns) and the streaming turn endpoint now accept an optional context string (up to 5,000 characters). This lets you inject or update context on a per-turn basis.

  • context on WebSocket sessions - The WebSocket session endpoint now accepts a context query parameter (up to 5,000 characters). The context is applied when the session connects and the agent produces its opening message.

  • auto_greet replaced by start_mode - The previously removed auto_greet parameter is fully superseded by start_mode. The agent_first start mode provides equivalent functionality with more explicit semantics. The create conversation response now includes greeting turns in the turns array when start_mode is agent_first, rather than always returning an empty array.

Who is affected:

Platform API users who create text conversations or interact via WebSocket sessions. No action is required for existing integrations - the default start_mode is user_first, which preserves previous behavior. To have the agent speak first, set start_mode to agent_first in your create conversation request.

No breaking changes.

chevron-rightv0.9.521 - Platform API: Viewport Dimensions for Text Channels (July 2026)hashtag

Viewport Dimensions for Text Channels

Text-based conversations now support optional viewport dimensions that tell the agent how wide (and optionally how tall) the user's display surface is, measured in characters. The agent uses this information to tailor response formatting - for example, producing shorter lines for narrow SMS screens and wider layouts for web or email.

What changed:

  • viewport_width and viewport_height on conversation turns - The create turn endpoint (POST /conversations/{id}/turns) now accepts two optional integer fields: viewport_width (range 20-500) and viewport_height (range 5-500). When provided, the agent formats its responses to fit within the specified character dimensions. When omitted, the platform applies sensible defaults based on the channel (e.g., narrower for SMS, wider for web and email).

  • viewport_width and viewport_height on WebSocket sessions - The WebSocket session endpoint now accepts viewport_width and viewport_height as query parameters. Values outside the allowed ranges are silently ignored. The viewport dimensions are fixed for the lifetime of the session - they are set at connection time and apply to every turn.

  • Channel-specific defaults - Each text channel now carries a default viewport width that reflects typical display characteristics. SMS defaults to 40 characters, WhatsApp to 45, and email and web to 80. These defaults apply when no explicit viewport dimensions are provided.

Who is affected:

Platform API users who interact with text-based channels (SMS, WhatsApp, email, web, WebSocket sessions). No action is required - existing integrations continue to work with the channel-specific defaults. To take advantage of viewport-aware formatting, pass viewport_width and optionally viewport_height in your turn requests or WebSocket connection parameters.

No breaking changes.

chevron-rightv0.9.520 - Platform API: Remove auto_greet from Conversation Creation (July 2026)hashtag

Remove auto_greet from Conversation Creation

The auto_greet parameter has been removed from the create conversation endpoint. The agent greeting is now handled automatically by the context graph welcome state, so callers no longer need to control whether a greeting is produced at conversation creation time.

What changed:

  • auto_greet parameter removed from POST /conversations - The auto_greet boolean field is no longer accepted in the create conversation request body. Previously, this parameter controlled whether the platform produced an agent greeting turn when creating a conversation. The context graph welcome state now manages greeting behavior, making this parameter unnecessary.

  • Create conversation response always returns an empty turns array - The turns array in the create conversation response is now always empty. Agent greetings are delivered through the context graph welcome state rather than being included inline in the creation response.

Who is affected:

All Platform API users who create conversations via the API. If your integration passes auto_greet in the request body, remove it. The field is no longer recognized. If your integration relied on the create conversation response containing greeting turns, update your flow to receive the greeting through the normal conversation interaction path instead.

Breaking changes:

  • auto_greet has been removed from the create conversation request schema. Requests that include this field may be rejected.

  • The turns array in the create conversation response no longer contains greeting turns.

chevron-rightv0.9.519 - Platform API: Greeting Ready Before Call Connects (July 2026)hashtag

Greeting Ready Before Call Connects

Inbound voice calls now wait for the agent greeting to be fully prepared before connecting the caller. Previously, greeting preparation ran in the background while the call connected, which could cause a brief delay before the caller heard the agent speak. Now the caller hears their phone's normal ring-back tone for a few seconds while the greeting loads, and the agent is ready to speak the moment the call connects.

What changed:

  • Greeting is prepared during ring time - The agent engine now finishes loading the greeting before returning the call connection response. The caller's phone rings normally during this preparation (typically 2-3 seconds). When the call connects, the greeting plays immediately with no dead air or loading delay.

  • No change to caller experience - Callers hear standard ring-back tone from their phone while the greeting prepares. This is indistinguishable from a normal phone call that takes a moment to answer. The previous behavior occasionally produced a connected call with a brief silence before the greeting played.

Who is affected:

All Platform API users with inbound voice use cases. No configuration changes are required. Callers may notice that calls ring slightly longer before connecting, but the agent greeting plays immediately once the call is answered.

No breaking changes.

chevron-rightv0.9.518 - Platform API: Voice Routing Uses Per-Use-Case Telephony Application (July 2026)hashtag

Voice Routing Uses Per-Use-Case Telephony Application

All voice call routing - inbound webhooks, outbound dispatch, and mid-call credential resolution - now reads the telephony application identifier from the use case rather than from the setup. This completes the migration started in v0.9.517, where each voice use case received its own dedicated telephony application at creation time.

What changed:

  • Inbound voice routing reads telephony application from the use case - When an inbound call arrives on a use-case-scoped webhook, the agent engine now resolves the telephony application identifier from the use case record. Previously, this was read from the setup. If a voice use case is missing its telephony application identifier (e.g., a use case created before v0.9.517 that has not been backfilled), the inbound call returns fallback audio instead of connecting to the agent.

  • Outbound voice dispatch reads telephony application from the use case - Outbound calls initiated via a use case now resolve the telephony application identifier from the use case. If the use case has no telephony application configured, the dispatch fails with a 502 error and a message indicating that the use case needs a telephony application configured in the channel setup.

  • Mid-call credential resolution reads telephony application from the use case - When the agent engine resolves credentials for an active voice session (e.g., for conference management or call transfers), it now reads the telephony application identifier from the use case associated with the session.

  • twiml_app_sid removed from setup response schema - The twiml_app_sid field is no longer present on setup responses from GET /v1/twilio-setup/{id} or any endpoint that returns setup objects. This field was deprecated in v0.9.517 when telephony applications moved to the use case level. Consumers should read twiml_app_sid from the use case response instead.

Who is affected:

All Platform API users with voice use cases. Existing use cases created in v0.9.517 or later already have a per-use-case telephony application and require no action. Use cases created before v0.9.517 must be backfilled with a telephony application before inbound or outbound voice routing will work. Contact support if you have pre-v0.9.517 use cases that have not been migrated.

Breaking changes:

  • twiml_app_sid has been removed from setup response payloads. Read it from the use case response instead.

chevron-rightv0.9.517 - Platform API: Region and Environment on Use Cases (July 2026)hashtag

Region and Environment on Use Cases

Use cases now require a deployment region and environment at creation time. These fields pin the use case to a specific regional deployment of the voice agent engine, ensuring that all voice traffic for the use case routes to the intended region and stage. Each voice use case also receives its own dedicated telephony application resource scoped to that region, replacing the previous shared-per-setup application.

What changed:

  • environment and region required on use case creation - Both POST /v1/use-case (Twilio channel) and POST /v1/use-case (email channel) now require environment and region fields. environment accepts staging or production. region accepts us-east-1, ap-southeast-2, eu-central-1, or ca-central-1. These fields are immutable after creation - to change region or environment, delete the use case and create a new one.

  • Per-use-case telephony application - Voice use cases (inbound_voice and outbound_voice) now receive a dedicated telephony application at creation time. The application's voice endpoint is configured to route to the agent engine deployment matching the use case's region and environment. Ringless voicemail use cases do not receive a telephony application because they use a separate delivery path with no agent leg. The telephony application is automatically cleaned up when the use case is deleted.

  • twiml_app_sid on use case responses - GET /v1/use-case/{id}, GET /v1/use-cases, and the create response now include a twiml_app_sid field. This is the identifier of the per-use-case telephony application for voice channels, or null for ringless voicemail use cases.

  • environment and region on use case responses - All use case response payloads now include the environment and region fields.

  • twiml_app_sid removed from setup responses - The GET /v1/twilio-setup/{id} response no longer includes a twiml_app_sid field. Telephony applications are now scoped per use case, not per setup. Consumers that previously read the application SID from the setup response should read it from the use case response instead.

  • Setup creation no longer creates a telephony application - POST /v1/twilio-setup no longer provisions a shared telephony application. The application is created per use case at use case creation time instead.

  • Phone number assignment uses use case region - When assigning a phone number to an inbound voice use case, the phone number's voice endpoint is now configured using the use case's region and environment rather than a single global endpoint.

Who is affected:

All Platform API users creating use cases. Existing use cases are unaffected. Consumers reading twiml_app_sid from setup responses must migrate to reading it from use case responses.

Breaking changes:

  • environment and region are now required fields on use case creation requests.

  • twiml_app_sid has been removed from the setup response schema.

chevron-rightv0.9.516 - Platform API: Greeting Uses Full Tool Pipeline (July 2026)hashtag

Greeting Uses Full Tool Pipeline

The agent greeting now runs through the same tool execution pipeline used for all other conversation turns. Previously, greetings were generated through a simplified path that bypassed tool execution. The greeting now has access to skills, platform functions, and other tools during the initial message, enabling richer and more context-aware opening interactions.

What changed:

  • Full tool access during greeting - The agent's opening greeting now executes through the standard reasoning pipeline with full tool access. This means the greeting can invoke skills, query platform functions, and use any other tools configured on the agent. Previously, the greeting was generated without tool access, limiting it to static or prompt-only content.

  • Tool call events emitted for greeting - Because the greeting now uses the full pipeline, any tool calls made during greeting generation are emitted as tool call events on the session, consistent with how tool calls are reported during subsequent turns.

Who is affected:

All Platform API voice and text session users. No API or integration changes are required. Agents with tools configured may produce richer greetings that incorporate live data from skills or platform functions. Agents without tools configured will see no behavioral difference.

No breaking changes.

chevron-rightv0.9.515 - Platform API: Greeting Cache and Faster Cold-Start (July 2026)hashtag

Greeting Cache and Faster Cold-Start

The voice agent engine now caches generated greeting text so that subsequent calls to the same service reuse a cached greeting instead of regenerating it. Combined with tighter timeouts on the pre-warm path, this reduces time-to-first-speech on cold-start calls.

What changed:

  • Greeting text caching - When the platform generates a greeting during pre-warm, the result is stored in a short-lived cache keyed by workspace, service, and caller context. If a second call arrives before the cache expires, the greeting is served from cache (sub-millisecond) instead of calling the language model again (seconds). Anonymous and household greetings use a longer cache lifetime because they are identical across calls. Known-caller personalized greetings use a shorter lifetime to stay fresh as caller data changes.

  • Cold-init cache lookup - When a call connects to a pod that did not perform the pre-warm, the engine checks the greeting cache before falling back to language model generation. In most cases the pre-warm pod has already written the greeting, so the connecting pod reads it instantly.

  • Reduced pre-warm timeout - The pre-warm window now fails fast if it has not completed promptly, letting the cold-init path start sooner rather than consuming the full ring window. The greeting generation timeout within pre-warm has also been tightened.

Who is affected:

All Platform API voice agent users. No API or integration changes are required. Callers should experience shorter silence before the agent begins speaking, especially on the first call after a period of inactivity or when the call lands on a different pod than the one that handled the pre-warm.

No breaking changes.

chevron-rightv0.9.514 - Platform API: Persistent WebSocket Text Sessions (July 2026)hashtag

Persistent WebSocket Text Sessions

Text session WebSocket connections now use a persistent end-to-end WebSocket architecture instead of proxying each turn through an intermediate streaming protocol. The agent engine keeps the conversation session alive across turns, so subsequent messages reuse the warm session rather than reinitializing on every turn.

What changed:

  • End-to-end WebSocket session - The platform API's /connect WebSocket endpoint now establishes a persistent WebSocket connection to the agent engine for the duration of the session. Previously, each user message triggered a separate streaming request that initialized a new session context. The new architecture initializes the session once on connect and reuses it for all subsequent turns, significantly reducing per-turn latency.

  • Bidirectional bridge - The platform API acts as a bidirectional WebSocket bridge between the client and the agent engine. Client frames are forwarded upstream and agent frames are forwarded downstream without intermediate protocol translation. Frame size limits are enforced in both directions.

  • Idle timeout behavior unchanged - Sessions still close after a period of inactivity. The client receives an idle timeout error event before the connection closes, consistent with existing behavior.

  • Same client-facing protocol - The WebSocket frame protocol is unchanged. Clients still send user_text frames and receive message, tool_call, done, and error events. No client-side changes are required.

Who is affected:

Platform API users with WebSocket text session integrations. The change is transparent - existing clients work without modification. Users should observe lower latency on the second and subsequent turns within a session because the agent no longer reinitializes on every message.

SDK users connecting via sessionConnectUrl benefit automatically.

No breaking changes.

chevron-rightv0.9.513 - Platform API: Voice Media Gateway Removed (July 2026)hashtag

Voice Media Gateway Removed

The standalone voice media gateway service has been removed. Audio transport, speech-to-text, and text-to-speech processing are handled directly by the agent engine, eliminating the separate media-plane service and the internal relay protocol between the two.

What changed:

  • Media gateway service removed - The dedicated service that handled audio transport, speech recognition, and text-to-speech synthesis as a separate deployment has been removed. All voice audio processing now runs within the agent engine service, simplifying the voice architecture.

  • Internal relay protocol removed - The bidirectional message protocol used for communication between the media gateway and the agent engine has been removed. This was an internal implementation detail and had no effect on external APIs or client integrations.

  • Internal media session endpoint removed - The internal endpoint previously used by the media gateway to relay voice session data to the agent engine has been removed. This endpoint was not part of the public API.

Who is affected:

No customer-facing changes. This is an internal architecture simplification. Voice calls continue to work through the same telephony flow and public API endpoints. No client-side or integration changes are required.

No breaking changes.

chevron-rightv0.9.512 - Platform API: Workspace Region and Environment Now Required (July 2026)hashtag

Workspace Region and Environment Now Required

Workspace creation now requires an explicit environment value and derives region automatically from the regional API endpoint that handles the request. These fields no longer have defaults - callers must commit to an environment, and the platform determines the region.

What changed:

  • environment is required on workspace creation - The environment field (production, staging, or development) no longer defaults to staging. You must provide it explicitly when creating a workspace. Requests without environment are rejected.

  • region removed from create request body - The workspace region is now set automatically based on the regional API endpoint you call. Each region has its own ingress host, and a workspace cannot migrate between regions after creation. The region field is no longer accepted in the create workspace request body.

  • environment and region are always present on workspace responses - Both fields are guaranteed to be non-null on all workspace objects returned by the API. Previously, these fields could be absent or null for workspaces created before they were tracked as dedicated fields.

  • Multi-region deployment - The agent engine now deploys across four regions (US East, Asia Pacific Southeast, EU Central, and Canada Central), matching the platform API's regional footprint.

Who is affected:

Platform API users who create workspaces. If your integration passes region in the create workspace request body, remove it - the region is now determined by which regional endpoint you call. If your integration omits environment, you must now provide it explicitly.

Clients that read environment or region from workspace responses and handle null values can simplify their logic - both fields are now always present.

Breaking changes:

  • environment is now a required field on POST /v1/me/workspaces (previously defaulted to staging)

  • region is no longer accepted in the create workspace request body (previously accepted with a default)

chevron-rightv0.9.511 - Platform API: Voice Media Gateway Session Loop and TTS Integration (July 2026)hashtag

Voice Media Gateway Session Loop and TTS Integration

The voice media gateway now runs a full session loop that handles real-time audio transport, speech-to-text, text-to-speech playback, and bidirectional communication with the agent engine. This completes the media-plane split where all audio processing runs in the media gateway while reasoning and conversation logic remain in the agent engine.

What changed:

  • Media stream endpoint active - The media gateway now accepts inbound voice connections and runs a complete audio session. Previously, the endpoint was stubbed out. The gateway performs a transport handshake, validates session metadata against expected state, and establishes the audio pipeline.

  • Session loop with concurrent pipelines - Each voice session runs concurrent pipelines for receiving caller audio, streaming it to speech recognition, relaying transcripts to the agent engine, and dispatching agent engine commands back to the caller. The session enforces a maximum call duration and handles graceful cleanup when any pipeline exits or fails.

  • Speech-to-text integration - The gateway streams caller audio to a speech recognition service for real-time transcription. Turn detection (start of speech, end of speech) drives the conversation flow. Transcripts are relayed to the agent engine as they complete. The STT integration supports dynamic reconfiguration mid-call (key terms, language hints, detection thresholds) in response to agent engine commands.

  • Text-to-speech playback - Agent responses are synthesized to audio using a persistent streaming connection to a TTS service. The gateway uses an actor-based architecture with dedicated send and receive loops to avoid contention on the connection. Each utterance is tracked as a separate context, enabling independent lifecycle management.

  • Agent engine command dispatch - The session processes commands from the agent engine including utterance playback, speaker interruption (barge-in), speaker stop, speaker drain, STT reconfiguration, and session termination. Each command type is dispatched to the appropriate local subsystem.

  • Circuit breakers for external services - Connections to speech recognition and TTS services are protected by circuit breakers that track failure rates within a sliding window and temporarily halt requests when failure thresholds are exceeded. This prevents cascading failures when an upstream service degrades.

  • Capacity management - The gateway enforces a per-pod session limit. When at capacity, new connections are rejected immediately with a capacity metric emitted, preventing overload from degrading active sessions.

Who is affected:

Platform API users with voice agents. This is an infrastructure improvement that enables the media-plane architecture. No client-side or integration changes are required. Voice calls continue to work through the same telephony flow - the media gateway now handles the audio pipeline that was previously co-located with the agent engine.

No breaking changes.

chevron-rightv0.9.510 - Platform API: Unified WebSocket Session Proxy with Terminal Frame Guard (July 2026)hashtag

Unified WebSocket Session Proxy with Terminal Frame Guard

The WebSocket text session now uses a single unified streaming proxy for both the initial auto-greeting and user message turns. A terminal frame guard ensures that every turn delivers a final done or error event to the client, even when the upstream response stream closes without emitting one.

What changed:

  • Unified streaming for greetings and user messages - The auto-greeting sent when a WebSocket session connects now uses the same streaming proxy path as regular user messages. Previously, greetings used a separate batch interaction path (introduced in v0.9.508) while user messages used the streaming path. Both now flow through a single proxy, simplifying the protocol and making greeting delivery consistent with the rest of the session.

  • Terminal frame guard - Every turn - whether greeting or user message - is now guaranteed to deliver a terminal frame (done or error) to the client. If the upstream response stream closes without emitting a terminal event, the proxy synthesizes a done frame automatically. This prevents clients from hanging indefinitely when transport-layer buffering swallows the final event on short responses.

  • No protocol changes - The WebSocket event format is unchanged. Clients receive the same message, tool_call, done, and error events as before. The only behavioral difference is improved reliability: turns that previously could stall without a terminal event now always complete.

Who is affected:

Platform API users with WebSocket text sessions. This is a reliability improvement with no client-side changes required. Clients that implemented their own timeout-based workarounds for missing terminal events can simplify their logic, though existing workarounds remain compatible.

No breaking changes.

chevron-rightv0.9.509 - Platform API: Removed Direct Stream Endpoint and Legacy Configuration (July 2026)hashtag

Removed Direct Stream Endpoint and Legacy Configuration

The /direct-stream WebSocket endpoint and several legacy configuration options have been removed from the voice agent engine. These were internal testing artifacts that are no longer used.

What changed:

  • /direct-stream endpoint removed - The direct audio WebSocket endpoint, previously used for local voice-to-voice testing without a telephony provider, has been removed. This endpoint was already disabled in staging and production environments. All voice testing should use the standard telephony-backed endpoints or the Developer Console playground.

  • Legacy configuration options removed - Four configuration options that were no longer referenced by any active code path have been removed:

    • Voice agent configuration for static system prompt injection via environment config

    • Companion skills feature flag (companion skills are now always eligible for activation via the platform feature flag system)

    • Async task execution feature flag (async task execution eligibility is now controlled entirely by the platform feature flag system)

  • Simplified system prompt resolution - When no context graph engine is loaded, the voice agent now uses the default system prompt directly instead of attempting to parse it from a configuration string. This does not change behavior for any production deployment, since production sessions always load a context graph engine.

Who is affected:

No production impact. The removed endpoint was disabled in staging and production. The removed configuration options were either unused or have been superseded by platform-level feature flags. No client-side or integration changes are required.

No breaking changes.

chevron-rightv0.9.508 - Platform API: WebSocket Greeting Delivery Fix (July 2026)hashtag

WebSocket Greeting Delivery Fix

The auto-greeting sent when a WebSocket text session connects now uses the batch interaction path instead of the streaming path. This fixes an issue where short greeting responses could stall and never deliver their final event to the client due to transport-layer buffering.

What changed:

  • Greeting uses batch interaction - When a WebSocket session connects, the agent greeting is now retrieved as a complete response rather than streamed token by token. The greeting is a single deterministic response with no tool calls, so streaming provided no benefit and introduced reliability issues on short responses.

  • Consistent done event - The done event is now always sent after the greeting completes, regardless of whether the greeting produced messages or encountered an error. Previously, the done event could be skipped if the streaming path failed to emit a terminal chunk.

  • Simplified greeting frame format - Greeting messages are delivered as message events with role and text fields, consistent with the structure used elsewhere in the session protocol.

Who is affected:

Platform API users with WebSocket text sessions. Clients that previously experienced stalled or missing greetings on short agent responses should see reliable delivery. No client-side changes are required - the event format is compatible with the existing protocol.

No breaking changes.

chevron-rightv0.9.507 - Platform API: WebSocket Sessions for Persistent Text Conversations (July 2026)hashtag

WebSocket Sessions for Persistent Text Conversations

Text sessions now support a persistent WebSocket connection mode. Instead of making a separate HTTP request for each conversation turn, clients open a single WebSocket connection and exchange messages with streamed agent responses for the lifetime of the session. This reduces per-turn latency from the HTTP round-trip overhead to a few seconds after the initial handshake.

What changed:

  • New /sessions/connect WebSocket endpoint - Opens a persistent connection for text conversations. The endpoint accepts service_id, entity_id, and optional tool_events query parameters. Authentication uses the Sec-WebSocket-Protocol header with the format auth, <api_key_or_jwt>, supporting both API keys and JWT access tokens.

  • Streamed turn events - After each user message, the server streams turn events over the WebSocket in real time. These are the same event types used in the streaming HTTP text session path, so existing event-handling logic works without modification. Tool execution events are included when tool_events=true.

  • Auto-greeting on connect - When the connection is established, the server automatically sends the agent's greeting as a stream of turn events, so the client receives the first agent message without sending a user message.

  • Automatic thread resolution - The platform resolves or creates a conversation thread for each unique entity and service combination. Reconnecting with the same entity and service resumes the existing conversation, preserving history across sessions.

  • Structured error events - Errors during a turn (upstream failures, timeouts, invalid input) are sent as error events with a code and retryable flag. The connection stays open after non-fatal errors, so the session remains usable.

  • Idle timeout - Connections that receive no messages within the idle window are closed with an error event. Clients can reconnect to continue the conversation.

  • Custom close codes - Pre-acceptance validation failures (bad parameters, auth failure, resource not found, service unavailable) use typed close codes (4000, 4001, 4004, 4503) so clients can programmatically determine the failure reason.

Who is affected:

Platform API users building text-based agent integrations. The existing HTTP text session endpoints continue to work unchanged. The WebSocket mode is a new option for applications that benefit from lower latency and persistent connections, such as chat interfaces and SDK integrations.

No breaking changes.

chevron-rightv0.9.506 - Platform API: Voice Media Gateway Audio and Playback Engine (July 2026)hashtag

Voice Media Gateway Audio and Playback Engine

The voice media gateway now includes a complete audio playback engine and transport layer, continuing the media layer separation introduced in v0.9.502. The gateway can independently manage audio output to callers - including speech synthesis streaming, silence detection, barge-in handling, and call drain - without depending on the agent reasoning engine for audio-level concerns.

What changed:

  • Audio playback engine - The media gateway now has its own speech output pipeline. It dequeues utterances from a priority queue, streams synthesized audio to the caller one utterance at a time, and tracks estimated client playback position. This means audio delivery is managed entirely within the media layer, decoupled from agent reasoning.

  • Barge-in support - When a caller speaks over the agent, the gateway interrupts the current utterance and discards queued speech. The interruption is immediate at the next audio chunk boundary, and the gateway tracks what the caller actually heard before the interruption for accurate conversation history.

  • Silence monitoring - The gateway monitors caller silence after agent responses. If the caller remains quiet, the gateway can prompt with check-in messages at configurable intervals with increasing delays between attempts. After a maximum number of unanswered check-ins, the gateway initiates a graceful call ending with a goodbye message.

  • Transport abstraction - Audio input and output now flow through a transport abstraction that handles codec conversion at the boundary. The pipeline works with canonical audio formats internally, and transports convert to and from their native format. This makes it straightforward to support additional telephony providers and audio protocols in the future.

  • Playback-aware call termination - When ending a call, the gateway waits for queued speech to finish playing to the caller before disconnecting. A transport-level acknowledgment mechanism confirms that audio reached the caller, replacing the previous estimate-based approach. If the acknowledgment does not arrive within a timeout, the gateway falls back to a grace period before disconnecting.

  • Priority-based utterance queue - Speech output is managed through a priority queue where urgent responses (such as tool results the caller is waiting for) take precedence over lower-priority items like filler phrases or silence check-ins. The queue supports targeted removal and bulk drain operations for barge-in scenarios.

Who is affected:

All Platform API users running voice agent sessions. Call behavior is unchanged from the caller's perspective - this is an infrastructure improvement that enables the media gateway to handle audio concerns independently. No API changes, no new endpoints, and no action required.

No breaking changes.

chevron-rightv0.9.505 - Platform API: Internal Media Relay for Voice Pipeline (July 2026)hashtag

Internal Media Relay for Voice Pipeline

The voice pipeline now includes a relay layer that connects the media layer to the agent engine using a bidirectional session protocol. This is the next phase of the media layer split introduced in v0.9.502, wiring the two layers together so that voice sessions flow through the separated architecture.

What changed:

  • Bidirectional session relay - The media layer now opens a persistent session connection to the agent engine for each active call. Session lifecycle, speech transcripts, playback status, and tool execution signals flow from the media layer to the engine. Utterance requests, playback controls, and session termination commands flow back. This replaces the previous monolithic path where audio processing and reasoning ran in the same process.

  • Session handshake - Each relay session begins with a structured handshake that carries call metadata, workspace context, and service identity. The agent engine validates the handshake before accepting the session, ensuring that only properly identified sessions are processed.

  • Automatic reconnection - If the relay connection drops mid-session, the media layer attempts to re-establish the connection with exponential backoff. If reconnection fails after multiple attempts, the session degrades gracefully rather than terminating abruptly.

  • Connection security - The relay endpoint only accepts connections from within the platform's internal network boundary. Connections from outside the trust boundary are rejected before the session handshake begins.

Who is affected:

All Platform API users running voice agent sessions. Call behavior is unchanged from the caller's perspective - this is an infrastructure improvement that enables independent scaling of audio processing and agent reasoning. No API changes, no new endpoints, and no action required.

No breaking changes.

chevron-rightv0.9.504 - Platform API: Service-Level Template Cache for Session Init (July 2026)hashtag

Service-Level Template Cache for Session Init

The agent engine now caches service-level configuration across sessions, so that repeat calls to the same service skip redundant configuration fetches. This reduces session initialization latency - particularly for text greeting flows - by reusing previously loaded configuration, skills, integration definitions, and workspace settings.

What changed:

  • Service template caching - When the agent engine initializes a session, it now checks an in-process cache for the service's configuration, skills, integration definitions, and workspace settings. On a cache hit, session initialization only needs to resolve caller context and session credentials, skipping the configuration fetch phase entirely. The cache is keyed by workspace, service, and version set, with time-based expiration and bounded capacity.

  • Deferred tool cache warming - Tool cache warming is now deferred until the caller actually needs it. Voice sessions and standard text turns warm the tool cache before processing. Auto-greet text sessions skip tool warming entirely because the greeting does not invoke tools, reducing first-message latency for text channels.

  • Faster text greeting latency - The combination of service template caching and deferred tool warming significantly reduces the time to deliver the first greeting in text sessions, especially for services that have already handled a recent session on the same engine instance.

Who is affected:

All Platform API users running voice or text agent sessions. Session behavior is unchanged - this is a latency improvement only. No API changes, no new endpoints, and no action required.

No breaking changes.

chevron-rightv0.9.503 - Platform API: Config Cache Invalidation on Save (July 2026)hashtag

Config Cache Invalidation on Save

Saving a service configuration, context graph version, or version set now immediately invalidates cached configuration so that the voice agent engine picks up changes without waiting for the cache to expire.

What changed:

  • Immediate config propagation - Previously, after saving a service config, context graph version, or version set, the voice agent engine could serve stale configuration until the cache TTL expired. Now, saving any of these resources immediately invalidates the relevant cached entries so the next agent session loads fresh configuration.

  • Scoped invalidation - When a service configuration or version set is updated, only the cache entries for that specific service are invalidated. When a context graph version is created, all cached service configurations in the workspace are invalidated, because context graphs can be shared across multiple services.

Who is affected:

All Platform API users who update service configurations, context graph versions, or version sets. Configuration changes now take effect immediately for new agent sessions instead of being delayed. No API changes, no new endpoints, and no action required.

No breaking changes.

chevron-rightv0.9.502 - Platform API: Voice Media Layer Split (July 2026)hashtag

Voice Media Layer Split

The voice subsystem now separates audio processing from agent reasoning into two independently deployable layers. This is the first phase of a multi-phase architecture change that improves scalability, deployment safety, and audio processing performance.

What changed:

  • Separate media layer - Telephony connections, speech-to-text, and text-to-speech processing now run in a dedicated media layer that scales independently from the agent engine. This allows audio-intensive workloads to scale based on concurrent call volume without affecting reasoning capacity, and vice versa.

  • Typed relay protocol - The media layer and agent engine communicate over a structured protocol with typed messages in each direction. Messages from the media layer include session lifecycle events, speech transcripts with timing metadata, and playback completion status. Messages from the agent engine include utterance requests, playback controls, speech recognition configuration, and session termination commands.

  • Graceful rolling deployments - During deployments, the media layer stops accepting new call sessions while allowing in-flight calls to complete naturally. Health probes now distinguish between liveness (the process is running) and readiness (the service is accepting new calls), enabling the load balancer to drain traffic without dropping active calls. Active sessions are tracked with concurrency limits to prevent overload.

  • Session concurrency management - The media layer enforces a configurable limit on concurrent call sessions per instance. When the limit is reached, new sessions are rejected and routed to other available instances. During shutdown, new sessions are rejected immediately while existing sessions are given time to complete.

Who is affected:

All voice agent users. The separation is transparent to API consumers - call behavior, audio quality, and all existing endpoints remain unchanged. No configuration changes are required.

No breaking changes.

chevron-rightv0.9.501 - Platform API: Client Config API and Voice Agent Cold Start Improvements (July 2026)hashtag

Client Config API

A new endpoint returns client-safe configuration values for a workspace. This is useful for embedding platform-provided keys (such as mapping service API keys) in browser-side code without exposing backend secrets.

What changed:

  • New endpoint: GET /v1/{workspace_id}/config/client - Returns client-safe configuration for the authenticated workspace. Currently exposes google_maps_api_key when configured. The endpoint requires workspace authentication and is rate-limited.

  • Response model - Returns a JSON object with optional fields for client-safe keys. Fields are null when the corresponding key is not configured or is set to a placeholder value.

Who is affected:

Frontend applications that need platform-managed API keys for client-side services (e.g., map rendering). No action is required for existing integrations.

No breaking changes.

Voice Agent Cold Start Improvements

Voice agent session initialization is now faster on cold starts. Service configuration is cached so that subsequent session starts on any pod avoid redundant round trips to the configuration service.

What changed:

  • Configuration caching - Service configuration is now cached with a short TTL during voice session initialization. When a session starts on a pod that does not have the configuration in memory, the cache is checked first, avoiding the full configuration fetch. This reduces cold start latency by several seconds in common deployment scenarios.

  • Non-critical task isolation - Heartbeat, event subscriptions, and surface event listeners within a voice session are now isolated so that a failure in one of these non-critical tasks does not crash the entire session. Failures are logged and monitored but no longer cause unexpected disconnects.

  • Pre-warm timeout increase - The best-effort engine pre-warm window has been extended to accommodate the additional caching step, improving the success rate of pre-warm attempts.

Who is affected:

All voice agent users benefit from improved cold start performance and session stability. No configuration changes are required.

No breaking changes.

chevron-rightv0.9.500 - Platform API: Unified Credential Management (July 2026)hashtag

Unified Credential Management

All platform services now share a single credential provider for authenticating to the data layer and file storage APIs. Previously, each service maintained its own independent authentication cache, which could result in redundant token exchanges and slightly different refresh behaviors across services.

What changed:

  • Single shared credential per pod - Each service now constructs one credential provider at startup and threads it into every component that needs authenticated access to the data layer, file storage, or SQL execution APIs. This replaces the previous pattern where each component (file storage clients, SQL clients, database engines, branch clients) independently managed its own token cache and refresh logic.

  • Consistent token caching - Bearer tokens and database credentials are now cached per service principal and per endpoint, with automatic refresh before expiry. The previous behavior where different components could refresh at slightly different times - occasionally causing a brief spike in token exchange calls - is eliminated.

  • No behavioral changes - All authentication flows, API capabilities, and service behavior remain the same. File uploads, SQL execution, database connections, and branch operations continue to work identically. No configuration changes are required.

  • Environment variable consolidation - Services that connect to the data layer now read authentication configuration from a consistent set of environment variables. Services that were previously reading these variables from different env mixins now use a single shared configuration source. All existing environment variables continue to work - no renaming or removal occurred.

Who is affected:

No action is required. This is an internal infrastructure improvement. All APIs, authentication flows, and service capabilities are unchanged.

No breaking changes.

chevron-rightv0.9.499 - Platform API: Emotion Detection Provider Consolidation (July 2026)hashtag

Emotion Detection Provider Consolidation

Emotion detection now uses a single internal provider for all workspaces. The previous multi-provider configuration has been removed, simplifying setup and eliminating the need for external emotion detection API keys.

What changed:

  • Single emotion provider - Emotion detection is now handled exclusively by the platform's built-in emotion engine. The previous option to select between external and internal emotion providers has been removed. Workspaces that had emotion detection enabled continue to work without any configuration changes.

  • Simplified configuration - The emotion_provider and external emotion API key environment variables have been removed. Emotion detection is controlled solely by the workspace-level emotion_detection_enabled voice setting and the voice_agent.emotion_detection feature flag, as before.

  • No behavioral changes - Emotion signals, compound emotion resolution, and speaker normalization continue to work the same way. The emotion data model, signal format, and downstream analytics are unchanged.

Who is affected:

No action is required. Workspaces with emotion detection enabled will continue to receive emotion signals. Workspaces that previously relied on an external emotion detection API key can remove that key from their environment - it is no longer read.

No breaking changes.

chevron-rightv0.9.498 - Platform API: Multi-Region Deployment (July 2026)hashtag

Multi-Region Deployment

The Platform API now runs in four regions: US East, Australia, Europe, and Canada. Each regional deployment routes AI service calls to the nearest available endpoint, reducing round-trip latency for voice and enrichment workloads.

What changed:

  • Four production regions - The Platform API is now deployed in US East, Australia (Sydney), Europe (Frankfurt), and Canada (Montreal). Each region operates as an independent deployment with its own compute and configuration.

  • Regional AI routing - AI-backed services (enrichment, form auto-correction, and OCR) now route to the AI endpoint closest to the serving region. Previously, all regions routed to a single US-based AI endpoint. Regional routing reduces latency for customers outside the US.

  • No API changes - The API surface, authentication, and request/response schemas are unchanged. Clients connect to the same base URL and are routed to the nearest region automatically.

Who is affected:

All Platform API customers benefit from reduced latency if their traffic originates near one of the new regions. No client-side changes are required.

No breaking changes.

chevron-rightv0.9.497 - Platform API: Per-Session World Tool Cache (July 2026)hashtag

Per-Session World Tool Cache

The agent engine now caches read-only world tool results on a per-session basis, so preloaded tool lookups return instantly when the agent calls them during engagement. This reduces latency for conversations that rely on entity data fetched during session setup.

What changed:

  • Per-session tool result caching - When a session starts, the engine warms a local cache by executing any preloaded tool calls defined in the current action state. The results are stored in a session-scoped cache keyed on tool name and parameters. When the agent invokes the same tool with the same parameters during the conversation, the cached result is returned instantly without re-executing the underlying query.

  • Read-only tools only - Only stateless, read-only entity lookups are eligible for caching. Tools that depend on mutable session state (such as slot-based or EHR-context tools) are excluded from the cache and always execute live.

  • Cache lifetime - The cache lives for the duration of a single conversation session. It is not shared across sessions, not persisted, and not accessible outside the session that created it. Each session gets its own isolated cache instance.

  • Preload warming - Preloaded tools defined in the action state are now warmed individually and concurrently during session setup. Each tool has an independent timeout. If a single tool fails to warm, the failure is logged and the remaining tools continue. The cache is populated with whatever succeeds, and tools that failed to warm will execute normally when called during engagement.

  • Observability - Cache hit and miss counts are emitted as gauges after preload warming completes, giving visibility into how effectively the cache is being utilized per session.

Who is affected:

Teams using preloaded world tools in their action states. Preloaded lookups that previously re-executed on every agent call now return from cache, reducing per-call latency. No configuration changes are required - caching is automatic for eligible tools.

No breaking changes.

chevron-rightv0.9.496 - Platform API: Simulation Entity Binding (July 2026)hashtag

Simulation Entity Binding

Simulation sessions, bridge runs, and forked sessions now support binding to a specific world entity for caller context resolution. This lets you pin simulations to a known test patient so the agent resolves identity the same way it would on a production call for that patient.

What changed:

  • Entity ID on simulation sessions - The create-session endpoint now accepts an optional entity_id field (UUID). When provided and the entity exists in the workspace, the session resolves caller context directly from that entity rather than falling back to phone-based lookup. If the entity does not exist (stale, deleted, or wrong workspace), the session falls back to phone lookup against caller_id with no error - the simulation is survivable. Malformed UUIDs are rejected with HTTP 422 before the request reaches the agent engine.

  • Entity ID on bridge runs - The bridge endpoint now accepts an optional entity_id field. The value is forwarded to every scenario session created during the bridge run and inherited by any forks. This lets you pin an entire regression suite to a specific test patient.

  • Entity persistence across forks - When a simulation session is forked, the entity binding from the parent session is automatically inherited by all child branches. This ensures forked conversations maintain the same patient context as the original session.

  • Resolution precedence - Entity match takes priority over phone-based lookup. When entity_id resolves to a matching entity, caller_id is not used for identity resolution. The supplied caller_id is still recorded on the session and surfaced in greeting metadata regardless of which resolution path wins.

  • Updated caller_id handling - Empty and whitespace-only caller_id values are now explicitly normalized to the simulation sentinel, matching the behavior of voice test calls. Previously, certain empty-string edge cases could bypass normalization.

New fields on create-session request:

Field
Type
Required
Default
Description

entity_id

uuid

No

null

World entity UUID to bind caller context directly. Entity match wins over phone lookup; stale UUIDs fall back to phone lookup.

New fields on bridge request:

Field
Type
Required
Default
Description

entity_id

uuid

No

null

World entity UUID forwarded to every scenario session and inherited by forks. Same precedence rules as session-level entity binding.

Who is affected:

Teams running simulations that require specific patient context. Previously, patient resolution in simulations relied on caller_id phone matching. You can now pass an entity UUID directly for deterministic resolution. Existing simulations without entity_id continue to work unchanged.

No breaking changes.

chevron-rightv0.9.495 - Platform API: Decoupled Engage Model and Greeting Cache Improvements (July 2026)hashtag

Decoupled Engage Model and Greeting Cache Improvements

The agent engine now uses separate model configurations for navigation and engagement, and the greeting cache has been extended to cover personalized known-caller greetings.

What changed:

  • Separate navigation and engage models - Navigation (state routing) and engagement (tool-calling and response generation) now resolve their model independently. Each can be configured via version set preferences or environment defaults. This lets you optimize navigation for deterministic routing and engagement for response quality, latency, or cost without coupling the two.

  • New engage model preference in version sets - Version set llm_model_preferences now supports an engage key alongside the existing nav key. When set, engagement sessions (text, simulation, and voice) use the specified model for response generation and tool calling. When unset, the platform default engage model is used.

  • Known-caller greeting caching - Personalized greetings for known callers are now cached using a context-hashed key, avoiding redundant generation on rapid redials and pod-affinity misses. The cache uses a shorter TTL than anonymous or household greetings to limit stale greeting risk. Anonymous and household greetings continue to use workspace-scoped caching.

  • Eager TTS connection - The voice pipeline now establishes the text-to-speech WebSocket connection during session setup rather than waiting for the first utterance. If the pre-connect times out, the system falls back to lazy connection on first use with no impact on the call.

  • Broader model compatibility - The engine now centralizes model-family compatibility checks so that models requiring specific parameter handling (such as omitting temperature) are detected consistently across navigation and engagement paths.

Who is affected:

Workspaces using version set llm_model_preferences for the nav key can now also set an engage key to control the engagement model independently. Existing configurations without an engage preference continue to work unchanged - the platform default is used. Known-caller greeting behavior improves automatically with no configuration required.

No breaking changes.

chevron-rightv0.9.494 - Platform API: State-Level Tool Preload (July 2026)hashtag

State-Level Tool Preload

Action states in context graphs now support a preload field - a list of tool calls that execute deterministically when the agent enters the state, before any LLM turn. This lets you assemble known data requirements on state entry without relying on the LLM to decide which tools to call.

What changed:

  • New preload field on action states - Each action state can now include a preload array of up to 20 tool call specifications. When the agent enters the state, all preloads execute in parallel and their results are injected into the conversation context so the LLM sees them as pre-loaded data on its first turn.

  • Template variable support - Preload parameters support {caller_mrn} and {entity_id} template variables, resolved from the caller's identity context. This lets you fetch patient-specific data (e.g., upcoming appointments, medication lists) without LLM involvement.

  • Failure isolation - If a preload tool call fails or times out, the failure is logged but does not block the conversation. The LLM turn proceeds with whatever data was successfully loaded.

New fields on action state:

Field
Type
Required
Default
Description

preload

array[object]

No

[]

Tool calls to execute on state entry before any LLM turn. Max 20 items.

Preload spec object:

Field
Type
Required
Default
Description

tool_id

string

Yes

-

Identifier of the tool to execute. Max 256 characters.

params

object

No

{}

Parameters for the tool call. Supports {caller_mrn} and {entity_id} template variables. Max 20 keys.

Example:

Who is affected:

This is a purely additive change. Existing action states without preload behave identically to before. No migration required.

chevron-rightv0.9.493 - Platform API: Data Query Fix and Entity Sort Support (July 2026)hashtag

Data Query Fix and Entity Sort Support

The data query endpoint now correctly handles workspace filtering across all table types, and the entity listing endpoint supports server-side sorting.

What changed:

  • Fixed workspace filtering for synced tables - Data queries against tables backed by synced data sources previously failed with a type mismatch error when filtering by workspace. This has been fixed. All table types now work correctly with workspace isolation.

  • New sortable columns on data query - The data query table registry for entities now includes name, phone, email, and status as queryable columns. These columns can be selected and filtered in data queries alongside existing columns.

  • Entity listing now supports sorting - The entity listing endpoint accepts a new order query parameter for server-side sorting. The parameter uses PostgREST-style syntax (e.g. last_event_at.desc, display_name.asc). Multiple sort clauses can be comma-separated, up to a maximum of 3.

New query parameter on entity listing:

Parameter
Type
Required
Default
Description

order

string

No

null

Sort order using PostgREST-style syntax. Max length 128 characters.

Allowed sort columns: confidence, display_name, entity_type, event_count, last_event_at, name, projected_at, source

Sort syntax:

  • column.asc - ascending (default if direction omitted)

  • column.desc - descending

  • column1.desc,column2.asc - multiple sort clauses

Unrecognized column names return a 422 error with the list of allowed columns.

Who is affected:

The workspace filtering fix resolves errors for workspaces querying synced entity data. The sort parameter is purely additive - existing calls without order behave identically to before.

chevron-rightv0.9.492 - Platform API: Request Transform for Integration Endpoints (July 2026)hashtag

Request Transform for Integration Endpoints

Integration endpoint configurations now support an optional request_transform that reshapes the outbound request body before it is sent to the external service. This complements the existing response-side pipeline (response_filter, result_key, result_template) with a symmetric request-side capability.

What changed:

  • New request_transform field on endpoint configs - Each endpoint in an integration configuration can now include a request_transform object. The transform is applied after path parameter substitution and auth header resolution, immediately before the HTTP call is made.

  • Wrap caller params - The wrap_params_key field nests the caller-supplied parameters under a specified key. This is useful when an external API expects request data inside an envelope (e.g. {"data": {...}}) rather than at the top level.

  • Inject static fields - The inject field merges static key-value pairs into the top-level request body. Injected values support the {endpoint_name} placeholder, which is replaced at call time with the resolved endpoint name. Injected fields take precedence over caller-supplied params on key conflict, ensuring the integration contract is enforced.

  • Ordering guarantee - When both wrap_params_key and inject are used, wrapping happens first. Injected fields are placed at the top level alongside the wrapper key, not inside the wrapped sub-object.

  • Method restriction - Request transforms are only valid on POST, PUT, and PATCH endpoints. The API rejects endpoint configurations that set request_transform on GET or DELETE endpoints.

New fields on endpoint config:

Field
Type
Required
Default
Description

request_transform

object

No

null

Transform applied to the outbound request body.

request_transform.wrap_params_key

string

No

null

Nests caller params under this key. Max 128 characters.

request_transform.inject

object

No

{}

Static fields merged into the top level. Max 20 entries. Supports {endpoint_name} placeholder.

Who is affected:

This is a purely additive change. Existing integration configurations without request_transform behave identically to before. No migration required.

chevron-rightv0.9.491 - Platform API: Channel Manager Client Required (July 2026)hashtag

Channel Manager Client Required

The channel management dependency is now required for both the agent engine and Platform API services. Previously, the telephony channel management integration was optional and services could start without it, falling back to legacy resolution paths. It is now a mandatory startup dependency - the platform will fail fast at startup if the channel management connection is not configured.

What changed:

  • Channel management is no longer optional - The agent engine and Platform API both require a valid channel management connection at startup. Previously, missing configuration caused the services to start in a degraded mode where inbound and outbound call routing fell back to legacy paths. This silent degradation made it difficult to diagnose routing failures in production.

  • Fail-fast startup validation - If the channel management connection is not configured, the service exits immediately with a clear error instead of starting in a partially functional state. This ensures misconfigurations are caught during deployment rather than at runtime when a call arrives.

  • Removed legacy fallback guards - Inbound call routing via use case and outbound call dispatch no longer check whether channel management is available before proceeding. Since the dependency is guaranteed at startup, these runtime guards were redundant. The inbound webhook path previously returned a fallback response when channel management was unavailable; it now assumes the dependency is present.

  • Simplified credential resolution - Session credential lookups no longer skip channel management checks. The credential resolution path assumes channel management is always available, removing a conditional branch that could silently produce incomplete session configurations.

Who is affected:

Self-hosted and custom deployment configurations that previously omitted the channel management connection. These deployments must now provide the channel management configuration before the service will start. Standard managed deployments are unaffected - the configuration has been present in all managed environments.

No breaking changes to API contracts. All existing endpoints, request formats, and response shapes are unchanged.

chevron-rightv0.9.490 - Platform API: Twilio Access Token Minting (July 2026)hashtag

Twilio Access Token Minting

The channel management service now provisions a dedicated signing key during telephony setup and exposes an endpoint for minting short-lived access tokens. This enables browser-based voice capabilities through the platform's operator interface without exposing signing credentials to downstream services.

What changed:

  • Signing key provisioned at setup time - When a new telephony setup is created, the platform now provisions a dedicated signing key on the subaccount and stores both halves securely. This key is used exclusively for minting access tokens and is never exposed to other services. The signing key is created as part of the existing setup flow - no additional API call is required.

  • Access token mint endpoint - A new endpoint mints short-lived access tokens scoped to a specific telephony setup. The token is signed server-side using the provisioned signing key, so the key material never leaves the channel management boundary. Tokens are voice-scoped and can be passed directly to browser-based voice SDKs. The caller specifies an identity string, the application to authorize outbound dialing against, and an optional TTL (default 1 hour, maximum 4 hours). The response includes the signed token, the echoed identity, and a wall-clock expiry timestamp that clients can use to schedule pre-expiry refresh.

  • Setup ID allocated deterministically - The telephony setup ID is now allocated at the start of the setup flow rather than at the end. This ensures the signing key can be stored at a deterministic path before the setup row is persisted, preventing orphaned credentials if a later step fails.

New endpoint:

Method
Path
Description

POST

/v1/twilio-setup/{setup_id}/access-token

Mint a short-lived access token for browser-based voice

Request body:

Field
Type
Required
Default
Description

identity

string

Yes

-

Identity claim for the token. Maximum 121 characters.

outgoing_application_sid

string

Yes

-

Application SID the token bearer is authorized to dial through.

ttl_seconds

integer

No

3600

Token lifetime in seconds. Minimum 60, maximum 14400.

Response (200):

Field
Type
Description

access_token

string

Signed JWT for use with browser-based voice SDKs.

identity

string

Echo of the request identity.

expires_at

datetime

Wall-clock token expiry (ISO 8601).

Error responses:

Status
Description

404

Telephony setup not found.

503

No signing key provisioned for this setup yet (pre-migration setups).

Who is affected:

Platform users building browser-based operator voice experiences. The access token endpoint is consumed by the operator interface to establish voice connections. Existing telephony setups created before this release do not yet have signing keys provisioned - calling the mint endpoint for those setups returns a 503 until a backfill is applied.

No breaking changes. The setup creation flow is backward-compatible - the additional signing key provisioning step is transparent to callers.

chevron-rightv0.9.489 - Platform API: LLM Model Preferences and Default Model Upgrade (July 2026)hashtag

LLM Model Preferences and Default Model Upgrade

The agent engine now supports per-version-set model preferences for navigation and engagement, and the platform default model has been upgraded for improved accuracy.

What changed:

  • Per-version-set model override - Version sets can now include an llm_model_preferences map that overrides the default model used for context graph navigation and conversational engagement. When a version set specifies a nav preference with a model name, that model is used for the session instead of the platform default. This lets you pin specific agent versions to specific models, enabling controlled rollouts and A/B testing of model upgrades without changing global configuration.

  • Default model upgrade - The platform default model for navigation and engagement has been upgraded. The new default reduces hallucinations by 52% on medical and financial content compared to the previous generation, with no change in per-token latency. Existing deployments that do not set explicit model preferences in their version sets will automatically use the new default.

  • Consistent model resolution across channels - The resolved model preference is now consistently applied across voice sessions, text sessions, and simulation runs. Previously, model selection was determined solely by the environment default. Now the resolution order is: version set override, then environment default.

Who is affected:

All platform users. Workspaces without explicit llm_model_preferences in their version sets will see the upgraded default model take effect automatically. If you need to pin a specific model version, configure llm_model_preferences in your version set.

No breaking changes. The upgrade is backward-compatible - existing version sets without model preferences continue to work and will use the new default.

chevron-rightv0.9.488 - Platform API: iMessage Phone Number Management and Setup Narrowing (July 2026)hashtag

iMessage Phone Number Management and Setup Narrowing

The iMessage channel now supports adding additional phone lines to an existing setup and listing all phone lines with status filtering. The setup GET endpoint has been narrowed to return only live lines, giving callers the operationally relevant view by default.

What changed:

  • Add phone number to existing setup - A new endpoint lets you add additional phone lines to an already-provisioned iMessage setup. Each setup starts with one line at creation time; this endpoint provisions a second, third, or subsequent line on the same subaccount. You can optionally request a preferred 3-digit area code, though availability is not guaranteed. New lines start in a pending state and are assigned a phone number asynchronously through the existing line assignment process.

  • List phone numbers with status filtering - A new endpoint returns every phone line under a setup, with a repeatable status query parameter to filter by line state. Three statuses are supported: pending (line requested but not yet assigned a number), assigned (line has a number and is available for sending), and blocked (line has been permanently flagged). Defaults to returning all three statuses. Returns 404 if the setup ID does not exist, so callers can distinguish "no lines" from "bad setup ID".

  • Setup GET returns only live lines - GET /v1/sendblue-setup/{setup_id} now returns only lines that are assigned and not blocked. Pending and blocked lines are excluded from the phone_numbers array. Use the dedicated phone number list endpoint with a status filter to see pending or blocked lines.

  • Setup list counts only live lines - GET /v1/sendblue-setup now reports phone_number_count as the number of assigned, non-blocked lines. This matches the narrowed view from the setup GET endpoint.

New endpoints:

Method
Path
Description

POST

/v1/sendblue-setup/{setup_id}/phone-number

Add a phone line to an existing setup

GET

/v1/sendblue-setup/{setup_id}/phone-number

List phone lines under a setup with optional status filtering

Add phone number request body:

Field
Type
Required
Description

desired_area_code

string or null

No

Optional 3-digit area code preference. Not guaranteed - if no inventory matches, a different area code is assigned.

Add phone number response (201):

Returns a phone number record with the line in pending state (phone_number is null, line_request_id is set).

List phone numbers query parameters:

Parameter
Type
Default
Description

status

string (repeatable)

pending, assigned, blocked

Filter by line status. Repeat to include multiple statuses.

List phone numbers response:

Field
Type
Description

items

array

Phone number records matching the status filter, ordered most-recent-first.

Updated endpoints:

Method
Path
Change

GET

/v1/sendblue-setup/{setup_id}

phone_numbers now contains only assigned, non-blocked lines

GET

/v1/sendblue-setup

phone_number_count now counts only assigned, non-blocked lines

chevron-rightv0.9.487 - Platform API: iMessage Line Blocking and Ticket-Based Line Assignment (July 2026)hashtag

iMessage Line Blocking and Ticket-Based Line Assignment

The iMessage channel now handles blocked lines and uses ticket-based polling for deterministic phone line assignment. These changes improve line health tracking and make line provisioning resilient to webhook delivery gaps.

What changed:

  • Line blocking - When the upstream iMessage provider flags a phone line as blocked (carrier action, abuse, or suspension), the platform records the block timestamp on the affected phone line record. Blocked lines are permanently excluded from the send path - the platform filters them out when selecting lines for outbound messages. There is no unblock capability because the upstream provider does not support it. The block status is visible on phone line records returned by the setup endpoints.

  • Blocked line field on phone line records - Phone line records returned by GET /v1/sendblue-setup/{setup_id} and GET /v1/sendblue-setup now include a blocked_at timestamp field. This field is null when the line is healthy and set to the time the block was recorded when the line has been flagged. Once set, this field is never cleared.

  • Ticket-based line assignment - The line_assigned webhook handler now uses ticket polling to determine which pending phone line received an assigned number. Instead of matching by payload contents alone, the handler polls each pending line's provisioning ticket with the upstream provider and fills in the phone number only when the ticket reports a fulfilled status. This makes assignment deterministic even when webhook payloads lack explicit ticket-to-number mapping.

  • Resilient to webhook gaps - Because assignment is driven by ticket status rather than webhook payload order, re-delivered or delayed webhooks produce the same result. Pending lines that were already assigned in a previous delivery are skipped. Lines with tickets still in progress are re-polled on the next webhook delivery.

  • Line blocked webhook - POST /v1/webhook/sendblue/event now handles line_blocked events in addition to line_assigned events. When the upstream provider reports blocked lines, matching phone line records are stamped with a block timestamp. Re-deliveries preserve the original block timestamp.

Updated endpoints:

Method
Path
Change

GET

/v1/sendblue-setup/{setup_id}

Phone line records now include blocked_at

GET

/v1/sendblue-setup

Phone line records now include blocked_at

POST

/v1/webhook/sendblue/event

Now handles line_blocked events; line_assigned uses ticket polling

New fields on phone line records:

Field
Type
Description

blocked_at

datetime or null

Timestamp when the line was flagged as blocked. Null when the line is healthy. Once set, never cleared.

chevron-rightv0.9.486 - Platform API: SMS Channel Removed (July 2026)hashtag

SMS Channel Removed

SMS has been removed as a messaging channel. The platform no longer supports creating, receiving, or managing SMS-based text sessions. WhatsApp and web remain as supported text channels.

What changed:

  • SMS session creation removed - The POST /v1/{workspace_id}/sessions/start endpoint no longer accepts sms as a channel_kind. The only supported value is web. Requests specifying sms will receive a validation error.

  • Outbound SMS removed - The internal outbound SMS capability has been removed. Phone-based outbound text sessions are no longer supported. Outbound communication continues to be available through voice calls and other supported channels.

  • SMS-specific fields removed from session start - The following fields have been removed from the start session request body: phone_to, surface_id, and idempotency_key. These fields were only used for phone-based text channels (SMS and WhatsApp). The greeting field remains available for web sessions.

  • SMS-specific fields removed from session start response - The phone_to and phone_from fields have been removed from the start session response.

  • SMS webhooks removed - Inbound SMS webhook and SMS delivery status callback endpoints are no longer available. These endpoints were used by the upstream telephony provider to deliver inbound messages and delivery receipts.

Who is affected:

  • Integrations that created SMS text sessions via the session start endpoint. Migrate to web text sessions or WhatsApp.

  • Workflows that relied on outbound SMS for patient communication. Use voice calls, WhatsApp, or other supported channels instead.

  • Any automation that referenced sms as a channel kind in API requests. Update to use web or remove those code paths.

Breaking changes:

  • channel_kind: "sms" is no longer accepted by the session start endpoint.

  • phone_to, surface_id, and idempotency_key request fields have been removed from the session start endpoint.

  • phone_to and phone_from response fields have been removed from the session start response.

  • SMS inbound and status webhook endpoints no longer exist.

chevron-rightv0.9.485 - Platform API: iMessage Channel Setup and Line Provisioning (July 2026)hashtag

iMessage Channel Setup and Line Provisioning

The platform now supports iMessage as a messaging channel. A new set of endpoints lets you provision iMessage subaccounts, track phone line assignments, and receive webhook notifications when lines are placed.

What changed:

  • iMessage subaccount provisioning - POST /v1/sendblue-setup creates a new iMessage subaccount for a business identity. The platform provisions the subaccount with the upstream iMessage provider, registers webhook endpoints, and securely stores per-subaccount credentials. The response includes the subaccount identifier, an operator-facing label, and the initial phone line status.

  • Phone line lifecycle - Each subaccount is assigned a phone line during provisioning. If a line is available immediately, the setup response includes the assigned phone number. If the line requires carrier placement, the setup is created in a pending state and the phone number is populated automatically when the upstream provider assigns it. The line_assigned webhook event triggers this transition.

  • Read and list setups - GET /v1/sendblue-setup/{setup_id} returns a single subaccount setup with its phone lines. GET /v1/sendblue-setup lists all setups with phone line counts. Phone lines include their assignment status - either an E.164 phone number when assigned, or a pending indicator when the line is awaiting placement.

  • Webhook for line assignment - POST /v1/webhook/sendblue/event receives line assignment notifications from the upstream provider. When a pending line is assigned a phone number, the webhook updates the corresponding phone line record. Re-deliveries of the same event are handled idempotently. Webhook authentication uses a per-subaccount secret verified on every delivery. Both unknown-account and signature-mismatch responses return an identical error to prevent account enumeration.

New endpoints:

Method
Path
Description

POST

/v1/sendblue-setup

Create an iMessage subaccount

GET

/v1/sendblue-setup

List all iMessage subaccount setups

GET

/v1/sendblue-setup/{setup_id}

Get a single iMessage subaccount setup

POST

/v1/webhook/sendblue/event

Receive iMessage provider webhook events

Setup response fields:

Field
Type
Description

id

string

Unique identifier for the setup

friendly_name

string

Operator-facing label

subaccount_company_name

string

Name assigned by the upstream provider

api_key_id

string

Public identifier for the subaccount credentials

phone_numbers

array

Phone lines under this subaccount

created_at

datetime

When the setup was created

updated_at

datetime

When the setup was last modified

Phone number fields:

Field
Type
Description

id

string

Unique identifier for the phone line

phone_number

string or null

E.164 phone number, null while pending

line_request_id

string or null

Upstream line request ticket, null when assigned directly

created_at

datetime

When the phone line record was created

updated_at

datetime

When the phone line record was last modified

Create request body:

Field
Type
Required
Description

friendly_name

string

Yes

Operator-facing label (1-256 characters)

company_name

string

Yes

Business name for the subaccount (1-256 characters)

Who is affected:

  • Platform operators who want to add iMessage as a communication channel. This is a new capability with no impact on existing channels.

  • Webhook consumers who need to handle line assignment events for iMessage setups.

No breaking changes.

chevron-rightv0.9.484 - Platform API: Tool Call Truncation Metadata and Text Session Reasoning Traces (July 2026)hashtag

Tool Call Truncation Metadata and Text Session Reasoning Traces

Tool call responses in call traces and conversation turns now include truncation metadata when a tool response exceeds the platform's trace size limit. Text session conversation turns now persist reasoning details - tool calls, state transitions, and timing - that were previously only available for voice sessions.

What changed:

  • Tool call truncation metadata on call traces - The call trace API now returns three additional fields on each tool call entry: output_truncated (boolean indicating whether the response was clipped), output_original_length (character count of the full response before clipping), and output_truncated_to (character count after clipping). These fields appear only when the tool response exceeded the trace size limit. When a response is not truncated, output_truncated is false and the length fields are null.

  • Text session reasoning traces - Conversation turns produced by text sessions now include the same reasoning trace fields available on voice call turns: trigger (what initiated the agent turn), agent_action (whether the agent responded or completed the conversation), tool_calls (list of tools invoked during the turn with input, output, truncation metadata, duration, and success status), and state_transitions (list of context graph state changes with previous state, next state, and navigation timing). Previously, text session turns persisted only the message content and role.

  • New completion reason: STT fatal error - Voice calls that terminate due to an unrecoverable speech-to-text failure now report error as the completion reason instead of being left without a reason. This aligns STT failures with other error-class terminations in call analytics.

Who is affected:

  • API consumers reading call traces who need to know whether a tool response was truncated. The three new fields are additive and default to non-truncated values, so existing integrations are unaffected.

  • Developers building analytics or debugging tools for text sessions. Reasoning traces are now available on text conversation turns without any configuration changes.

  • Dashboards or reports that filter on completion reasons. Calls that previously had no completion reason for STT failures now report error.

No breaking changes.

chevron-rightv0.9.483 - Platform API: Workspace Query Tools in Context Graphs (July 2026)hashtag

Workspace Query Tools in Context Graphs

Context graphs can now reference workspace query tools by identifier, enabling per-state tool gating for workspace-defined query tools. Previously, context graph states could only gate skills (by slug) and built-in tools. Workspace query tools were available globally but could not be scoped to specific conversation states.

What changed:

  • Workspace query tools as state-gated tools - Context graph states can now include workspace query tool identifiers in their tool specifications. The agent engine resolves these identifiers at session initialization and restricts tool availability to the states where they are referenced, just like skills and built-in tools.

  • Validation updated - The context graph validation endpoint now validates workspace query tool references. If a tool identifier does not match a known skill slug, built-in tool, platform function, or workspace query tool, validation returns an error. The error message has been updated from "No skill found with slug" to "No skill or workspace tool found for" to reflect the broader set of supported tool types.

  • No changes to workspace query tool registration - Workspace query tools are still defined and managed through the existing workspace query tools API. This change only affects how context graphs reference them.

Who is affected:

  • Workspace administrators building context graphs who want fine-grained control over when workspace query tools are available during a conversation. Previously, workspace query tools were available in every state once registered.

  • No changes needed for workspaces that do not use context graphs or do not need per-state tool gating for workspace query tools.

No breaking changes.

chevron-rightv0.9.482 - Platform API: Per-Service Call Forwarding Configuration (July 2026)hashtag

Per-Service Call Forwarding Configuration

Call forwarding configuration has moved from phone numbers to services. Forwarding destinations are now defined on the service's voice configuration rather than on individual phone numbers. This simplifies forwarding setup and aligns it with the rest of the per-service voice pipeline configuration.

What changed:

  • Forwarding is now per-service - Call forwarding destinations are configured on the service's voice configuration object (voice_config.forwarding) instead of on individual phone numbers. Each service can define a single forwarding destination with a phone number, transfer behavior (AI drops off or stays on), and warm vs. cold transfer mode.

  • New forwarding field on voice configuration - The service voice configuration now includes an optional forwarding object with three fields:

    • forward_to (string, required) - E.164 destination phone number

    • should_disconnect (boolean, default true) - Whether the AI drops off after transfer

    • warm_transfer (boolean, default true) - Whether the agent briefs the human before connecting the caller. Set to false for IVR, voicemail, or emergency destinations.

  • Per-phone forwarding deprecated - The forwarding configuration on phone number resources is deprecated. The fields are still accepted for one release for backward compatibility but are no longer read by the voice agent at session time. A deprecation warning is logged when per-phone forwarding fields are set. These fields will be removed in a future release.

  • Internal forwarding resolution endpoint removed - The internal endpoint previously used by the voice agent to resolve per-phone forwarding at session start has been removed. Forwarding configuration is now read directly from the service configuration, eliminating a network round-trip during session initialization.

  • Escalation policy forwarding updated - The forward escalation action now resolves its target from the service's voice configuration forwarding destination. Previously, it resolved from the inbound phone number's forwarding configuration.

  • Forward call tool behavior unchanged - The forward_call tool remains gated by voice_config.forward_call_enabled. When enabled without a static forwarding destination, the LLM must supply the phone number explicitly. When a static destination is configured via voice_config.forwarding, it serves as the fallback when the LLM does not provide an explicit number.

Migration:

  • Move any forwarding configuration from phone numbers to the corresponding service's voice configuration. Set voice_config.forwarding with the same forward_to number and transfer settings.

  • If you use escalation policies with the forward action, ensure the target service has voice_config.forwarding configured. The escalation forward action no longer reads from phone number configuration.

  • Per-phone forwarding fields will continue to be accepted temporarily but have no effect on call routing. Remove them when convenient.

Who is affected:

  • API consumers who configure call forwarding on phone number resources. These configurations are no longer used by the voice agent.

  • Workspaces using escalation policies with the forward action. The forwarding target must now be set on the service's voice configuration.

  • No changes needed if you do not use call forwarding or if you already configure forwarding through service-level settings.

Breaking changes:

  • Per-phone forwarding configuration is no longer read at session time. Forwarding must be configured on the service's voice configuration to take effect.

  • The internal forwarding resolution endpoint has been removed.

chevron-rightv0.9.481 - Platform API: Channel Type and Outreach Rule Cleanup (July 2026)hashtag

Channel Type and Outreach Rule Cleanup

The surface delivery channel options have been simplified to reflect the email-and-web-only delivery model introduced in recent releases. Outreach rules and gap scanner settings now default to email instead of SMS, and unsupported channel values are rejected earlier in the pipeline.

What changed:

  • Channel type restricted to email and web - The set of allowed channel values for surfaces and outreach rules is now limited to email and web. Previously, legacy values such as sms, whatsapp, imessage, and voice were still accepted by the channel type enum even though surface delivery only supported email and web. These legacy values are no longer valid for new resources.

  • Outreach rule default channel changed to email - Gap scanner requirements and outreach rules now default to email when no channel is specified. Previously, the default was sms. Existing outreach rules that explicitly specify a channel are not affected.

  • Unsupported channels skipped during scanning - When the gap scanner encounters an outreach rule with a channel other than email or web, it now skips the rule with a warning instead of attempting to create a surface that would fail validation. This prevents errors when legacy outreach rules reference channels that are no longer supported for surface delivery.

  • SMS auto-delivery removed from gap scanner - The gap scanner no longer triggers outbound text message delivery for surfaces. Auto-delivery is now limited to scheduling outbound voice calls. Surface delivery for email and web channels is handled by the surface delivery pipeline.

  • Quiet hours description updated - Quiet hours configuration is no longer described as SMS-specific. The quiet hours window applies to all outbound outreach regardless of channel.

Migration:

  • If you have outreach rules or gap scanner requirements that specify sms, whatsapp, imessage, or voice as the channel, update them to email or web. Rules with unsupported channels will be skipped during scanning.

  • If you relied on the default channel being sms for gap scanner requirements created without an explicit channel, note that new requirements will default to email.

  • No changes are needed if your outreach rules already use email or web channels.

Who is affected:

  • API consumers creating surfaces or outreach rules with channel values other than email or web. These requests will now return validation errors.

  • Workspace administrators with legacy outreach rules configured for SMS or other non-email/web channels. These rules will be skipped during gap scanning with a warning logged.

Breaking changes:

  • Channel values sms, whatsapp, imessage, and voice are no longer accepted when creating new surfaces or outreach rules.

  • The default channel for gap scanner requirements changed from sms to email.

  • SMS-based auto-delivery from the gap scanner has been removed.

chevron-rightv0.9.480 - Platform API: Surface Email Delivery Through Channel Manager (July 2026)hashtag

Surface Email Delivery Through Channel Manager

Surface email delivery now routes through the platform's centralized email delivery service instead of a direct third-party transport. This unifies email sending with the same sender identity, DNS verification, and suppression management used by all other platform email channels.

What changed:

  • Unified email delivery path - When a surface is delivered to an email address, the platform now sends the email through the same delivery infrastructure used by other email channels (use case bindings, workspace-level sender identity, DNS verification). Previously, surface emails were sent through a separate transport that bypassed workspace email configuration.

  • Sender identity from workspace configuration - Surface emails are now sent from the workspace's configured email sender identity rather than a platform-wide default address. This means surface emails match the sender domain and DKIM signatures of all other emails sent from the workspace.

  • Updated delivery metadata - The delivery response and event payloads now include the platform email identifier and the underlying message identifier from the email provider. The delivery_provider field in the response is now ses instead of gmail. The from_address field is no longer included in delivery metadata - the sender is determined by the workspace's email configuration.

  • Error mapping - Delivery failures now return more specific error codes. If the surface's email use case is not configured or not found, the endpoint returns 422 Unprocessable Entity. If the workspace's email DNS verification is not complete, the endpoint returns 503 Service Unavailable. Previously, all email failures returned a generic 502 Bad Gateway.

  • Removed platform-level email credentials - The platform no longer requires separate email service credentials at the platform level. Email delivery is fully managed through workspace-level channel configuration.

  • HTML email body - Surface delivery emails are now sent as HTML rather than plain text. The email contains a clickable link to the surface form. The subject line and messaging are unchanged.

Migration:

  • If you consume the delivery response or delivery events, update your code to handle the new metadata fields (delivery_provider changing from gmail to ses, new channel_manager_email_id and ses_message_id fields, removal of from_address).

  • If you relied on the message_id field in delivery events, note that it now contains the email provider's message identifier rather than the previous transport's message identifier.

  • No changes are needed to the delivery request itself. The endpoint signature is unchanged.

Who is affected:

  • API consumers that deliver surfaces via email and parse the delivery response metadata. Update field references as described above.

  • Workspace administrators should ensure their email channel setup (sender identity, DNS verification) is complete before delivering surfaces via email. Surfaces delivered before DNS verification is complete will return a 503 error.

  • Voice agent sessions that trigger surface delivery are not affected - the platform handles email routing automatically.

Breaking changes:

  • The delivery_provider value in delivery responses changes from gmail to ses.

  • The from_address field is no longer present in delivery metadata.

  • The message_id field in delivery events now contains a different identifier format.

  • Email delivery failures may return different HTTP status codes (422 or 503) instead of the previous 502.

chevron-rightv0.9.479 - Platform API: Email Use Case Binding on Surface Creation (July 2026)hashtag

Email Use Case Binding on Surface Creation

Surfaces created with channel email now require a use case identifier that links the surface to a configured email delivery binding. This lets the platform route email delivery through the correct transport configuration without requiring callers to manage delivery details separately.

What changed:

  • use_case_id field on surface creation - The create surface request now accepts an optional use_case_id field (UUID). When the channel is email, this field is required and must reference a valid email use case binding in the workspace. When the channel is web, the field is ignored. The field appears in both the create response and the get/list surface responses.

  • Validation against use case bindings - When use_case_id is provided with an email channel, the platform validates that the use case exists in the workspace and that its bound channel matches the surface channel. If the use case is not found or the channel does not match, the request returns a 422 Unprocessable Entity error.

  • Channel restriction - Only email and web channels are now accepted on surface creation. Other channel values (legacy types such as sms or voice) return a validation error. Existing surfaces with legacy channel values are not affected.

  • Agent engine auto-resolution - When the voice agent creates surfaces during a conversation (either through tool calls or state machine transitions), the platform automatically resolves the email use case from the session's service configuration. If the service has an email use case binding, the surface defaults to email delivery. If not, the surface falls back to web delivery. The agent does not need to specify the use case - the platform infers it from the session context.

Migration:

  • If you create surfaces with channel: "email" via the API, include use_case_id in your request body. The value must be a UUID referencing a use case that is bound to an email channel in your workspace.

  • If you create surfaces with channel: "web", no changes are needed. The use_case_id field is optional and ignored for web surfaces.

  • If you create surfaces with legacy channel types (sms, voice), switch to email or web. Legacy channel values are no longer accepted on new surface creation.

Who is affected:

  • API consumers creating email surfaces directly. Add use_case_id to your create requests.

  • Voice agent sessions that create surfaces are not affected - the platform resolves the use case automatically from the service configuration.

Breaking changes:

  • Surface creation with channel: "email" now requires use_case_id. Requests without it return a validation error.

  • Surface creation with channel values other than email or web now returns a validation error.

chevron-rightv0.9.478 - Platform API: SMS Surface Delivery Removed (July 2026)hashtag

SMS Surface Delivery Removed

SMS delivery for surfaces has been removed from the platform. Phone-number-shaped delivery addresses now return a 422 error instead of attempting SMS delivery. Email and web delivery continue to work as before.

What changed:

  • SMS delivery path removed - The surface delivery endpoint no longer sends surfaces via SMS. Previously, passing a phone number as the delivery address would send an SMS containing a link to the surface. This path has been removed because it had zero production usage across all regions.

  • Phone numbers return 422 - Delivery requests with a phone-number-shaped address now return a 422 Unprocessable Entity error with a message indicating that phone surfaces are no longer supported. Use email or web delivery instead.

  • vCard endpoint removed - The public endpoint that served vCard contact cards for workspace phone numbers has been removed. This endpoint was used to help patients save the sending number so that iOS would render SMS links as tappable. With SMS delivery removed, this endpoint is no longer needed.

  • Simplified platform configuration - The platform no longer initializes SMS delivery infrastructure at startup. This reduces startup dependencies and simplifies the platform's runtime configuration.

Migration:

  • If you previously delivered surfaces via SMS by passing a phone number as the channel address, switch to email delivery (pass an email address) or web delivery (use the surface URL directly).

  • If you used the vCard endpoint to distribute contact cards, this endpoint is no longer available. Remove any references to it from your integration.

Who is affected:

  • API consumers that pass phone numbers as the channel address in surface delivery requests. These requests will now receive a 422 error. Switch to email or web delivery.

  • Integrations that referenced the vCard endpoint. Remove these references.

Breaking changes:

  • Surface delivery with a phone number address now returns 422 instead of sending an SMS.

  • The vCard endpoint has been removed and returns 404.

chevron-rightv0.9.477 - Platform API: Phone Number Provisioning Simplification (July 2026)hashtag

Phone Number Provisioning Simplification

The phone number provisioning endpoint no longer accepts an optional use case assignment during purchase. Use case assignment is now exclusively handled by the dedicated use case assignment endpoint, which owns all channel-specific side effects.

What changed:

  • Removed use case parameter from provisioning - The phone number provisioning request no longer accepts an optional use case identifier. Previously, you could pass a use case ID to assign the number to a use case at purchase time. This parameter has been removed. To assign a use case to a provisioned phone number, use the existing use case assignment endpoint after provisioning.

  • Simplified error responses - The 404 response no longer covers missing use cases - it applies only when the telephony setup is not found. The 422 response no longer references use case channel mismatches - it applies only to country/number type and address requirement validation.

  • No capability pre-validation against use case - The provisioning endpoint previously validated that the purchased number's capabilities (e.g. voice) matched the requested use case's channel requirements. This validation now happens at use case assignment time instead.

Migration:

If you previously passed a use case identifier when provisioning a phone number, update your integration to use a two-step flow:

  1. Provision the phone number (without a use case).

  2. Assign the use case to the provisioned number using the use case assignment endpoint.

Who is affected:

  • API consumers that pass a use case identifier in the phone number provisioning request body. Remove this field from your request payload. The field is no longer accepted.

  • API consumers that relied on the provisioning response to include assigned use case IDs. The response no longer includes use case assignments from provisioning. Query the use case assignment after making the separate assignment call.

Breaking changes:

  • The use case identifier field has been removed from the phone number provisioning request body. Requests that include this field may receive a validation error.

  • The provisioning response no longer returns use case assignments made during purchase.

chevron-rightv0.9.476 - Platform API: SMS Delivery Provider Simplification (July 2026)hashtag

SMS Delivery Provider Simplification

SMS delivery for surfaces now uses a single telephony provider instead of a dual-provider setup with automatic fallback. The secondary SMS provider has been removed from the platform.

What changed:

  • Single SMS delivery path - Surface delivery via SMS now routes exclusively through the primary telephony provider. The previous behavior, which attempted delivery through a secondary provider first and fell back to the primary provider on failure, has been removed.

  • Simplified vCard contact resolution - The vCard endpoint for SMS contact cards now always resolves the sender phone number from the workspace's configured telephony number. The previous override that used a separate provider-specific sender number has been removed.

  • Removed secondary SMS provider configuration - The secondary SMS provider credentials and sender phone number configuration are no longer read or used by the platform. Workspaces that had these configured require no migration - SMS delivery continues through the primary telephony provider.

Who is affected:

  • No action required for most API consumers. SMS delivery continues to work through the primary telephony provider.

  • Workspaces that relied on the secondary SMS provider for delivery will now use the primary telephony provider exclusively. Verify that the workspace has a valid primary telephony number configured.

Breaking changes:

  • None. The API request and response shapes for surface delivery are unchanged.

chevron-rightv0.9.475 - Platform API: Causal Ledger v1 Endpoints Removed (July 2026)hashtag

Causal Ledger v1 Endpoints Removed

The Causal Ledger v1 HTTP endpoints have been removed from the Platform API. These endpoints provided descriptive SPR (Standardized Prevalence Ratio) driver attribution and were deprecated in favor of a forthcoming causal attribution pipeline.

What changed:

  • Removed GET /v1/{workspace_id}/causal/drivers - This endpoint returned ranked SPR drivers for a given outcome, with support for filtering by feature family and arity. It is no longer available. Requests to this endpoint will return a 404.

  • Removed Causal Ledger tag from the API - The "Causal Ledger" tag and all associated request/response schemas have been removed from the OpenAPI specification.

Who is affected:

  • API consumers that query the causal drivers endpoint should remove these calls. There is no replacement endpoint at this time. A future causal attribution API will be introduced separately.

Breaking changes:

  • GET /v1/{workspace_id}/causal/drivers has been removed and will return 404.

chevron-rightv0.9.474 - Platform API: Unified Call Source Values (July 2026)hashtag

Unified Call Source Values

The call source value used for simulation-originated calls has been standardized to simulation across all API responses. Previously, simulation calls could appear with an inconsistent source label depending on the code path, which caused errors when listing calls that included simulation results.

What changed:

  • Consistent simulation source value - All simulation-originated calls now return source: "simulation" in both call list summaries and call detail responses. The previous value simulated is no longer returned by the API.

  • Updated allowed values - The source field on call responses now accepts one of: real, simulation, playground, or scribe. The previous value simulated has been removed from the allowed set.

  • Fixed 500 error on call listing - A server error that occurred when listing calls containing simulation results has been resolved. The error was caused by the inconsistent source value failing response validation.

Who is affected:

  • API consumers that filter or match on the call source field value simulated should update to use simulation instead.

  • No changes are required for consumers that do not inspect the source field.

Breaking changes:

  • The source field on call list and call detail responses no longer returns simulated. The value is now simulation.

chevron-rightv0.9.473 - Platform API: Entity Read Path Migration (July 2026)hashtag

Entity Read Path Migration

All entity read operations now use the optimized read-path data store exclusively. This eliminates the dual-path routing that previously fell back to the primary data store for certain query patterns, resulting in more consistent query performance and simpler filtering behavior.

What changed:

  • Single read path for all entity queries - Entity listing, search, detail, and count operations now route through a single optimized read path. The previous dual-path behavior, where queries using semantic search, tag filters, or state containment filters fell back to the primary data store, has been removed. All entity reads now use the same data source.

  • Removed query parameters - The semantic and tags query parameters have been removed from the entity listing endpoint. Semantic search over entity embeddings and tag-based filtering are no longer available through this endpoint. Callers passing these parameters will receive an error.

  • Removed search_entities_by_state capability - State containment filtering (querying entities by nested state field values) is no longer available. Callers that previously searched for entities by phone number or email via state containment should use the dedicated phone and email filter parameters on the entity listing endpoint instead.

  • New phone and email filter parameters - The entity listing and search endpoints now accept optional phone and email parameters for direct field-level filtering. These replace the previous pattern of filtering by nested state fields.

  • Escalation and safety fields temporarily unavailable on call detail - Call detail responses no longer include escalation, safety, or human_segments data derived from entity state. These fields will return null or empty values until a dedicated projection provides them. Call intelligence data (quality scores, completion reasons, conversation summaries) remains fully available.

  • Dashboard escalation and operator status endpoints return empty results - The active escalation calls and operator availability status dashboard endpoints now return empty results. These will be restored once the underlying data projections are updated to support the new read path.

  • Semantic search endpoint returns empty results - The research query semantic search capability now returns empty results. Entity semantic search via embeddings is not supported on the optimized read path.

  • Data query table name change - The queryable table name for entity data has changed from world.entities to world.entities_synced_v3 in the data query API. The available columns have been updated to reflect the optimized read path schema: canonical_id is replaced by mrn, state is no longer a queryable column, and created_at/updated_at are replaced by last_event_at and projected_at. The tags and embedding columns are no longer available.

  • Operator listing filter change - Operator listing now filters by source origin rather than role-based state filtering. The behavioral result is equivalent for operators created through the platform, but operators created through other channels may not appear in the operator list until they are re-synced.

Who is affected:

  • Callers using the semantic or tags query parameters on entity listing will need to remove these parameters. Semantic search and tag filtering are no longer supported.

  • Callers using state containment queries to find entities by phone or email should migrate to the new phone and email filter parameters.

  • Dashboard integrations that depend on escalation call counts or operator availability status will see empty results until the underlying projections are updated.

  • Data query API consumers referencing the old table name or removed columns will need to update their queries.

  • Call detail consumers should not depend on escalation, safety, or human_segments fields from entity state until these are restored through a dedicated data source.

Breaking changes:

  • semantic query parameter removed from entity listing endpoint.

  • tags query parameter removed from entity listing endpoint.

  • State containment search (search_entities_by_state) removed.

  • Data query table world.entities renamed to world.entities_synced_v3 with updated column set.

  • escalation, safety, and human_segments fields on call detail responses are temporarily empty.

chevron-rightv0.9.472 - Platform API: Session Initialization Performance Improvement (July 2026)hashtag

Session Initialization Performance Improvement

Agent session startup is now significantly faster. Greeting and context injection messages no longer invoke tool resolution, and independent initialization steps now run concurrently instead of sequentially.

What changed:

  • Tool-free greetings and context injection - Greeting and context injection messages now skip tool resolution entirely. These messages operate on patient context that is already fully resolved in the prompt, so tool calls added latency with no informational gain. This eliminates multiple round trips during session startup.

  • Parallel session initialization - Independent initialization steps that were previously sequential - including tool registration across multiple sources and clinical data enrichment - now run concurrently. This reduces startup wall-clock time by overlapping independent operations that do not depend on each other.

  • Startup latency reduction - Together, these changes reduce typical session initialization time from approximately 18 seconds to approximately 3 seconds. The improvement applies to all session types including voice calls, text conversations, and scribe sessions.

  • Partial failure resilience - If any individual initialization step fails during parallel execution, the remaining steps continue to completion. Partial failures are logged for observability but do not block session startup. This improves availability in scenarios where one upstream dependency is temporarily slow or unavailable.

Who is affected:

All users experience faster session startup. No API changes, no behavioral changes to agent responses, and no changes to tool availability during conversations. The agent has the same tools and context available once initialization completes - it simply completes faster.

No breaking changes.

chevron-rightv0.9.471 - Platform API: Patient Extension Fields and Observation Interpretation Normalization (July 2026)hashtag

Patient Extension Fields and Observation Interpretation Normalization

The world model now surfaces additional patient-level fields from FHIR Patient extensions, and observation interpretation values are normalized to standard codes for consistent downstream use.

What changed:

  • New patient entity fields: occupation and health_summary - Patient entities now expose two additional optional fields projected from FHIR Patient extensions. occupation contains the patient's reported occupation as free text. health_summary contains a longer-form health summary narrative. Both fields are nullable strings and appear on entity detail responses and entity listing results.

  • Observation interpretation normalization - Observation entities now normalize free-text interpretation values into standard interpretation codes. Text values like "High", "Critical High", "Low", "Critical Low", "Abnormal", "Suboptimal", and "Poor" are mapped to their standard single-letter equivalents (H, HH, L, LL, A). Text values indicating normal or optimal results are treated as no interpretation flag. Previously, only coded interpretation values were surfaced - free-text interpretation values were ignored.

  • Condition clinical status fallback - Condition entities now derive a clinical status from the verification status when no explicit clinical status is present. Conditions with verification status values indicating confirmed, suspected, or future risk are treated as active. Conditions with a historical verification status are treated as inactive. This improves clinical status coverage for data sources that populate verification status but omit clinical status.

Who is affected:

  • Teams querying patient entities will see the new occupation and health_summary fields in entity responses. These fields are optional and null for patients without the corresponding data.

  • Observation consumers may see interpretation values appear where they were previously null, if the source data used free-text interpretation labels instead of coded values.

  • Condition consumers may see clinical status values appear where they were previously null, if the source data populated verification status but not clinical status.

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

chevron-rightv0.9.470 - Platform API: Entity Filtering by FHIR Resource Type and Voiceprint Deprecation (July 2026)hashtag

Entity Filtering by FHIR Resource Type and Voiceprint Deprecation

The entity listing endpoint now supports filtering by FHIR resource type, making it easier to retrieve only entities that correspond to a specific FHIR resource (e.g. Patient, Practitioner) without relying on entity type alone. Separately, voiceprint enrollment and verification endpoints have been removed.

What changed:

  • fhir_resource_type filter on entity listing - The list entities endpoint now accepts an optional fhir_resource_type query parameter. When provided, results are filtered to entities associated with the specified FHIR resource type (e.g. Patient, Practitioner). This filter can be combined with existing entity type, tag, text search, and other filters. Maximum length is 64 characters.

  • FHIR Patient search uses unified entity model - The FHIR Patient search endpoint now queries person entities filtered by FHIR resource type rather than using a separate patient entity type. This aligns patient search with the unified entity model where patients are person entities with a FHIR Patient resource type association. Search behavior, parameters, and response format are unchanged.

  • Voiceprint endpoints removed - The voiceprint status and verification endpoints now return HTTP 410 Gone. Voiceprint enrollment status checks and speaker verification are no longer available. Clients calling these endpoints should remove voiceprint-related code paths.

Who is affected:

  • Teams using the entity listing endpoint can now filter by FHIR resource type for more precise queries.

  • FHIR Patient search consumers see no change in behavior - the same search parameters and response format continue to work.

  • Any integration relying on voiceprint enrollment status or speaker verification must be updated to remove those calls.

Breaking changes:

  • Voiceprint status and verification endpoints return 410 Gone instead of their previous responses.

chevron-rightv0.9.469 - Platform API: FHIR Import Content-Hash Deduplication (July 2026)hashtag

FHIR Import Content-Hash Deduplication

FHIR import endpoints now detect and skip identical re-uploads automatically. When a FHIR resource is uploaded with the same content as the most recently ingested version, the platform skips event emission entirely instead of creating a duplicate event. This reduces noise in the event stream and avoids unnecessary downstream processing for unchanged data.

What changed:

  • Content-hash deduplication - The FHIR import endpoints (bundle and NDJSON streaming) now compute a content hash for each uploaded resource and compare it against the previously ingested version. If the content is identical, the resource is reported as skipped in the import response rather than emitting a new event. The dedup window extends automatically as long as uploads keep arriving for the same resource.

  • New dedup parameter - Both the bundle import endpoint and the NDJSON streaming endpoint accept a new dedup boolean parameter (default: true). Set to false to force event emission regardless of whether the content has changed. This is useful for workflows that need to guarantee an event is emitted on every upload.

  • Three-state action reporting - The import response now reports three possible actions per resource instead of two:

    • created - first event for this FHIR resource

    • updated - superseded an existing event (content changed)

    • skipped - identical content already current (dedup hit, no event emitted)

  • Supersedes tracking - When a resource is uploaded with changed content, the new event automatically supersedes the previous event for that resource. This provides a clean lineage chain showing how a resource evolved over time.

Who is affected:

  • All FHIR import consumers. The default behavior now skips identical re-uploads. If your workflow depends on an event being emitted for every upload regardless of content, set dedup=false.

  • Import response consumers should handle the new skipped action value. Previously, all successful imports returned created. Now they may return created, updated, or skipped.

  • Downstream event consumers will see fewer duplicate events for unchanged data, which may affect event counts in monitoring dashboards.

No breaking changes. The dedup parameter defaults to true, which changes the default behavior for identical re-uploads from emitting a duplicate event to skipping. If you need the previous behavior, explicitly set dedup=false.

chevron-rightv0.9.468 - Platform API: Python and UDTF Platform Functions (July 2026)hashtag

Python and UDTF Platform Functions

Platform functions now support four function types end-to-end: sql, ai, python, and udtf. Previously, python and udtf were reserved values. They are now fully wired for authoring, deployment, execution, and invocation through the agent tool spec.

What changed:

  • python function type - Register a Python function body with a def main(...) entrypoint. At deploy time, the platform compiles the body into a managed scalar function in the data warehouse's sandboxed runtime. At invocation, the platform calls the deployed function through the warehouse and returns a single typed value. The returns field must be scalar. A new returns_type field lets you declare the scalar return type (string, integer, number, or boolean).

  • udtf function type - Register a Python function body that yields or returns multiple rows. At deploy time, the platform compiles the body into a managed table-valued function in the data warehouse. At invocation, the platform calls the deployed function and returns all rows. The returns field must be table. A new returns_columns field is required, declaring the output schema as a list of {name, type, description} objects.

  • body field replaces sql - The function body field is now canonically named body. The previous name sql continues to work as a legacy alias for backward compatibility. New integrations should use body.

  • returns_type field - New optional field for python functions to declare the scalar return type. Defaults to string. Must remain string for sql, ai, and udtf function types.

  • returns_columns field - New field for udtf functions declaring the output table schema. Each entry specifies a column name, type, and optional description. Required and non-empty for udtf; must be empty for other function types. Maximum 32 columns.

  • Deploy-time validation for Python/UDTF - The deploy pipeline validates that the Python body contains a def main(...) with a signature matching parameters[], rejects *args/**kwargs/keyword-only arguments, and (for UDTFs) verifies the body yields or returns an iterable. The body is then compiled into a managed function in the warehouse - if compilation fails, the deploy is rejected and no version is created.

  • Warehouse-sandboxed execution - Python and UDTF function bodies execute in the data warehouse's own sandboxed runtime, not in the platform process. This provides OS-level isolation, governance, lineage, and audit. Authored code cannot access platform credentials or other workspaces' data.

Who is affected:

  • Teams authoring platform functions can now write Python logic for data transformations, string processing, or multi-row generation that would be awkward in pure SQL.

  • Existing sql and ai functions are unaffected. The sql body field alias continues to work.

  • The body field rename is backward-compatible - no migration is required for existing YAML files or API payloads using sql.

Breaking changes:

  • The returns_type field is validated: setting it to a non-string value on sql, ai, or udtf functions is rejected.

  • The returns_columns field is validated: providing it on sql, ai, or python functions is rejected. Omitting it on udtf functions is rejected.

  • python functions must use returns: scalar. udtf functions must use returns: table. Mismatches are rejected at deploy time.

chevron-rightv0.9.467 - Platform API: Parallel Tool Execution and Patient Lookup Performance (July 2026)hashtag

Parallel Tool Execution and Patient Lookup Performance

Tool calls within a single conversation turn are now executed in parallel instead of sequentially. This reduces turn latency when the agent invokes multiple tools at once - for example, looking up a patient's medications, appointments, and lab results in a single reasoning step. Results are returned in the same order as the original tool calls, so downstream behavior is unchanged.

Patient-scoped clinical resource lookups now use an optimized matching strategy. The platform matches resources to patients using a pre-indexed patient linkage rather than parsing resource content at query time. This improves lookup speed for clinical tools, particularly in workspaces with large volumes of clinical data. A secondary fallback match continues to cover records that have not yet been linked through the primary path.

What changed:

  • Parallel tool execution - When the agent issues multiple tool calls in a single turn, all calls now run concurrently. Previously, tool calls were executed one at a time in sequence. The resolved results maintain the same ordering as the original calls, so downstream processing and callbacks see results in the expected order. Individual tool failures continue to be captured as failed results rather than aborting the entire batch.

  • Faster patient-scoped clinical lookups - Clinical resource queries scoped to a patient (medications, observations, conditions, appointments, etc.) now use a pre-computed patient linkage for matching. This eliminates per-row content parsing during queries, significantly reducing latency for patients with large clinical histories. Resources not yet covered by the pre-computed linkage fall back to an ID-based matching strategy, ensuring no data is missed during the transition.

Who is affected:

  • All voice agent and text session consumers benefit from reduced turn latency when multiple tools fire in the same turn. No API changes are required.

  • Clinical data queries scoped to a patient return the same results faster. No migration is needed.

No breaking changes.

chevron-rightv0.9.466 - Platform API: Outbound Call Use Case Routing (July 2026)hashtag

Outbound Call Use Case Routing

Outbound calls now support use-case-based phone number selection. Instead of specifying a caller ID directly, you can pass a use case ID and the platform automatically selects an outbound phone number bound to that use case. This aligns outbound calling with the same use-case routing model used for inbound calls.

What changed:

  • use_case_id parameter on outbound call creation - The POST outbound call endpoint now accepts an optional use_case_id field (UUID). When provided, the platform selects an outbound phone number associated with the specified use case. The use_case_id and phone_from fields are mutually exclusive - provide one or the other, not both.

  • phone_from is now optional - The phone_from field on outbound call creation is no longer required. You must provide either phone_from (direct caller ID override) or use_case_id (platform-selected number), but not both. If neither is provided, the request is rejected with a validation error.

  • Resolved phone number returned in response - The outbound call creation response now includes a phone_from field containing the phone number that was used for the call. When use_case_id is used, this shows which number was selected. When phone_from is provided directly, the same value is echoed back.

  • setup_id no longer returned - The setup_id field in the outbound call creation response is now always null. Phone number selection is handled internally by the platform and the setup identifier is no longer surfaced to API consumers. The field remains in the response model for backward compatibility.

  • Workspace ownership validation for direct caller ID - When phone_from is provided directly (without use_case_id), the platform validates that the phone number belongs to the calling workspace. When use_case_id is used, workspace ownership is enforced through the use case binding.

Who is affected:

  • Consumers using phone_from directly are unaffected - existing calls continue to work.

  • Consumers that previously resolved phone numbers manually before calling the outbound endpoint can now pass use_case_id instead, letting the platform handle number selection.

  • Consumers reading setup_id from the response should migrate away from this field - it now always returns null.

Breaking changes:

  • setup_id in the outbound call response is now always null. If your integration depends on this value, you need to update your logic.

  • Sending both phone_from and use_case_id in the same request is rejected with a 422 validation error.

  • Sending neither phone_from nor use_case_id is rejected with a 422 validation error.

chevron-rightv0.9.465 - Platform API: Clinical Resource Entity Model Revision (July 2026)hashtag

Clinical Resource Entity Model Revision

Observation and Condition FHIR resources are now standalone entities in the world model instead of being attached to the parent patient timeline. This revision restores Observation and Condition as first-class entities with their own identity, queryable through the standard FHIR resource search and get endpoints. DiagnosticReport is no longer treated as a patient-linked resource type and is excluded from the patient-filterable resource set until a typed read surface is available.

The patient detail read model endpoint (GET /fhir/patients/{patient_id}/detail) has been removed. Consumers that used this endpoint should query individual resource types through the existing FHIR search endpoints instead.

What changed:

  • Observation and Condition restored as standalone entities - Observation and Condition resources now resolve to their own entity rows in the world model rather than being attached to the parent patient entity. Each Observation and Condition gets its own entity ID, and patient linkage is derived at projection time from the FHIR subject or patient reference. Agent tools for observation and condition lookups now query these standalone entity rows directly.

  • Patient detail endpoint removed - The GET /fhir/patients/{patient_id}/detail endpoint has been removed. This endpoint returned a joined read model combining patient demographics, labs, conditions, medications, appointments, and diagnostic reports in a single response. Consumers should use the individual FHIR search endpoints (GET /fhir/{resource_type}) to retrieve related resources for a patient.

  • Observation FHIR reads re-enabled - Observation resources can now be read and searched through the standard FHIR resource endpoints (GET /fhir/Observation, GET /fhir/Observation/{id}). These endpoints were temporarily disabled in a previous release while Observation was served from the patient timeline.

  • DiagnosticReport removed from patient-filterable types - DiagnosticReport is no longer included in the set of FHIR resource types that support patient-scoped filtering. It remains writable through FHIR import but does not have a typed read surface yet.

  • Patient detail response models removed - The response models for the patient detail endpoint (demographics, labs section, conditions section, medications section, diagnostic reports section, and provenance) have been removed from the API schema.

Who is affected:

  • Consumers of GET /fhir/patients/{patient_id}/detail must migrate to individual FHIR search endpoints. This is a breaking change for any integration that depends on the joined patient detail response.

  • Consumers reading Observations through FHIR search endpoints benefit from re-enabled reads without any migration.

  • Agent tool consumers see updated response shapes for observation and condition lookups - responses now include standalone entity IDs instead of the parent patient entity ID, and event IDs are no longer included.

Breaking changes:

  • GET /fhir/patients/{patient_id}/detail has been removed. Returns 404.

  • Observation and condition agent tool responses no longer include event_id or skipped_malformed fields. The entity_id field now contains the standalone entity ID for the specific observation or condition rather than the parent patient entity ID.

  • DiagnosticReport is no longer filterable by patient reference in FHIR search.

chevron-rightv0.9.464 - Platform API: FHIR Import Universal Upsert (July 2026)hashtag

FHIR Import Universal Upsert

FHIR import now always upserts resources regardless of data source type. Previously, only imports from certain source types used upsert behavior - other sources could create duplicate resources when the same data was re-uploaded. Now, every FHIR import - whether from an EHR sync, a file upload, or any other source - supersedes existing records with matching identifiers instead of duplicating them.

This applies to both single-bundle and streaming import paths.

What changed:

  • Universal upsert on FHIR import - All FHIR bundle imports now use upsert semantics. When a resource with a matching identifier already exists in the world model, the import overwrites the existing record rather than creating a new one. This was previously limited to EHR sync sources and now applies uniformly to all import sources.

  • Re-uploads supersede instead of duplicating - Uploading the same FHIR bundle a second time updates the existing resources in place. The result is idempotent - importing identical data multiple times produces the same world model state as importing it once.

Who is affected:

All Platform API consumers using the FHIR import endpoints. If your workflow previously relied on re-uploads creating separate records (e.g., for version tracking through duplicate entries), those imports now overwrite existing records instead. Use the world model event history to track changes over time.

Breaking changes:

None from an API contract perspective - request and response shapes are unchanged. However, the behavioral change means re-uploads no longer produce duplicate records, which may affect consumers that counted on duplication as a side effect.

chevron-rightv0.9.463 - Platform API: Inbound Voice Routing and Use Case Phone Number Pool (July 2026)hashtag

Inbound Voice Routing and Use Case Phone Number Pool

Phone number assignment for inbound voice use cases now automatically configures the underlying telephony provider to route incoming calls directly to the correct use case. Previously, assigning a phone number to an inbound voice use case only created the platform-side binding - operators had to manually configure call routing in the telephony provider. The platform now handles this automatically on assign and cleans it up on unassign.

The use case detail endpoint also now returns the phone numbers currently assigned to a use case, giving consumers a single call to resolve both use case configuration and its active phone number pool.

What changed:

  • Automatic inbound call routing on phone number assignment - When a phone number is assigned to an inbound voice use case, the platform rewrites the phone number's incoming call webhook to route directly to the use case. Inbound calls to that number are delivered to the agent associated with the use case without manual telephony configuration. If the assignment transaction fails after the webhook is updated, the platform automatically reverts the webhook to its previous value.

  • Automatic routing cleanup on phone number unassignment - When a phone number is unassigned from an inbound voice use case, the platform clears the incoming call webhook so the number returns to the provider's default unconfigured state. The same rollback protection applies - if the database transaction fails after the webhook is cleared, the previous webhook URL is restored.

  • New GET /twilio-setup/{setup_id}/credentials endpoint - Returns the sub-account authentication token for a telephony setup. The token is fetched live from the provider (not cached) and is used by the voice infrastructure to verify inbound webhook signatures and authenticate call control operations. Returns 404 if the setup does not exist.

  • Phone numbers included in use case detail response - GET /use-case/{id} now returns a phone_numbers field containing the E.164 phone numbers currently assigned to the use case. For telephony-backed channels (outbound voice, inbound voice, ringless voicemail), this is the active number pool. For email use cases, the field is always empty. The field is present on all use case response variants for uniform response shape. Order is unspecified.

Who is affected:

All Platform API consumers working with inbound voice use cases. Phone number assignment now has a side effect on the telephony provider - the incoming call webhook is rewritten automatically. Consumers that previously configured webhooks manually should stop doing so to avoid conflicts with the platform-managed routing.

Consumers of GET /use-case/{id} receive a new phone_numbers field. The field is additive and defaults to an empty list.

Breaking changes:

None. All changes are additive. Existing phone number assignments for non-inbound-voice channels are unaffected.

chevron-rightv0.9.462 - Platform API: Patient Detail Read Model (July 2026)hashtag

Patient Detail Read Model

A new patient detail endpoint returns a joined, frontend-ready view of a single patient entity and all related clinical resources in one request. Instead of fetching the patient record and then issuing separate calls for labs, conditions, medications, appointments, and diagnostic reports, consumers can now retrieve everything in a single round-trip.

What changed:

  • New GET /patients/{patient_id}/detail endpoint - Returns a composite response containing patient demographics, the FHIR Patient resource, record counts by resource type, and pre-built sections for labs (observations), conditions, medications, appointments, and diagnostic reports. Each section includes items, a total count, a has_more flag for pagination, and a degraded flag indicating whether that section experienced a partial fetch failure. Query parameters section_limit (1-100, default 20) and abnormal_limit (1-50, default 10) control how many items are returned per section and how many abnormal lab results are highlighted.

  • Labs section with abnormal highlighting - The labs section returns two lists: latest (most recent observations up to section_limit) and abnormal (observations flagged with abnormal interpretation codes, up to abnormal_limit). Abnormal detection uses standard clinical interpretation codes (A, AA, H, HH, L, LL, and others) from the observation resource.

  • Unified medication section - Medication statements and medication requests are merged into a single medications section, sorted by effective date. The record_counts field breaks out individual totals for each underlying resource type so consumers can distinguish between the two.

  • Demographic detail - The demographics object includes name, phone, email, birth date, gender, MRN, structured address, preferred language, race, ethnicity, marital status, emergency contact, and insurance information. Fields are populated from entity attributes with fallback to demographic state when direct attributes are not available.

  • Per-item provenance - Every resource item in the response includes a provenance object with source, source system, data source identifier, confidence score, effective timestamp, ingestion timestamp, and last-updated timestamp. A top-level provenance block carries entity-level provenance for the patient record itself.

  • Graceful degradation - If fetching a particular resource type fails, that section is returned empty with degraded: true rather than failing the entire request. The response is always structurally complete.

  • DiagnosticReport added to patient-filterable resource types - DiagnosticReport is now included in the set of FHIR resource types that support patient-scoped filtering, alongside Condition, Encounter, MedicationRequest, AllergyIntolerance, Immunization, and Coverage.

  • Entity lookups now workspace-scoped - Entity reads across CRM (companies, contacts, deals), operator actions, enrichment, and FHIR patient endpoints now include the workspace in the lookup query rather than fetching globally and checking the workspace after the fact. This is a defense-in-depth change with no behavioral difference for correctly-scoped requests.

Who is affected:

All Platform API consumers building patient-facing UIs. The new endpoint eliminates the need for multiple sequential API calls to assemble a patient detail view. Existing endpoints are unchanged.

Breaking changes:

None. The new endpoint is additive.

chevron-rightv0.9.461 - Platform API: Tool Call Duration on Conversation Turns (July 2026)hashtag

Tool Call Duration on Conversation Turns

The conversation turn response now includes execution timing for each tool call, giving callers visibility into how long individual tool executions took without needing to instrument timing independently.

What changed:

  • duration_ms added to tool call details - Each tool call object in the POST /conversations/{id}/turns response now includes a duration_ms field (number or null). The value represents the wall-clock execution time of the tool in milliseconds. The field is null on older turns that did not capture timing - all new turns populated through the live pipeline always include it.

  • Validation on duration_ms - The field enforces a minimum of 0 and a maximum of 3,600,000 (one hour). Values outside this range from upstream processing are treated as invalid and result in a 502 response rather than surfacing misleading data to callers.

  • Streaming events updated - The tool_call_completed streaming event also carries duration_ms with the same semantics, so clients consuming the event stream get timing data in real time.

Who is affected:

All Platform API consumers using POST /conversations/{id}/turns. The new field is additive and nullable - existing integrations that do not read duration_ms are unaffected.

Breaking changes:

None. The new field is optional and defaults to null when not present.

chevron-rightv0.9.460 - Platform API: Patient-Linked Clinical Resources and FHIR Data Integrity (July 2026)hashtag

Patient-Linked Clinical Resources and FHIR Data Integrity

Observation, Condition, DiagnosticReport, and Coverage FHIR resources are now attached to the parent Patient timeline instead of being created as standalone entities. Agent tools for observations and conditions now return results from the patient timeline with richer event-level detail. FHIR data ingestion enforces source system identity on all FHIR events, and the Observation read endpoint is temporarily unavailable while the migration completes.

What changed:

  • Observations and Conditions moved to patient timeline - Observation, Condition, and DiagnosticReport resources are now linked to the parent Patient entity rather than stored as standalone entities. This means patient timelines and patient-detail views show related clinical resources directly on the patient record. The agent tools for observation and condition lookups now query the patient timeline and return both the patient entity_id and a per-result event_id for traceability.

  • Observation and Condition lookup responses updated - The observations_lookup and conditions_lookup agent tools now return entity_id (the patient entity) and event_id (the specific clinical event) in each result item. The event_id is a response reference for traceability - it identifies the specific Observation or Condition event on the patient timeline. A skipped_malformed counter is included in the response to surface data quality issues without silently dropping results.

  • Source system required for FHIR events - All FHIR events ingested through connector and EHR sync sources now require a non-empty source system identifier. Events missing this identifier are rejected before reaching the data pipeline. Non-connector API writes that lack an explicit source system default to the normalized source namespace. This prevents malformed patient references from creating unjoinable records.

  • Observation FHIR read endpoint temporarily unavailable - The GET and search endpoints for Observation resources return HTTP 501 (Not Implemented) while Observations transition from standalone entity reads to patient timeline reads. Other FHIR resource types are not affected.

  • Pipeline data quality enforcement - The data pipeline now enforces that FHIR events carry a valid source system and that Observation events have a non-empty status. Events that fail these checks are dropped before entering the pipeline. Patient-linked resource types (Condition, Coverage, DiagnosticReport, Encounter, MedicationRequest, Observation) are prevented from creating standalone entity rows.

  • FHIR data coercion improvements - FHIR payloads in various runtime formats (JSON strings, nested mappings, and other serialization shapes) are now normalized to plain dictionaries at a single boundary before entity resolution. This fixes edge cases where non-dictionary payloads caused resolution failures or silent data loss.

Who is affected:

All Platform API workspaces that use FHIR Observation or Condition resources. Workspaces using the observations_lookup or conditions_lookup agent tools will see the updated response shape with event_id fields. Workspaces reading Observations through the FHIR GET/search endpoints will receive 501 responses until the timeline-backed read surface is available.

Integrations that emit FHIR events through connector or EHR sync sources must ensure a non-empty source system is provided. API-originated FHIR writes without an explicit source system will have one defaulted automatically.

Breaking changes:

  • The FHIR GET /Observation/{id} and GET /Observation?... search endpoints now return HTTP 501. Use the observations_lookup agent tool or the patient timeline to access Observation data.

  • The observations_lookup response now includes event_id per result and skipped_malformed at the top level. Consumers parsing the response shape should accommodate these new fields.

  • The conditions_lookup response now includes event_id per result and skipped_malformed at the top level.

  • FHIR events from connector and EHR sync sources that lack a source system identifier are now rejected instead of accepted with an empty value.

chevron-rightv0.9.459 - Platform API: Use Case Service Bindings (July 2026)hashtag

Use Case Service Bindings

Use cases are now bound directly to platform services instead of workspaces. This replaces the previous workspace-level binding model with a more precise service-level routing that connects a use case to a specific service within a workspace. Binding a service is now the act of claiming the use case for the workspace - there is no separate workspace-claim step.

What changed:

  • Service-level binding replaces workspace binding - Use cases are now bound to a specific platform service rather than a workspace directly. The binding carries the workspace context through the service, so inbound webhook events still resolve to the correct workspace. Outbound dispatch from a service routes through the bound use case for its channel.

  • New PUT endpoint for binding - A new PUT /{use_case_id}/service-binding endpoint replaces the previous POST /{use_case_id}/bindings endpoint. The request body accepts a service_id to bind. PUT semantics mean rebinding the same use case to a different service replaces the prior binding. Returns 409 if a different use case already binds the same service and channel pair. Returns 404 if the service or use case is not found or belongs to another workspace.

  • New GET endpoint for binding - A new GET /{use_case_id}/service-binding endpoint returns the current service binding for a use case in the workspace, or 404 if unbound. Requires Channel.view permission.

  • Updated DELETE endpoint - The unbind endpoint has moved from DELETE /{use_case_id}/bindings to DELETE /{use_case_id}/service-binding. Behavior is the same: soft-delete of the binding row, 404 if not currently bound.

  • Richer binding response - The binding response now includes service_id, created_at, and updated_at fields in addition to use_case_id, workspace_id, and channel.

  • Channel values updated - The channel discriminator now uses the upstream values directly (inbound_voice, outbound_voice, ringless_voicemail, email) instead of the previously collapsed set (voice, voicemail, email).

  • Delete preflight updated - Deleting a use case now checks for active service bindings instead of workspace bindings. The error message reflects this: "Use case is bound to a service; unbind it first."

Who is affected:

All Platform API workspaces using the use case binding endpoints. The previous POST/DELETE /{use_case_id}/bindings endpoints are replaced by PUT/GET/DELETE /{use_case_id}/service-binding. Existing integrations that bind use cases to workspaces need to update to provide a service_id in the binding request.

Breaking changes:

  • The POST /{use_case_id}/bindings endpoint is removed. Use PUT /{use_case_id}/service-binding with a service_id body instead.

  • The DELETE /{use_case_id}/bindings path has changed to DELETE /{use_case_id}/service-binding.

  • The binding response model has changed: new fields service_id, created_at, updated_at; all ID fields are now UUIDs instead of strings.

  • Channel values have changed from voice/voicemail/email to inbound_voice/outbound_voice/ringless_voicemail/email.

chevron-rightv0.9.458 - Platform API: Skill Tier Realignment for Disabled Autonomous and Browser Skills (July 2026)hashtag

Skill Tier Realignment for Disabled Autonomous and Browser Skills

Disabled skills that were previously configured as autonomous or browser execution tiers are now automatically realigned to a supported tier. This ensures that re-enabling a skill does not result in unexpected autonomous or browser behavior.

What changed:

  • Automatic tier reassignment - Skills that are currently disabled and were set to the autonomous or browser execution tier have been moved to a standard supported tier. When these skills are re-enabled, they will execute at the reassigned tier rather than the previously configured autonomous or browser tier.

  • No action required - This change applies automatically to all affected skills across all workspaces. Skills that are currently enabled or set to other execution tiers are not affected.

Who is affected:

All Platform API workspaces that had disabled skills configured with autonomous or browser execution tiers. No manual configuration changes are needed.

No breaking changes.

chevron-rightv0.9.457 - Platform API: Graceful Handling of Unsupported Phone Number Types (July 2026)hashtag

Graceful Handling of Unsupported Phone Number Types

The phone number search and provisioning endpoints now return empty results instead of errors when a requested number type is not available for a given country.

What changed:

  • Search returns empty instead of failing - When searching for available phone numbers, if the requested number type (local, mobile, toll-free, or national) is not enabled for the selected country, the API now returns an empty list instead of an error. Previously, requesting an unsupported number type for a country could result in an unexpected error response. This makes it safe to search across all number types without needing to know in advance which types each country supports.

  • Provisioning returns a clear conflict - When attempting to provision a phone number whose number type is not available for the selected country, the API now returns a 409 conflict ("number not available") instead of an unexpected error. This is consistent with the behavior when a specific number is simply not available for purchase.

Who is affected:

All Platform API workspaces using the phone number search or provisioning endpoints. No configuration changes required. Clients that previously handled errors from unsupported number type and country combinations can simplify their error handling.

No breaking changes.

chevron-rightv0.9.456 - Platform API: Patient Lookup by Entity ID (July 2026)hashtag

Patient Lookup by Entity ID

The patient lookup tool now accepts a direct entity ID for instant patient resolution, eliminating the need for search-based matching when the entity identifier is already known from conversation context.

What changed:

  • Direct entity ID lookup - Patient lookup now supports an optional entity ID parameter. When provided, the tool resolves the patient record directly by ID rather than searching by name, date of birth, phone number, or medical record number. This is the fastest lookup path and is used automatically when the agent already has an entity reference from context graph bindings or prior conversation state.

  • Graceful fallback - If the entity ID does not resolve to a valid patient record, the tool falls back to the standard search parameters (identifier, date of birth, name, phone number). Existing lookup behavior is unchanged when no entity ID is provided.

Who is affected:

All Platform API workspaces using the patient lookup tool. No configuration changes required. Agents that already have entity context will automatically use the faster lookup path.

No breaking changes.

chevron-rightv0.9.455 - Platform API: Connector Content-Hash Deduplication for Availability and Booking Preferences (July 2026)hashtag

Connector Content-Hash Deduplication for Availability and Booking Preferences

The connector framework now applies content-hash deduplication to availability and booking preference polling, eliminating redundant event emission when upstream data has not changed.

What changed:

  • Content-hash dedup for availability polling - Each availability poll now checks whether the payload has changed since the last emission before writing an event. If the content hash matches, the record is skipped. This eliminates the amplification previously observed during steady-state polling, where every cycle re-emitted identical records.

  • Content-hash dedup for booking preference polling - Booking preference polls now use the same content-hash dedup flow. Unchanged records are suppressed, and the visit-types cache is refreshed regardless of whether the record was emitted, keeping downstream enrichment lookups warm.

  • Accurate emission counts - Poll outcome metrics now reflect actual emissions rather than poll attempts. Records suppressed by dedup report zero emissions, giving operators a precise view of data throughput versus polling activity.

Who is affected:

All Platform API workspaces using connectors that poll availability or booking preference endpoints. No configuration changes required. Event consumers see fewer duplicate events. Dedup state is managed automatically.

No breaking changes.

chevron-rightv0.9.454 - Platform API: Clinical Detection Loop Prevention (July 2026)hashtag

Clinical Detection Loop Prevention

The clinical detection pipeline now prevents self-triggering loops where detection-generated events re-enter the pipeline and produce duplicate results on every refresh cycle.

What changed:

  • Source-based filtering - Clinical detection now excludes events that were written by the detection pipeline itself. Previously, every analysis event generated by a detection rule re-entered the pipeline on the next refresh, triggering its own rule again and producing duplicate detections that grew with each cycle.

  • Deterministic detection identifiers - Each detection result now carries a stable identifier derived from its type, workspace, entity, and event attributes. This identifier remains consistent across pipeline refreshes, allowing downstream consumers to recognize previously processed detections even when other metadata changes between refreshes.

  • Downstream dedup - The detection sync process uses the stable detection identifier to skip detections it has already processed. Detections that have been seen within a configurable window are not re-emitted, preventing duplicate downstream events. The dedup mechanism is fail-open - if the dedup check is unavailable, detections are processed normally rather than dropped.

Who is affected:

All Platform API workspaces using clinical detection. No configuration changes required. Workspaces that previously experienced duplicate analysis events will see a significant reduction in duplicate detections.

No breaking changes.

chevron-rightv0.9.453 - Platform API: Restricted Query Execution Role (July 2026)hashtag

Restricted Query Execution Role

User-submitted SQL queries and query tool executions now run under a restricted database role that limits operations to the minimum required privileges, adding a defense-in-depth layer beyond row-level security.

What changed:

  • Restricted execution role for ad-hoc queries - When a workspace SQL query is executed (via the API, CLI, or Developer Console SQL editor), the platform now switches to a restricted role scoped to the current transaction before running the query. This role can only read from the world model entity table and read, insert, update, or delete rows in workspace custom tables. It cannot create or drop tables, alter schemas, or access platform-internal tables. The restriction is transaction-scoped and resets automatically when the query completes.

  • Restricted execution role for query tools - Query tool execution during agent sessions now uses the same restricted role. This ensures that even if a query tool's SQL is broader than intended, the database enforces a hard boundary on what operations are permitted.

  • No behavioral changes for valid queries - Queries that read from world model entities or operate on custom tables continue to work identically. Only queries that attempt operations outside these boundaries - such as accessing platform-internal tables or performing schema modifications - are now blocked at the database level rather than relying solely on application-level validation.

Who is affected:

All Platform API workspaces using ad-hoc SQL queries or query tools. No configuration changes required. Queries that were valid before remain valid. Queries that attempted out-of-scope operations will now receive a permission error.

No breaking changes.

chevron-rightv0.9.452 - Platform API: Synced Entity Store Schema Alignment (July 2026)hashtag

Synced Entity Store Schema Alignment

The synced entity store now reads from a schema-aligned data source that mirrors the upstream catalog structure, replacing the previous flat table layout.

What changed:

  • Schema-aligned reads - The read path for synced clinical entities now uses a data source whose schema matches the upstream data catalog. Previously, the synced entity store read from a flat table in a shared namespace. The new layout places synced entities in a namespace that mirrors the catalog structure, improving clarity and reducing the risk of naming collisions as the number of synced tables grows.

  • No behavioral changes - Entity queries, platform function lookups, and all downstream consumers continue to work identically. The data shape, column types, and query semantics are unchanged. This is a storage-layer alignment only.

Who is affected:

No user-facing changes. All Platform API workspaces using clinical entities, platform functions, or the world model continue to work without modification.

No breaking changes.

chevron-rightv0.9.451 - Platform API: Workspace Query Tool Discovery at Session Start (July 2026)hashtag

Workspace Query Tool Discovery at Session Start

Workspace query tools are now automatically discovered and registered when a session starts, making them available to the agent without any additional configuration.

What changed:

  • Automatic tool discovery - When a voice or text session starts, the platform loads all enabled query tools defined for the workspace and registers them as callable tools the agent can invoke during the conversation. Previously, query tools were only manageable through the API but were not available to the agent at runtime.

  • Read-only validation at load time - Each query tool's SQL is validated for read-only safety when the session starts. Tools with queries that do not pass validation are skipped and logged, ensuring that only safe read operations are exposed to the agent.

  • Row-level security scoping - Query tool execution is scoped to the workspace's data boundary using row-level security. The agent cannot access data outside the workspace, even if the stored query does not explicitly filter by workspace.

  • Execution constraints - Query tool execution is time-bounded and result sets are capped to stay within real-time conversation latency requirements. If a query exceeds the execution limit, it returns a structured error rather than blocking the conversation turn.

  • Parameterized execution - Query tools accept declared parameters from the agent and bind them safely to the stored query. Undeclared parameters are ignored.

Who is affected:

All Platform API workspaces with enabled query tools. Query tools created through the API or CLI are now automatically available to agents during sessions. No additional configuration is required beyond creating and enabling the query tool.

No breaking changes.

chevron-rightv0.9.450 - Platform API: Self-Refreshing Connector Deduplication (July 2026)hashtag

Self-Refreshing Connector Deduplication

Connector deduplication cache entries now self-refresh on every poll cycle where the record content is unchanged, eliminating redundant writes caused by fixed-duration cache expiry.

What changed:

  • Self-refreshing cache lifetime - When a connector polls a record and its content matches the cached hash, the cache entry's lifetime is automatically extended. Previously, cache entries expired on a fixed 24-hour schedule regardless of polling activity. This caused unchanged records to re-enter the data pipeline after expiry, producing 7-13x write amplification on clinical data adapters even when the underlying data never changed.

  • Extended base cache lifetime - The default cache lifetime has been increased from 24 hours to 30 days. Combined with self-refreshing behavior, this protects against data loss in scenarios where polling is paused for extended periods (e.g., a workspace is suspended for several days and then resumes). The cache entry survives the pause and prevents a full re-sync on restart.

  • Input validation on cache keys - The deduplication layer now validates that all key components (workspace, data source, and record identifier) are non-empty before constructing a cache key. Previously, empty components could produce colliding keys across workspaces. Invalid inputs now raise an immediate error with a diagnostic message indicating which components were empty, without exposing the raw values.

  • Graceful degradation on cache refresh failure - If the cache lifetime refresh fails due to a transient connection issue, the system continues without error. At worst, the affected record re-enters the pipeline on the next poll cycle, which is safe because downstream projections are idempotent.

Who is affected:

All Platform API workspaces using connectors. This is a behavioral improvement with no API surface changes. Workspaces with high-volume clinical data sources (FHIR adapters, EHR connectors) will see the most significant reduction in redundant writes.

No breaking changes.

chevron-rightv0.9.449 - Platform API: Workspace Lakebase - Fork, Query, and Tool Routes (July 2026)hashtag

Workspace Lakebase - Fork, Query, and Tool Routes

Workspaces now have built-in data exploration capabilities. Three new route groups let you create sandbox database forks, execute validated SQL queries against workspace data, and define reusable query tools that the reasoning engine can call during conversations.

What changed:

  • Fork lifecycle - New endpoints to create, inspect, and destroy sandbox forks of the workspace data layer. Forks provide an isolated environment for experimentation with a configurable time-to-live (1 to 30 days). Only one fork can exist per workspace at a time. Creating a fork when one already exists returns a conflict error.

  • Query execution - A new endpoint executes SQL queries against the workspace data layer with built-in validation and a 30-second execution timeout. Results are capped at 1,000 rows. The SQL validator enforces safety rules: multi-statement queries are rejected, privilege escalation is blocked, and write operations on the shared data layer are restricted to the custom schema. DDL operations are not permitted on the shared data layer.

  • Query tools (CRUD) - Five new endpoints for managing reusable query tools: create, list, update, delete, and test. Query tools are parameterized SQL templates that agents can invoke mid-conversation to retrieve data. Each tool's SQL is validated on creation and update. The test endpoint executes a tool with sample parameters and returns results, verifying that the query works before it is used in production. Undeclared parameters are rejected during testing.

  • Workspace data layer endpoint - Workspaces now track a data layer connection endpoint, enabling fork routing and query execution against the correct data source.

New endpoints:

Method
Path
Description

POST

/v1/{workspace_id}/fork

Create a sandbox fork

GET

/v1/{workspace_id}/fork

Get fork status

DELETE

/v1/{workspace_id}/fork

Destroy fork

POST

/v1/{workspace_id}/lakebase/query

Execute SQL query

POST

/v1/{workspace_id}/query-tools

Create a query tool

GET

/v1/{workspace_id}/query-tools

List query tools

PATCH

/v1/{workspace_id}/query-tools/{tool_id}

Update a query tool

DELETE

/v1/{workspace_id}/query-tools/{tool_id}

Delete a query tool

POST

/v1/{workspace_id}/query-tools/{tool_id}/test

Test a query tool

Who is affected:

All Platform API workspaces. These are new additive endpoints. No existing behavior is changed.

No breaking changes.

chevron-rightv0.9.448 - Platform API: Modular FHIR Extension Registry and Vitals Columns (July 2026)hashtag

Modular FHIR Extension Registry and Vitals Columns

The entity data pipeline now supports a config-driven extension registry that automatically promotes FHIR extensions into typed, queryable columns on the entity snapshot. The first extensions wired through this registry add patient vitals - height, weight, and BMI - to the demographics projection.

What changed:

  • Extension registry - A new declarative registry maps FHIR extension URLs to typed columns on entity projections. Adding a new extension column requires only a configuration entry specifying the extension URL, target column name, value type (string, decimal, boolean, or integer), and destination projection. No code changes are needed. The registry currently supports string, decimal, boolean, and integer extraction patterns.

  • Patient vitals columns - Three new columns are now available on the entity snapshot for patients: height (cm), weight (kg), and BMI. These values are extracted from FHIR extensions emitted by connected clinical data sources that follow the standard extension value conventions. The columns are nullable and populated automatically on the next pipeline run.

  • Decimal and boolean extension extraction - The projection engine now supports extracting numeric (decimal) and boolean values from FHIR extensions, in addition to the existing string extraction. Decimal values are cast to floating-point numbers for direct comparison and filtering. Boolean values are extracted natively without string conversion.

  • Entity snapshot updated - The entity snapshot includes the new vitals columns, so platform functions, agent tools, and downstream analytics consumers can access patient vitals directly from the projected entity view.

Who is affected:

All Platform API workspaces with patient demographic data. New columns are nullable and populated on the next data pipeline run. Existing integrations are unaffected.

No breaking changes.

chevron-rightv0.9.447 - Platform API: FHIR Query Performance - Typed Column Reads (July 2026)hashtag

FHIR Query Performance - Typed Column Reads

FHIR resource queries now read exclusively from typed, indexed columns instead of parsing stored resource payloads at query time. This completes another phase of the structured data migration for FHIR reads, improving query performance and consistency across all FHIR resource endpoints.

What changed:

  • Practitioner identification uses typed columns only - Practitioner vs. Patient disambiguation for person-type entities now relies entirely on typed NPI and specialty columns. Previously, the query could also fall back to inspecting the stored resource payload. Removing that fallback path simplifies the query plan and ensures consistent behavior across all workspaces.

  • Patient-scoped resource filtering uses typed columns - Queries that filter clinical resources by patient reference (Appointments, Conditions, Observations, Medication Statements, and other clinical types) now use dedicated typed columns for the patient relationship. Appointment queries match on the typed patient reference column, while all other clinical resource types match on the typed linked patient identifier column. This replaces the previous approach of parsing nested references from stored resource payloads at query time.

  • Unified patient filter path - Clinical resource types that previously required separate filter logic for subject, patient, and beneficiary reference styles are now handled through a single typed column. This simplifies the query path and ensures consistent performance regardless of how the source system structured the patient reference.

Who is affected:

All Platform API workspaces using FHIR resource queries. No configuration changes required. Query behavior is unchanged - the same filters return the same results, but queries execute against indexed columns instead of parsing stored payloads.

No breaking changes.

chevron-rightv0.9.446 - Platform API: Typed Columns for Clinical Entity Details (July 2026)hashtag

Typed Columns for Clinical Entity Details

Clinical entities in the world model now expose key clinical details as typed, queryable columns instead of requiring consumers to parse the raw FHIR resource. This is the first phase of structured clinical data extraction, covering observations, medications, allergies, clinical notes, and family history.

What changed:

  • Observation detail columns - Observation entities now include dedicated columns for numeric value, unit, interpretation code, reference range low, reference range high, and category. Numeric values are stored as floating-point numbers, enabling direct comparison and range-based filtering without parsing the resource payload.

  • Medication statement detail columns - Medication statement entities now surface dosage instructions and clinical notes as text columns. Previously, this information was only accessible by parsing the full resource.

  • Allergy intolerance detail columns - Allergy entities now expose reaction description and severity as dedicated columns. Reaction text falls back gracefully between coded and free-text representations.

  • Clinical note detail columns - DocumentReference entities now include note type and note date as typed columns, extracted from the resource type and date fields.

  • Family history detail columns - Family history entities now expose the relationship descriptor as a typed column, with fallback between text and coded representations.

  • Resource type discriminator - All clinical entities now carry a resource type field, making it possible to filter and route entities by clinical type without inspecting the resource payload.

  • Entity snapshot updated - The entity snapshot includes all new typed columns, so platform functions, agent tools, and downstream analytics consumers can access clinical details directly from the projected entity view.

Who is affected:

All Platform API workspaces with clinical data. New columns are nullable and populated on the next data pipeline run. Existing integrations are unaffected - the full FHIR resource blob remains available alongside the new typed columns.

No breaking changes.

chevron-rightv0.9.445 - Platform API: Patient-Scoped Resource Identity and Clinical Status Resilience (July 2026)hashtag

Patient-Scoped Resource Identity and Clinical Status Resilience

Two data-integrity improvements in this release: clinical resource identifiers are now globally unique across patients, and clinical status extraction is more resilient when source data uses varying formats.

What changed:

  • Patient-scoped resource identifiers - Clinical resource IDs (observations, medications, conditions, family history, questionnaire responses, and clinical notes) ingested from external data sources are now prefixed with the patient identifier before entity resolution. Previously, resource IDs were only unique within a single patient's record. If two patients shared the same raw resource ID, the platform's entity resolution would collapse them into a single entity, silently dropping one patient's data. Resource IDs are now globally unique across patients within a workspace, producing distinct entity IDs and preventing cross-patient data loss.

  • Deduplicated source records before clinical resource expansion - The ingestion pipeline now deduplicates source records per patient before expanding clinical resource arrays. Previously, duplicate source rows (e.g. from re-uploads with the same modification time) could multiply into N duplicate clinical resource events per resource. Deduplication now happens at the patient level before array expansion, preventing duplicate events from propagating into downstream data stores.

  • Resilient clinical status extraction - Entity projections for conditions, observations, medication statements, and related clinical types now fall back gracefully when clinical status is provided in different formats. If the structured coded representation is not present, the platform extracts status from the text representation instead. This prevents clinical status from appearing blank on entities ingested from sources that use simpler status formats.

  • Condition clinical status enrichment - Condition resources now include a structured coded clinical status alongside the text representation. This aligns condition data with the FHIR clinical status coding convention, improving interoperability with downstream systems that expect coded status values.

  • Agent clinical data lookups use projected status - When the agent retrieves observations, medication statements, clinical notes, or questionnaire responses during a conversation, the lookup now falls back to the entity's projected clinical status if the FHIR resource does not contain an inline status field. This ensures that status information is always available to the agent regardless of how the source system encoded it.

Who is affected:

All Platform API workspaces that ingest clinical data from external sources. Existing entities with colliding resource IDs across patients will be resolved to separate entities on the next data sync. No configuration changes required.

No breaking changes.

chevron-rightv0.9.444 - Platform API: Explicit Use Case Binding and Unbinding (July 2026)hashtag

Explicit Use Case Binding and Unbinding

Use case lifecycle now separates creation from workspace ownership. Creating a use case no longer automatically associates it with the calling workspace. Instead, two new endpoints let you explicitly bind and unbind use cases, giving you full control over which workspace receives inbound events for a given use case.

What changed:

  • Bind use case endpoint - A new POST /v1/{workspace}/use-cases/{use_case_id}/bindings endpoint claims a use case for a workspace. Inbound webhook events (email delivery notifications, SMS status callbacks, voice events) for that use case will resolve to this workspace. The endpoint is idempotent for the same workspace. If the use case is already bound to a different workspace, the request returns 409 Conflict. If a previous binding was removed, the new bind revives it and points it at the calling workspace. Requires Channel create permission.

  • Unbind use case endpoint - A new DELETE /v1/{workspace}/use-cases/{use_case_id}/bindings endpoint releases a use case from a workspace. After unbinding, inbound events for that use case no longer resolve to any workspace until it is re-bound. Returns 404 if the use case is not currently bound to the calling workspace. Requires Channel delete permission.

  • Create no longer auto-binds - The create use case endpoint (POST /v1/{workspace}/use-cases) now only creates the use case upstream. It does not automatically bind the use case to the calling workspace. Callers must explicitly POST to the bindings endpoint after creation to associate the use case with their workspace.

  • Delete requires unbinding first - The delete use case endpoint (DELETE /v1/{workspace}/use-cases/{use_case_id}) now returns 409 Conflict if the use case is still bound to any workspace. You must unbind the use case before deleting it. This prevents orphaned bindings that would route inbound events to a workspace for a use case that no longer exists upstream.

  • Inbound event resolution updated - The internal webhook event resolver now uses the use case identifier directly to determine which workspace should receive an event, replacing the previous provider-specific setup identifier lookup. This simplifies the resolution path and aligns it with the explicit binding model.

Binding response schema:

Field
Type
Description

use_case_id

string (UUID)

The bound use case identifier

workspace_id

string (UUID)

The workspace that owns the binding

channel

string

Channel type: voice, voicemail, or email

Who is affected:

All Platform API workspaces that create use cases. If your integration relies on use cases being automatically associated with the workspace at creation time, you must add an explicit bind call after creation. Existing use cases that were auto-bound before this release are unaffected - their bindings remain active.

Breaking changes:

  • Creating a use case no longer binds it to the workspace. Callers must explicitly bind after creation.

  • Deleting a use case now fails with 409 if it is still bound. Callers must unbind before deleting.

chevron-rightv0.9.443 - Platform API: Transport Close Details and Simulation Case Library Endpoints (July 2026)hashtag

Transport Close Details and Simulation Case Library Endpoints

Two improvements in this release: voice call records now capture structured transport close details, and two new endpoints let you browse and inspect durable simulation cases.

What changed:

  • Transport close details on call records - When a voice call ends, the platform now records structured details about how the transport layer closed. This includes the close source (client-initiated, network disconnect, or protocol error), any close code provided by the caller's client, and a sanitized close reason when available. These details appear on call intelligence records, call-ended events, and post-call analysis data. This gives you precise visibility into whether a call ended because the caller hung up, the network dropped, or the client sent an explicit stop signal - information that was previously only available as a single completion reason string.

  • Post-call analysis merge - Post-call analysis results are now merged additively into existing call analysis data rather than replacing it. If transport close details were already recorded during call teardown, subsequent analysis results are combined with them instead of overwriting. This ensures that infrastructure-measured close details are always preserved alongside LLM-generated analysis.

  • List simulation cases endpoint - A new GET /simulations/cases endpoint returns a paginated list of durable simulation cases for a workspace. You can filter by service ID and by tags (up to 20). This supports case library browsing in dashboards and CI pipelines that need to discover available test cases programmatically.

  • Get simulation case endpoint - A new GET /simulations/cases/{case_id} endpoint returns a single simulation case by ID. The response includes the full case definition: persona, scenario instructions, initial message, temperament, fixtures, constraints, target specification, assertions, tags, and provenance.

Who is affected:

All Platform API workspaces. Transport close details are recorded automatically with no configuration changes. The new simulation case endpoints require the service view permission. Existing integrations are not affected.

No breaking changes to any API endpoints or response schemas.

chevron-rightv0.9.442 - Platform API: Entity Binding for Simulation Sessions (July 2026)hashtag

Entity Binding for Simulation Sessions

Simulation session creation now accepts an optional entity ID, allowing you to bind a specific patient entity to a simulation session. This gives simulated conversations access to the same patient context resolution that production calls use, so you can test agent behavior against real entity data in your workspace.

What changed:

  • Entity ID on session creation - The simulation session creation endpoint now accepts an optional entity_id parameter (UUID). When provided, the session resolves patient context from the specified entity, giving the agent access to the entity's clinical data, demographics, and linked records during the simulation. This applies to both simulation run sessions and standalone test conversations.

  • Workspace-scoped resolution - Entity IDs are resolved within the scope of the workspace that owns the simulation. An entity ID from a different workspace resolves to nothing, ensuring no cross-tenant data exposure.

  • No impact on existing sessions - The entity_id parameter is optional and defaults to none. Existing simulation sessions that do not specify an entity ID continue to work exactly as before.

Who is affected:

All Platform API workspaces using simulations. This is an additive change. Existing integrations are not affected.

No breaking changes to any API endpoints or response schemas.

chevron-rightv0.9.441 - Platform API: Surface Status Returns Submitted Data (July 2026)hashtag

Surface Status Returns Submitted Data

The check_surface_status tool now returns the data a patient submitted when a surface is completed, along with additional lifecycle timestamps. Previously, checking surface status returned the lifecycle state but not the actual submission payload, requiring a separate lookup to retrieve what the patient entered.

What changed:

  • Submitted data included on completion - When a surface reaches the completed status, the status response now includes the full submitted data payload. This lets agents immediately act on patient-provided information - confirming answers, extracting clinical details, or branching conversation logic - without an additional API call.

  • Lifecycle timestamps - The status response now includes delivery, open, and submission timestamps in addition to the creation timestamp that was already present. These timestamps give agents and downstream analytics precise visibility into how long each stage of the surface lifecycle took.

  • Tool description updated - The check_surface_status tool description now documents that submitted data is returned when the surface is completed, so agents can reason about the availability of submission data based on the lifecycle status.

Who is affected:

All Platform API workspaces using surfaces. The additional fields are additive. Existing integrations that consume surface status responses will continue to work without changes. Agents that previously made separate calls to retrieve submitted data can now read it directly from the status response.

No breaking changes to any API endpoints or response schemas.

chevron-rightv0.9.440 - Platform API: Snapshot-Diff Sync for Reference Data (July 2026)hashtag

Snapshot-Diff Sync for Reference Data

Connector sync for slow-changing reference data (payers, facilities, visit types, fee schedules, staff) now uses snapshot-diff semantics instead of emitting every record on every poll cycle. The connector compares each poll response against the prior snapshot and emits only items that were created or updated since the last sync.

What changed:

  • Snapshot-diff for lookup-table endpoints - Reference data endpoints that return the full current roster on every poll cycle now diff against the previously seen snapshot. Only new and changed items are emitted as events. Unchanged items are skipped entirely, reducing redundant processing for data that changes infrequently.

  • Deletion detection - Items present in the prior snapshot but absent from the current response are detected and tracked. In this initial release, removals are logged and counted but not emitted as events. Removal-event emission will land per resource type as downstream projections gain explicit removal handling.

  • Fail-open on state unavailability - If the persisted snapshot is unavailable (first sync, state loss, or infrastructure error), the connector treats all items as updates. This matches the previous behavior where every record was emitted every cycle, ensuring no data is silently dropped.

  • Atomic state transitions - The snapshot pointer is updated only after all created and updated events have been successfully delivered. If event delivery fails or times out, the snapshot is not advanced, and the next poll cycle re-emits the current items. This guarantees at-least-once delivery without requiring downstream idempotency beyond what already exists.

  • Bounded state lifecycle - Snapshot state for each workspace, data source, and resource type is retained with a long expiration window and refreshed on every successful sync. State for deleted or inactive workspaces is automatically cleaned up.

Who is affected:

All Platform API workspaces with connected EHR integrations that sync reference data. The change is transparent - no configuration changes are required. Workspaces will see significantly fewer redundant events for reference data endpoints, reducing downstream processing volume.

No breaking changes to any API endpoints or response schemas.

chevron-rightv0.9.439 - Platform API: Get Use Case by ID (July 2026)hashtag

Get Use Case by ID

The channel manager now exposes an endpoint to fetch a single use case by its identifier, complementing the existing list endpoint. This enables callers to retrieve authoritative use case details - including channel type, setup binding, and configuration - without filtering a full list response.

What changed:

  • New GET endpoint for individual use cases - A new endpoint accepts a use case ID and returns the full use case resource, including its channel-specific binding (email or voice). If the use case does not exist or has been soft-deleted, the endpoint returns 404. This gives callers a clear distinction between "use case not found" and "service unreachable," enabling proper error handling (404 vs 502) in upstream workflows.

  • Response matches list endpoint shape - The response structure for the new endpoint is identical to individual items returned by the list endpoint. Email use cases include setup ID, configuration set name, sender address, email type, tier, unsubscribe eligibility, and cold inbound acceptance. Voice use cases include setup ID and channel type (outbound voice, inbound voice, or ringless voicemail).

  • List endpoint query improvements - The existing list use cases endpoint now uses more efficient query construction internally. No changes to request parameters, response shape, or filtering behavior.

  • Client library updated - The platform client library includes a new method for fetching a single use case by ID. The method returns the use case resource on success, returns nothing when the use case is not found (404), and raises on transport or server errors.

Who is affected:

All Platform API consumers working with use cases. The new endpoint is additive. No breaking changes to existing endpoints or response schemas.

chevron-rightv0.9.438 - Platform API: SES Setup Shared Across Workspaces (July 2026)hashtag

SES Setup Shared Across Workspaces

SES email channel setups are now shared platform-wide rather than scoped to individual workspaces. A single setup can serve use cases bound to multiple workspaces, removing the previous restriction that tied each setup to the workspace that created it.

What changed:

  • Setups are no longer workspace-scoped - The SES setup endpoints still include the workspace segment in the URL for backward compatibility, but the workspace is no longer used to filter or restrict access. Any caller with the appropriate channel permission can list, view, create, or delete any SES setup on the platform.

  • List endpoint returns all setups - The list SES setups endpoint now returns every setup on the platform, not just those created by the current workspace. Results are paginated and sorted deterministically.

  • Delete no longer soft-deletes a workspace binding - Deleting an SES setup tears down the upstream tenant and identity directly. The previous soft-delete of a workspace-level ownership record has been removed. The endpoint still returns 409 if the setup has active use cases.

  • Cross-workspace visibility - GET and verify endpoints return setup details regardless of which workspace created the setup. Previously, requesting a setup created by a different workspace returned 404.

Who is affected:

All Platform API consumers using the SES email channel setup endpoints. Callers that previously relied on workspace-level isolation of setups should be aware that all setups are now visible platform-wide. Permission checks (Channel.create, Channel.view, Channel.delete) still apply.

No breaking changes to request or response schemas. The workspace segment in the URL is retained for compatibility but is functionally inert for these endpoints.

chevron-rightv0.9.437 - Platform API: Text Session Entity Binding and Streaming Tool Call Identifiers (July 2026)hashtag

Text Session Entity Binding and Streaming Tool Call Identifiers

Text sessions now correctly bind entity context at conversation start, and SSE streaming events for tool execution include a stable call identifier for correlating tool start and tool end events.

What changed:

  • Entity context binding on text sessions - Text conversations (both batch and streaming) now bind the workspace context at session start, ensuring that entity lookups and patient resolution work correctly throughout the conversation. Previously, text sessions could fail to resolve entity data when the workspace context was not established early enough in the request lifecycle.

  • Tool call identifier on SSE events - The tool_start and tool_end Server-Sent Events emitted during streaming text interactions now include a call_id field. This identifier is stable across the start and end events for the same tool invocation, allowing clients to correlate which tool completion corresponds to which tool invocation when multiple tools execute in parallel or sequence.

  • Observations lookup returns coding metadata and identifiers - The observations lookup tool now returns additional fields: code_system (the terminology system for the observation code), code_value (the coded value within that system), and identifiers (the list of business identifiers associated with the observation). These fields give agents and downstream consumers richer context for interpreting clinical observations.

  • Entity reads use synced projection for all lookup paths - Patient lookup by phone and patient lookup by ID now both read from the synced entity projection, consistent with the change introduced in v0.9.435 for other entity lookup tools. This completes the migration of all entity read paths to the synced store.

Who is affected:

All Platform API consumers using text sessions (batch or streaming) with entity context. Consumers parsing SSE tool events will see the new call_id field on tool_start and tool_end events. Consumers using the observations lookup tool will see three new fields in the response. All changes are additive.

No breaking changes.

chevron-rightv0.9.436 - Platform API: Per-Turn Context Window Policy (July 2026)hashtag

Per-Turn Context Window Policy

The agent engine's context window management now bases compaction decisions on the actual prompt size of each turn rather than cumulative token counts across the session. This eliminates false-positive context pressure signals that previously triggered premature history compaction in longer conversations.

What changed:

  • Per-turn prompt measurement - Context window utilization is now calculated from the most recent turn's prompt token count rather than the running total of all tokens sent and received during the session. Cumulative totals grow faster than actual context size (because earlier turns are already represented in history), so the previous approach over-estimated pressure and degraded context quality too early.

  • Progressive compaction - When prompt size crosses the warning threshold, the engine switches to summarized history for past conversation states. If prompt size reaches the escalation threshold, the engine applies compact history rendering and caps the number of history entries included in prompts. Compaction only ratchets up during a session - it never relaxes back to a less aggressive level.

  • Strategy resolution - Each conversation state can declare its own context strategy via turn policy. The engine now resolves the effective strategy by comparing the engine-level compaction override (set by context pressure) against the per-state turn policy and applying whichever is more aggressive. This ensures that context pressure always takes effect, even when a state's policy would otherwise allow full history.

Who is affected:

All Platform API consumers using voice agents or text sessions with context graphs. No API changes - this is a behavioral improvement to how the engine manages prompt history under context pressure. Agents in longer conversations should see more relevant context retained for longer before compaction kicks in.

No breaking changes.

chevron-rightv0.9.435 - Platform API: World Tool Reads from Synced Entity Store (July 2026)hashtag

World Tool Reads from Synced Entity Store

All built-in entity lookup tools now read from a dedicated synced projection of the entity store instead of the primary write table. This improves read consistency and aligns entity lookups with the platform's event-sourced data pipeline.

What changed:

  • Entity reads use synced projection - The built-in world tools (patient lookup, observations, conditions, allergies, medication statements, clinical notes, family history, questionnaire responses, intake uploads, persons, conversations, and calls) now read entity data from a continuously updated projection that reflects the latest state derived from the event pipeline. Previously, these tools read from the primary entity table, which could show intermediate states during concurrent writes.

  • Write path unchanged - Entity creation, shell entity generation, and field updates continue to write to the same entity store as before. Only the read path used by agent-facing lookup tools has changed.

  • No API changes - All tool parameters, response shapes, and filtering behavior remain identical. Agents and API consumers do not need to change anything.

Who is affected:

All Platform API consumers using built-in entity lookup tools during agent conversations. The change is transparent - tool inputs, outputs, and filtering behavior are unchanged. Entity data returned by lookups may reflect updates slightly faster due to the optimized read path.

No breaking changes.

chevron-rightv0.9.434 - Platform API: Event-Sourced Operator and Patient State Projection (July 2026)hashtag

Event-Sourced Operator and Patient State Projection

Operator and patient entity state is now fully projected from events rather than written inline during API operations. This completes the migration to event-sourced state for these entity types, improving consistency and eliminating race conditions during concurrent updates.

What changed:

  • Operator state projection - Creating or updating an operator no longer patches entity state inline. Instead, the platform emits events that are processed through the standard data pipeline to project the final entity state. This means operator state (availability, profile, performance counters) is always derived from the authoritative event history rather than ad-hoc writes during API calls.

  • Patient entity management - Patient entity creation and deduplication logic has been consolidated into the platform's entity service layer. The voice agent no longer manages patient entities directly. Patient data flows through the same event-sourced pipeline as all other entity types, with deduplication handled by the entity service.

  • Patient data in agent context - The patient data made available to agents during conversations has been streamlined. Clinical details (conditions, medications, allergies, appointments, insurance) are no longer embedded in the patient summary. Each clinical data category is accessed through its own dedicated lookup tool (conditions lookup, allergies lookup, medication statements lookup, observations lookup), which query purpose-built data structures with typed fields. This improves query precision and avoids stale embedded data.

Who is affected:

Platform API consumers who create or update operators, or who rely on patient entity state. The API request and response shapes are unchanged. State updates may take a brief moment to propagate through the event pipeline rather than appearing synchronously in the response. Agent tool behavior is unchanged - clinical data tools continue to work as documented.

No breaking changes.

chevron-rightv0.9.433 - Platform API: Conditions and Allergies Lookup Tools (July 2026)hashtag

Conditions and Allergies Lookup Tools

Two new built-in tools are now available for agents to retrieve patient clinical data during conversations: conditions lookup and allergies lookup. These join the existing set of typed clinical data retrieval tools (observations, medication statements, clinical notes) and follow the same patterns.

What changed:

  • Conditions lookup - Agents can now retrieve a patient's health conditions (diagnoses) mid-conversation. The tool returns condition name, ICD-10 code, code system, clinical status, and onset date. Results can be filtered by clinical status (active, resolved, remission), condition name substring, date range (onset date), and row limit (default 50, max 100). The patient_id parameter is required and accepts platform UUID, canonical ID, MRN, or FHIR Patient ID.

  • Allergies lookup - Agents can now retrieve a patient's allergies and intolerances (drug, food, environmental) mid-conversation. The tool returns allergen name, code, clinical status, severity, and manifestation. Results can be filtered by clinical status (active, resolved, inactive), allergen name substring, and row limit (default 50, max 100). The patient_id parameter is required and accepts the same identifier formats as other patient-scoped tools.

Conditions lookup parameters:

Parameter
Type
Required
Description

patient_id

string

Yes

Patient identifier (platform UUID, canonical ID, MRN, or FHIR Patient ID)

search_text

string

No

Substring filter on condition name

status

string

No

Clinical status: active, resolved, or remission

date_from

string

No

ISO date; onset date on or after this value

date_to

string

No

ISO date; onset date on or before this value

limit

integer

No

Max rows returned (1-100, default 50)

Allergies lookup parameters:

Parameter
Type
Required
Description

patient_id

string

Yes

Patient identifier (platform UUID, canonical ID, MRN, or FHIR Patient ID)

search_text

string

No

Substring filter on allergen name

status

string

No

Clinical status: active, resolved, or inactive

limit

integer

No

Max rows returned (1-100, default 50)

Who is affected:

Platform API consumers building agents that need access to patient conditions or allergy data during conversations. These are new tools - no existing tools or responses are changed.

No breaking changes.

chevron-rightv0.9.432 - Platform API: A2P 10DLC Brand Registration (July 2026)hashtag

A2P 10DLC Brand Registration

The channel setup flow now supports A2P 10DLC brand registration - the carrier-facing authorization required before registering messaging campaigns on local (10DLC) phone numbers in the US. Brand registration is managed through two new endpoints on the Twilio setup resource, with asynchronous status updates delivered via the existing compliance event stream.

What changed:

  • New endpoint: submit brand registration - POST /v1/twilio-setup/{setup_id}/bundle/a2p-brand-registration creates or resubmits a brand registration. The request body accepts a brand_type field with two options: standard (full secondary vetting, higher carrier throughput, required for non-profit and government organizations) or low-volume-standard (secondary vetting skipped, lower throughput cap, available for private and public companies only). The endpoint validates prerequisites before submission: the setup's customer profile must be approved, and the setup must have an approved A2P Messaging Profile bundle.

  • Create and resubmit via single endpoint - The POST endpoint handles both initial creation and resubmission. If no brand registration exists for the setup, a new one is created. If an existing registration has failed primary vetting (primary_vetting_status is unverified), the same endpoint resubmits it for re-vetting. Resubmission requires the caller to fix upstream profile data before calling - the re-vetting runs against whatever data is currently committed on the upstream bundles. The brand_type cannot be changed on resubmit. Resubmits are capped at 3 per brand; exceeding the limit returns 422.

  • New endpoint: get brand registration - GET /v1/twilio-setup/{setup_id}/bundle/a2p-brand-registration returns the current brand registration state for a setup. Returns 404 if no registration exists.

  • Two-axis vetting status - Brand registration tracks two independent vetting outcomes. primary_vetting_status reflects identity vetting (pending, verified, or unverified). secondary_vetting_status reflects secondary compliance vetting (pending, verified, failed, or skipped). Low-volume-standard brands always carry skipped for secondary vetting. Each axis is updated independently based on compliance events - one axis never auto-transitions based on the other.

  • Structured vetting errors - When primary or secondary vetting fails, the registration carries structured error arrays (primary_vetting_errors and secondary_vetting_errors) with error codes and descriptions from the upstream compliance system. Errors are cleared on successful resubmit.

  • Asynchronous status updates - Brand registration status changes are delivered via the same compliance event stream already configured on each setup. The event stream subscription now includes four brand registration event types that update the registration row: identity verified, fully vetted (primary and secondary both verified), identity unverified (with error details), and secondary vetting failed (with error details). No additional setup configuration is required - the subscription is configured automatically when the setup is created.

  • Event stream schema versions - The event stream subscription now specifies per-event-type schema versions. The identity-unverified event type uses schema version 3 to include structured error arrays; other brand registration events use schema version 2.

  • Tier validation - Non-profit and government organizations are rejected at submission time if low-volume-standard is requested. These organization types require full secondary vetting and must register as standard.

Response fields:

Field
Type
Description

setup_id

string

Setup this registration belongs to

brand_sid

string

Upstream brand identifier (stable for the lifetime of the registration)

customer_profile_bundle_sid

string

Customer profile bundle used at creation

a2p_profile_bundle_sid

string

A2P Messaging Profile bundle used at creation

brand_type

string

standard or low-volume-standard

primary_vetting_status

string

pending, verified, or unverified

secondary_vetting_status

string

pending, verified, failed, or skipped

primary_vetting_errors

array of object

Error code and description from failed primary vetting

secondary_vetting_errors

array of object

Error code and description from failed secondary vetting

resubmit_count

integer

Number of times the registration has been resubmitted (max 3)

created_at

datetime

When the registration was created

updated_at

datetime

When the registration was last updated

Error responses:

Status
Condition

404

Setup not found, or no brand registration exists (GET only)

409

Customer profile not approved, A2P Messaging Profile bundle missing or not approved, or existing registration is not in a resubmittable state

422

Tier mismatch (low-volume-standard for non-profit/government), brand type change on resubmit, resubmit limit exceeded, or upstream rejected the request

Who is affected:

Platform API consumers managing US 10DLC messaging compliance. This is a new capability - no existing endpoints or responses are changed.

No breaking changes.

chevron-rightv0.9.431 - Platform API: Clinical Entities as First-Class Citizens (July 2026)hashtag

Clinical Entities as First-Class Citizens

Clinical resources like conditions, allergies, observations, and medications are now promoted to first-class entities in the world model. Each clinical resource gets its own standalone entity with structured, queryable fields extracted from the underlying clinical data - rather than existing only as nested arrays on a patient record.

What changed:

  • Standalone clinical entities - Conditions and allergies now appear as independent entities in the world model with their own entity IDs, in addition to being summarized on the parent patient record. Previously, these resources were only accessible as array fields on the patient entity. Now they can be queried, filtered, and retrieved individually.

  • Structured clinical fields on entities - All clinical entity types (observations, medications, conditions, allergies, and others) now carry structured fields extracted from the underlying clinical data: a human-readable code name, the terminology system (e.g. ICD-10, LOINC, RxNorm), the coded value, clinical status, clinically relevant timestamp, measured value with unit (for observations), and a link back to the parent patient entity. These fields are queryable and filterable without parsing the raw clinical resource blob.

  • Patient link on clinical entities - Every clinical entity now carries a reference back to the patient it belongs to. This link is derived from the clinical resource's subject or patient reference at projection time, enabling efficient lookups like "show all active conditions for this patient" without joining through intermediate resolution tables.

  • New agent tools for conditions and allergies - Two new agent tools are available for retrieving condition and allergy entities during conversations. Both tools accept patient ID, optional status filter, optional text search, and date range filters (conditions only). Results include the coded value, terminology system, clinical status, and onset date. These tools complement the existing observation and medication lookup tools.

  • Expanded medication matching - The medications array on patient entities now includes both medication requests and medication statements. Previously, only medication requests were included. This provides a more complete view of a patient's active medications.

  • Dual projection for conditions and allergies - Conditions and allergies are projected in two ways: as summary arrays on the parent patient entity (for population-level queries and patient overviews), and as standalone entities (for individual clinical resource queries and agent tool lookups). Both projections are kept in sync automatically.

Who is affected:

All Platform API consumers working with clinical data. The new standalone entities and structured fields are additive - existing patient-level clinical arrays continue to work as before. Agent tool consumers gain two new tools (conditions_lookup and allergies_lookup) that can be registered on agent configurations.

No breaking changes.

chevron-rightv0.9.430 - Platform API: Canonical Call Completion Reasons (July 2026)hashtag

Canonical Call Completion Reasons

All call completion reasons returned by the API are now normalized to a canonical set of values. Previously, API responses and real-time events could surface internal labels that were not part of the documented vocabulary. With this release, every completion reason is mapped to a canonical value before it appears in any API response, real-time event, or data export.

What changed:

  • Completion reasons normalized at the source - Call completion reasons are now mapped to the canonical vocabulary at the point they are produced, before they reach API responses, real-time events, or data exports. Previously, internal labels could appear in responses and were only normalized at the data storage layer. Now, all downstream consumers see a single, bounded set of values.

  • Wider vocabulary type retired - The API response schema for call detail, call list, and call-ended events previously accepted a superset of completion reason values that included internal labels. The schema now accepts only the canonical set: completed, abandoned, escalated, transferred, timeout, error, voicemail, no_answer, caller_hangup, forwarded, terminal_state, warm_transfer_completed, no_inbound_audio, and cancelled.

  • Historical data handled gracefully - Call detail and call list responses apply defensive normalization to historical records that may predate this change. Records with unmapped completion reasons return null for the completion_reason field rather than failing the request.

  • Real-time events carry canonical values - The call.ended server-sent event now carries only canonical completion reason values. SDK consumers and dashboard integrations that previously needed to handle both canonical and internal labels can simplify their parsing logic.

Who is affected:

Consumers who were handling internal completion reason labels (such as raw timeout or disconnection variants) in API responses or SSE events should update to use only the canonical set listed above. Consumers already using only canonical values are unaffected.

Breaking changes:

  • The completion_reason field on call detail, call list, and call-ended event responses no longer returns internal labels. Any client-side logic that matched on non-canonical values will stop matching.

  • The response schema enum for completion_reason is narrowed to the canonical set. Clients with strict enum validation that included internal labels should remove those values.

chevron-rightv0.9.429 - Platform API: Skill Execution Tier Simplification (July 2026)hashtag

Skill Execution Tier Simplification

The autonomous and browser execution tiers have been removed from the Skills API. Skills that previously used these tiers have been migrated automatically. Going forward, the platform supports three execution tiers: direct, orchestrated, and computer_use.

What changed:

  • autonomous execution tier removed - Skills configured with execution_tier: "autonomous" are no longer supported. Existing autonomous-tier skills have been migrated to orchestrated. The autonomous tier previously delegated skill execution to a standalone agent worker with session resumption and checkpoint capabilities. These capabilities are now handled through the orchestrated tier.

  • browser execution tier removed - Skills configured with execution_tier: "browser" are no longer supported. Existing browser-tier skills have been migrated to computer_use. The browser tier was a specialized variant of computer use execution - the computer_use tier now covers all desktop and browser automation use cases.

  • Browser-specific fields removed - The browser_start_url, browser_allowed_domains, and browser_auth_integration fields have been removed from skill create, update, and response schemas. These fields were only relevant to the browser execution tier. Skills that had these fields set will no longer return them in API responses.

  • execution_tier enum narrowed - The execution_tier field on skill create and update requests now accepts only direct, orchestrated, or computer_use. Requests that specify autonomous or browser will receive a 422 validation error.

  • Existing skills migrated automatically - A data migration has converted all autonomous-tier skills to orchestrated and all browser-tier skills to computer_use. No manual action is required for existing skill configurations.

Who is affected:

Consumers who create or update skills with execution_tier set to autonomous or browser must update to use orchestrated or computer_use respectively. Consumers who read skill responses and expect browser_start_url, browser_allowed_domains, or browser_auth_integration fields should remove references to these fields. Consumers using only direct, orchestrated, or computer_use tiers are unaffected.

Breaking changes:

  • execution_tier values autonomous and browser are no longer accepted on create/update requests (422 error)

  • browser_start_url, browser_allowed_domains, and browser_auth_integration fields removed from request and response schemas

  • Skill responses no longer include autonomous or browser as possible execution_tier values

chevron-rightv0.9.428 - Platform API: Text Session Lifecycle Simplification (July 2026)hashtag

Text Session Lifecycle Simplification

Two internal endpoints used during text session lifecycle management have been removed. These endpoints were previously used to coordinate conversation state transitions between internal services during session resume and actor initialization. The behavior they provided is now handled automatically by the implicit reactivation and state-save mechanisms introduced in v0.9.426.

What changed:

  • Removed reactivation endpoint - The internal endpoint that explicitly transitioned a dormant text conversation back to active before resuming is no longer available. Since v0.9.426, the platform handles this transition implicitly when the next message arrives, so the explicit round-trip was redundant. Consumers who previously relied on calling a reactivation step before resuming idle text sessions should have already migrated to the implicit behavior introduced in v0.9.426.

  • Removed actor-start-failed rollback endpoint - The internal endpoint that rolled back a conversation's state when session initialization failed mid-startup has been removed. Under the implicit transition semantics introduced in v0.9.426, no state mutation occurs before session initialization completes, so there is nothing to roll back on failure. Session cleanup (lease release, channel unregistration) continues to happen automatically.

  • No changes to public API behavior - These were internal coordination endpoints not exposed in the public API. Conversation lifecycle, the lifecycle field, implicit reactivation on resume, and all public conversation endpoints continue to work exactly as documented.

Who is affected:

No external consumers are affected. These were internal-only endpoints used for service-to-service coordination. The public conversation API, text session behavior, and lifecycle field semantics are unchanged.

No breaking changes to the public API.

chevron-rightv0.9.427 - Platform API: Cold Inbound Email Support (July 2026)hashtag

Cold Inbound Email Support

Email use cases can now accept inbound messages that are not replies to a previous outbound email. Previously, the platform operated in a strict thread-only model where every inbound email had to reference one of your outbound messages. With this release, use cases can opt in to receiving cold inbound - messages sent to the use case's sender address by external parties who have never been contacted first.

What changed:

  • New accepts_cold_inbound field on email use cases - When creating an email use case, you now provide an accepts_cold_inbound boolean. When set to true, the platform accepts inbound emails addressed to the use case's sender address even when they do not reply to a prior outbound message. When false (the default stance for all existing use cases), the use case remains thread-only and cold inbound is silently dropped. This is a required field - opening a public inbox is an explicit decision, not a default.

  • Authentication gates for cold inbound - Cold inbound messages must pass two authentication checks before acceptance. The sender's domain must pass DMARC alignment (only PASS is accepted - FAIL, GRAY, and PROCESSING_FAILED all drop). Additionally, the message must not be flagged as spam (FAIL drops; PASS, GRAY, and PROCESSING_FAILED are accepted). These gates reduce spoofed-sender abuse at the cost of dropping some legitimate non-aligned forwarders.

  • in_reply_to_email_id is now nullable - On inbound email responses, the in_reply_to_email_id field is now null for cold inbound messages instead of always referencing a parent outbound email. Threaded replies continue to populate this field as before. Consumers that assumed this field was always present should add a null check.

  • accepts_cold_inbound on use case responses - The use case detail and list endpoints now include the accepts_cold_inbound field, reflecting whether each email use case accepts unsolicited inbound messages.

  • Webhook callback payload updated - The inbound email received webhook callback now sends in_reply_to_email_id as null for cold inbound messages. Consumers should handle null values in this field.

Who is affected:

All consumers of inbound email endpoints and email use case endpoints. The in_reply_to_email_id field changing from always-present to nullable is a behavioral change - consumers that assume it is non-null should update their handling. The new accepts_cold_inbound field on use case create requests is required for email use cases going forward.

chevron-rightv0.9.426 - Platform API: Conversation Lifecycle Predicate and Implicit Reactivation (July 2026)hashtag

Conversation Lifecycle Predicate and Implicit Reactivation

Conversation responses now include a computed lifecycle field that tells you whether a conversation is actively in use, sitting idle, or permanently closed - without requiring you to interpret raw status values and timestamps yourself. Additionally, text sessions that resume after going idle no longer require an explicit reactivation step; the platform handles the transition automatically when the next message arrives.

What changed:

  • New lifecycle field on all conversation responses - Every conversation summary and detail response now includes a lifecycle field with one of three values: active, dormant, or closed. This field is computed at read time from the conversation's status and how recently it was updated, so it always reflects the current state without requiring a separate status-refresh call.

  • active - The conversation is not closed and was updated within the idle threshold for its channel. Voice and web conversations use a 5-minute threshold; SMS uses 30 minutes; WhatsApp and email use 60 minutes.

  • dormant - The conversation is not closed but has been idle longer than the channel's threshold. The conversation can still be resumed by sending a new message.

  • closed - The conversation has been permanently closed. No further interaction is possible.

  • Implicit reactivation on resume - When a text session receives a new message after going idle, the platform automatically transitions the conversation back to an active state. Previously, consumers needed to call a separate reactivation endpoint before sending the next message. That extra round-trip is no longer necessary.

  • Smarter session save behavior - Text sessions now distinguish between transient request boundaries and genuine dormancy when saving state. Sessions that end due to idle timeouts, duration limits, or disconnections save in a dormant state with compression. Sessions that end because a request completed save in an active state, avoiding unnecessary compression on every turn.

Who is affected:

All consumers of the conversation list, conversation detail, and conversation create endpoints. The new lifecycle field is additive - existing fields are unchanged. Consumers that previously called a reactivation endpoint before resuming idle text sessions can remove that step. No breaking changes.

chevron-rightv0.9.425 - Platform API: Standalone Entity Resolution for Non-Patient FHIR Resources (July 2026)hashtag

Standalone Entity Resolution for Non-Patient FHIR Resources

Non-Patient FHIR resources (Observation, MedicationStatement, DocumentReference, FamilyMemberHistory, QuestionnaireResponse, and others) now emit events without a pre-linked entity identifier. The downstream data pipeline resolves each resource to its own standalone entity row, and linkage back to the originating Patient is reconstructed at projection time via the resource's subject reference.

Previously, the platform attempted to attach non-Patient resources directly to the Patient entity at write time. The data pipeline's entity resolver expected unlinked events and silently skipped pre-linked ones, so non-Patient resources never produced their own entity rows. This fix aligns all three write paths - single-resource create, single-resource update, and bundle import - so every FHIR resource type flows through entity resolution consistently.

What changed:

  • Single-resource create - Creating a non-Patient FHIR resource (e.g., Observation, MedicationStatement) no longer looks up and attaches the referenced Patient's entity identifier. The event is emitted without a pre-set entity identifier, allowing the data pipeline to derive a standalone entity.

  • Single-resource update - Updating a non-Patient FHIR resource now emits the event without an entity identifier, matching the create path. Patient updates continue to preserve the existing entity identifier since the Patient itself is the entity.

  • Bundle import - Bundle imports (both JSON and NDJSON streaming) no longer resolve Patient references for non-Patient resources in the bundle. Only Patient entries carry entity identifiers; all other resource types emit unlinked events.

  • Entity linkage preserved - Relationships between non-Patient resources and their Patient are not lost. The subject reference on each resource is preserved in the event payload, and the data pipeline reconstructs the linkage when projecting entity views.

Who is affected:

All workspaces that import or create non-Patient FHIR resources. After this change, the data pipeline will create standalone entity rows for these resources during its next processing cycle. No API contract changes - request and response schemas are unchanged. Patient resource handling is unaffected.

No breaking changes.

chevron-rightv0.9.424 - Platform API: Unified Conversation ID Filter on Prompt Logs (July 2026)hashtag

Unified Conversation ID Filter on Prompt Logs

The prompt logs endpoint now accepts a conversation_id parameter - the canonical conversation identifier that works uniformly across voice, text, SMS, sim, and scribe modalities. This replaces the need for callers to obtain and pass modality-specific call SIDs.

What changed:

  • New conversation_id query parameter - Pass a conversation entity UUID to filter prompt logs for any conversation regardless of modality. The platform resolves the conversation identifier to the underlying call-level identifier automatically. This is the recommended filter for all new integrations.

  • call_sid retained as legacy filter - The existing call_sid parameter continues to work for callers that already hold the direct identifier. conversation_id and call_sid are mutually exclusive - passing both returns a 400 error.

  • Resolution metadata in response - When filtering by conversation_id, the response includes two new fields: resolved_call_sid (the underlying identifier the lookup resolved to) and resolved_conversation_kind (the modality category: call for voice/sim/scribe, conversation for text/SMS/WhatsApp/email). These let callers drill into per-call surfaces without re-querying.

  • Graceful handling of conversations without prompt logs - If the conversation entity exists but has no associated prompt log identifier (e.g., certain scribe sessions), the endpoint returns an empty page rather than scanning all data.

  • New error responses - 400 when both conversation_id and call_sid are supplied. 404 when conversation_id does not match any conversation in the workspace.

Who is affected:

All prompt log consumers. The conversation_id parameter provides a simpler, modality-agnostic way to retrieve prompt logs. Existing callers using call_sid are unaffected. No breaking changes.

chevron-rightv0.9.423 - Platform API: Smarter Text Session Conversation Compression (July 2026)hashtag

Smarter Text Session Conversation Compression

Text session conversation compression now runs only when a session becomes genuinely dormant, instead of running after every turn. Previously, compression could fire on every actor lifecycle transition - including the per-turn request-response cycle used by the playground and REST integrations - causing redundant summarization on every single message. This added latency to the user's critical path and produced lossy re-summarization of the full transcript each turn.

What changed:

  • Compression gated on real dormancy - Conversation compression now only triggers when the session ends for a sustained reason such as idle timeout, maximum duration, disconnect, or transport failure. Transient lifecycle transitions (per-turn REST cleanup, errors, cancellations, and lease handoffs) no longer trigger compression. The raw transcript is preserved intact for these cases, so the next session reactivation replays from the full turn history directly.

  • Unknown completion reason warnings - If the platform encounters a completion reason it does not recognize, it now emits a warning log and increments a metric. This ensures that new completion vocabulary added in future releases does not silently skip compression without being noticed.

  • Improved observability - Session lifecycle logs (hydration, thaw, state save, compression) now include the workspace identifier for easier cross-referencing in monitoring dashboards. The state-saved log event also uses a renamed field for lifecycle status to avoid collisions with log severity mapping in monitoring pipelines.

Who is affected:

All text session users benefit from reduced latency and more accurate conversation history. Playground and REST-based text integrations see the largest improvement since they previously triggered compression on every turn. No API or configuration changes required.

No breaking changes.

chevron-rightv0.9.422 - Platform API: List Registered Platform Functions Endpoint (July 2026)hashtag

List Registered Platform Functions Endpoint

A new endpoint returns the latest version of every registered platform function in a workspace, giving API consumers and the Developer Console a single call to build a workspace-wide directory of deployed functions.

What changed:

  • New list endpoint - A new GET endpoint on the platform functions resource returns one entry per registered function, each representing the latest (alias-pinned) version. This provides a flat directory view of all deployed functions in the workspace without requiring callers to enumerate functions individually and then fetch versions for each one.

  • Distinct from legacy function list - The new endpoint is separate from the existing workspace-level function list, which returns function metadata stored in the workspace settings object. Both endpoints co-exist. Clients working with registered platform functions should prefer the new endpoint, which reflects the current registration-based function model.

  • Permissions - Requires read-level workspace access (the same permission level used by other read-only workspace endpoints).

  • Rate limiting - The endpoint is subject to the same read rate limit as other function endpoints.

Who is affected:

SDK consumers and Developer Console users who need a complete view of registered platform functions in a workspace. The Developer Console platform functions page uses this endpoint to populate the function directory. No changes to existing endpoints.

No breaking changes.

chevron-rightv0.9.421 - Platform API: Wider Call Completion Reasons on API Responses (July 2026)hashtag

Wider Call Completion Reasons on API Responses

Call detail, call list, and real-time event responses now return the full set of completion reason values that the platform can produce, including raw labels from the voice engine that were previously not represented in the API schema. Previously, API response schemas only documented the canonical set of completion reasons written to long-term storage. When the voice engine emitted a reason outside that canonical set - such as max_duration, idle_timeout, client_stop, transport_error, disconnected, transport_closed, conference_ended, or unknown - the value still appeared in responses but was not covered by the documented schema, causing strict SDK validators to reject otherwise valid payloads.

What changed:

  • Wider completion reason vocabulary on responses - The completion_reason field on call detail responses, call list summaries, and call.ended SSE events now documents the full set of values that can appear. This includes the canonical values (completed, abandoned, escalated, transferred, timeout, error, voicemail, no_answer, caller_hangup, forwarded, terminal_state, warm_transfer_completed, no_inbound_audio, cancelled) plus the voice-engine labels (max_duration, idle_timeout, client_stop, transport_error, disconnected, transport_closed, unknown, conference_ended).

  • Normalization for analytics - The wider labels are automatically mapped to their canonical equivalents before being written to long-term analytical storage. For example, max_duration and idle_timeout both map to timeout, and transport_error maps to error. API consumers who only care about broad categories can apply the same mapping client-side, or use the raw label for more granular instrumentation.

  • No change to write paths - Long-term storage and analytics queries continue to use only the canonical completion reason set. The wider vocabulary applies only to real-time API responses and SSE events.

Who is affected:

SDK consumers and API clients that perform strict validation on the completion_reason field should update their allowed value sets to include the new labels. Clients that treat completion_reason as an opaque string are unaffected. The change is backward-compatible - all previously valid values remain valid.

No breaking changes.

chevron-rightv0.9.420 - Platform API: Patient-Scoped Clinical Data Retrieval Fix (July 2026)hashtag

Patient-Scoped Clinical Data Retrieval Fix

Agent world tools that retrieve clinical data for a specific patient now return the full set of matching records instead of missing the majority of results. Previously, patient-scoped lookups for observations, family history, questionnaire responses, and other clinical entities could miss over 95% of available records when the underlying data used certain reference conventions.

What changed:

  • Broader patient matching - Patient-scoped world tools now use two matching strategies combined with an OR condition. The first strategy matches the standard patient reference field on the clinical resource. The second strategy matches resources whose identifier encodes the patient identity by convention - a pattern common in bulk data imports where internal references are not fully resolved during ingestion. Previously, only the first strategy was used, which caused the vast majority of records from certain ingestion paths to be invisible to the agent.

  • Family history resources included - Family history lookups use a different reference field than most clinical resources. The updated matching logic now correctly applies both strategies to family history resources using the appropriate reference field, ensuring consistent coverage across all clinical resource types.

  • Input validation - The patient matching logic now validates that the patient identifier is non-empty before building the filter. An empty identifier would previously produce an overly broad query pattern that could match unrelated records across the workspace. The filter now raises an error if an empty identifier is provided.

  • Safe pattern construction - Special characters in patient identifiers are escaped before being used in pattern matching, preventing any possibility of the pattern matching records belonging to other patients.

Who is affected:

All workspaces with clinical data ingested through bulk import paths (such as FHIR Bundle ingestion) where resource references may not be fully resolved. Workspaces that ingest data through pipelines that normalize all references during ingestion are unaffected but benefit from the additional validation. The fix is automatic - no configuration changes are needed.

No breaking changes.

chevron-rightv0.9.419 - Platform API: Per-Turn Context Graph State on Text Sessions (July 2026)hashtag

Per-Turn Context Graph State on Text Sessions

Text sessions now persist the agent's context graph position and wait condition on every turn, matching the behavior voice sessions already had. This ensures that when a durable text conversation is resumed - whether after a timeout, a cold start, or a channel switch - the agent picks up exactly where it left off without running an unnecessary navigation step or emitting a redundant message.

What changed:

  • State persisted per turn - Every agent turn in a text conversation now records the context graph state the agent was in when the turn was emitted. Previously, text sessions only persisted conversation text and metadata, and the agent always restarted from the configured initial state on resume.

  • Wait condition persisted per turn - If the agent was paused waiting for an external event (such as a form submission or approval), that wait condition is now recorded alongside the state on each turn. Without this, a resumed session would lose the pause, run an unnecessary navigation, and potentially emit a redundant message before re-establishing the wait on its next turn.

  • Automatic restoration on resume - When a text session hydrates from a durable conversation, the platform reads the state and wait condition from the most recent turn and restores the agent to that position. The agent resumes as a function of its durable state alone, without needing a separate sidecar.

  • Graceful fallback for legacy conversations - Conversations that pre-date this change have no state or wait condition on their turns. The agent falls back to the configured initial state and unpaused condition, preserving backward compatibility.

  • Turn data includes new fields - Turn objects returned by the conversation API now include state (string or null) and waiting_for (string or null) fields. These are null on turns from conversations created before this release.

Who is affected:

All workspaces using text-based conversations with context graphs that have multiple states or wait conditions. The improvement is automatic - no configuration changes are needed. Existing conversations continue to work; the new fields appear only on turns emitted after this release.

No breaking changes.

chevron-rightv0.9.417 - Platform API: Provider Email Change Re-Verification (July 2026)hashtag

Provider Email Change Re-Verification

Provider access grants now support a secure email change flow that requires the new address to verify ownership before the change takes effect.

What changed:

  • Email change verification flow - When an admin changes the email on a provider access grant, the platform does not update the grant immediately. Instead, a time-limited one-time code is sent to the new email address. The provider's existing email continues to authenticate normally during the verification window. The email on the grant is only updated after the new address holder confirms the code.

  • Confirmation endpoint - A new POST /auth/email-change/confirm endpoint accepts the workspace ID, grant ID, and six-digit verification code. On success, the grant's email is updated, the verification timestamp is refreshed, and the response returns {"status": "confirmed"}. No authentication token is required - the workspace ID, grant ID, and OTP triple serve as the proof of ownership.

  • Automatic session invalidation - On successful confirmation, all outstanding refresh tokens for the grant are revoked. Every device where the provider was previously authenticated is forced to re-authenticate with the new email. This ensures no stale sessions persist under the old identity.

  • Grant status transition - Grants in pending_verification status are automatically moved to active upon successful email confirmation. Grants that are pending for other reasons (such as entity binding) remain in their current status.

  • Attempt limiting and lockout - The verification code has a configurable maximum number of attempts (default: 5). After exhausting all attempts, the verification is permanently locked and must be re-issued by an admin. An IP-based rate limit provides defense in depth against brute-force attempts across multiple grants.

  • Configurable TTL - The verification code TTL is configurable (default: 24 hours, maximum: 48 hours). Expired codes return a 410 Gone response.

  • Audit logging - Successful email changes and failed confirmation attempts are recorded in the audit log with the action type, old email, new email, grant ID, and client IP address.

  • Error responses - The endpoint returns distinct status codes for each failure mode:

    Scenario
    Status
    Detail

    Success

    200

    confirmed

    Code expired

    410

    verification_expired

    Wrong code

    401

    invalid_code

    Locked after max attempts

    401

    verification_locked

    No pending verification or grant not found

    404

    verification_not_found

    IP rate-limited

    429

    too_many_attempts

Configuration:

Variable
Default
Range
Description

EMAIL_CHANGE_OTP_TTL_SECONDS

86400 (24h)

60 - 172800 (48h)

How long the verification code remains valid

EMAIL_CHANGE_OTP_MAX_ATTEMPTS

5

1 - 20

Maximum wrong attempts before the code is locked

Who is affected:

Workspaces that manage provider access grants. Admins changing a provider's email will now trigger the verification flow automatically. Providers will receive an email at their new address with a confirmation code. No changes are needed for workspaces that do not use provider access grants.

No breaking changes.

chevron-rightv0.9.416 - Platform API: Narrative-Derived Coded Resources from Patient-Reported Text (July 2026)hashtag

Narrative-Derived Coded Resources from Patient-Reported Text

The FHIR import pipeline now synthesizes coded clinical resources from free-text patient-reported narrative carried on Patient resources, enabling projection into structured clinical state for patients whose data arrives as unstructured text rather than coded FHIR.

What changed:

  • Automatic synthesis at import time - When a Patient resource carries a patient-reported narrative extension with free-text sub-extensions for allergies, conditions, or medications, the import pipeline now synthesizes one coded resource per sub-extension. These synthetic resources flow through the same import path as authored FHIR resources, so existing projection branches populate the patient's structured clinical state (allergies, active conditions, active medications) without any configuration changes.

  • Supported narrative categories - Three narrative sub-extension types are recognized:

    Narrative category
    Synthesized resource type
    Projection target

    Allergy description

    AllergyIntolerance

    Allergies

    Condition description

    Condition (active)

    Active conditions

    Medication description

    MedicationRequest (active)

    Active medications

  • Input sanitization - Free-text narrative values are sanitized before they are placed on the synthesized resource. HTML tags, JavaScript event handlers, javascript: URIs, and entity-encoded markup are stripped. Whitespace is normalized. If sanitization removes all content (e.g., the input was pure markup from a stored-XSS attempt), no resource is synthesized for that sub-extension - no stub events with empty content are emitted.

  • Deterministic resource IDs - Each synthesized resource receives a stable, deterministic ID derived from the workspace, patient, and narrative category. Re-imports under EHR sync mode deduplicate naturally against previously synthesized resources without creating duplicates.

  • Provenance tagging - Synthesized resources carry a provenance extension that identifies them as derived from patient-reported narrative. Downstream consumers can use this to distinguish narrative-derived entries from resources that were authored as coded FHIR.

  • Bundle and NDJSON support - Narrative synthesis runs in both the bundle import path and the NDJSON streaming import path. In NDJSON mode, synthesized resources are emitted inline immediately after the Patient line, preserving event ordering.

  • Immutable request data - The original import request payload is not mutated. Synthesized entries are concatenated into a new list for processing, so any future audit or async post-processing that captures the original bundle sees the unmodified input.

Who is affected:

Workspaces that import Patient resources carrying patient-reported narrative extensions (e.g., from Everlab). These workspaces will now see structured clinical state (allergies, active conditions, active medications) populated from narrative text that previously had no projection path. Workspaces that do not import patients with narrative extensions are unaffected.

No breaking changes.

chevron-rightv0.9.415 - Platform API: Fail-Loud Platform Function Loading (July 2026)hashtag

Fail-Loud Platform Function Loading

Platform function loading at session startup now fails loudly on errors instead of silently disabling registered functions.

What changed:

  • Explicit error logging - When registered platform functions cannot be loaded at session initialization (e.g., due to a transient data store outage or misconfiguration), the error is now logged with full diagnostic context including the workspace and exception details. Previously, load failures were silently suppressed, which could disable all registered functions across a workspace without any indication in logs.

  • Clearer skip reporting - When no session factory is available (e.g., in simulation sessions or local development), the platform now logs an informational message explaining why platform function registration was skipped, rather than silently proceeding without them.

  • Fail-loud on missing dependencies - Session initialization now surfaces missing internal dependencies immediately at startup rather than silently degrading. If a required component is absent due to a refactor or configuration error, the session fails to start with a clear error instead of proceeding with an incomplete function set.

The session still degrades gracefully for transient infrastructure issues - if function loading fails due to a temporary outage, the session continues with legacy, built-in, and catalog-discovered functions. The change ensures that the failure is visible in logs so operators can detect and remediate the issue.

Who is affected:

All workspaces using registered platform functions. No configuration changes required. Operators monitoring logs will now see explicit warnings when platform function loading fails, where previously these failures were invisible.

No breaking changes.

chevron-rightv0.9.414 - Platform API: Registered Platform Functions in Agent Sessions (July 2026)hashtag

Registered Platform Functions in Agent Sessions

Agent sessions now automatically load and use platform functions registered through the Platform Functions API, giving registered functions the highest resolution priority over all other function sources.

What changed:

  • Registered functions override legacy sources - Functions created through the Platform Functions API (with version aliases, SQL templates, and typed parameters) are now loaded at session initialization and take precedence over catalog-discovered, built-in, and workspace-setting functions. When a registered function shares a name with a function from any other source, the registered version is used and the legacy version is excluded.

  • Typed parameter schemas - Each registered function's parameters are automatically converted into a strict tool schema presented to the agent. The schema enforces declared types (string, integer, number, boolean), required/optional flags, and default values. Undeclared arguments are rejected at validation time rather than passed through to execution.

  • Dedicated execution path - Registered functions execute through a dedicated function executor that binds caller-supplied arguments into the function's SQL template, runs the query with a configurable timeout, and shapes the response according to the function's declared returns kind. This path is separate from the generic catalog function call used by legacy sources.

  • Graceful degradation - If registered functions cannot be loaded (database unavailable, misconfiguration, or other errors), the session continues with legacy, built-in, and catalog-discovered functions. No session initialization failures are introduced by this feature.

  • Error reporting - When a registered function execution fails, the agent receives a structured error response containing the error message and function name, consistent with how other function errors are reported.

Resolution priority (highest to lowest):

Priority
Source
Description

1 (highest)

Registered platform functions

Created via Platform Functions API, alias=latest

2

Workspace settings

Functions defined in workspace configuration

3

Built-in defaults

Curated functions shipped with the platform

4 (lowest)

Catalog discovery

Auto-discovered from the connected data warehouse

Who is affected:

Workspaces that have registered platform functions through the Platform Functions API. Functions registered with a "latest" alias are now automatically available to agents during voice and text sessions. No configuration changes are required - if you have already registered functions, they will begin appearing in agent sessions.

Workspaces without registered platform functions are unaffected. Existing legacy, built-in, and catalog-discovered functions continue to work as before.

No breaking changes.

chevron-rightv0.9.413 - Platform API: SES Email Channel Setup CRUD (July 2026)hashtag

SES Email Channel Setup CRUD

A new set of endpoints under /v1/{workspace_id}/channels/ses-setup lets you provision, inspect, verify, and tear down verified email domains for your workspace.

What changed:

  • Create an SES setup - POST /v1/{workspace_id}/channels/ses-setup provisions an isolated email tenant and domain identity, returning the DNS records (DKIM CNAMEs, MX, DMARC TXT) that must be published at your DNS provider. Requires a tenant_name (1-64 alphanumeric characters including hyphens and underscores) and a domain_identity (the domain to verify). Returns 201 with the full setup detail on success, 409 if the tenant name or domain already exists, or 422 for invalid input.

  • List SES setups - GET /v1/{workspace_id}/channels/ses-setup returns a paginated list of SES setups owned by the workspace. Each item includes a dns_verified boolean aggregate and a dns_checked_at timestamp from the last verification check.

  • Get SES setup with live DNS refresh - GET /v1/{workspace_id}/channels/ses-setup/{setup_id} returns the full setup detail with per-record DNS verification status. Each call triggers a live DNS lookup, so the verified flag on each record reflects the current state rather than a cached value.

  • Explicit DNS verification - POST /v1/{workspace_id}/channels/ses-setup/{setup_id}/verify triggers the same live DNS refresh as the GET endpoint, but exposed as a POST so UI "Verify now" actions read as intentional operations.

  • Delete an SES setup - DELETE /v1/{workspace_id}/channels/ses-setup/{setup_id} tears down the upstream email tenant and domain identity. Returns 409 if any use case still references the setup - those must be deleted first. Returns 204 on success.

  • Workspace isolation - Each SES setup is bound to the workspace that created it. Requests for a setup owned by a different workspace return 404, even if the caller knows the setup ID.

New models:

Model
Key fields

SES Setup Detail

id, tenant_name, domain_identity, dns_checked_at, dns_records (array), created_at, updated_at

SES Setup List Item

id, tenant_name, domain_identity, dns_verified (boolean aggregate), dns_checked_at, created_at, updated_at

DNS Record

address, record, type (CNAME, MX, or TXT), verified

Permissions:

Endpoint
Permission

Create

Channel.create

List, Get, Verify

Channel.view

Delete

Channel.delete

Who is affected:

Teams configuring email channels for their workspace. This is a new endpoint surface - no existing endpoints are changed.

chevron-rightv0.9.412 - Platform API: Accurate Call Completion Reasons for Playground and Direct-Stream Sessions (July 2026)hashtag

Accurate Call Completion Reasons for Playground and Direct-Stream Sessions

Voice sessions initiated through the Developer Console playground or direct WebSocket streaming now report accurate completion reasons, distinguishing explicit caller hangups from unexpected connection drops.

What changed:

  • Caller hangup vs. connection drop - Previously, all session endings over a WebSocket transport were recorded as the same generic completion reason, regardless of whether the caller explicitly ended the call or the connection dropped unexpectedly. The platform now distinguishes between an explicit caller-initiated stop and an unexpected transport closure. This distinction flows through to call intelligence records, analytics dashboards, and outbound task completion events.

  • New completion reasons - Sessions may now report the following additional completion reasons:

    • caller_hangup - The caller explicitly ended the session (e.g. sent a stop signal from the playground)

    • transport_closed - The connection dropped without an explicit stop signal (network interruption, browser tab closed, etc.)

    • conference_ended - The telephony conference ended due to the caller hanging up (not agent-initiated)

    • unknown - The session ended without any completion reason being recorded (treated as an error condition)

  • Outbound task events use canonical reasons - Outbound task completion events now carry canonical completion reasons instead of internal labels. The outcome field maps to human-readable values: caller_ended_call, caller_disconnected, system_error, caller_silent, goal_completed, max_duration_reached, and others as appropriate.

  • Completion reason validation - The platform now validates completion reasons at session exit. Unrecognized values are coerced to unknown and logged as warnings. This prevents unexpected values from appearing in analytics or inflating metric cardinality.

  • Default completion reason corrected - Sessions that exit without an explicit completion reason are now labeled unknown instead of being silently attributed to a caller hangup. This makes it easier to identify and investigate sessions that ended unexpectedly.

Who is affected:

Any integration that reads completion reasons from call intelligence data, analytics dashboards, or outbound task completion events. Previously, all WebSocket-transported sessions (including playground calls) were labeled as caller hangups regardless of how they actually ended. After this change, the completion reason accurately reflects what happened.

Consumers that filter or aggregate on completion reason values should account for the new values (transport_closed, conference_ended, unknown) appearing in their data. The unknown reason is classified as a failure condition in success-rate calculations.

No breaking changes to existing API response schemas. All new completion reason values are additive.

chevron-rightv0.9.411 - Platform API: Person Lookup Returns Patient Identity, Contact, and Vitals (July 2026)hashtag

Person Lookup Returns Patient Identity, Contact, and Vitals

The persons_lookup tool now returns a wide set of patient identity, contact, and vitals fields, replacing the previous minimal response that only included entity ID, canonical ID, name, and gender.

What changed:

  • Expanded response fields - The tool now returns birth_date, age_years, phone, email, mrn, address_state, address_city, height_cm, weight_kg, and bmi alongside the existing entity_id, canonical_id, name, and gender fields. Previously, these fields were intentionally excluded from the response; they are now included for authorized workspace-scoped consumers.

  • Server-computed age - A new age_years field is derived server-side from birth_date. The value is an integer representing the patient's age in whole years, or null when the birth date is missing or invalid. Rows with non-ISO-formatted birth dates are excluded from age computation rather than causing query failures.

  • Best-effort vitals from FHIR extensions - height_cm, weight_kg, and bmi are extracted from FHIR extension data when present. These values are sourced from structured extension entries on the patient resource. All three fields are nullable - bmi may be null even when height and weight are available. Values outside plausible clinical ranges are excluded as a data-quality safeguard.

  • Input parameter descriptions simplified - The mrn, birth_date_from, and birth_date_to parameters no longer carry "search filter only" language in their descriptions. These remain server-side filter inputs, but the distinction is no longer necessary because the matched values are now returned in the response.

  • PHI handling - All returned values are PHI. The response is scoped to the calling workspace via workspace-level isolation. Consumers must treat the data as sensitive and must not surface it in cross-workspace contexts.

Response fields:

Field
Type
Description

entity_id

string

Unique entity identifier

canonical_id

string

Canonical patient identifier

name

string

Patient display name

gender

string

Gender (male, female, other)

birth_date

string or null

ISO date of birth

age_years

integer or null

Server-computed age in whole years

phone

string or null

Phone number

email

string or null

Email address

mrn

string or null

Medical record number

address_state

string or null

State portion of address

address_city

string or null

City portion of address

height_cm

number or null

Height in centimeters (from FHIR extensions)

weight_kg

number or null

Weight in kilograms (from FHIR extensions)

bmi

number or null

Body mass index (from FHIR extensions)

Who is affected:

Any integration consuming persons_lookup responses. The response object now contains additional fields. Existing consumers that only read entity_id, canonical_id, name, and gender are unaffected. Consumers that parse the full response object will see the new fields.

The previously documented behavior where MRN, birth date, phone, email, and address fields were never returned no longer applies. If your application logic relied on these fields being absent from the response, update accordingly.

No breaking changes to existing fields. All new fields are additive and nullable.

chevron-rightv0.9.410 - Platform API: Actionable 404 Details on Service Config Lookup (July 2026)hashtag

Actionable 404 Details on Service Config Lookup

The internal service configuration endpoint now returns specific, actionable error messages when a resource is missing, replacing generic 404 responses with details that identify exactly what is missing and how to fix it.

What changed:

  • Missing agent on service - When a service has no agent assigned, the 404 response now explains that the service has no agent and includes the API path to set one.

  • Missing agent version - When the requested agent version number does not exist, the error message includes the agent identifier, the version number that was requested, and the API path to list available versions. When no versions exist at all (and the lookup resolved to "latest"), the error explains that the agent has no versions and includes the API path to create one.

  • Missing context graph on service - When a service has no context graph assigned, the 404 response explains that the service has no context graph and includes the API path to set one.

  • Missing context graph version - When the requested context graph version number does not exist, the error message includes the context graph identifier, the version number that was requested, and the API path to list available versions. When no versions exist at all, the error explains that the context graph has no versions and includes the API path to create one.

  • Tenant identifier hygiene - Error detail strings render the workspace identifier as a placeholder rather than the actual tenant UUID. This prevents tenant identifiers from appearing in APM dashboards and log aggregation systems. Resource identifiers (service, agent, context graph) are included verbatim because they are opaque platform identifiers that operators need for triage.

Who is affected:

Consumers of the internal service configuration endpoint who parse 404 error details. The previously generic messages ("Agent version not found" and "HSM version not found") are replaced with longer, structured messages that vary depending on the specific failure case. If your error handling matches on exact detail strings, update your patterns.

This change improves debuggability for voice agent startup failures. When the voice agent cannot load its configuration, the error message now tells the operator exactly which resource is missing and what API call to make to fix it.

No breaking changes to successful responses.

chevron-rightv0.9.409 - Platform API: Email OTP Passwordless Login (July 2026)hashtag

Email OTP Passwordless Login

Operators can now sign in using a one-time code sent to their email address, removing the need for password-based credentials or external identity provider configuration.

What changed:

  • Email OTP initiation endpoint - A new endpoint accepts an email address and sends a 6-digit one-time code. The response is always the same regardless of whether the email belongs to an existing account, preventing account enumeration. Codes expire after a configurable window (default 10 minutes) and are limited to a fixed number of verification attempts.

  • grant_type=email_otp on the token endpoint - The token endpoint now accepts email_otp as a grant type. Callers submit the email address, the 6-digit code, and an optional intent field ("operator" or "provider"). On successful verification, the platform returns an access token and refresh token following the same flow as other grant types, including workspace resolution, IP allowlist checks, MFA enforcement, and lockout protections.

  • Rate limiting - The initiation endpoint enforces per-IP and per-email rate limits. Exceeding either threshold returns 429. Rate limit windows and thresholds are configurable via environment variables.

  • Lockout integration - Failed code verification attempts count toward both IP-based and email-based lockout counters. This prevents brute-force attacks from a single IP as well as distributed attacks targeting a specific email address.

  • Single-use codes - A valid code is consumed on successful verification and cannot be reused. Codes are also deleted when the maximum attempt count is reached, even if the correct code was never submitted.

  • Intent namespacing - Codes are namespaced by intent (operator or provider), so a code minted for one intent cannot be replayed against the other. Provider intent is not yet wired and returns 501 until a future release completes the provider authentication path.

  • Multi-workspace support - If the operator belongs to multiple workspaces and no workspace_id is specified, the token endpoint returns a workspace selection token (HTTP 300) following the same pattern as SSO-based grants.

Who is affected:

This is a new capability. No existing authentication flows are changed. Operators who want to use email-based login need an existing account with a registered email address. No auto-provisioning occurs through this flow - operators must already exist in the workspace directory.

Email delivery requires the platform's outbound email sender to be configured. When the sender is not configured, code generation is disabled but verification of pre-existing codes still works.

chevron-rightv0.9.408 - Platform API: Phone Number Write Fields Removed (July 2026)hashtag

Phone Number Write Fields Removed

The channel_phone_id and sub_account_sid fields have been removed from the phone number create and update request bodies. These fields were made obsolete when credential resolution moved to a cached lookup path and the underlying storage columns were dropped.

What changed:

  • channel_phone_id removed from create and update requests - The channel_phone_id field is no longer accepted when creating or updating a phone number. Previously, this field allowed callers to associate a channel-manager phone identifier with a platform phone number record. Credential resolution no longer depends on this field.

  • sub_account_sid removed from create and update requests - The sub_account_sid field is no longer accepted when creating or updating a phone number. This field previously carried the telephony sub-account identifier used for credential lookup. Credential resolution now happens automatically through the channel manager without requiring this value on the phone number record.

  • channel_phone_id retained on responses (deprecated) - The channel_phone_id field continues to appear on phone number response objects for SDK backward compatibility, but always returns null. This field will be removed from the response schema after the standard two-release deprecation window.

  • Bind channel phone endpoint unchanged - The bind-channel-phone endpoint continues to look up the phone from the channel manager by ID and create the local binding. Credential resolution at call time flows through the channel manager automatically.

Who is affected:

Clients that pass channel_phone_id or sub_account_sid when creating or updating phone numbers. These fields are now silently ignored by older SDK versions and rejected by updated SDKs. Remove these fields from your request payloads.

Clients that read channel_phone_id from phone number responses should prepare for its removal in a future release. The field currently always returns null.

No breaking changes for clients that do not send these fields.

chevron-rightv0.9.407 - Platform API: Legacy Text Stream WebSocket and Session Connect Proxy Removed (July 2026)hashtag

Legacy Text Stream WebSocket and Session Connect Proxy Removed

The legacy real-time text stream WebSocket endpoint and the session connect WebSocket proxy have been removed. All real-time text conversation functionality is now served exclusively through the turn-based conversation API and SSE-based turn streaming.

What changed:

  • Text stream WebSocket removed - The legacy WebSocket endpoint for real-time bidirectional text chat has been removed. This endpoint provided a persistent WebSocket connection for text conversations with frame types including session_started, session_ended, message, typing, tool_call_started, tool_call_completed, error, ping, and response_complete. Clients using this endpoint must migrate to the turn-based conversation API.

  • Session connect WebSocket proxy removed - The /sessions/connect WebSocket endpoint, which proxied bidirectional frames between clients and the text stream backend, has been removed. This proxy handled authentication, origin validation, per-workspace concurrency caps, burst rate limiting, and upstream connection management. Clients using this endpoint must migrate to the turn-based conversation API.

  • Text stream frame schema removed from OpenAPI - The TextStreamFrame discriminated union schema and all constituent frame type schemas have been removed from the published OpenAPI specification. SDK consumers that imported these types should remove references to them.

  • WebSocket transport removed - The internal WebSocket-based text transport used by the text stream endpoint has been removed. Text conversations now use the standard turn-based transport exclusively.

Who is affected:

Clients that connected to the text stream WebSocket endpoint for real-time text conversations, or to the session connect WebSocket proxy. These clients must migrate to the turn-based conversation API, which provides equivalent functionality through explicit conversation creation and turn submission with SSE-based streaming responses.

Clients already using the turn-based conversation API are not affected.

Migration guide:

  1. Replace WebSocket connection setup with a conversation creation call followed by turn submissions.

  2. Replace WebSocket frame listening with SSE turn stream consumption.

  3. Remove any client-side handling of the 9 text stream frame types (session_started, session_ended, message, typing, tool_call_started, tool_call_completed, error, ping, response_complete).

  4. Remove any imports of TextStreamFrame or related frame types from SDK packages.

This is a breaking change for clients using the removed endpoints.

chevron-rightv0.9.406 - Platform API: Canonical ID Resolution for Sessions and Outbound Calls (July 2026)hashtag

Canonical ID Resolution for Sessions and Outbound Calls

The session start and outbound call endpoints now accept a canonical identifier as an alternative to the entity UUID, so integrations that work with source-system identifiers can reference patients without a prior entity lookup.

What changed:

  • canonical_id on session start - The /sessions/start endpoint now accepts an optional canonical_id field (formatted as source:resource_type:id, e.g. revolution:Patient:67890) as an alternative to entity_id. The platform resolves the canonical identifier against the world model to find the corresponding person entity in the workspace. Exactly one of entity_id or canonical_id must be provided - supplying both or neither returns a validation error.

  • patient_canonical_id on outbound calls - The /calls/outbound endpoint now accepts an optional patient_canonical_id field as an alternative to patient_entity_id. The same resolution and mutual-exclusivity rules apply. The resolved entity UUID is used for all downstream processing.

  • Structural validation on canonical identifiers - Canonical identifiers are validated against a strict format: three colon-separated alphanumeric segments (allowing ., _, -), between 3 and 256 characters. This rejects free-form text, spaces, and special characters that could carry regulated content. Values that fail validation receive a 422 response without echoing the rejected input.

  • PHI-safe error handling - Validation errors on both endpoints suppress input values from error response bodies. If a canonical identifier or phone number fails validation, the error message describes the constraint violation without echoing the submitted value.

  • Projection lag consideration - Canonical identifier resolution runs against the projected world model. An entity created moments before the API call may not yet be visible if the projection has not caught up. In this case, the endpoint returns a 404.

Who is affected:

Integrations that initiate text sessions or outbound calls and already have a source-system patient identifier (e.g. from an EHR or practice management system). These integrations can now pass the canonical identifier directly instead of first resolving it to an entity UUID via a separate API call.

Existing integrations that pass entity_id or patient_entity_id continue to work without changes. Both fields remain supported.

No breaking changes.

chevron-rightv0.9.405 - Platform API: EHR Patient Roster Sync, Credential-Scope Detection, and Outbound Endpoint Corrections (July 2026)hashtag

EHR Patient Roster Sync, Credential-Scope Detection, and Outbound Endpoint Corrections

The EHR connector now syncs the full patient roster with demographics, detects credential-scope misconfigurations that limit clinical data visibility, and corrects the outbound write-back endpoints for patient creation and appointment booking.

What changed:

  • Full patient roster sync - The connector now syncs patient demographics (name, date of birth, assigned provider, phone numbers) directly from the EHR's patient registry endpoint instead of relying solely on patient stubs materialized from appointment references. Patients are emitted as FHIR Patient resources through the standard connector pipeline with content-based deduplication. The roster sync runs on its own cadence, independent of appointment and availability polling.

  • Replaces patient stub materialization - Previous releases emitted minimal Patient resources (identifier only) when an appointment referenced an unknown patient. The connector no longer emits these stubs from appointment references because the patient registry and calendar use different identifier spaces with no observed join key. Emitting stubs from both sources would produce duplicate entities. The full roster sync is now the canonical patient source, and cross-source linking is handled by the entity resolver.

  • Date of birth parsing - The connector now parses the EHR's epoch-millisecond date format for patient dates of birth. Parsed dates are emitted as standard ISO 8601 date strings on the FHIR Patient resource. Unparseable or missing dates are omitted rather than emitting a zero-epoch placeholder.

  • Phone number mapping - Patient phone numbers from the EHR are mapped to FHIR telecom entries with appropriate use codes (mobile, home, work) based on the phone type reported by the EHR. When the EHR returns phone records in an unrecognized format, the connector logs a structured warning and omits the affected entries rather than emitting empty telecom data.

  • Credential-scope detection - The connector now detects when EHR credentials lack clinical-calendar visibility. If the calendar endpoint returns only administrative entries (such as block-out periods) with no clinical sessions, the connector emits a structured error indicating that the credentials likely need to be rotated to a clinical role or granted additional permissions. Patient demographics continue to flow via the roster sync even when calendar visibility is restricted.

  • Administrative event filtering - Non-clinical calendar entries (block-out periods, administrative holds) are now filtered from the appointment sync. Previously these entries were emitted as FHIR Appointments, which created phantom patient-less appointments visible to downstream consumers.

  • Outbound endpoint corrections - The outbound write-back endpoints for patient creation and appointment booking have been corrected to target the EHR's actual API endpoints. The write-back guard introduced in v0.9.403 continues to prevent these endpoints from firing in production until field-level validation is complete against a live capture of the EHR's form submission.

  • Roster size safety cap - The patient roster sync enforces a safety cap to guard against multi-tenant configuration errors. If the roster exceeds the cap, it is truncated with a structured error log so operators can investigate.

Who is affected:

Workspaces using the EHR connector for practice management integration. Patient data now appears in the world model with full demographics rather than identifier-only stubs. Existing appointment sync behavior is unchanged except for the filtering of administrative entries.

No breaking changes.

chevron-rightv0.9.404 - Platform API: Typed Text Stream WebSocket Frames (July 2026)hashtag

Typed Text Stream WebSocket Frames

The text-stream WebSocket endpoint now has a formally defined frame schema, giving SDK consumers a typed contract for every frame the server can emit.

What changed:

  • Typed frame schema - The text-stream WebSocket now publishes a discriminated union schema (TextStreamFrame) covering every frame type the endpoint emits. Each frame is distinguished by a type field. SDK consumers can switch on type to handle each frame variant without maintaining local type definitions that can drift from the server contract.

  • Frame inventory - The schema covers the full set of frames:

    • Lifecycle frames (always emitted): session_started, session_ended, error, ping, typing, response_complete, message

    • Tool call frames (emitted when tool_events=true): tool_call_started, tool_call_completed

  • Frame details:

    Frame type
    Key fields
    Description

    session_started

    session_id, conversation_id

    First frame after the WebSocket handshake. Carries the server-assigned session ID and the conversation ID (newly created or the one supplied via query param).

    session_ended

    reason

    Graceful end of conversation. Reason echoes the agent's completion reason (e.g. stopped, completed, escalated, disconnected, other).

    error

    message

    Recoverable error mid-session. The connection may remain open; terminal errors close the WebSocket with a status code instead.

    ping

    (none)

    Keepalive frame. Consumers should reset their dead-socket watchdog and otherwise ignore it.

    typing

    (none)

    Indicates the agent is preparing a response. Pure UX hint.

    response_complete

    duplicate

    Marks the end of an agent turn. duplicate is true when the server suppressed a repeated response.

    message

    role, text

    Final consolidated agent message for a turn. role defaults to agent.

    tool_call_started

    tool_name, call_id, input

    A tool call from the most recent agent turn. input is the tool's input as an object, string, or null.

    tool_call_completed

    tool_name, call_id, result, succeeded

    Companion to tool_call_started. result is the tool's stringified output. succeeded indicates whether the tool returned successfully.

  • Flat wire format - Text-stream frames place all fields at the top level of the JSON object (e.g. {"type": "tool_call_started", "tool_name": "...", ...}). This differs from the voice observer WebSocket, which nests payload fields inside a data envelope. The distinction is now explicit in the published schema, preventing the class of integration bugs where consumers apply the wrong envelope expectation.

  • Forward compatibility - Consumers that encounter an unknown type value should drop the frame and continue. The server may add new frame types in future releases without a breaking change.

  • OpenAPI schema - The TextStreamFrame discriminated union and all constituent frame schemas are now published as named components in the Platform API OpenAPI specification.

Who is affected:

Platform API users who integrate with the text-stream WebSocket. SDK users get typed frame models automatically. Direct WebSocket consumers can reference the OpenAPI schema for validation. No wire-format changes - this release formalizes and documents the existing frame shapes.

No breaking changes.

chevron-rightv0.9.403 - Platform API: EHR Appointment Sync, PHI-Safe Field Filtering, and Outbound Write-Back Guard (July 2026)hashtag

EHR Appointment Sync, PHI-Safe Field Filtering, and Outbound Write-Back Guard

The EHR connector now syncs scheduled appointments alongside therapist rosters and availability, applies stricter PHI filtering to all synced data, and gates outbound write-back until endpoint verification is complete.

What changed:

  • Appointment inbound sync - The EHR connector now polls scheduled appointments on the same cadence as availability data. Each poll covers a configurable window of recent past and upcoming future appointments, so the world model reflects both completed sessions and upcoming bookings. Appointments are emitted as FHIR Appointment resources through the standard connector pipeline with content-based deduplication.

  • Patient stub materialization - When an appointment references a patient not yet known to the world model, the connector emits a minimal Patient resource containing only the patient identifier. This ensures appointment-to-patient references resolve immediately. Full patient demographics are backfilled by a separate patient detail sync.

  • PHI-safe field allowlisting - Raw EHR fields attached to synced resources are now filtered through an explicit allowlist. Only fields that have been reviewed and confirmed free of protected health information are forwarded. Previously, all unmapped non-empty fields were included. Fields like appointment titles (which can contain patient names in plain text), account balances, and payment status are now excluded by default. New fields from upstream schema changes are blocked until explicitly reviewed.

  • Outbound write-back endpoint guard - Outbound write-back to the EHR is now gated behind an explicit verification flag. Write-back requests are logged and tracked but not executed until the target endpoints have been verified against a live tenant. This prevents silent failures where write-back requests would land on error pages without any indication of data loss. The guard applies to both patient creation and appointment creation write-back paths.

  • Improved error classification - Transient network errors and temporary upstream failures during connector syncs are now classified separately from permanent errors. Transient failures skip the current sync tick and retry on the next poll cycle. Permanent failures (such as invalid credentials) propagate immediately so monitoring alerts fire without delay. Error logs no longer include stack traces that could contain patient identifiers.

Who is affected:

Platform API users with EHR integrations. Appointment data will begin appearing in the world model automatically. The PHI field filtering change may reduce the number of raw fields visible on synced resources - only reviewed, PHI-free fields are included. Outbound write-back users will see write-back attempts logged as skipped until endpoint verification is completed in a future release.

No breaking changes.

chevron-rightv0.9.402 - Platform API: WhatsApp Text Turns and Per-Number Response Modality (July 2026)hashtag

WhatsApp Text Turns and Per-Number Response Modality

The platform now supports text-based WhatsApp conversations alongside the existing voice note path, with per-number configuration controlling whether the agent responds with text or voice notes.

What changed:

  • New text turn endpoint - A new POST /v1/{workspace_id}/services/{service_id}/text-turn endpoint accepts a user's text message and phone number, runs one conversational turn through the agent, and returns the agent's text reply synchronously. Session continuity is managed server-side, keyed on the combination of workspace, service, and phone number - no caller-supplied session identifier is needed. The endpoint returns 200 with the agent's text reply, 204 if the agent elects silence, or 409 if a concurrent turn for the same speaker is already in progress.

  • Per-number response modality - Each WhatsApp number can now be configured with a response modality: voice note or text. Numbers configured for voice note responses continue to work as before - inbound voice notes are processed through the voice turn pipeline and the agent replies with audio. Numbers configured for text responses route inbound text messages through the new text turn pipeline and the agent replies with text.

  • Cross-modality handling - When a user sends a message in the wrong modality for a number (e.g., a voice note to a text-only number, or a text message to a voice-only number), the platform replies with a brief message directing the user to the supported modality. This prevents messages from being silently dropped.

  • Shared session model - Text turns use the same session continuity, concurrent-turn protection, and engine pipeline as voice turns. The conversation state persists across turns for the same speaker, so multi-turn text conversations maintain context.

Request body (POST /v1/{workspace_id}/services/{service_id}/text-turn):

Field
Type
Required
Description

phone_number

string

Yes

User's phone number in E.164 format (e.g., +15551234567)

text

string

Yes

User's text message (1-8192 characters)

Response body (200):

Field
Type
Description

text

string

Agent's text reply

Who is affected:

Platform API users who want to support text-based WhatsApp conversations. The existing voice turn endpoint is unchanged. Numbers not configured for the new text modality continue to work exactly as before.

No breaking changes.

chevron-rightv0.9.401 - Platform API: Channel Endpoint Resolution and Outbound Call Routing (July 2026)hashtag

Channel Endpoint Resolution and Outbound Call Routing

The platform now resolves channel configuration through a unified endpoint registry, improving outbound call routing reliability and reducing lookup latency for high-volume workspaces.

What changed:

  • Unified channel endpoint resolution - Inbound webhook processing now resolves the target workspace through a unified channel endpoint registry before falling back to the legacy workspace binding lookup. This dual-read approach ensures continuity for existing configurations while transitioning to the new registry. The resolution path is tracked on each event so migration completeness can be verified before the legacy lookup is removed.

  • Faster outbound call routing - Outbound calls now resolve sender credentials through a two-tier shared cache. The first tier is per-process and survives for the duration of the process. The second tier is shared across all processes and survives process restarts, so a cold process can serve outbound calls without scanning all channel configurations. For workspaces with many phone numbers, this eliminates the per-call configuration scan that previously added latency to every outbound call.

  • Dual-write for new channel configurations - When a new channel use case is created, the platform now writes to both the legacy workspace binding table and the new channel endpoint registry. This ensures the new registry is populated going forward without requiring a backfill migration. Existing configurations continue to work through the legacy lookup until a future release backfills them.

  • Resolution source attribution on outbound calls - Outbound call log entries now include the source that resolved the sender credentials (legacy lookup, channel registry, or unresolved). This makes it easier to diagnose misrouted calls during the transition period.

Who is affected:

All Platform API users who use outbound calling or receive inbound channel events (email delivery notifications, voicemail events). No configuration changes required. Existing channel configurations continue to work without modification.

No breaking changes.

chevron-rightv0.9.400 - Platform API: Enriched Tool Call Event Schemas (July 2026)hashtag

Enriched Tool Call Event Schemas

Tool call events emitted by the observer stream and the conversation turn stream now carry richer metadata, making it easier to trace tool execution across nested calls, correlate calls with integrations, and diagnose failures.

What changed:

  • Call ID on all tool call events - Every tool call started and tool call completed event now includes a unique call identifier. Observer events and turn stream events both carry this identifier, so you can correlate a started event with its corresponding completed event across either stream.

  • Nested tool call tracing - Tool call events now support a parent call identifier. When a tool invokes another tool during execution, the child call references the parent, giving you a full call tree for complex multi-step tool chains.

  • Integration and endpoint attribution - Tool call events can now include the integration name, endpoint name, and protocol associated with the call. This lets you see which external system a tool targeted and how it connected, without inspecting tool configuration separately.

  • Flexible input representation - The tool call started event now accepts input as either a structured object or a string, accommodating tools that receive free-form text inputs alongside those that accept structured parameters.

  • Consistent error reporting - The error field on tool call completed events has been renamed to a dedicated error message field with a maximum length, providing clearer separation between error reporting and other event metadata.

  • Field length constraints - Tool name, call identifier, integration name, endpoint name, and protocol fields now enforce minimum and maximum length constraints. These constraints ensure consistent event payloads and prevent oversized values from degrading downstream consumers.

Who is affected:

All Platform API users who consume the observer SSE stream or the conversation turn stream. The new fields are additive. Existing consumers that do not read the new fields continue to work without changes.

Breaking change: The tool_input field on tool call started observer events has been renamed to input, and the error field on tool call completed observer events has been renamed to error_message. Consumers that reference these fields by name must update accordingly.

chevron-rightv0.9.399 - Platform API: Provider Principal Type and Scribe Scopes (July 2026)hashtag

Provider Principal Type and Scribe Scopes

The Platform API identity system now supports a dedicated provider principal type with its own fixed scope set. Provider tokens are issued to FHIR Practitioner-bound identities through the scribe provider-grant flow and carry only scribe-specific permissions. This establishes a hard isolation boundary between provider credentials and standard user/agent/service-account credentials.

What changed:

  • Provider principal type - Tokens issued through the scribe provider-grant flow now carry principal_type: "provider" and a provider_entity_id claim bound to the FHIR Practitioner entity. The provider_entity_id always equals sub, giving downstream services a dedicated claim to gate provider-scoped reads without re-decoding the subject.

  • Scribe scopes - Two new scopes, scribe:read and scribe:write, are minted exclusively for provider tokens. These scopes are never included in standard role expansions (viewer, member, operator, admin, owner) and are never delegatable through agent session children. This means no standard role - including owner - can pass a scribe:read or scribe:write permission check, and provider tokens cannot carry any non-scribe scopes.

  • Bidirectional isolation - The identity verifier enforces strict separation in both directions. Provider tokens must carry only scribe scopes, must include a valid provider_entity_id equal to sub, and must not carry a role claim. Non-provider tokens must not carry scribe scopes or a provider_entity_id claim. Tokens that violate these constraints are rejected at verification time.

  • Role expansion unchanged - The owner role remains the universal-grant role for standard principals, but its scope set no longer includes scribe scopes. All existing role-based permission checks continue to work exactly as before. The only change is that scribe scopes are excluded from role expansion by design.

Who is affected:

All Platform API users who work with the clinical scribe or provider access features. Existing user, agent, and service-account tokens are not affected. Provider tokens issued through the scribe provider-grant flow now carry the new principal type and scopes automatically.

No breaking changes to existing tokens or role-based permissions.

chevron-rightv0.9.398 - Platform API: Provider Access Grants and Email Verification (July 2026)hashtag

Provider Access Grants and Email Verification

The Platform API now supports granting providers access to specific workspaces and verifying provider email addresses before access is activated. This enables organizations to onboard individual providers with verified identity, scoped workspace access, and configurable permission levels.

What changed:

  • Provider access grants - A new resource lets you grant a provider access to a workspace with a specific role. Each grant ties a provider identity to a workspace and tracks its lifecycle through pending, active, suspended, and revoked states. Grants can be created, listed, retrieved, updated, and revoked through the API. When a grant is created for a provider whose email has not yet been verified, the grant remains in a pending state until verification completes.

  • Provider email verification - A new verification flow lets you confirm a provider's email address before activating their workspace access. The platform sends a verification message to the provider's email, and the provider completes verification through a confirmation step. Once verified, any pending access grants for that provider are automatically activated. Verification status is tracked per provider and can be queried through the API.

  • Scoped permissions - Each access grant includes a role that determines what the provider can do within the workspace. Roles follow the same permission model used elsewhere in the platform, so organizations can control provider access at the same granularity as other workspace members.

  • Lifecycle management - Grants can be suspended and reactivated without being revoked, allowing temporary access changes. Revoking a grant is permanent. The full state history is preserved for audit purposes.

Who is affected:

All Platform API users who manage provider access to workspaces. The new resources are additive and do not affect existing workspace membership or authentication flows.

No breaking changes.

chevron-rightv0.9.397 - Platform API: NDJSON Streaming FHIR Import (July 2026)hashtag

NDJSON Streaming FHIR Import

A new streaming import endpoint lets you send FHIR resources as NDJSON (one resource per line) without buffering the entire payload. This bypasses the body-size cap on the existing batch import endpoint, making it suitable for large data loads.

What changed:

  • New endpoint: POST /fhir/import-stream - Accepts an application/x-ndjson body where each line is a standalone FHIR resource (not wrapped in a Bundle). The server processes resources line-by-line as bytes arrive, so memory usage stays constant regardless of payload size. Query parameters source, source_system, and data_source_id replace the JSON body fields used by the batch endpoint.

  • Caller contract - Patient resources must appear before any resource that references them (Observation, Condition, etc.), because the streaming reader processes lines in arrival order. Bundle-internal urn:uuid: references must be pre-resolved to {ResourceType}/{id} before sending - the streaming route does not maintain a reference map.

  • Same response shape - The response body matches the existing batch import endpoint: events_created, events_skipped, events_updated, entities_created, entities_updated, and errors. Per-line errors are appended to the errors list with their line number; processing continues past errors.

  • Same upsert semantics - When source is ehr_sync, the streaming route uses the same upsert logic as the batch route (skip identical, supersede on change). Other source values use blind insert.

  • Safety limits - Individual lines are capped at 1 MiB and the total stream is capped at 1 million lines. Exceeding either limit returns a 400 error.

  • Batch endpoint unchanged - The existing POST /fhir/import endpoint continues to work as before. Internal refactoring shares common logic between the two routes but introduces no behavioral changes to the batch path.

Who is affected:

All Platform API users who import FHIR data. The new endpoint is additive - existing integrations using POST /fhir/import are not affected.

No breaking changes.

chevron-rightv0.9.396 - Platform API: Simulation Metric Availability (July 2026)hashtag

Simulation Metric Availability

Simulation runs, sessions, coverage graphs, and benchmark results now expose metric availability status, so clients can tell whether asynchronous metric evaluation has completed without polling separate endpoints.

What changed:

  • Metric availability on runs - The get-simulation-run endpoint now returns three new fields: metric_status (one of pending, available, or unavailable), metric_result_count (number of metric results produced so far), and metrics_last_checked_at (timestamp of the last availability check). These fields indicate whether the asynchronous metric evaluation pipeline has produced results for the run.

  • Metric availability on sessions - The list-simulation-sessions and coverage-graph endpoints now include the same three metric availability fields on each session object when filtered by run. Sessions also include immediate_score and immediate_score_rationale, preserving the original simulation scores alongside the delayed metric results.

  • Metric availability on benchmarks - The benchmark results endpoint now includes aggregate-level metric availability (metric_status, metric_result_count, metrics_last_checked_at) computed across all constituent runs. Each per-run summary also includes per-run metric availability and preserves the original immediate scores as immediate_average_score, immediate_passed, immediate_pass_count, and immediate_fail_count.

  • Graceful degradation - If the metric availability check fails for any reason, the response defaults to pending status with zero results rather than failing the entire request. This ensures that simulation endpoints remain reliable even when the metric pipeline is temporarily unavailable.

Who is affected:

All Platform API users who use simulations or benchmarks. The new fields are additive and default to safe values (pending status, zero count, null timestamp), so existing integrations are not affected.

No breaking changes.

chevron-rightv0.9.395 - Platform API: Typed Entity Lookup Tools (July 2026)hashtag

Typed Entity Lookup Tools

Nine new built-in tools give agents structured, read-only access to specific entity types in the world model. Each tool returns flat, agent-friendly results scoped to the current workspace, with patient-scoped tools accepting a flexible patient identifier.

What changed:

  • Nine new lookup tools - One tool per entity type, each returning filtered, flat results capped at 100 rows:

Tool
Scope
Description

observations_lookup

Patient

Lab results, vitals, and biomarker observations. Filter by marker name, category, status, date range, or out-of-range flag.

medication_statements_lookup

Patient

Medications the patient is or was taking (distinct from prescriptions). Filter by drug name, status, or date range.

clinical_notes_lookup

Patient

Clinical note metadata (type, status, date, encounter reference). Note body content is not returned - metadata only. Filter by note type or date range.

family_history_lookup

Patient

Family member history with relationship, conditions, and deceased flag. Filter by relationship or condition name.

questionnaire_responses_lookup

Patient

Intake forms and screening questionnaires with status, date, and item count. Filter by questionnaire name, status, or date range.

intake_uploads_lookup

Workspace

Intake file metadata (filename, type, size, upload date). Filter by filename, MIME type, or date range.

persons_lookup

Workspace

Person entities with privacy-conservative output (name, gender, and identifiers only - no phone, email, date of birth, or address in responses). Supports search by name, gender, MRN, or date-of-birth range as input filters.

conversations_lookup

Workspace

Agent conversation sessions. Filter by channel type, status, or date range.

calls_lookup

Workspace

Voice call records. Filter by direction, outcome, or date range.

  • Flexible patient identifier - Patient-scoped tools accept a patient_id parameter that resolves against multiple identifier types: platform UUID, canonical ID (e.g. patient_054), MRN, or FHIR Patient ID. The platform resolves the identifier server-side, so agents do not need to know which identifier format a patient uses.

  • Existing tools updated - Several existing tools (update_demographics, get_encounters, get_medications, refill_prescription, insurance_create, log_triage, and surface template tools) now accept the same flexible patient identifier format. Previously these tools required the platform UUID only.

  • Privacy-conservative design - The persons_lookup tool returns only entity ID, canonical ID, name, and gender. Sensitive fields (phone, email, MRN, date of birth, address) are accepted as search filters but are never included in the response. This prevents sensitive data from appearing in agent context or conversation logs.

Who is affected:

All Platform API users. The new tools are available immediately for any agent with world model access enabled. Existing tools continue to work unchanged - the flexible identifier acceptance is backward-compatible (platform UUIDs still work).

No breaking changes.

chevron-rightv0.9.394 - Platform API: Per-Entity Enrichment in Agent Context (July 2026)hashtag

Per-Entity Enrichment in Agent Context

Workspace-curated enrichment data attached to patient entities now appears automatically in the agent's conversation context. This gives agents access to operator-defined key-value pairs (such as external system identifiers or custom labels) without requiring additional tool calls.

What changed:

  • Enrichment in caller context - When a known caller is identified, any enrichment key-value pairs associated with their entity are rendered into the agent's system prompt alongside existing demographic and clinical context. Values are sorted alphabetically by key for consistent prompt ordering across turns.

  • Enrichment in state rendering - The same enrichment data is included when rendering the full patient state context, ensuring consistency between the caller identification path and the general state rendering path.

  • Safety controls - Enrichment values are sanitized before inclusion in the prompt: non-string values are skipped, empty values are omitted, and newline characters are replaced with spaces to prevent prompt structure injection.

Who is affected:

Workspaces that use entity enrichment. Enrichment values that were previously only accessible through the world model API now appear in agent context automatically. No configuration changes required.

No breaking changes.

chevron-rightv0.9.393 - Platform API: Conversation Turn Data Coercion Hotfix (July 2026)hashtag

Conversation Turn Data Coercion Hotfix

Fixed a data shape inconsistency in conversation turn records where certain array fields could be stored as serialized strings rather than native arrays. The platform now normalizes these fields on read, preventing validation errors when loading conversation history.

What changed:

  • Automatic field normalization - The tool_calls and state_transitions fields on conversation turn records are now coerced to arrays on read. Previously, historical data written by earlier platform versions could contain these fields as serialized strings, causing turn deserialization to fail.

  • Graceful handling of malformed data - If a field contains an unparseable value or an unexpected type, the platform returns an empty array rather than failing the entire turn load. Anomalous values are logged for operational visibility without exposing field contents.

Who is affected:

Workspaces with conversation history predating the fix. Turn loading that previously failed with validation errors now succeeds. No action required.

No breaking changes.

chevron-rightv0.9.392 - Platform API: JSON Token Exchange Auth and Integration Auth Flexibility (July 2026)hashtag

JSON Token Exchange Auth and Integration Auth Flexibility

Integrations now support a new json_token_exchange authentication type for APIs that accept credentials as a JSON body rather than form-encoded OAuth2 requests. Additionally, REST and FHIR integrations can now be created and updated without an auth configuration, and PATCH operations can explicitly clear auth by setting it to null.

What changed:

  • json_token_exchange auth type - New authentication method that POSTs credentials as a JSON object to a token endpoint and extracts a bearer token from the JSON response. The request body field names and the response token path are fully configurable, making this compatible with non-standard token APIs. Token lifetime is determined automatically from the response, the token's embedded expiry, or a configured fallback. Tokens are cached and refreshed before expiry.

  • New auth configuration fields - Three new fields on the integration auth configuration support the JSON token exchange flow:

Field
Type
Description

token_request_client_id_field

string (1-256 chars)

JSON field name for the client ID in the token request body

token_request_client_secret_field

string (1-256 chars)

JSON field name for the client secret in the token request body. Must differ from the client ID field name.

token_response_path

string (1-512 chars)

Dot-delimited path to the access token in the JSON response (e.g., data.access_token)

  • Auth no longer required for REST/FHIR integrations - REST and FHIR integrations can now be created without an auth block. This supports integrations that connect to endpoints not requiring authentication, or where auth will be configured later.

  • PATCH can clear auth - Sending {"auth": null} in a PATCH request now explicitly removes the auth configuration from an integration. Previously, null values were ignored during partial updates.

  • PATCH validates auth on update - When a PATCH request includes a non-null auth block, the platform validates the auth configuration before applying the update. Previously, auth validation only ran during integration creation.

Required fields for json_token_exchange:

token_url, client_id, client_secret_ssm_param_path (or inline secret), token_request_client_id_field, token_request_client_secret_field, token_response_path

Who is affected:

No impact on existing integrations. The new auth type is opt-in. Existing REST/FHIR integrations with auth configurations continue to work unchanged. The auth-optional creation and PATCH-clear behaviors are additive.

chevron-rightv0.9.391 - Platform API: Scheduling Rules Enforcement in Slot Search (July 2026)hashtag

Scheduling Rules Enforcement in Slot Search

The slot search tool now supports opt-in deterministic scheduling-rule enforcement. When enabled, workspace-level scheduling rules are evaluated against candidate slots before results are returned, and any slots that violate the rules are dropped with a per-slot reason.

What changed:

  • apply_scheduling_rules parameter - New boolean parameter on slot search. When set to true, the platform loads the scheduling rule set configured for the workspace and agent kind, then filters candidate slots through the active rules before returning results. Off by default - existing callers see no behavior change.

  • agent_kind parameter - New string parameter (tms, ketamine, or general) that selects which rule set to apply. Required when apply_scheduling_rules is true. Pass the kind that matches the calling agent's clinical context.

  • patient_entity_id parameter - Optional patient entity UUID. Required to enforce the rolling safety-window rule (patient-specific scheduling cap). When apply_scheduling_rules is true and no patient context is provided, safety-window rules are reported as skipped in the response metadata rather than silently ignored.

  • Rolling safety-window rule - The ninety-day rolling rule is now fully wired into the slot search pipeline. When a patient entity ID is provided, the platform checks the patient's recent appointment history and drops any slots that fall within the configured exclusion window of an existing appointment. The rule enforces a symmetric window around each existing appointment.

  • Rule drop reporting - Slots removed by scheduling rules appear in search_metadata.rule_drops with a per-slot rule_kind and human-readable reason string. This lets callers explain to patients why specific times are unavailable.

  • Active rule metadata - The response includes search_metadata.scheduling_rules_applied (the agent kind used), search_metadata.scheduling_rules_active_kinds (which rule types were evaluated), and optional scheduling_rules_degraded and scheduling_rules_skipped lists. Degraded rules are ones where the backing data fetch failed - the platform surfaces the gap rather than silently allowing slots that might violate the rule. Skipped rules are ones where the required input (e.g., patient context) was not provided.

  • Graceful degradation - If a rule's backing data cannot be fetched within the response budget, that specific rule is disabled for the request and reported in the degraded metadata. Other rules continue to enforce normally. The platform never silently claims clean enforcement when a safety rule could not run.

  • Filtering before truncation - Rule filtering runs before the max_results cap is applied, so dropped slots are replaced by the next surviving candidates rather than reducing the returned count.

New slot search parameters:

Parameter
Type
Required
Description

apply_scheduling_rules

boolean

No

Opt-in flag for deterministic scheduling-rule enforcement. Off by default.

agent_kind

string

When apply_scheduling_rules is true

Agent kind (tms, ketamine, or general) selecting the rule set.

patient_entity_id

string (UUID)

No

Patient entity UUID. Required for safety-window rules; other rules ignore this field.

New search_metadata fields:

Field
Type
Description

scheduling_rules_applied

string or null

The agent kind used for rule enforcement, or null if rules were not applied.

scheduling_rules_active_kinds

array of strings

Rule types that were evaluated (e.g., clinic_open_hours, ninety_day_rolling).

scheduling_rules_degraded

array of strings

Rule types where the backing data fetch failed. Only present when non-empty.

scheduling_rules_skipped

array of strings

Rule types skipped due to missing call context. Only present when non-empty.

rule_drops

array of objects

Slots removed by rules. Each entry has slot_id, rule_kind, and reason.

Who is affected:

No impact on existing callers. The new parameters are opt-in. Callers that begin passing apply_scheduling_rules=true must also pass a valid agent_kind or they will receive a 400-level validation error.

chevron-rightv0.9.390 - Platform API: Skills Route Hardening and Audit Logging (July 2026)hashtag

Skills Route Hardening and Audit Logging

The skills API now enforces stricter input validation on all create and update fields, emits audit events for every skill mutation, and documents additional error responses.

What changed:

  • Audit logging for skill mutations - Create, update, and delete operations now emit audit events (skill.create, skill.update, skill.delete) that capture the workspace, skill ID, skill name, slug, execution tier, and the identity of the API key that performed the action. Update events also record which fields were changed. Audit events are fire-and-forget and never block the response to the client.

  • Stricter field validation - Several fields now enforce minimum length and maximum size constraints that were previously absent:

    • slug validates against a pattern requiring lowercase alphanumeric characters, hyphens, and underscores (2-63 characters, must start and end with a letter or digit).

    • name, description, and system_prompt use the platform's standard bounded-string types (name: 1-255 chars, description: 1-1000 chars, system prompt: up to 10,240 chars).

    • model, browser_start_url, and browser_auth_integration now enforce minimum length of 1 when provided, rejecting empty strings with 422.

    • input_schema and result_schema are validated against a maximum serialized size (100 KiB) to prevent oversized payloads.

  • Typed execution tier filter - The execution_tier query parameter on the list endpoint now validates against the set of known tiers (direct, orchestrated, autonomous, browser, computer_use). Previously, any string was accepted and silently returned no results if it did not match a known tier.

  • Delete conflict response - Deleting a skill that is referenced by one or more context graphs now returns 409 Conflict instead of succeeding silently. The response body includes details about the referencing context graphs.

  • Rate limit responses documented - All skill endpoints now document 429 Too Many Requests in their OpenAPI response schemas.

  • Update field semantics documented - The update endpoint description now explicitly states that omitted fields and explicit null both leave the existing value unchanged, and that clearing an optional field back to null is not currently supported via PUT.

Who is affected:

API consumers sending skill create or update requests. Requests that previously passed validation may now receive 422 if they send empty strings for model, browser_start_url, or browser_auth_integration, or if schemas exceed the size bound. Skill slugs that do not match the documented pattern will also be rejected.

No changes to the response schema for successful requests.

chevron-rightv0.9.389 - Platform API: Entity Resolve Endpoint and Scheduling Rules Engine (July 2026)hashtag

Entity Resolve Endpoint

A new endpoint lets callers resolve a polymorphic identifier - phone number, email, MRN, external system ID, or entity UUID - to ranked entity candidates in a single request. This powers inbound caller identification, webhook entity matching, and any workflow where you know one identifier and need to find the corresponding entity.

What changed:

  • POST /v1/{workspace_id}/entities/resolve - Accepts a required entity_type plus any subset of identifier fields (phone, email, canonical_id, external_id, entity_id). Identifiers are OR-ed: a row matches if any provided identifier matches. Results are ranked by match confidence and by the number of identifiers that actually matched the row. Returns at most limit candidates (default 25, max 50).

  • Confidence scoring - Each match includes a confidence score (0-1) and a matched_on list showing which identifiers contributed to the match. A direct UUID lookup returns confidence 1.0. Phone and system-issued IDs use the same confidence tier as the platform's entity merge resolver, so scoring semantics are consistent across resolution paths.

  • Phone format tolerance - Phone lookups accept any common format (10-digit, 11-digit with country code, E.164 with plus prefix) and generate all plausible variants internally. A stored number in any of these formats will match regardless of how the caller formatted the query.

  • External ID matching - External system identifiers are matched by value across all keys in the entity's external identifiers map. The system field (e.g. epic, hubspot, charm) is informational for scoring; it does not constrain the lookup, since different adapters use different key naming conventions.

  • Compact summary - Each match includes a summary with display name, contact info, MRN, canonical ID, external IDs, last activity timestamp, event count, and tags. Full entity state is available via the existing GET /v1/{workspace_id}/entities/{entity_id} endpoint.

  • Request validation - At least one identifier must be provided. Requests with no identifiers return 400. The entity_type field is required to scope the lookup to the correct index partition.

Request body:

Field
Type
Required
Description

entity_type

string

Yes

Entity type filter (e.g. person).

phone

string

No

E.164 phone number.

email

string

No

Email address (case-insensitive match).

canonical_id

string

No

Canonical/MRN identifier.

external_id

object

No

{system, value} - external system identifier reference.

entity_id

UUID

No

Direct entity UUID lookup.

limit

integer

No

Max candidates (1-50, default 25).

Response fields (per match):

Field
Type
Description

entity_id

UUID

Matched entity ID.

entity_type

string

Entity type.

confidence

float

Match confidence (0-1).

matched_on

string[]

Identifier kinds that matched (phone, email, canonical_id, external_id, entity_id).

summary

object

Compact identity card (display name, phone, email, MRN, canonical ID, external IDs, tags, last activity, event count).

Scheduling Rules Engine

The scheduling rules engine now evaluates workspace-configured rule sets at slot search time, filtering appointment slots before they reach the agent. This completes the server-side enforcement layer for the scheduling rule sets introduced in v0.9.388.

What changed:

  • Deterministic slot filtering - When an agent searches for available appointment slots, the engine loads the active rule set for the workspace and agent kind, then applies each rule in fixed precedence order. Slots that violate a rule are dropped from the results with a reason annotation, so the agent can explain why a slot is unavailable.

  • Rule evaluation order - Rules are applied in this order: clinic open hours, TMS mapping release, TMS session grid, ketamine block overlap, concurrent start block. A slot dropped by an earlier rule is not checked by later rules, keeping the drop reason to one per slot.

  • Fail-open on configuration errors - If rule configuration cannot be loaded (database unavailable, malformed parameters, unknown rule kind), the engine degrades to a no-op filter rather than failing the call. Configuration errors are tracked via telemetry counters so operational issues are visible without impacting live calls.

  • No-op for unconfigured workspaces - Workspaces without active scheduling rules pass all slots through unchanged. The engine short-circuits without evaluating any rules.

Who is affected:

All users of the entity and scheduling APIs. The resolve endpoint is additive. The scheduling rules engine activates automatically for workspaces that have configured rule sets via the v0.9.388 endpoints.

No breaking changes.

chevron-rightv0.9.388 - Platform API: Scheduling Rule Sets (July 2026)hashtag

Scheduling Rule Sets

A new set of endpoints lets workspace operators configure deterministic scheduling rules that filter appointment slots before they reach the agent. Each rule set binds an agent kind (TMS, ketamine, or general) and a rule kind to typed parameters that control slot filtering behavior.

What changed:

  • Scheduling rule set CRUD - Five new endpoints under /v1/{workspace_id}/scheduling-rule-sets support listing, getting, creating, updating, and deleting scheduling rule sets. Rule sets are workspace-scoped, and the combination of agent kind and rule kind is unique per workspace.

  • Typed rule parameters - Each rule kind has its own parameter shape, enforced at the API boundary via a discriminated union on the rule_kind field. Supported rule kinds: clinic_open_hours, tms_mapping_release, tms_session_grid, ketamine_block_overlap, ninety_day_rolling, and concurrent_start_block.

  • Immutable identifiers - The agent_kind and rule_kind fields are immutable after creation. To change either, create a new rule set and delete the old one. The update endpoint enforces this constraint and returns 422 if the submitted params discriminator does not match the existing rule's kind.

  • Conflict detection - Creating a rule set that duplicates an existing (agent kind, rule kind) pair returns HTTP 409 with guidance to update or delete the existing row.

  • Disable without deleting - Rule sets can be toggled on and off via the is_active field without removing the configuration. The list endpoint supports filtering by is_active and by agent_kind.

  • Audit logging - All mutations (create, update, delete) are recorded in the audit log with the acting entity, rule kind, and change summary.

Who is affected:

Workspace operators configuring scheduling behavior for TMS, ketamine, or general agents. The new endpoints are additive. No existing endpoints are changed.

No breaking changes.

chevron-rightv0.9.387 - Platform API: Simulation Benchmark Runs (July 2026)hashtag

Simulation Benchmark Runs

A new benchmark runner lets you execute a batch of saved simulation cases as a single operation, then retrieve aggregated results across the entire batch. This supports regression testing workflows where you run a tagged suite of cases after every agent or context graph change.

What changed:

  • Benchmark run endpoint - POST /simulations/benchmarks/run selects saved simulation cases by tag and launches one simulation run per matching case. Cases run concurrently up to a configurable limit (default 1, maximum 20). Each batch is assigned a stable batch identifier for audit and observability correlation. The response includes per-case launch status (started, skipped, or failed to start), the run identifiers for successfully launched cases, and an aggregate summary with counts.

  • Benchmark results endpoint - POST /simulations/benchmarks/results aggregates status and scores across the run identifiers returned by the benchmark run endpoint. Results include per-run summaries (status, session counts, scores, pass/fail determination), overall averages, and a capability breakdown that groups results by capability tag. Returns 404 if any requested run identifiers are not found.

  • Batch correlation - Each benchmark dispatch produces a batch_id (a stable UUID) that is recorded in the audit log and included in the response. Use this identifier to correlate individual runs back to the batch that launched them.

  • Per-case run refactored - The existing POST /simulations/cases/{case_id}/run endpoint is unchanged in behavior. Internally, the benchmark runner reuses the same case execution logic, ensuring benchmark results are directly comparable to individual case runs.

  • Capability breakdown - Benchmark results include a capability_breakdown map that groups runs by their capability tags (e.g., capability:location_disambiguation, capability:urgent_triage). Each group shows run count, status distribution, scores, and pass/fail counts, giving a per-capability view of agent performance.

Who is affected:

All users of the simulation system. The new endpoints are additive. Existing simulation case and bridge endpoints are unchanged.

No breaking changes.

chevron-rightv0.9.386 - Platform API: Durable Simulation Cases (July 2026)hashtag

Durable Simulation Cases

Simulation scenarios generated by the bridge are now automatically persisted as durable simulation cases. Cases capture the full scenario definition - persona, instructions, initial message, grounding fixtures, constraints, and target specification - so they can be browsed, edited, tagged, and re-run independently of the original simulation run.

What changed:

  • Automatic case persistence - When the simulation bridge generates scenarios (both synchronous and asynchronous modes), each scenario is saved as a simulation case before sessions begin. The bridge response now includes a case_ids array containing the identifiers of all persisted cases. If a run is replayed, previously persisted cases are reused rather than duplicated.

  • Simulation case CRUD - New endpoints support creating, retrieving, listing, and updating simulation cases. Cases are scoped to a workspace and optionally to a specific service. Listing supports filtering by service and by tags, with pagination (maximum page size of 500). Updates are partial - only the fields you include are modified.

  • Case model - Each case includes persona (object), description, scenario_instructions, initial_message, temperament, fixtures (grounding facts snapshot), constraints (rules governing simulated caller behavior), target_spec (scoring specification), assertions (reserved for future automated evaluation), tags (free-form string array), and provenance (manual for hand-authored cases, bridge for generated cases).

  • Streaming partial persistence - In asynchronous bridge runs with streaming scenario generation, cases are persisted incrementally as each scenario arrives from the generator. This ensures that cases are saved even if generation fails partway through.

  • Bridge response updated - The bridge response now includes a case_ids field listing the identifiers of all persisted simulation cases. Existing response fields are unchanged.

Who is affected:

All users of the simulation bridge. Scenarios are now persisted automatically - no changes are required to existing integrations. The case_ids field in the bridge response is additive. Simulation case CRUD endpoints are new and do not affect existing endpoints.

No breaking changes.

chevron-rightv0.9.385 - Platform API: Typed Streaming Endpoint for Conversation Turns (July 2026)hashtag

Typed Streaming Endpoint for Conversation Turns

A new dedicated streaming endpoint for conversation turns provides typed SSE frames without requiring Accept header negotiation. Each frame is validated against a discriminated event union before delivery, so SDK consumers always receive well-formed, predictable payloads.

What changed:

  • New POST /turns/stream endpoint - A new sibling to the existing POST /turns endpoint that always returns text/event-stream regardless of the Accept header. This eliminates the need for clients to set Accept: text/event-stream to opt into streaming. The endpoint accepts the same request body as POST /turns and shares the same validation, rate limiting, and error handling. Use this endpoint for new integrations; the existing POST /turns endpoint continues to support both JSON and SSE responses via Accept header negotiation.

  • Typed event frames - Every SSE frame emitted by both POST /turns/stream and the streaming mode of POST /turns is now validated against the TurnStreamEvent discriminated union before delivery. Each frame carries an event: line with the discriminator value (token, tool_call_started, tool_call_completed, thinking, message, done, error) and a data: line with the full typed JSON payload. Malformed or unrecognized upstream frames are dropped at the API boundary rather than forwarded to clients.

  • Structured error frames - Error frames always include a stable code field and a retryable boolean, so SDK consumers can branch deterministically. Defined codes are upstream_error (the upstream agent returned an HTTP error) and stream_interrupted (transport failure or unexpected stream termination). The status_code field is included on upstream_error frames when available.

  • Guaranteed terminal frame - The stream always ends with a terminal frame (done or error). If the upstream closes without emitting one, the API synthesizes a stream_interrupted error frame so clients never block waiting for a terminator that will not arrive.

  • OpenAPI schema updated - Both POST /turns and POST /turns/stream now reference the TurnStreamEvent schema under the text/event-stream content type in the OpenAPI spec.

Who is affected:

All integrations that consume streaming conversation turns. Existing POST /turns consumers are unaffected - the endpoint continues to work with both Accept: application/json (synchronous) and Accept: text/event-stream (streaming). The new POST /turns/stream endpoint is additive.

SDK consumers that previously parsed raw SSE text will benefit from the typed event contract. Each frame now conforms to a known schema, removing the need for defensive JSON parsing on the client side.

No breaking changes.

chevron-rightv0.9.384 - Platform API: Trigger and Webhook Destination Validation, Rate Limiting, and Audit Logging (July 2026)hashtag

Trigger and Webhook Destination Validation, Rate Limiting, and Audit Logging

Trigger and webhook destination endpoints now enforce stricter input validation, per-route rate limiting, and structured audit logging for all mutating operations. These changes harden the API surface without altering existing request or response shapes for valid inputs.

What changed:

  • Typed field validation on triggers - The event_type field on trigger create and update requests now enforces a consistent format: alphanumeric characters plus ., _, -, :, and *, up to 128 characters. Wildcard patterns (e.g. *.escalated) are permitted so triggers can subscribe to event categories. The schedule field is now validated as a 5- or 6-field cron expression at submission time rather than at fire time, so invalid schedules are rejected immediately with a 422 response. The timezone field is validated against the IANA timezone database, preventing typos like PST or GMT+8 from being accepted.

  • Bounded JSON fields - The event_filter, input_template, and fire-time input override fields on triggers are now validated for structural bounds: maximum nesting depth, maximum number of keys per object, maximum array length, maximum string value length, and a total node count cap. Payloads that exceed these bounds receive a 422 response with a stable error message. This prevents oversized or deeply nested payloads from consuming disproportionate storage or processing resources.

  • Typed field validation on webhook destinations - The accepted_event_types list on webhook destination create and update requests now uses the same event type format as triggers, ensuring subscribers and matchers agree on the same shape. Previously, webhook destinations used a separate validation rule.

  • Rate limiting on all routes - Every trigger and webhook destination endpoint now carries an explicit rate limit. Read operations (list, get, delivery history, run history) and write operations (create, update, delete, pause, resume, fire, rotate secret) are rate-limited independently. Requests that exceed the limit receive a 429 response.

  • Audit logging for mutations - All mutating trigger operations (create, update, delete, pause, resume, fire) and all mutating webhook destination operations (create, update, delete, rotate secret) now emit structured audit events. Each audit event records the workspace, the API credential that performed the operation, the resource affected, and operation-specific metadata. Audit events are written after the underlying operation commits, so the audit trail only contains operations that actually succeeded.

  • DELETE returns 404 for missing resources - Deleting a trigger or webhook destination that does not exist now returns 404 instead of silently succeeding with 204. This matches the behavior of GET on the same resource.

  • Error handling on pause, resume, and fire - The pause, resume, and fire trigger endpoints now return 422 for business-rule violations (e.g. pausing an already-paused trigger) instead of returning an unstructured server error.

Who is affected:

All integrations that create or update triggers and webhook destinations. Requests with valid inputs are unaffected. Requests that previously passed with loosely validated fields (non-IANA timezones, malformed cron expressions, oversized JSON payloads, or event types with disallowed characters) will now receive 422 validation errors.

Integrations that relied on DELETE returning 204 for non-existent resources should handle 404 responses.

No breaking changes to response schemas. All new validation applies to request bodies only.

chevron-rightv0.9.383 - Platform API: Payer Entities in World Model (July 2026)hashtag

Payer Entities in World Model

Payers are now promoted to first-class entities in the world model. Insurance payers ingested from connected EHR systems appear as their own entity type alongside patients, providers, locations, and organizations. This lets eligibility and insurance-acceptance workflows query payers directly without filtering through organization records.

What changed:

  • New payer entity type - Payer records from connected practice management systems are now projected into the world model as standalone entities with entity_type='payer'. Previously, payer information was only available as reference data attached to coverage records. Payers now have their own identity, display name, and identifier set, making them queryable and filterable independently.

  • Payer search support - Payer entities carry name and trading partner identifiers, enabling fuzzy name matching and exact-ID lookups for eligibility verification tools. Downstream tools such as payer search can filter on the payer entity type to find the correct payer for a coverage check without scanning unrelated organization records.

  • Coverage references preserved - Coverage records continue to reference payers using standard FHIR-conformant organization references. Existing integrations that read coverage data are unaffected. The new payer entity type is additive - it provides a direct query path to payer records without changing how coverage resources reference them.

  • Identifier systems - Each payer entity carries identifiers from the source system (practice-level payer ID and, when available, the clearinghouse trading partner ID used for electronic eligibility checks). These identifiers enable precise matching during eligibility workflows.

Who is affected:

Workspaces with connected EHR or practice management systems that sync payer/insurance company data. Payer entities appear automatically in the world model after the next sync cycle. No configuration changes are required.

Eligibility verification tools and insurance-acceptance queries benefit from the dedicated payer entity type. Existing coverage-based workflows continue to work unchanged.

No breaking changes.

chevron-rightv0.9.382 - Platform API: Text Conversation Turn Resume Preserves Entity Binding (July 2026)hashtag

Text Conversation Turn Resume Preserves Entity Binding

Resuming a text conversation that is bound to an entity no longer fails with a mismatch error. The platform now automatically forwards the conversation's entity binding when submitting a new turn, so callers do not need to re-specify the entity on every turn.

What changed:

  • Automatic entity forwarding on turn resume - When you create a new turn on an existing text conversation that was originally started with an entity binding, the platform reads the entity from the conversation record and includes it in the turn request. Previously, the turn request omitted the entity, causing the backend to reject it because the stored conversation had an entity but the incoming request did not.

  • Applies to both streaming and non-streaming turns - The fix applies to standard (synchronous) turn requests and to streaming turn requests that use server-sent events. Both paths now include the entity from the conversation record.

  • No API changes required - Callers do not need to pass any additional parameters. If the conversation has an entity binding, it is forwarded automatically. If the conversation has no entity binding, behavior is unchanged.

Who is affected:

Any integration that creates text conversations with an entity binding and then submits follow-up turns. Previously, the second and subsequent turns on entity-bound conversations would fail. This is now handled automatically.

No breaking changes.

chevron-rightv0.9.381 - Platform API: Extended STT Provider Routing for Clinical Scribe and Multi-Participant Calls (July 2026)hashtag

Extended STT Provider Routing for Clinical Scribe and Multi-Participant Calls

The automatic speech-to-text provider routing introduced in v0.9.379 now extends to the clinical scribe (copilot) path and per-participant call streams, ensuring consistent transcription quality across all audio channels.

What changed:

  • Scribe path routing - The clinical scribe audio path now uses the same language-based provider routing as phone calls. Previously, scribe sessions always used the primary transcription engine regardless of language. Now, a scribe session for an unsupported language (such as Arabic) automatically routes to the fallback provider, producing usable transcripts instead of near-empty auto-detect output.

  • Workspace scribe language configuration - The workspace-level scribe language setting is now included in the routing decision. When patient demographics have not been populated, the workspace scribe language serves as the routing signal, preventing silent fallback to the primary engine for workspaces configured for unsupported languages.

  • Per-participant stream routing - In conference-mode calls, per-participant audio streams now route through the same provider selection logic. Participant streams that lack language context (because the telephony URL does not carry workspace settings) default to the primary engine and emit a distinct routing metric so operators can distinguish "no language context available" from "language was resolved and primary engine supports it."

  • Operator audio policy enforcement - Operator (clinical staff) audio is enforced to always use the primary transcription engine. This policy is applied at construction time and verified at runtime with a defense-in-depth check. If the invariant is ever violated, the system emits a dedicated alert metric and fails immediately rather than silently routing operator audio to an unintended provider.

  • Independent scribe path kill-switch - A new environment-level setting allows operators to disable the fallback provider for the scribe audio path independently from the phone call path. This lets operators stage and validate the scribe integration without affecting the already-deployed phone call routing. The scribe fallback path is disabled by default and must be explicitly enabled after validation.

  • Unified routing observability - All routing decisions now carry a role tag (caller, operator, or scribe) in metrics, enabling SRE dashboards to compare routing distributions across audio paths. Routing reasons are extended with new values for the scribe kill-switch and the no-language-context case.

Who is affected:

Workspaces using the clinical scribe (copilot) feature with patients speaking languages not supported by the primary transcription engine will see improved transcription quality automatically once the scribe path kill-switch is enabled. Workspaces using conference-mode calls with per-participant streams gain routing observability. The operator audio policy enforcement adds a safety layer for all workspaces using operator escalation.

No breaking changes to the API. Provider selection remains transparent to API consumers. Transcription results are returned in the same format regardless of which provider produced them.

chevron-rightv0.9.380 - Platform API: Workspace-Grounded Simulation Callers (July 2026)hashtag

Workspace-Grounded Simulation Callers

Simulated callers in the simulation bridge are now grounded in workspace-specific facts, so they reference real data from your workspace rather than inventing fictitious locations, providers, appointment types, or other scheduling details.

What changed:

  • Automatic fact resolution - When a simulation run starts, the platform resolves grounding facts from the service configuration, context graph, and connected clinical data sources. Resolved fact categories include locations, appointment types, visit reasons, providers, transfer targets, and escalation rules. Facts are deduplicated and normalized automatically.

  • Caller prompt grounding - Simulated caller prompts now include a grounding block that constrains the caller to use only resolved facts. If the agent asks for a location, provider, appointment type, visit reason, or transfer target, the simulated caller selects from the resolved list rather than generating a plausible-sounding but incorrect value.

  • Graceful degradation - When no workspace-specific facts are resolved for a category, the simulated caller is instructed to acknowledge uncertainty rather than fabricate information. A warning is logged when no facts are resolved at all, but the simulation proceeds normally.

  • No configuration required - Fact resolution is automatic. Workspaces with scheduling data in their service configuration, context graph, or connected clinical data sources benefit immediately. No API changes or new parameters are needed.

Who is affected:

All workspaces using the simulation bridge. Simulated callers will produce more realistic and accurate conversations, especially for scheduling workflows where specific locations, providers, and appointment types matter. No breaking changes to the simulation API. Existing simulation runs are unaffected.

chevron-rightv0.9.379 - Platform API: Automatic STT Provider Fallback for Unsupported Languages (July 2026)hashtag

Automatic STT Provider Fallback for Unsupported Languages

The voice agent now automatically selects a secondary speech-to-text provider for languages the primary transcription engine does not support, such as Arabic. Previously, callers speaking unsupported languages were transcribed by the primary engine's auto-detect mode, which produced lower-quality results for those languages.

What changed:

  • Automatic language-based routing - When a caller's resolved language is not supported by the primary transcription engine, the platform routes their audio to an alternative provider that handles that language natively. The language is resolved from caller demographic data, workspace voice settings, or defaults to English. Supported primary languages include English, Spanish, French, German, Hindi, Russian, Portuguese, Japanese, Italian, and Dutch. All other languages route to the fallback provider.

  • Operator kill-switch - A new environment-level setting allows operators to disable the fallback provider entirely. When disabled, all calls use the primary transcription engine regardless of language. This lets operators respond to provider outages without redeploying.

  • Force-language list - A new environment-level setting accepts a comma-separated list of ISO-639-1 language codes that always route to the fallback provider, even when the primary engine supports them. This enables controlled rollout and A/B comparison of transcription quality for specific languages.

  • Strict environment variable validation - Boolean configuration values (such as the kill-switch) now reject unrecognized values at startup rather than silently defaulting. A typo in a configuration value causes the service to fail immediately with a descriptive error instead of running with unexpected behavior.

  • Required credential validation - API credentials required for transcription are validated as non-empty at startup. Previously, an empty credential would cause silent authentication failures on every API call rather than failing at startup.

  • Session rotation - Long calls automatically rotate the fallback provider's session before hitting upstream time limits, preventing mid-call transcription interruptions.

  • Reconnection with backoff - Transient connection failures to the fallback provider trigger automatic reconnection with cooldown, up to a configurable attempt limit.

Who is affected:

Workspaces with callers speaking languages not supported by the primary transcription engine (notably Arabic) will see improved transcription quality automatically. No API changes are required. Workspaces using only supported languages are unaffected - their calls continue to use the primary engine.

No breaking changes to the API. The provider selection is transparent to API consumers. Transcription results are returned in the same format regardless of which provider produced them.

chevron-rightv0.9.378 - Platform API: Credential Scope and Role Consistency Validation (July 2026)hashtag

Credential Scope and Role Consistency Validation

The admin credentials API now validates that the scopes on a credential are consistent with its declared role before the credential is created or updated. This prevents credentials from being saved with a role that does not match their actual permission set, which previously could cause agent session tokens to resolve to a lower role at runtime and produce unexpected 403 errors.

What changed:

  • Scope validation on create - When creating a credential, every scope in the request must be a recognized platform scope. Unrecognized scope names (typos, removed scopes) are rejected with a 422 response that lists the invalid values.

  • Role validation on create - The declared role must be a recognized platform role. Unknown role values are rejected with a 422 response.

  • Scope-role consistency on create - When both a role and scopes are provided, the scope set must contain the delegatable scopes required by that role. If the scope set is too narrow for the declared role, the request is rejected with a 422 response listing the missing scopes and suggesting either widening scopes or choosing a narrower role.

  • Scope-role consistency on update - When updating a credential, the same consistency check runs against the effective state after the update. If the patch supplies only a new role, the existing stored scopes are checked against it. If the patch supplies only new scopes, the existing stored role is checked against them. If both are supplied, they are validated together. This prevents partial updates from producing inconsistent credentials.

  • Role validation on update - Unknown role values in update requests are rejected the same way as on create.

  • Scope validation on update - Unrecognized scope names in update requests are rejected the same way as on create.

Who is affected:

Any integration that creates or updates credentials through the admin API. Credentials with valid scope and role combinations are unaffected. Requests that previously succeeded with typos in scope names or with a role that did not match the scope set will now receive a 422 validation error.

This is a hardening change. Existing valid credentials are not modified. Only new create and update requests are subject to the additional validation.

No breaking changes to valid requests. Invalid requests that previously succeeded silently will now fail with descriptive error messages.

chevron-rightv0.9.377 - Platform API: Canonical Workspace Creation Endpoint (July 2026)hashtag

Canonical Workspace Creation Endpoint

Self-service workspace creation has moved to a new canonical endpoint under the account scope. The previous workspace creation path has been removed.

What changed:

  • New endpoint: POST /v1/me/workspaces - Creates a workspace under the authenticated identity. This replaces the previous self-service workspace creation endpoint. The request and response schemas are unchanged - only the path has moved.

  • Removed endpoint: POST /v1/workspaces/self-service - The legacy self-service workspace creation path has been deleted. All callers must migrate to POST /v1/me/workspaces.

  • Account-scoped grouping - The new endpoint appears under the "Account" tag in the API reference, reflecting that it operates on the authenticated caller's account rather than within a specific workspace.

  • Authentication enforcement - The endpoint requires a valid identity token. Unauthenticated requests receive a 401 response.

Who is affected:

Any integration or SDK that calls POST /v1/workspaces/self-service must update to POST /v1/me/workspaces. The request body and response format are identical - only the URL path changes.

Breaking change: POST /v1/workspaces/self-service no longer exists and will return a 404.

chevron-rightv0.9.376 - Platform API: Members Can Create Initial Agent and Context Graph Versions (July 2026)hashtag

Members Can Create Initial Agent and Context Graph Versions

Creating the first version of an agent or context graph now requires the create permission instead of the update permission. This allows workspace members to complete the setup workflow for new agents and context graphs without needing elevated privileges.

What changed:

  • Agent version creation permission split - Creating the first version of an agent now requires Agent.create permission. Subsequent versions continue to require Agent.update permission. Previously, all version creation required Agent.update, which meant members who could create an agent could not publish its first version without an admin granting additional permissions.

  • Context graph version creation permission split - Creating the first version of a context graph now requires ContextGraph.create permission. Subsequent versions continue to require ContextGraph.update permission. The same permission gap that affected agents also applied to context graphs.

  • API description updated - The create-agent-version and create-context_graph-version endpoint descriptions now document the split permission requirement.

Who is affected:

Workspace members who create agents or context graphs. Members with create permission can now publish the initial version without needing update permission. Existing workflows that rely on update permission for version creation are unaffected - update is still required for all versions after the first.

No breaking changes. Users who already have update permission will continue to work as before.

chevron-rightv0.9.375 - Platform API: Agent Session Token Role Derivation (July 2026)hashtag

Agent Session Token Role Derivation

Agent session tokens now derive their role from the parent token rather than carrying elevated privileges. This closes a privilege escalation path where short-lived session tokens issued on behalf of admin or owner credentials could carry higher permissions than intended.

What changed:

  • Role claim derived from parent - When a session token is minted from a parent credential, the child token's role is now derived from the parent's actual permissions rather than being copied verbatim. The platform infers the parent's effective role from its permission set, honors an explicit role claim only when it is consistent with the parent's actual permissions, and caps the child role at member level regardless of parent privilege. This prevents automated agent sessions from operating with admin or owner level access.

  • Scope set clamped for elevated parents - Session tokens minted from admin or owner credentials now receive a reduced scope set matching member-level permissions. Previously, admin-level scopes such as credential management and identity administration could flow through to delegated session tokens. Sensitive scopes that should never appear on delegated tokens - including credential access, session creation, identity administration, and test-only operations - are always stripped.

  • Bidirectional role claim validation - The platform now validates role claims in both directions at every trust boundary. A role claim that is wider than the token's actual permissions (e.g. a viewer-scoped token claiming admin) is rejected, and a role claim that is narrower than the token's actual permissions (e.g. admin-scoped token claiming operator) is also rejected. The previous validation only caught the wider-claim case. Both producer and consumer services apply the same validation.

  • Consistent role resolution across routes - All platform API routes now resolve roles through a single code path that honors explicit role claims when consistent with scopes and falls back to permission-based inference otherwise. Previously, some routes used inference-only resolution while others honored the explicit claim, which could produce different effective roles for the same token depending on which route was called.

  • Audit trail for role decisions - Session creation events now include a structured record of the role derivation decision, documenting the parent's claimed role, the inferred role, the effective role applied, whether the role was capped, and parent token provenance. When a role claim is rejected as inconsistent with the parent's permissions, a dedicated audit event is emitted so security teams can identify forged or drifted credentials.

  • Malformed parent token handling - Session token minting now fails closed with a 401 response when the parent token contains malformed identifier claims, rather than raising an unhandled error. An audit event is emitted with forensic metadata before the rejection response is returned.

Who is affected:

All consumers of agent session tokens. Session tokens minted from member or lower credentials are unchanged. Session tokens minted from admin or owner credentials will now carry member-level roles and a reduced scope set. Automated agents that previously relied on admin-level scopes flowing through session tokens will need to use direct credentials for admin operations.

No breaking changes to the token API request format. The token response now includes a role field on agent session tokens.

chevron-rightv0.9.374 - Platform API: Call Intelligence Metrics Use Typed Fields End-to-End (July 2026)hashtag

Call Intelligence Metrics Use Typed Fields End-to-End

All built-in voice metrics now extract values from typed fields on call intelligence records instead of parsing nested summary objects at query time. This completes the typed-field migration across the metric evaluation pipeline, following the analytics layer (v0.9.372) and operator surfaces (v0.9.373).

What changed:

  • Metric extraction paths simplified - Built-in voice metrics (escalation rate, risk level, average TTFB, tool failure rate, barge-in count, loop count, and silence ratio) now read from top-level typed fields on the call intelligence record. Previously, each metric extracted its value from a nested summary object at evaluation time, which was slower and susceptible to key-name drift.

  • 29 new typed fields on call intelligence records - Call intelligence records now expose 29 typed fields covering emotion analysis (dominant emotion, valence, arousal, peak negative valence, barge-in count), risk assessment (composite score, level), latency measurements (engine, audio TTFB, navigation, and render timing at avg/p50/p95, plus turn count and silence ratio), conversation structure (turn count, states visited, unique states, loop count, barge-in count), tool usage (total calls, succeeded, failed, failure rate), safety (match count), and operator state (escalated, operator active). These fields are parsed once when the record is created rather than on every read.

  • Single-segment extraction paths - Custom metrics targeting call intelligence data can now use single-segment paths (e.g. $.risk_level) that resolve directly to typed fields. Two-segment paths that reference nested summary objects continue to work for backward compatibility.

  • Historical data continuity - Records created before this release are backfilled with typed field values derived from the same summary objects, so trend queries and period comparisons return consistent results across the migration boundary.

Who is affected:

All consumers of the metric evaluation pipeline and call intelligence analytics. Built-in metric values are unchanged - this release improves extraction reliability and query performance. Custom metrics using two-segment extraction paths (e.g. $.risk_summary.level) continue to work without changes.

No breaking changes.

chevron-rightv0.9.373 - Platform API: Operator Briefing and Dashboard Reads Use Typed Fields (July 2026)hashtag

Operator Briefing and Dashboard Reads Use Typed Fields

The operator briefing builder and command center dashboard queries now read call intelligence data from typed fields instead of extracting values from nested summary objects. This completes the migration started in v0.9.372 for the analytics layer, extending it to the operator-facing surfaces.

What changed:

  • Operator briefing sections use typed fields - The briefing that operators see when reviewing a call now pulls conversation metrics (turn count, states visited, unique states, loop count), safety match count, escalation status, dominant emotion, and average valence from typed fields on the call intelligence record. Previously these values were extracted from nested summary objects, which was fragile and could silently return empty data if summary key names drifted.

  • Safety actions still read from summary object - The list of escalation handler outcomes shown in the safety section of the briefing continues to be read from the summary object because this data is a free-form list without a typed field equivalent. All other briefing fields now use typed fields.

  • Command center escalation count uses typed field - The dashboard query that counts today's escalated calls now reads the typed escalation flag directly instead of extracting it from a nested summary object. This makes the count consistent with the typed-field reads used elsewhere and eliminates a potential source of inaccurate escalation counts.

Who is affected:

Operators using the command center dashboard and call briefing views. The data displayed is the same - this change improves the reliability and consistency of how that data is retrieved internally. No API request or response format changes.

No breaking changes.

chevron-rightv0.9.372 - Platform API: Analytics Aggregation Accuracy Fixes (July 2026)hashtag

Analytics Aggregation Accuracy Fixes

The call intelligence analytics endpoints now return accurate values for several metrics that were previously silently returning empty results. This release fixes data retrieval issues in the analytics layer and migrates all aggregation queries to use the typed response fields introduced in v0.9.371.

What changed:

  • TTFB period comparison fixed - The period-comparison endpoint previously read a non-existent field for average time-to-first-byte, causing the metric to always return null. The query now reads the correct field and returns real latency values.

  • Tool success rate period comparison fixed - The period-comparison endpoint previously read a non-existent success_rate field from tool summaries. The platform only produces a failure_rate, so the analytics layer now correctly computes success rate as 1 - failure_rate. Calls with no tool invocations are excluded from the average rather than treated as zero.

  • Emotion trend valence and arousal fixed - The emotion analytics trend endpoint previously read mismatched field names for average valence and average arousal, causing both metrics to always return null. The queries now read the correct fields and return real values.

  • All analytics queries migrated to typed fields - Every analytics aggregation query now uses the typed response fields from the call intelligence schema rather than extracting values from nested summary objects. This improves query performance and eliminates an entire class of field-name mismatch issues.

Who is affected:

All consumers of the call intelligence analytics endpoints on the Platform API. The Developer Console analytics dashboard will now display real values for TTFB comparisons, tool success rates, and emotion trends where it previously showed empty or null results. No request format changes - all fixes are in response data accuracy.

No breaking changes. All endpoint signatures, request parameters, and response shapes remain the same. Previously-null fields now return real values.

chevron-rightv0.9.371 - Platform API: Call Intelligence Response Schema Alignment (July 2026)hashtag

Call Intelligence Response Schema Alignment

The call intelligence summary response models now reflect the fields the platform actually produces. Several fields that were declared in the response schema but never populated have been removed, and new fields that the platform does produce are now included in the typed response.

This is a breaking change to the response schema for call intelligence summary endpoints. A breaking-change waiver covers this release. SDK consumers (Developer Console, Agent Forge) should update to the latest versions.

What changed:

  • Emotion summary - Removed avg_valence, emotion_shifts, and caller_distress_detected (never populated). Added average_valence, average_arousal, peak_negative_valence, and barge_in_count.

  • Risk summary - Removed flags (never populated). The composite_score and level fields remain unchanged.

  • Latency summary - Removed total_silence_seconds (never populated). Added avg_engine_ms, p50_engine_ms, p95_engine_ms, avg_audio_ttfb_ms, avg_nav_ms, avg_render_ms, and turn_count. The silence_ratio, p50_audio_ttfb_ms, and p95_audio_ttfb_ms fields remain unchanged.

  • Conversation summary - Removed topic_changes and avg_turn_duration_seconds (never populated). Added turn_count, states_visited_count, unique_states, and loop_count. The barge_in_count field remains unchanged.

  • Tool summary - Added succeeded field for successful tool invocations. The total_calls, failed, and failure_rate fields remain unchanged.

  • Safety summary - Removed categories (never populated). The match_count field remains unchanged.

  • Operator intelligence summary - Removed operator_handle_time_seconds (never populated). Added operator_active with three-valued semantics: true means an operator was active during escalation, false means escalation occurred but no operator picked up, and null means no escalation occurred. The escalated field remains unchanged.

Who is affected:

All consumers of the call intelligence summary endpoints on the Platform API. Any code that reads the removed fields (avg_valence, emotion_shifts, caller_distress_detected, flags, total_silence_seconds, topic_changes, avg_turn_duration_seconds, categories, operator_handle_time_seconds) must be updated. These fields were never populated by the platform, so any values read from them were always defaults.

Consumers reading the newly added fields will get richer call intelligence data without additional API calls.

Breaking changes: Yes - removed fields from multiple response models. Covered by a breaking-change waiver.

chevron-rightv0.9.370 - Platform API: Request Field Validation and Operator Phone Format (July 2026)hashtag

Request Field Validation and Operator Phone Format

Several Platform API endpoints now enforce stricter length and format constraints on request fields. These constraints prevent oversized or malformed payloads from reaching downstream processing and give callers immediate, actionable validation errors.

What changed:

  • Operator phone number format - The phone_number field on create and update operator requests now requires E.164 format (e.g. +15551234567). Previously, the field accepted any string. Requests that supply a phone number not in E.164 format will receive a 422 validation error.

  • Operator skills - The skills list on create and update operator requests now enforces a maximum of 50 entries, and each skill tag must be between 1 and 64 characters. Previously, the list length and individual tag length were unbounded.

  • Data source entity types - The entity_types list items on create and update data source requests now require between 1 and 64 characters each. Previously, individual item length was unbounded.

  • Data source sync schedule - The sync_schedule field on create and update data source requests now enforces a maximum length of 256 characters.

  • Surface resource type - The resource_type field on create, update, and response surface models now enforces a maximum length of 64 characters.

  • Unification rule fields - The source_event_type and created_by fields now enforce a maximum length of 128 characters, and target_entity_type enforces a maximum of 64 characters on create and update unification rule requests.

  • Voice settings fields - Multiple voice configuration fields now enforce length limits:

    • voice_id and pronunciation_dict_id: max 128 characters

    • tone: max 2,000 characters

    • language: max 32 characters

    • keyterms: max 200 items, each 1-128 characters

    • correction_categories, sensitive_topics: max 50 items each, each 1-128 characters

  • Channel event email ID - The email_id field on channel event requests now enforces a maximum length of 256 characters.

Who is affected:

All Platform API consumers sending create or update requests for operators, data sources, surfaces, unification rules, voice settings, or channel events. Requests that previously sent oversized or free-form values for these fields may now receive 422 validation errors. The operator phone_number field is the most likely to require changes - any integration passing non-E.164 phone numbers must update to the E.164 format.

No breaking changes to response schemas. All constraints are additive input validation.

chevron-rightv0.9.369 - Platform API: Detailed Regulatory Bundle Rejection Reasons (July 2026)hashtag

Detailed Regulatory Bundle Rejection Reasons

When a regulatory bundle is rejected during phone number provisioning, the platform now returns per-document rejection reasons alongside the bundle-level failure message. Previously, rejection notifications only included a generic pointer (e.g. "issue with one of your Supporting Documents") without identifying which document failed or why.

What changed:

  • Per-document failure reasons - When a regulatory bundle is rejected, the platform now inspects each supporting document attached to the bundle and collects individual rejection reasons. The bundle-level failure message remains the first entry, followed by one line per rejected document showing the document name and its specific rejection reason.

  • Actionable error messages - Instead of a single generic failure string, the rejection details now tell you exactly which supporting document was rejected and what needs to be corrected. This eliminates the need to manually investigate each document through external dashboards.

  • Best-effort enrichment - If per-document details cannot be retrieved (e.g. due to a transient upstream error), the bundle-level rejection reason is still recorded. The enrichment never blocks or delays the status update.

Who is affected:

All users provisioning phone numbers through the Platform API or Developer Console. Regulatory bundle rejections now surface more detailed, actionable failure information in the setup status. No API contract changes - the failure details are returned in the same field that previously held only the generic message.

No breaking changes.

chevron-rightv0.9.368 - Platform API: Call Intelligence Typed Analytics Columns (July 2026)hashtag

Call Intelligence Typed Analytics Columns

Call intelligence records now expose 29 individually typed fields for the metrics previously available only inside unstructured summary objects. This makes call-level analytics queryable, sortable, and filterable without parsing nested data.

What changed:

  • Emotion metrics - Dominant emotion label, average valence, average arousal, peak negative valence, and barge-in count are now discrete fields on every call intelligence record.

  • Risk metrics - Composite risk score and risk level (e.g. low, medium, high) are available as standalone fields.

  • Latency metrics - Average, p50, and p95 engine latency; average, p50, and p95 audio time-to-first-byte; average navigation latency; average render latency; turn count; and silence ratio each have their own field.

  • Conversation metrics - Turn count, states visited, unique states, loop count, and barge-in count are now individual fields.

  • Tool metrics - Total tool calls, succeeded count, failed count, and failure rate are broken out into separate fields.

  • Safety metrics - Safety match count is now a standalone field.

  • Operator metrics - Whether the call escalated to a human operator and whether the operator was active are now boolean fields. Absence (null) means the data was not produced for that call - it does not mean false.

  • Backward compatible - The existing summary objects continue to be populated. The new fields are additive. Calls recorded before this release will have null values for the new fields.

Who is affected:

All consumers of call intelligence data through the Platform API, Data Access layer, or analytics dashboards. Queries that previously needed to parse summary objects can now filter and aggregate on individual fields directly.

No breaking changes.

chevron-rightv0.9.367 - Platform API: Schema Defaults Applied at Tool Execution Time (July 2026)hashtag

Schema Defaults Applied at Tool Execution Time

Tool and skill execution now automatically fills in missing parameters from the JSON schema defaults defined on the tool or skill. Tool-calling models frequently omit optional fields that carry a default value in the schema - for example, fixed API version query parameters or constant configuration values. Previously, these omissions could cause integration requests to fail because the required parameter was absent from the outbound request. The platform now fills missing top-level parameters from schema defaults before the request is sent.

What changed:

  • Automatic default fill for missing parameters - When a tool-calling model omits a parameter that has a default value defined in the tool's or skill's JSON schema, the platform now injects that default before executing the integration request. This applies to both skill-level execution and direct integration tool calls.

  • Caller-supplied values are never overwritten - If the model explicitly provides a parameter value, including explicit null, the caller-supplied value is preserved. Only keys that are entirely absent from the input are filled from schema defaults.

  • Top-level properties only - Default filling applies to top-level schema properties. Nested object defaults are not recursed into. Integration tool schemas consumed by the platform are flat, so this covers all current use cases.

  • Multiple execution paths covered - Defaults are applied consistently whether the tool is invoked through skill execution, direct integration tool calls, or the tool execution pipeline. Each path applies defaults exactly once to avoid duplicating or shadowing values.

Who is affected:

All users of integration tools and skills on the Platform API. This is a bug fix - no API contract changes. Integrations that previously failed because the model omitted a defaulted parameter (such as a fixed API version string) will now work without requiring the model to explicitly include every default value.

No breaking changes.

chevron-rightv0.9.366 - Platform API: Tool-Only Voice Agent Responses Now Delivered (July 2026)hashtag

Tool-Only Voice Agent Responses Now Delivered

The voice agent streaming pipeline previously dropped tool call results when the model response contained only tool calls with no spoken content. This caused the agent to appear unresponsive on turns where it needed to invoke a tool without speaking first. Tool calls are now delivered to the consumer regardless of whether the turn also produced audio.

What changed:

  • Tool-only turns no longer dropped - When the model emits tool calls without any spoken content in a single turn, those tool calls are now yielded to the stream consumer. Previously, tool calls were only delivered when the turn also produced audio output, which meant silent tool invocations (such as a background data lookup or a status update) were silently discarded.

  • Improved agent responsiveness - Agents that rely on tool calls without intermediate spoken responses (for example, performing a lookup before deciding what to say) now behave as expected. The tool executes and the agent continues the conversation flow, rather than appearing to hang.

Who is affected:

All consumers of the voice agent streaming pipeline. This is a bug fix - no API contract changes. Agents that previously appeared to stall on tool-only turns will now correctly execute the tool and continue the conversation.

No breaking changes.

chevron-rightv0.9.365 - Platform API: Hardened Realtime Streaming Surfaces (July 2026)hashtag

Hardened Realtime Streaming Surfaces

The three realtime streaming surfaces - SSE event stream, WebSocket session connect, and conversation turn stream - now carry structured error frames, concurrency guards, and improved observability across the board.

What changed:

  • Structured error frames on turn stream - Error events on the conversation turn stream now include a stable code field and a retryable boolean, so SDK consumers can branch on error type programmatically without parsing free-form message text. Codes include upstream_error (with the upstream HTTP status when available), stream_interrupted (transient transport failure, retryable), and client_error. The retryable field tells callers whether reissuing the same turn is likely to succeed.

  • Turn stream non-resumable header - The turn stream response now includes a header indicating the stream is not resumable. SDKs should not attempt to send a reconnect cursor on retry. Callers that need durable delivery should use the workspace event stream instead.

  • SSE event stream concurrency cap - Each workspace is now limited to 50 simultaneous SSE event stream connections. Over-cap clients receive a single error frame with code too_many_streams and the connection closes. The error frame sets a longer retry interval so rejected clients do not immediately reconnect in a tight loop. Slots held by crashed clients are automatically reclaimed.

  • SSE event stream maximum duration - Long-lived SSE connections are now capped at a maximum duration. When the limit is reached, the stream emits a stream.expired control frame and closes gracefully. SDKs reconnect automatically using Last-Event-ID for gapless replay.

  • SSE event stream lifecycle frames - The event stream now emits a stream.opened control frame when the connection is established, carrying a connection identifier for log correlation during incident response. Control frames do not carry an event ID, so they do not anchor the SDK reconnect cursor.

  • WebSocket session connect origin allowlist - WebSocket session connections now validate the Origin header when present. Browser-originated connections must come from an allowed origin. Server-to-server callers (SDKs, BFFs) that omit the Origin header are unaffected.

  • WebSocket concurrent connection cap - Each workspace is limited to 25 simultaneous WebSocket session connections. Over-cap clients receive close code 4029 with a generic reason. Slots held by crashed clients are automatically reclaimed.

  • WebSocket burst rate limit - A sliding-window burst limiter prevents runaway reconnect loops from overwhelming the handshake path. Clients that exceed the burst threshold receive close code 4029.

  • WebSocket structured close codes - Close codes are now documented and consistent across all rejection paths:

    • 4001: client error (missing or invalid parameters, bad UUID, bad token format)

    • 4029: rate limit or concurrency cap exceeded

    • 4403: authentication rejected or workspace mismatch

    • 4408: session lifetime exceeded

    • 4500: upstream connection failed

    • 4502: upstream rejected handshake

    • 4503: upstream temporarily unavailable

  • Observability - All three surfaces now emit counters for connection opened, closed (with reason), errors, and replay events. The WebSocket surface additionally emits a duration distribution. Error logging across all surfaces now records only the exception type, not the full exception body, to avoid capturing sensitive data.

Who is affected:

All consumers of the SSE event stream, WebSocket session connect, and conversation turn stream endpoints.

  • SSE event stream consumers should handle the new stream.opened and stream.expired control events, and the too_many_streams error code. Existing reconnect logic using Last-Event-ID continues to work.

  • WebSocket consumers should handle close codes 4029 (back off and retry after a delay) and should not send an Origin header from server-to-server environments. Browser-based consumers from allowed origins are unaffected.

  • Turn stream consumers should update error handling to use the code and retryable fields instead of parsing the message string.

No breaking changes to existing request or response contracts. All new fields are additive.

chevron-rightv0.9.364 - Platform API: Streaming Engage Empty-Response Retry and Reliability Improvements (July 2026)hashtag

Streaming Engage Empty-Response Retry and Reliability Improvements

The voice agent streaming engage pipeline now retries when the model returns empty content with no tool calls on a tool-capable turn, matching the behavior already available on the batch path. Additional reliability improvements prevent the streaming event consumer from hanging if the background processing exits unexpectedly.

What changed:

  • Empty-response retry on streaming path - When the model returns empty content and zero tool calls on a turn where tools are available, the pipeline now automatically retries once with a narrowed tool selection before surfacing an empty result. This addresses cases where the model occasionally produces a blank response despite having tools available. The retry is transparent to SSE consumers - only events from the accepted attempt are delivered.

  • Empty-response retry on batch path - The same empty-response retry behavior is now enabled on the batch engage path as well. Previously the batch path did not retry on empty tool-capable responses; it now uses the same single-retry strategy as streaming.

  • Streaming consumer hang protection - The SSE event stream now includes defensive timeout and sentinel guarantees so that the consumer cannot hang indefinitely if the background processing task exits without signaling completion. If no events arrive within a safety window and the background task has finished, the stream terminates gracefully.

  • Backpressure handling - The streaming event bridge now handles slow consumers gracefully. If the consumer falls behind and the internal buffer fills, excess events are dropped with observability rather than crashing the processing pipeline. The front-end SSE consumer tolerates occasional dropped token events without user-visible impact.

Who is affected:

All consumers of the voice agent engage endpoints (both batch and streaming). The empty-response retry reduces the frequency of blank agent responses on tool-capable turns. The streaming reliability improvements are transparent - SSE event types and shapes are unchanged.

No breaking changes to request or response contracts.

chevron-rightv0.9.363 - Platform API: Surface Tools Entity Reference Normalization (July 2026)hashtag

Surface Tools Entity Reference Normalization

Surface tool endpoints now accept entity references in FHIR-style formats in addition to bare UUIDs, eliminating 422 and 404 errors that occurred when the agent echoed back a FHIR-shaped reference it read from the data context.

What changed:

  • Entity ID normalization on surface tools - The entity_id parameter on surface creation, surface listing by entity, surface insights retrieval, and template-based surface creation now accepts three input formats: bare UUID ("abc-123-..."), FHIR relative reference ("Patient/abc-123-..."), and FHIR URN reference (`"urn:uuid:abc-123-..."``, case-insensitive prefix). All formats are normalized to the canonical workspace UUID before the request is processed. Previously, only bare UUIDs were accepted, causing failures when the agent passed through a reference format it encountered in its data context.

  • Safe error handling - When an entity reference cannot be parsed as a valid workspace UUID after normalization, the error message uses a generic label and never echoes the raw input value. This prevents connector-side canonical identifiers or other potentially sensitive substrings from appearing in agent-visible error responses.

  • Observability - Successful normalization of wrapped formats is logged for operational visibility, allowing teams to track how often the agent uses non-bare-UUID formats. Failed parse attempts are logged with sanitized metadata (input length and format shape only, no raw values).

Who is affected:

This change is transparent to all consumers. Surface tools that previously required bare UUIDs now accept additional formats. Existing integrations passing bare UUIDs are unaffected. Agents that previously received 422 or 404 errors when passing FHIR-shaped entity references will now succeed.

No breaking changes. This is a backward-compatible input normalization improvement.

chevron-rightv0.9.362 - Platform API: Integration Connection Probe and Health Metadata (July 2026)hashtag

Integration Connection Probe and Health Metadata

Integrations now support a pre-flight connection probe that validates authentication and upstream reachability without invoking any specific endpoint. The most recent probe result is persisted on the integration so the Developer Console can display a health badge without re-probing on every page load.

What changed:

  • New POST /integrations/{integration_id}/test-connection endpoint - Probes an integration's auth resolution and upstream reachability. For REST and FHIR integrations, the probe resolves credentials end-to-end and sends a lightweight HEAD request to the base URL. For MCP integrations using HTTP or SSE transport, the probe sends a HEAD request to the MCP server URL. For MCP stdio transport, the probe validates command configuration. The endpoint returns a structured result with a status classification, probe duration, HTTP status code (when applicable), and a human-readable message. Safe to run on production integrations - HEAD requests carry no side effects. Requires Integration.view permission.

  • Connection status classification - The probe returns one of six status values: healthy (auth resolved, upstream reachable), auth_failed (credentials could not be resolved or were rejected), unreachable (could not connect to the upstream), timeout (connection did not complete in time), ssl_error (TLS handshake failed), or misconfigured (integration configuration is incomplete). Each status maps to a distinct remediation message in the Developer Console.

  • Health metadata on integration responses - Integration list and detail responses now include two new fields: last_tested_at (timestamp of the most recent probe, null if never tested) and last_test_status (status from the most recent probe). These fields are advisory and may be stale relative to the current upstream state.

  • Bearer token exchange handling - For integrations using bearer token exchange authentication, the probe validates that the static secret resolves but reports that the full token exchange requires per-call parameters. The test-endpoint route should be used for a complete exchange test.

Who is affected:

All consumers of the integrations API. The new endpoint is additive. The two new response fields (last_tested_at, last_test_status) appear on all integration responses - they are nullable and do not affect existing integrations that have never been tested.

No breaking changes to existing request or response shapes.

chevron-rightv0.9.361 - Platform API: Stricter Request Typing and Phone Number Validation (July 2026)hashtag

Stricter Request Typing and Phone Number Validation

Phone number fields across the Platform API now use a unified validation type that normalizes input to E.164 format using a production-grade phone number parsing library. Numeric and list fields on several request models now enforce explicit range and length constraints.

What changed:

  • Phone number validation upgraded - All phone number fields on outbound call creation, phone number registration, phone number purchase, call forwarding configuration, and text session creation now validate and normalize phone numbers using a standards-compliant phone number library instead of a simple regex pattern. Numbers must include a country code (leading +) and must be a valid, dialable number. Invalid numbers return a 422 error with a fixed error message that does not echo the input, preventing phone numbers from appearing in error responses.

  • Agent version request bounds - The behaviors and communication_patterns lists on agent version creation now enforce a maximum of 200 items, with each item capped at 2,000 characters.

  • Monitor concept request bounds - Threshold fields (threshold, standalone_threshold) now enforce a 0.0-1.0 range. The tags list is capped at 50 items of up to 64 characters each. The action_space list is capped at 20 items of up to 64 characters each. Agent config fields enforce bounds: model (128 chars), system_prompt (10,000 chars), timeout_s (0.1-60.0 seconds). Escalation config fields enforce bounds: operator_type (64 chars), reason (2,000 chars), regulatory_basis (2,000 chars).

  • Skill request bounds - Numeric fields now enforce explicit ranges: max_tokens (1-200,000), max_result_chars (1-200,000), max_input_tokens (1-2,000,000), timeout_s (0.1-900.0 seconds), max_agent_turns (1-200). The integration_tools and static_tools lists are capped at 50 items each. The urgency_keywords list is capped at 50 items of up to 128 characters each. The browser_allowed_domains list is capped at 50 items of up to 253 characters each. String fields on skill update requests now enforce the same length limits as creation.

  • Service request bounds - The keyterms list is capped at 500 items of up to 128 characters each. The tags list is capped at 50 items.

  • Phone number request bounds - The capabilities list on phone number creation is capped at 2 items and restricted to inbound and outbound values. The provider_phone_sid field is capped at 64 characters.

  • Metering response model - The metering emit endpoint now returns a typed response model with status and event_type fields instead of an untyped dictionary.

  • Billing dashboard response - The billing dashboard endpoint now returns a typed response model instead of an untyped dictionary.

Who is affected:

All consumers of the listed endpoints. Requests that previously passed validation may now be rejected with a 422 response if they contain invalid phone numbers, exceed new length limits, or violate new range constraints. In practice, legitimate requests are well within these bounds. Phone number fields that previously accepted regex-valid but undiailable numbers (e.g., numbers with valid format but non-existent country/area codes) will now be rejected.

The metering emit and billing dashboard endpoints return the same data as before, now with explicit field typing. No fields were removed or renamed.

No breaking changes to response shapes for callers that consume JSON responses dynamically.

chevron-rightv0.9.360 - Platform API: Call Intelligence Channel Kind and Workspace Scoping (July 2026)hashtag

Call Intelligence Channel Kind and Workspace Scoping

Call intelligence records now include a channel_kind field and call intelligence lookups are scoped to the requesting workspace.

What changed:

  • Channel kind field - Each call intelligence record now carries a channel_kind field that identifies the channel type for the session: voice, sms, web, or whatsapp. This separates the communication channel from the call direction, which was previously the only way to infer channel context. The field is nullable for backward compatibility - older records that predate this change will have a null value.

  • Workspace-scoped lookups - Call intelligence queries now filter by workspace in addition to the call identifier. Previously, lookups matched on the call identifier alone. This tightens multi-tenant isolation so that a call intelligence record is only returned when the requesting API key belongs to the same workspace that owns the record.

  • Stricter input validation on internal endpoints - The workspace identifier on internal call intelligence endpoints is now validated as a well-formed UUID at the request boundary. Malformed values return a 422 validation error instead of propagating downstream.

Who is affected:

All consumers of call intelligence endpoints. The new channel_kind field appears in call intelligence response objects. Existing integrations are unaffected - the field is additive and nullable. Workspace scoping is enforced transparently through the API key; no client changes are required.

No breaking changes to request or response shapes.

chevron-rightv0.9.359 - Platform API: Input Length Bounds on Request Fields (July 2026)hashtag

Input Length Bounds on Request Fields

String fields across Platform API request parameters - query strings, path parameters, headers, and request bodies - now enforce maximum length constraints. Previously, many of these fields accepted unbounded strings, which could allow oversized payloads to reach downstream services.

What changed:

  • Query parameter bounds - Search queries (q), filter parameters (service, action, resource type, status, phone number, identifier, and similar filters), and period selectors across analytics, audit, CRM, FHIR, and voicemail endpoints now enforce maximum lengths appropriate to each field. For example, search text fields are capped at 200 characters, phone numbers at 16 characters, and general filter strings at 64 characters.

  • Path parameter bounds - Resource identifiers passed as path segments (contact IDs, company IDs, deal IDs, FHIR resource types, FHIR resource IDs, safety template IDs, session IDs, and intake link tokens) now enforce length limits, typically 64 or 128 characters depending on the resource type.

  • Header bounds - Intake file upload headers (SHA-256 hash, timestamp, signature, customer slug, filename, and content type) now enforce length limits matching their expected formats.

  • Request body bounds - Several request body fields now have explicit length constraints:

    • API key creation: the role field is capped at 64 characters, and the permissions list is limited to 128 entries of up to 128 characters each. The name field now uses a bounded name string type.

    • Audit export requests: service and action filter fields are capped at 64 and 128 characters respectively.

    • Safety configuration: the triage_model field is capped at 128 characters.

    • Insights SQL queries: capped at 50,000 characters.

    • Insights chat messages: capped at 16,000 characters.

  • Enumerated value enforcement - The call direction filter on advanced analytics now accepts only inbound or outbound (previously accepted any string). The voicemail status filter now accepts only valid status values (pending, skipped, failed, delivered, not_delivered) instead of arbitrary strings.

Who is affected:

All consumers of the listed endpoints. Requests that previously passed validation may now be rejected with a 422 response if they exceed the new length limits. In practice, legitimate requests are well within these bounds - the limits are set conservatively above any realistic input size. Response schemas are unchanged.

No breaking changes to response shapes.

chevron-rightv0.9.358 - Platform API: Paginated List Endpoints (July 2026)hashtag

Paginated List Endpoints

Twenty list endpoints across the Platform API now support limit and offset query parameters for pagination. Previously, these endpoints returned a fixed number of results with no way to page through larger data sets. All existing integrations continue to work without changes - the new parameters are optional and default to the same result sizes as before.

What changed:

  • Standard pagination parameters - The following endpoint groups now accept limit and offset query parameters:

    • Audit exports - limit (default 50, max 200) controls the number of export records returned.

    • Entity duplicates - limit (default 100, max 500) and offset (default 0) for paging through suspected duplicate entity pairs. Filter by entity type and confidence threshold as before.

    • Intake links - limit (default 100, max 500) and offset for paging through intake links. The uploads-per-link endpoint also supports limit (default 200, max 500) and offset.

    • Integrations (internal) - limit (default 500, max 1000) and offset for listing enabled integrations.

    • Skills (internal) - limit (default 500, max 1000) and offset for listing workspace skills.

    • Metrics - limit (default 100, max 500) and offset for listing metric values.

    • Voice judge results - offset (default 0) added alongside the existing limit parameter (default 20, max 100).

    • Entity enrichment values - limit (default 200, max 500) and offset for paging through enrichment rows for an entity.

    • Enrichment keys - limit (default 200, max 500) and offset for listing registered enrichment keys.

    • M42 analytics endpoints - District metrics, anomaly alerts, forecast fan, positive signals, ranked anomalies, cluster summary, cluster forecast, model registry, stratified fits, and patient labs all now accept limit and offset with endpoint-appropriate defaults and maximums.

  • Consistent behavior - All pagination parameters are validated server-side. Values outside the allowed range are rejected with a 422 response. The offset parameter defaults to 0 on all endpoints. Result ordering is preserved as documented for each endpoint.

  • Backward compatible - All parameters are optional. Omitting them returns the same result set as before this change. Existing API clients, Agent Forge commands, and Developer Console views are unaffected.

Who is affected:

All consumers of the listed endpoints. No breaking changes. Clients that need to iterate through large result sets can now use limit and offset instead of retrieving a fixed-size response.

chevron-rightv0.9.357 - Platform API: Hardened Integration Create, Update, and Delete (July 2026)hashtag

Hardened Integration Create, Update, and Delete

The integration management endpoints now enforce stricter input validation, emit audit events for all mutations, and clean up orphaned secrets when integrations are updated or deleted.

What changed:

  • Input bounds on all fields - The name field is now bounded to 2-128 characters and must match a slug pattern (lowercase alphanumeric with hyphens or underscores, starting and ending with a letter or digit). Secret values are capped at 8192 characters. Endpoint lists are limited to 50 entries. MCP arguments are limited to 32 items of up to 1024 characters each. MCP custom headers are limited to 32 entries with RFC 7230-compliant header names (max 256 chars) and values up to 2048 characters. CR/LF characters are rejected in MCP arguments and header values to prevent injection. Test endpoint params are limited to 64 keys.

  • Audit logging for all mutations - Creating, updating, and deleting an integration now records an audit event in the workspace audit log. Each event includes the actor, workspace, resource identifier, resource name, and action-specific metadata (such as protocol, fields updated, and whether authentication changed). Audit events are best-effort and do not block or roll back the primary operation if the audit system is temporarily unavailable.

  • Orphaned secret cleanup on update and delete - When an integration's authentication configuration is replaced during an update, secrets that are no longer referenced are deleted automatically. When an integration is deleted, all platform-managed secrets associated with it are cleaned up. Only secrets provisioned by the platform are affected - manually configured secret references are never deleted. Cleanup runs after the primary operation commits and is best-effort; transient failures are logged and can be resolved by an out-of-band process.

  • Workspace-scoped update and delete - The update and delete operations now verify that the integration belongs to the specified workspace before modifying or removing it. Previously, the workspace scope was enforced only at the route level.

Who is affected:

All consumers of the integration create, update, and delete endpoints. Requests that previously passed validation may now be rejected if they exceed the new bounds (for example, names longer than 128 characters or endpoint lists with more than 50 entries). Response schemas are unchanged.

No breaking changes to response shapes.

chevron-rightv0.9.356 - Platform API: Typed Response Models for Patient Surfaces and Intake Uploads (July 2026)hashtag

Typed Response Models for Patient Surfaces and Intake Uploads

All patient-facing surface endpoints and intake upload endpoints now return structured, validated response bodies with documented schemas. Previously, these endpoints returned ad-hoc JSON objects. Every success and error response is now defined in the OpenAPI specification with explicit field types, constraints, and descriptions.

What changed:

  • Surface endpoints return typed responses - The following endpoints now have fully typed response and error models in the OpenAPI spec:

    • GET /surface/spec - Returns a structured surface spec bundle including surface ID, entity ID, status, the full surface specification (title, description, fields, sections, branding, submit button text, completion copy, context), and any auto-saved field values.

    • POST /surface/submit (JSON path) - Returns a structured submission receipt with surface ID, status, list of submitted field keys, and completion copy (title, message, action URL).

    • PUT /surface/field - Returns a structured save acknowledgement.

    • POST /surface/heal - Returns a structured correction result with corrected value, explanation, and confidence score.

    • GET /surface/lookup - Returns a structured results envelope.

    • POST /surface/ocr - Returns structured extracted fields with a confidence score.

    • GET /surface/availability - Returns available appointment slots grouped by date, each slot including ID, start time, end time, and optional provider name.

    • POST /surface/book - Returns a structured booking acknowledgement with status, message, and slot ID.

  • Intake upload endpoints return typed responses - The following endpoints now have fully typed response and error models:

    • GET /intake/{token}/info - Returns link metadata including display name, customer slug, maximum upload size, and allowed content types.

    • POST /intake/{token}/upload - Returns an upload receipt with ID, filename, SHA-256 hash, size, scan status, and optional duplicate-detection info.

  • Consistent error envelopes - All error responses from surface endpoints use a common error structure with error_code (machine-readable), message (human-readable), and optional reason and details fields. Intake upload errors use a similar structure with error_code and message. Error models are documented per status code in the OpenAPI spec (401, 404, 409, 410, 413, 422, 500 as applicable).

  • Booking error responses no longer leak internal details - The book-surface-appointment endpoint now returns generic error messages for conflict (409) and validation (422) errors instead of forwarding raw exception details from downstream services. This prevents potential exposure of patient context or scheduling system internals in error responses.

  • New error status codes for booking - The book-surface-appointment endpoint now documents 404 (slot not found), 409 (slot unavailable), and 422 (validation error) responses in the OpenAPI spec, in addition to the previously documented 401 and 410.

  • Intake upload link error responses consolidated - The get-intake-link-info endpoint now documents 410 as covering both expired and exhausted links (previously these were separate descriptions). Rate limit responses (429) no longer carry an error model body.

Who is affected:

All consumers of patient-facing surface endpoints and intake upload endpoints. Response body shapes are unchanged - this is a backwards-compatible addition of schema validation and OpenAPI documentation. Clients that parse the existing JSON fields will continue to work. Clients that relied on raw exception text in booking error messages will now receive standardized error messages instead.

No breaking changes.

chevron-rightv0.9.355 - Platform API: Toll-Free Verification for SMS Compliance (July 2026)hashtag

Toll-Free Verification for SMS Compliance

US and Canadian toll-free phone numbers now support Toll-Free Verification (TFV), the carrier-required compliance step before a toll-free number can send SMS. TFV is a distinct compliance workflow from other trust and regulatory processes - it has its own submission, review lifecycle, and status tracking.

What changed:

  • Submit a Toll-Free Verification - POST /v1/twilio-setup/{setup_id}/phone-number/{phone_number_id}/tollfree-verification creates a new verification for a US or CA toll-free phone number. The request includes business details, use case information, opt-in workflow evidence, estimated message volume, and business contact information. On success, the verification enters a pending-review state and is submitted to the carrier for review. Returns 422 if the phone number is not a US or CA toll-free number.

  • Retrieve verification status - GET /v1/twilio-setup/{setup_id}/phone-number/{phone_number_id}/tollfree-verification returns the current verification state including status, all submitted fields, rejection reasons (if rejected), and whether the verification can be edited for resubmission.

  • Resubmission after rejection - If a verification is rejected, you can resubmit by calling POST again with updated information. The system handles the resubmission automatically - if the verification is still within its edit window, the existing submission is updated in place; if the edit window has closed, the old submission is replaced with a new one. Resubmission is only allowed when the verification is in a rejected state; attempting to resubmit while pending review, in review, or already approved returns 409.

  • Automated status tracking - Verification status updates (approved, rejected, expired) are received automatically and reflected in the verification record. When a verification is rejected, the response includes the specific rejection reasons and whether edits are permitted. When a verification expires (edit window closes on a rejected submission), the expired record is cleaned up automatically so the next submission starts fresh.

  • Phone number deletion guards - Deleting a phone number that has a verification in active review is blocked (409) because the carrier does not allow deletion mid-review. Phone numbers with verifications in any other state (pending review, approved, or rejected) can be deleted normally, and the associated verification is cleaned up automatically.

  • Verification statuses - A verification moves through these states: pending-review (submitted, awaiting carrier review), in-review (carrier is actively reviewing), twilio-approved (approved, terminal), and twilio-rejected (rejected, resubmittable).

Request fields for submit:

Field
Type
Required
Description

business_name

string

Yes

Legal business name as registered

business_website

string (URL)

Yes

Public business website

use_case_categories

array of strings

Yes

One or more traffic categories (e.g., "Appointments", "Healthcare Alerts", "2FA"). 1-10 items.

use_case_summary

string

Yes

Description of how messaging is used (max 4096 chars)

production_message_sample

string

Yes

Example message recipients would receive (max 2048 chars)

opt_in_image_urls

array of strings (URLs)

Yes

Publicly-hosted URLs to images showing the opt-in workflow. 1-10 items.

opt_in_type

string

Yes

How recipients opt in: VERBAL, WEB_FORM, PAPER_FORM, VIA_TEXT, or MOBILE_QR_CODE

message_volume

string

Yes

Estimated monthly volume bucket (e.g., "10", "1,000", "100,000", "1,000,000")

business_street_address

string

Yes

Business street address

business_street_address2

string

No

Address line 2

business_city

string

Yes

City

business_state_province_region

string

Yes

State, province, or region

business_postal_code

string

Yes

Postal code

business_country

string

Yes

ISO 3166-1 alpha-2 country code (e.g., "US", "CA")

business_contact_first_name

string

Yes

Contact first name

business_contact_last_name

string

Yes

Contact last name

business_contact_email

string (email)

Yes

Contact email

business_contact_phone

string (E.164)

Yes

Contact phone number

additional_information

string

No

Free-form context for reviewers (max 4096 chars)

Response fields:

Field
Type
Description

phone_number_id

string (UUID)

Phone number this verification is attached to

verification_sid

string

Verification identifier

status

string

Current status: pending-review, in-review, twilio-approved, or twilio-rejected

rejection_reasons

array of objects or null

When rejected: array of {code, description} entries

edit_allowed

boolean or null

When rejected: whether the verification can be updated in place

created_at

string (datetime)

When the verification was created

updated_at

string (datetime)

When the verification was last updated

(all submitted fields)

Mirrored back from the submission

Error responses:

Status
Condition

404

Setup, phone number, or verification not found

409

Verification is not in a rejected state (POST resubmit), or phone number has a verification in active review (DELETE phone number)

422

Phone number is not US or CA toll-free

Who is affected:

Workspaces that provision US or CA toll-free phone numbers for SMS messaging. Toll-Free Verification must be completed and approved before SMS sending is enabled on the number. This is Phase 1 - the SMS channel binding gate (requiring approved TFV before assigning a toll-free number to an SMS use case) will land in a subsequent release.

chevron-rightv0.9.354 - Platform API: Household-Aware Caller Identity for Shared Phone Lines (July 2026)hashtag

Household-Aware Caller Identity for Shared Phone Lines

The voice agent now correctly handles inbound calls from phone numbers shared by multiple patients in the same household. Previously, when a phone number matched more than one patient record, the system picked one patient and greeted the caller by that person's name - leading to incorrect greetings (e.g., saying "Hi James" when Jane was calling). The agent now detects shared phone lines and uses a neutral greeting, then confirms the caller's identity through the standard verification flow.

What changed:

  • Shared phone lines are no longer pre-bound to a single patient - When an inbound call arrives from a phone number associated with two or more patients, the agent no longer guesses which patient is calling. Instead, it treats the call as a household line and withholds all patient-specific details (name, date of birth, medical record number, conditions, medications) from the greeting. The caller's identity is resolved later through the existing identity confirmation step where the caller provides their name and date of birth.

  • Three caller identity states - The system now distinguishes three cases for every inbound call: (1) no patient records match the phone number (anonymous caller), (2) exactly one patient matches (known caller with full personalized greeting), and (3) two or more patients match (household phone with neutral greeting). Previously, cases 2 and 3 were collapsed into a single path that always selected one patient.

  • Greeting cache is partitioned by caller type - Pre-generated greeting audio is now cached separately for anonymous and household callers. Personalized greetings for known callers bypass the cache entirely to prevent a greeting generated for one patient from being replayed to a different caller. Previously, all greetings shared a single cache key per workspace and service, which could serve a personalized greeting to the wrong caller on a shared line.

  • Per-resident voice signals are not applied to household calls - Language preference, medical vocabulary hints for speech recognition, and voiceprint verification are only applied when exactly one patient is identified. On household lines, these signals are withheld because applying one resident's preferences would bias the system against the actual caller.

  • No API changes - This fix is internal to the voice agent call handling flow. No request or response schemas have changed. Inbound call webhooks, session creation, and all public endpoints continue to work with the same parameters.

Who is affected:

Workspaces where multiple patients share the same phone number (family households, care facilities, shared mobile devices). Callers from these numbers will now receive a neutral greeting followed by identity verification, instead of being incorrectly addressed by another household member's name.

chevron-rightv0.9.353 - Platform API: Phone Number Purchase Address Resolution Fix (July 2026)hashtag

Phone Number Purchase Address Resolution Fix

Phone number provisioning now correctly resolves the address used at purchase time when a regulatory bundle is involved. Previously, purchasing a phone number in certain countries could fail with an address mismatch error even when the address was valid and approved.

What changed:

  • Address resolution prefers the regulatory bundle address - When a regulatory bundle is required for a phone number purchase, the platform now uses the address recorded inside the bundle rather than the workspace-level address. This prevents purchase failures caused by the telephony provider rejecting an address that is not explicitly referenced inside the bundle, even when both addresses describe the same physical location.

  • Fallback to workspace address - If the regulatory bundle does not contain an address reference, or if no regulatory bundle is required, the platform falls back to the workspace-level address created during customer profile setup. This preserves existing behavior for countries and number types that do not require regulatory bundles.

  • No API changes - This fix is internal to the phone number provisioning flow. No request or response schemas have changed. Phone number purchase requests continue to use the same endpoint and parameters.

Who is affected:

Workspaces purchasing phone numbers in countries that require both an address and a regulatory bundle (e.g., toll-free numbers in certain Latin American markets). If you previously encountered address mismatch errors during phone number provisioning, this fix resolves those failures without any action on your part.

chevron-rightv0.9.352 - Platform API: Deterministic Built-in Integration Identifiers (July 2026)hashtag

Deterministic Built-in Integration Identifiers

Built-in integrations (Google Maps, Google Search, Stedi Healthcare, athenahealth EHR) now return stable, deterministic UUIDs instead of synthetic prefixed identifiers. This fixes 500 errors when listing or retrieving built-in integrations by ID.

What changed:

  • Stable UUIDs for built-in integrations - Each built-in integration now has a permanent UUID derived from its name. Previously, built-in integrations used a synthetic builtin:<name> identifier format that changed across requests, which caused GET-by-ID lookups, caching, and client-side keying to break. The new UUIDs are consistent across all API calls and services.

  • GET by UUID works for builtins - GET /v1/integrations/{id} now accepts the standard UUID for built-in integrations. The previous builtin:<name> format is no longer returned or accepted. Clients that stored the old builtin: prefixed IDs should update their cached references.

  • Update and delete guards preserved - Attempts to update or delete a built-in integration continue to return 403 Forbidden, now identified by UUID rather than prefix matching.

  • List endpoint no longer returns 500 - The integrations list endpoint previously could return a 500 error due to unstable built-in identifiers. This is resolved.

Migration notes:

If your client stores integration IDs and any of them use the builtin:<name> format, re-fetch the integrations list to obtain the new stable UUIDs. The builtin: prefix format is no longer used anywhere in the API response.

chevron-rightv0.9.351 - Analytics: Removed AI Classification from Field-Level Tracking (July 2026)hashtag

Analytics: Removed AI Classification from Field-Level Tracking

The field-level submission tracking view in the analytics pipeline no longer includes the AI-classified field intent column. This reduces analytics processing costs with no impact on API consumers.

What changed:

  • Removed field intent classification - The per-field engagement tracking view previously included an AI-classified intent label for each field submission (categorizing fields as required, demographic, clinical, consent, or optional). This classification has been removed. If you were querying field-level analytics data and using the intent classification, that column is no longer populated.

  • No API changes - This change affects the analytics data layer only. No API endpoints, request formats, or response schemas have changed.

chevron-rightv0.9.350 - Platform API: Rate Limiter Response Corrections (July 2026)hashtag

Rate Limiter Response Corrections

The platform rate limiter now returns grammatically correct error messages and more accurate reset timing when a request is throttled.

What changed:

  • Corrected retry message grammar - The 429 error message now uses the correct singular or plural form for the time unit. Previously, the message always said "seconds" even when the retry delay was exactly 1 second (e.g., "Retry after 1 seconds"). It now says "Retry after 1 second" or "Retry after 3 seconds" as appropriate.

  • More accurate rate limit reset time - The X-RateLimit-Reset header on throttled responses now reflects a more precise reset timestamp based on when the oldest request in the current window expires, rather than always projecting from the current time. This gives clients a better estimate of when their rate limit window will free up capacity.

No breaking changes. The Retry-After and X-RateLimit-Reset headers continue to be returned on 429 responses with the same semantics. Only the precision of their values and the grammar of the error message have changed.

chevron-rightv0.9.349 - Platform API: A2P Messaging Profile Company Type and Evaluation Handling (July 2026)hashtag

A2P Messaging Profile Company Type and Evaluation Handling

The A2P 10DLC messaging profile submission endpoint now uses the correct wire-format values for the company type field, and evaluation result parsing supports both legacy and current response shapes from the upstream compliance provider.

What changed:

  • Updated company type values - The company_type field on the A2P messaging profile submission endpoint now accepts private, public, non-profit, and government. The previous values (private_for_profit, public_for_profit, non_profit) are no longer accepted and will return a validation error. Note that the non-profit value uses a hyphen (non-profit), not an underscore.

  • Stock exchange and ticker validation updated - The stock_exchange and stock_ticker fields are now required when company_type is public (previously public_for_profit). They must be omitted for all other company types. Requests that do not match this rule receive a 422 validation error.

  • Evaluation result compatibility - The platform now handles both the legacy and current compliance evaluation response shapes. The legacy shape groups per-field results into separate passed/failed arrays, while the current shape uses a single array with a per-field pass/fail indicator. Both shapes produce the same flattened failure output. This change is transparent to API consumers - evaluation failure messages returned by the API are unchanged in format.

Migration notes:

If your integration submits A2P messaging profiles, update the company_type values in your requests:

Previous value
New value

private_for_profit

private

public_for_profit

public

non_profit

non-profit

government

government (unchanged)

Requests using the old values will be rejected with a 422 validation error.

chevron-rightv0.9.348 - Platform API: Removed Unauthenticated Workspace Creation (July 2026)hashtag

Removed Unauthenticated Workspace Creation

The unauthenticated POST /v1/workspaces endpoint has been removed. All workspace creation now requires authentication and goes through the self-service endpoint.

What changed:

  • Removed POST /v1/workspaces - The unauthenticated workspace creation endpoint has been permanently removed. This endpoint allowed workspace creation without any identity verification, which meant the created workspace had no owner assigned. Going forward, all workspace creation must use the authenticated POST /v1/workspaces/self-service endpoint, which creates the workspace and assigns the authenticated user as the owner in a single operation.

  • Orphan workspace cleanup - Existing workspaces that were created through the removed endpoint without an owner have been archived automatically. If you relied on the unauthenticated endpoint for programmatic workspace provisioning, switch to the self-service endpoint with a valid bearer token or API key.

Breaking change: Any integration calling POST /v1/workspaces will receive a 404 (or 405) response. Update your calls to use POST /v1/workspaces/self-service with proper authentication headers.

chevron-rightv0.9.347 - Platform API: First-Class UUID Identifiers (July 2026)hashtag

First-Class UUID Identifiers

All platform-owned resource identifiers are now typed as UUID (format: uuid) across the API. Path parameters, request bodies, and response models that reference platform resources use strict UUID validation and the OpenAPI format: uuid annotation. External identifiers (third-party system IDs, SIDs, customer-assigned keys) remain plain strings.

What changed:

  • UUID-typed resource identifiers - Fields such as workspace, agent, service, entity, data source, integration, operator, surface, trigger, skill, phone number, persona, and credential identifiers are now validated as UUIDs at the API boundary. Requests that pass a malformed UUID receive a 422 validation error with a clear message instead of silently accepting arbitrary strings.

  • OpenAPI schema annotations - All platform identifier path parameters and model fields now carry type: string, format: uuid in the OpenAPI specification. SDK code generators produce native UUID types (e.g. string with UUID format in TypeScript, uuid.UUID in Python) instead of untyped strings, giving you compile-time safety against accidentally swapping two different resource IDs.

  • Path parameter validation - Workspace-scoped route prefixes (/{workspace_id}/...) and resource-specific path parameters (e.g. /{service_id}, /{entity_id}) now enforce UUID format. The only exception is the call identifier path parameter, which continues to accept both UUIDs and telephony SIDs for backward compatibility.

  • Response model consistency - All response models that return platform resource IDs now serialize them as UUID strings. Fields that previously returned inconsistent formats (some as UUID, some as plain string) are unified.

Migration notes:

If your integration passes well-formed UUIDs today, no changes are required. If you were passing non-UUID strings for platform resource identifiers, those requests will now be rejected with a 422 error. External identifiers (e.g. EHR system IDs, telephony SIDs, CRM record IDs) are not affected and remain plain strings.

SDK users should regenerate their client types to pick up the stricter UUID typing. This enables compile-time detection of identifier mix-ups (e.g. accidentally passing an entity ID where a workspace ID is expected).

chevron-rightv0.9.346 - Platform API: Operator Dashboard Call Details and Audit Filtering (July 2026)hashtag

Operator Dashboard Call Details and Audit Filtering

The operator dashboard priority queue now returns richer call metadata, and the audit log supports filtering by operator and action type.

What changed:

  • Extended priority queue fields - Each call in the priority queue now includes the caller phone number (E.164 format), human-readable service name, call start time, a normalized risk level (low, medium, high, or critical), and data quality flags. These fields give operator console clients more context for triage decisions without requiring a separate lookup.

  • Risk level classification - Calls now include a risk_level field derived from the numeric risk score. This provides a consistent categorical label for UI display and filtering.

  • Data quality indicators - The priority queue reports data quality flags when upstream call metadata contains invalid values (e.g. an unrecognized call direction). Console clients can use these flags to surface data issues to supervisors.

  • Audit log filtering - The audit log endpoint now accepts optional operator_id and action query parameters. Filter by a specific operator's UUID to see their activity history, or by action type to isolate specific event categories.

  • Transcript access auditing - Viewing a call transcript now emits an audit event that records which credential accessed the transcript, the number of segments returned, and that PHI was accessed. This supports compliance requirements for tracking access to protected health information.

  • Escalation stats implementation - The escalation statistics, event stats, event list, and audit log dashboard queries are now fully implemented with real-time aggregation. Stats queries include average wait time and average handle time where applicable. All stats queries are bounded to a maximum lookback window to maintain query performance.

No breaking changes. New fields on the priority queue are additive. Existing audit log queries without filters continue to return all events.

chevron-rightv0.9.345 - Platform API: Typed Streaming Turn Events (July 2026)hashtag

Typed Streaming Turn Events

The SSE stream returned by POST /v1/{workspace_id}/conversations/{id}/turns (with Accept: text/event-stream) now publishes a fully typed TurnStreamEvent discriminated union in the OpenAPI specification. SDK consumers receive compile-time exhaustiveness over the seven event variants instead of having to parse loosely typed JSON blobs.

What changed:

  • Typed event union in the spec - Seven event variants are now defined as Pydantic models in the OpenAPI schema and exposed under the TurnStreamEvent discriminator (keyed on the event field): token (one response token), tool_call_started (agent invoked a tool), tool_call_completed (tool returned with success flag), thinking (reasoning-tier classification), message (final assembled agent response), done (terminal event with conversation_id, status, and turn_count), and error (error mid-stream). Existing wire format and event ordering are unchanged - this is a schema-only addition.

  • Generated discriminated unions in TypeScript - SDK clients running npm run gen-types against the published spec now get a TypeScript discriminated union for TurnStreamEvent. Switch statements over event.event are checked exhaustively at compile time, eliminating a class of "forgot to handle the new variant" bugs when new events are added.

  • Dual content type on the turns endpoint - The OpenAPI definition for the turns endpoint now declares both application/json (returns TurnResponse) and text/event-stream (returns TurnStreamEvent) response content types. Clients select between them with the Accept header.

No breaking changes. Clients that ignore the spec or that hand-parse the SSE stream are unaffected. SDK consumers regenerate types to pick up the new union.

chevron-rightv0.9.344 - Platform API: SSE Streaming on REST Turns and Public WebSocket Proxy (July 2026)hashtag

SSE Streaming on REST Turns and Public WebSocket Proxy

Text conversations now support real-time streaming responses and persistent WebSocket connections, giving chat interfaces lower perceived latency and bidirectional communication.

What changed:

  • SSE streaming on conversation turns - The create-turn endpoint now accepts Accept: text/event-stream to return a Server-Sent Events stream instead of the default synchronous JSON response. As the agent generates its reply, the stream emits token events with partial text chunks, tool_call_started and tool_call_completed events for tool invocations, a thinking event when the agent is reasoning, a message event with the complete reply, and a done event with the conversation status. This lets chat UIs render tokens as they arrive rather than waiting for the full response.

  • Public WebSocket endpoint for text sessions - A new WebSocket endpoint at the sessions connect path provides a persistent bidirectional connection for real-time text conversations. Clients authenticate via the Sec-WebSocket-Protocol subprotocol header (auth, <token>) rather than query parameters, preventing credential leakage in server logs. The WebSocket delivers the same event types as the SSE stream and accepts user messages as JSON text frames. Query parameters specify the service, entity, and optionally a conversation to resume.

  • WebSocket close codes - The WebSocket uses custom close codes to communicate specific failure conditions: 4001 for missing or invalid parameters, 4403 for authentication failures, 4408 for session timeout, 4500/4502 for upstream connection issues, and 4503 for agent service unavailability.

No breaking changes. Existing synchronous turn requests continue to work without modification. The SSE and WebSocket interfaces are additive.

chevron-rightv0.9.343 - Platform API: Normalized Simulation Call Direction (July 2026)hashtag

Normalized Simulation Call Direction

Simulation-originated calls now use a consistent direction label across all platform surfaces, resolving inconsistencies in call intelligence data and call log filtering.

What changed:

  • Consistent direction label for simulation calls - Calls originated from simulation runs now report a standardized direction value in call intelligence events, call logs, and analytics. Previously, simulation calls used a shortened label that did not match the value used elsewhere in the platform, which could cause simulation traffic to be missed by filters or reports that matched on the full label.

  • Backfill for existing data - Existing call intelligence records from previous simulation runs have been updated to use the normalized label. Historical analytics and metric queries that filter by direction will now correctly include all simulation traffic.

No breaking changes. Simulation calls that were previously hard to filter in call intelligence queries will now appear correctly alongside other simulation traffic.

chevron-rightv0.9.342 - Platform API: Revolution Slot Extension Alignment (July 2026)hashtag

Revolution Slot Extension Alignment

Slot resources ingested from Revolution EHR connectors now use the same extension URLs as all other connectors, ensuring that provider, facility, and visit-type filtering work consistently in slot search.

What changed:

  • Unified extension URLs for Slot resources - Revolution Slot resources now emit provider name, provider ID, and facility ID using the same vendor-neutral extension URLs that other connectors already use. Previously, Revolution slots used connector-specific extension URLs that the slot search pipeline did not recognize, causing provider and facility filters to return no results for Revolution-sourced slots.

  • Visit-type extensions on Revolution Slots - Revolution slots now include structured visit-type extensions (ID and display name per allowed visit type) matching the format used by other connectors. This enables appointment-type filtering in slot search for Revolution-sourced availability. Visit-type names containing the pipe character are sanitized to prevent ambiguity in downstream processing.

  • Backward-compatible status resolution - Slot status is now resolved from both the typed event field and the legacy data payload, ensuring that older slot events ingested before a recent infrastructure change continue to display the correct status. This is transparent to API consumers.

No breaking changes. Revolution slots that were previously missing from filtered slot search results will now appear correctly. Slots from other connectors are unaffected.

chevron-rightv0.9.341 - Platform API: Outbound Call Rate Limit Increase (July 2026)hashtag

Outbound Call Rate Limit Increase

The rate limit for creating outbound calls has been raised to support high-volume campaign dialers and scheduled outreach workflows.

What changed:

  • Higher outbound call limit - The create-outbound-call endpoint now allows 1,000 requests per minute per API key, up from the previous write-operation default of 10 requests per minute. This dedicated limit reflects the fact that a single workspace-scoped API key often drives batch outreach campaigns that fan out to hundreds of patients per minute.

  • Scoped to outbound calls only - The increased limit applies exclusively to the create-outbound-call endpoint. All other write endpoints retain their existing rate limits.

No breaking changes. Clients that were hitting the previous 10-per-minute limit on outbound call creation will now succeed at up to 1,000 per minute without any code changes.

chevron-rightv0.9.340 - Platform API: Auto-Greet on Conversation Creation (July 2026)hashtag

Auto-Greet on Conversation Creation

Creating a text conversation now automatically produces the agent's opening greeting turn, so the response includes the agent's first message without requiring a separate request.

What changed:

  • Greeting included in create response - POST /v1/{workspace_id}/conversations now returns the agent's opening greeting in the turns array of the response. Callers such as the Developer Console playground and SDKs can display the greeting immediately after creating the conversation, matching the auto-greet behavior of the WebSocket text-stream path.

  • New auto_greet parameter - The create request body accepts an optional auto_greet boolean (default true). When true, the agent produces its opening turn during creation. Set to false if the caller intends to send the first user message themselves, for example when replaying a transcript.

  • Non-fatal greeting failure - If the agent cannot produce the greeting (transient error, timeout, or misconfiguration), the conversation row is still created successfully. The turns array will be empty and the caller can proceed by sending the first user message. Failures are surfaced through platform metrics and logs, not through the API response status.

  • Web channel only - The automatic greeting is only produced for web-channel conversations. Other channel types are unaffected.

No breaking changes. Existing callers that do not send auto_greet get the greeting by default. Callers that do not use the turns field in the response are unaffected.

chevron-rightv0.9.339 - Platform API: FHIR Bundle Internal Reference Resolution (July 2026)hashtag

FHIR Bundle Internal Reference Resolution

FHIR bundle imports now resolve bundle-internal cross-references before processing, so downstream events and queries carry globally-resolvable references instead of bundle-scoped identifiers.

What changed:

  • Bundle-internal references resolved automatically - When importing a FHIR bundle, resources that reference other resources within the same bundle using temporary bundle-scoped identifiers (such as urn:uuid: values in fullUrl) are now rewritten to stable {ResourceType}/{id} references before events are emitted. This means patient filters, entity resolution, and downstream consumers receive references they can resolve independently, without needing the original bundle context.

  • Supported reference fields - Resolution covers standard patient-linking fields (subject, patient, beneficiary), participant actor references, and encounter references. These are the fields most commonly used for cross-referencing within clinical bundles.

  • No changes to the API contract - The FHIR import endpoint request and response shapes are unchanged. This is a data quality improvement - references that previously passed through as opaque bundle-scoped identifiers are now meaningful outside the bundle.

No breaking changes. Bundles that do not use internal cross-references are unaffected.

chevron-rightv0.9.338 - Platform API: Relaxed Conversation Create Rate Limit (July 2026)hashtag

Relaxed Conversation Create Rate Limit

The rate limit for creating text conversations has been increased to better support API keys that front many concurrent end users.

What changed:

  • Higher create limit - The POST endpoint for creating a new text conversation now allows 60 requests per minute per API key, up from the previous write-operation default of 10 requests per minute. This dedicated limit reflects the fact that a single API key often represents many users starting sessions at the same time.

  • Other endpoints unchanged - All other write, read, and list rate limits on conversation endpoints remain the same.

No breaking changes. Clients that were hitting the previous 10-per-minute limit on conversation creation will now succeed at up to 60 per minute without any code changes.

chevron-rightv0.9.337 - Platform API: Developer Settings Endpoint Removed (July 2026)hashtag

Developer Settings Endpoint Removed

The developer settings endpoint for managing preview URL overrides has been removed from the Platform API. Preview URL configuration is now handled entirely as a per-browser cookie in the Developer Console, with no server-side persistence.

What changed:

  • Removed GET /v1/{workspace_id}/settings/developer - This endpoint previously returned the workspace developer settings including the preview platform API URL. It has been removed.

  • Removed PUT /v1/{workspace_id}/settings/developer - This endpoint previously allowed updating the preview URL override at the workspace level. It has been removed.

  • Preview URL is cookie-only - The Developer Console stores the preview URL as a per-browser cookie. There is no workspace-level server-side storage. This change aligns the API with the Developer Console behavior shipped in v2.164.0, which already moved to cookie-only storage.

Breaking change. If you are calling the developer settings endpoints directly, those calls will now return 404. No migration is needed - the Developer Console handles preview URL configuration automatically via browser cookies.

chevron-rightv0.9.336 - Platform API: Bearer Token Exchange Auth Type (July 2026)hashtag

Bearer Token Exchange Auth Type

Integrations now support a new bearer_token_exchange authentication type for APIs that issue scoped bearer tokens from a workspace credential combined with per-request identity headers.

What changed:

  • New auth type: bearer_token_exchange - A pre-flight token exchange flow that calls a configured exchange endpoint with a workspace-level secret and zero or more per-request identity headers (e.g. user ID, project ID, organization ID). The returned bearer token is cached per unique combination of identity values and used as Authorization: Bearer on downstream API calls. This is useful for third-party APIs that mint short-lived, identity-scoped tokens from a service credential.

  • Dynamic identity headers from request params - The exchange_param_headers field maps request parameters to headers on the exchange call. Each mapping specifies which parameter feeds which header, whether the parameter is required, and whether it should be removed from the downstream request after use. Up to 20 mappings are supported.

  • Configurable exchange response parsing - The exchange_token_field and exchange_expires_in_field settings control which fields in the exchange response JSON hold the bearer token and TTL. A configurable default TTL (exchange_default_ttl_seconds, minimum 120 seconds) is used when the response does not include an expiration.

  • Inline secret provisioning - The workspace secret for the exchange call can be provided inline via exchange_secret_value (automatically provisioned to secure storage) or referenced via exchange_secret_ssm_param_path. The header name and value format are configurable via exchange_secret_header and exchange_secret_format.

  • SSRF protection on exchange URL - The exchange_url must use HTTPS and must not point to private, loopback, link-local, or reserved IP addresses. This validation runs both at configuration time and at runtime.

  • Improved URL validation - Private IP address detection for all URL fields (base URL, exchange URL, MCP URL) now correctly handles IPv6 addresses and edge cases that string-prefix matching could miss.

No breaking changes. Existing integrations and auth configurations are unaffected.

chevron-rightv0.9.335 - Platform API: MyBestPractice EHR Connector (July 2026)hashtag

MyBestPractice EHR Connector

A new bidirectional connector for the MyBestPractice (MBP) practice management system enables background sync of therapist rosters and appointment availability, plus write-back of patient records and appointment bookings.

What changed:

  • New connector type: mbp - MyBestPractice is now available as a data source connector type when configuring workspace integrations. The connector handles authentication and session management with the MBP portal automatically.

  • Inbound sync: therapist roster and availability - The connector periodically syncs the therapist staff roster and their availability slots from MBP. Therapist data is mapped to FHIR R4 Practitioner resources and availability blocks are mapped to FHIR R4 Slot resources. Both resource types flow through the standard world model pipeline with deduplication, so only changed records emit update events.

  • Outbound write-back: patients and appointments - Agent-created patients and booked appointments are written back to MBP automatically. FHIR Patient resources are mapped to MBP patient records, and FHIR Appointment resources are mapped to MBP session bookings. Write-back results are confirmed through the standard sync confirmation flow, and MBP-assigned identifiers are linked back to the corresponding world model entities.

  • FHIR R4 mapping - All data exchanged with MBP is normalized to FHIR R4 resources. Unmapped fields from MBP are preserved as extensions on the FHIR resource, ensuring no data is lost during transformation.

  • Cadence-based polling - Availability data syncs at a higher frequency than the therapist roster, since availability changes more often than staff records. Polling cadence is configurable per data source.

Connection configuration:

MBP connector credentials (base URL, username, password) are stored as secure parameters and resolved at runtime. Configure these through the standard data source connection configuration.

No breaking changes. Existing connectors and data sources are unaffected.

chevron-rightv0.9.334 - Platform API: Clinical Resource Types in FHIR API (July 2026)hashtag

Clinical Resource Types in FHIR API

The FHIR API now serves five additional clinical resource types - Observation, MedicationStatement, FamilyMemberHistory, QuestionnaireResponse, and DocumentReference - alongside the existing scheduling types. Clinical resources that were previously ingested but not queryable through the FHIR search endpoint are now available with full patient filtering support.

What changed:

  • Five new searchable resource types - Observation, MedicationStatement, FamilyMemberHistory, QuestionnaireResponse, and DocumentReference are now returned from the FHIR resource search endpoint. These resources are projected from the world model using the same pattern as scheduling resources.

  • Patient filtering for clinical types - The patient search parameter now works across all clinical resource types, not just Appointment. Each resource type uses the appropriate FHIR R4 reference field for patient matching: clinical resources like Observation, MedicationStatement, QuestionnaireResponse, and DocumentReference filter on subject.reference, while FamilyMemberHistory filters on patient.reference. This follows the FHIR R4 specification for each resource type.

  • Pass-through projection for clinical resources - Clinical resource types carry their complete FHIR-conformant data through the world model. Unlike scheduling types (which are assembled from individual fields at read time), clinical resources are stored as complete FHIR blobs and returned directly, with an id field added from the entity identifier when not already present.

  • Allowed resource type list updated - MedicationStatement, FamilyMemberHistory, and QuestionnaireResponse are now included in the set of allowed resource types for the FHIR search endpoint. Observation and DocumentReference were already allowed but were not previously backed by entity data.

No breaking changes. Existing FHIR search queries for scheduling types (Slot, Location, Practitioner, Patient, Appointment) are unchanged.

chevron-rightv0.9.333 - Platform API: Developer Settings for Preview URL Overrides (July 2026)hashtag

Developer Settings for Preview URL Overrides

Workspace settings now include a developer settings section for configuring preview URL overrides. Internal developers can point a workspace at a preview deployment of the platform API, enabling staging validation of backend changes before they reach production.

What changed:

  • New GET endpoint - GET /v1/{workspace_id}/settings/developer returns the current developer settings for the workspace, including any preview platform API URL override. Returns an empty configuration when no developer settings have been configured. Available to any authenticated user.

  • New PUT endpoint - PUT /v1/{workspace_id}/settings/developer updates the developer settings. The request body accepts a preview_platform_api_url field. The URL must match https://<subdomain>.platform.amigo.ai - other URLs are rejected with a 422 validation error. Set the field to null to clear the override.

  • Restricted write access - Only users with Amigo email addresses can update developer settings. API key authentication is not supported for writes - a user identity token is required. Non-Amigo accounts receive a 403 error. Read access is available to any authenticated user.

  • Audit logging - Updates to developer settings are recorded in the audit log, capturing the previous and new preview URL values.

No breaking changes. Existing workspace settings endpoints are unchanged.

chevron-rightv0.9.332 - Platform API: Download Intake Uploads (July 2026)hashtag

Download Intake Uploads

Operators can now download files that were submitted through intake links. A new endpoint proxies the stored file bytes back to the caller with appropriate content headers, enabling operators to retrieve uploaded documents directly from the API.

What changed:

  • New download endpoint - GET /intake/links/{link_id}/uploads/{upload_id}/download returns the raw file bytes for a specific upload. The response includes the original filename in the Content-Disposition header (using RFC 5987 encoding for non-ASCII characters), the stored content type, and cache-control headers that prevent browser caching of downloaded files.

  • Cross-tenant isolation - The download endpoint validates that the upload belongs to the specified link and workspace. Requests that reference an upload from a different link or workspace return 404, preventing cross-tenant data access.

  • Storage backend errors - If the storage backend is unavailable or returns an error, the endpoint returns 502 with a generic error message. No file paths or storage details are exposed in error responses.

  • PHI audit logging - Download requests are recorded in the PHI access audit log as intake.upload_download events, consistent with other PHI-accessing operations.

No breaking changes. Existing intake link and upload endpoints are unchanged.

chevron-rightv0.9.331 - Platform API: Test Caller Numbers Limit Raised to 100 (July 2026)hashtag

Test Caller Numbers Limit Raised to 100

The maximum number of test caller numbers per workspace has been raised from 20 to 100. This gives teams more room to register test phone numbers for simulation and QA workflows without hitting the previous cap.

What changed:

  • Higher test caller number cap - Workspaces can now register up to 100 test caller numbers, up from the previous limit of 20. The request and response shapes are unchanged. Existing test caller number configurations are unaffected.

No breaking changes. Requests that were valid before remain valid. The only difference is that lists of 21 to 100 numbers are now accepted.

chevron-rightv0.9.330 - Platform API: Legacy Voice Conversation Store Removed (July 2026)hashtag

Legacy Voice Conversation Store Removed

Voice conversation persistence now writes exclusively to the unified conversation store introduced in v0.9.327. The legacy voice-specific store is no longer written to. This completes Phase 5 of the storage migration that began with unified writes in v0.9.324 and read migration in v0.9.328.

What changed:

  • Single write path for voice conversations - Voice conversations are now persisted directly to the unified conversation store with per-turn records. The previous dual-write behavior, where conversations were written to both the legacy voice-specific store and the unified store, has been removed. All new voice conversations are stored only in the unified store.

  • No changes to API responses - All conversation read endpoints, call listings, call detail views, and analytics continue to return the same response shapes. The read paths were already migrated to the unified store in v0.9.328.

  • Conversation updates unaffected - Updating conversations by call identifier or conference identifier continues to work as before. Update paths remain functional during the transition period.

  • Writer dependency now required - The conversation writer must be configured for voice conversation persistence to succeed. If the writer is not configured, conversation data is not persisted and a warning is logged. Previously, the legacy store would persist data even without the unified writer configured.

No breaking changes to API request or response shapes. This is a backend storage simplification that removes the legacy write path.

chevron-rightv0.9.329 - Platform API: Bootstrap Membership on Ownerless Workspaces (July 2026)hashtag

Bootstrap Membership on Ownerless Workspaces

The workspace bootstrap-membership endpoint now supports claiming ownership of workspaces that have no current owner, even when non-owner members already exist. Previously, bootstrap was blocked if any active membership existed on the workspace. Now it checks specifically for an existing owner.

What changed:

  • Ownerless workspace recovery - Bootstrap membership now succeeds on workspaces that have active members but no owner. If the caller already has a non-owner membership on the workspace, bootstrap upgrades their role to owner instead of creating a duplicate membership. This supports recovery scenarios where a workspace loses its owner through account removal or deactivation.

  • Owner check replaces member check - The endpoint now verifies whether the workspace has an active owner rather than checking for any active member. Workspaces with non-owner members but no owner are treated as claimable. Workspaces that already have an owner return an error directing the caller to use the ownership-transfer flow instead.

  • Existing member upgrade - When the bootstrapping user already has an active non-owner membership, the endpoint upgrades their existing membership to owner rather than rejecting the request. The audit log records the previous role for traceability.

  • Already-owner short circuit - If the caller already has an active owner membership on the workspace, the endpoint returns the existing membership immediately without modification.

No breaking changes to request or response shapes. The endpoint accepts the same payload and returns the same membership structure as before.

chevron-rightv0.9.328 - Platform API: Conversation Reads from Unified Store with Backfill (July 2026)hashtag

Conversation Reads from Unified Store with Backfill

All conversation read paths - call listings, call detail, phone call volume, and the unified conversations API - now read from the unified conversation store introduced in v0.9.327. Historical voice conversation data has been backfilled into the unified store so that existing calls remain accessible without any gaps. This completes the migration from the previous voice-specific store to the unified model.

What changed:

  • All read queries use the unified conversation store - Call listings, call detail views, phone call volume analytics, and the unified conversations endpoint now read conversation data from the single shared store rather than the previous voice-specific store. Response shapes are unchanged. Callers of these endpoints see the same data as before, sourced from the unified store.

  • Turn data read from dedicated turn records - Call detail responses now build the conversation turn list from individual turn records in the unified turn store instead of reading from an embedded array on the conversation record. Each turn includes role, text, and timestamp. This aligns with the turn-level storage structure introduced in v0.9.327.

  • Historical data backfilled - All existing voice conversation records have been migrated into the unified conversation store. Conversations created before v0.9.327 are now queryable through the same read paths as new conversations. No data was removed from the previous store during the migration period.

  • Recording reference field updated - The recording_path field in call detail responses now reflects the prefix-based recording reference introduced in v0.9.327. The has_recording field logic is unchanged.

  • Conversation identifier consistency - Call detail responses now consistently use the unified conversation identifier. The id field in call detail and conversation summary responses reflects the conversation-level identifier from the unified store.

  • Completion reason and final state fallback - Conversation summaries now fall back to conversation-level completion reason and final state when call intelligence data is not available. Previously, these fields were only populated from call intelligence records.

  • Service ID resolution improved - Service ID in conversation responses now falls back to the conversation-level service reference when call intelligence data does not include one. This improves service attribution for conversations that completed before call intelligence processing.

No breaking changes to API response shapes. This is a read-path migration that completes the transition to the unified conversation store.

chevron-rightv0.9.327 - Platform API: Unified Conversation and Turn Storage (July 2026)hashtag

Unified Conversation and Turn Storage

Conversation storage has been restructured so that all channels - voice, text, web, and others - share a single conversation store with a dedicated turn store. Turn data is now stored as individual records with typed fields instead of embedded arrays. This replaces the previous split between the voice-specific store and the text conversation store.

What changed:

  • Single conversation store across all channels - Voice, text, web, and other channel types now write to the same conversation store. Each conversation record carries a channel kind, provider identifiers, call metadata (for voice), timing, recording references, completion reason, and structured observability data. Previously, voice conversations were stored separately from text conversations with different schemas.

  • Turn-level storage with typed fields - Individual conversation turns are now stored as separate records rather than embedded inside the conversation record. Each turn includes the user transcript, agent transcript, agent action, trigger, interruption status, speaker identity, emotion signals, speech-to-text confidence, end-of-turn confidence, state, tool call history, state transitions, inner thoughts, and per-turn latency metrics (engine time, navigation time, render time, audio time-to-first-byte). Audio timing windows (user speech start/end, agent speech start/end, audio window boundaries) are also captured per turn. This makes turn-level querying, filtering, and analytics possible without parsing embedded data structures.

  • Conversation-level observability fields promoted to typed columns - Data that was previously stored as unstructured metadata on voice conversations - emotional summary, barge-in events, states visited, forwarding details, call analysis, verified transcript, transcript accuracy, verified words, and per-turn accuracy - is now stored in dedicated typed fields on the conversation record. This makes these fields directly queryable and indexable.

  • Recording and telephony fields updated - Recording references now use a prefix-based path instead of a full file path. Telephony-specific fields (recording URL, recording duration) are stored as typed fields on the conversation record rather than in metadata.

  • Turn count tracked on conversation - Each conversation record maintains a turn count that reflects the number of turn records associated with it.

  • Backward-compatible rollout - Existing conversation data continues to be accessible. The new storage structure is additive. Queries against the previous voice-specific store remain functional during the migration period.

No breaking changes to customer-facing API endpoints. This is a storage-layer restructuring that improves query performance and enables turn-level analytics across all conversation channels.

chevron-rightv0.9.326 - Platform API: Per-Account Telephony Event Streams (July 2026)hashtag

Per-Account Telephony Event Streams

Telephony setup now provisions a dedicated event stream for each account. The platform subscribes to A2P 10DLC brand registration status change events at setup time and delivers them to a webhook endpoint for asynchronous processing. This lays the groundwork for real-time brand registration status tracking without polling.

What changed:

  • Event stream provisioned at setup time - When a new telephony setup is created via POST /v1/twilio-setup, the platform now provisions a webhook-based event stream sink and subscribes it to brand registration status change events. The stream is scoped to the individual telephony account created during setup. If provisioning fails, all resources created during the setup are rolled back automatically.

  • Brand registration event subscription - The event stream subscription covers all brand registration lifecycle events: registered, verified, vetted-verified, unverified, failure, secondary vetting failure, and invalid contact email. These events will drive automated status updates in a future release. For now, events are received, validated, and acknowledged.

  • Webhook endpoint for event delivery - A new webhook endpoint receives event stream deliveries. Each delivery is cryptographically validated against the originating account's credentials before processing. Events from unrecognized accounts are silently acknowledged. Deliveries containing events from multiple accounts are rejected to enforce data integrity.

  • Setup record tracks stream identifiers - The telephony setup record now includes identifiers for the event stream sink and subscription. These are required for teardown - any future setup deletion must remove the subscription and sink before closing the telephony account.

  • Rollback safety - If any step after event stream creation fails during setup, the stream resources are automatically cleaned up as part of the existing reversal mechanism. This prevents orphaned event streams on partial setup failures.

No breaking changes. Existing telephony setups created before this release do not have event streams and will be backfilled in a future migration. The new webhook endpoint is internal to the platform and not part of the customer-facing API surface.

chevron-rightv0.9.325 - Platform API: Simulation Call Intelligence Emission on Run Completion (July 2026)hashtag

Simulation Call Intelligence Emission on Run Completion

Completed simulation runs now emit call intelligence events that flow through the same metric evaluation pipeline as production calls. This closes the loop between simulation execution and quality measurement - simulation sessions are now scored by the same standard and custom metrics used for production traffic.

What changed:

  • Call intelligence emission on run completion - When a simulation run completes without errors, the platform emits one call intelligence event per session in the run. Each event carries the conversation transcript, tool call history (including per-call success/failure status), state traversal path, terminal state, session score, and the simulation run identifier. These events enter the analytical pipeline with a simulation source tag so they are evaluated separately from production data.

  • Metric evaluation parity - Simulation call intelligence events have the same structure as production call intelligence events. Standard quality metrics and any custom metrics configured for the workspace are evaluated against simulation sessions automatically. No additional configuration is needed to include simulation data in metric evaluation.

  • Deduplication - The metric evaluation pipeline deduplicates call intelligence events per session and run. If a run completion is retried or an event is replayed, duplicate emissions are collapsed so each session is evaluated exactly once. This prevents inflated metric counts from operational retries.

  • Errored runs skip emission - Runs that complete with an error do not emit call intelligence events. Session data from failed runs is incomplete, and evaluating metrics against partial transcripts would produce misleading quality scores. The run is still marked as failed and raw session data remains available for inspection.

  • Fail-open behavior - Call intelligence emission happens after the run is marked complete. If emission fails for any session, the failure is logged but does not change the run status or affect other sessions. The run remains marked as completed and previously emitted events are preserved.

No breaking changes. No new API endpoints or request/response changes. Existing simulation run workflows continue to work unchanged - this adds automatic metric evaluation for completed runs.

chevron-rightv0.9.324 - Platform API: Unified Conversation Table for Voice (July 2026)hashtag

Unified Conversation Table for Voice

Voice conversations are now persisted to the same unified conversation store used by text channels. During rollout, voice conversation data is written to both the legacy voice-specific store and the unified store. The unified write is best-effort - failures are logged but do not block the legacy write path.

{% hint style="info" %} Superseded: This release has been superseded by v0.9.327, which restructures the unified store to use dedicated turn-level records with typed fields and promotes observability metadata to typed columns. {% endhint %}

What changed:

  • Unified voice conversation persistence - When a voice call ends, the platform now writes the conversation record to the unified conversation store in addition to the existing voice-specific store. The unified record includes call identifiers, timing, direction, recording references, and completion reason as queryable fields. Observability data (emotional summary, barge-in events, call analysis, transcript accuracy, and similar blobs) is stored as structured metadata on the unified record.

  • Dual-write during rollout - Both stores receive writes during the rollout phase. The legacy voice store remains the source of truth. The unified store write is fire-and-forget - if it fails, the legacy write still succeeds and the failure is logged for operational visibility. This ensures zero risk to existing voice conversation data.

  • Upsert by call identifier - The unified write uses an upsert strategy keyed on workspace and call identifier. If a conversation record already exists for the same call, the write updates timing, completion, recording, status, and metadata fields rather than creating a duplicate.

  • Update operations pending - Update-by-ID, update-by-call-identifier, and update-by-conference-identifier operations on the unified store are implemented but not yet wired into the dual-write path. These will be enabled in a future release once the required workspace context is threaded through all update call sites.

No breaking changes. No new API endpoints or request/response changes. This is an internal persistence change that prepares the platform for a single conversation store across all channels.

chevron-rightv0.9.323 - Platform API: Data Source Provenance on FHIR Events and Orphan Event Cleanup (July 2026)hashtag

Data Source Provenance on FHIR Events and Orphan Event Cleanup

FHIR write and import endpoints now accept an optional data_source_id field that links emitted world events to a registered data source. When a data source is later deleted, orphaned events are automatically cleaned up by a periodic background process.

What changed:

  • data_source_id on FHIR create and update - The POST /v1/{workspace_id}/fhir/{resource_type} and PUT /v1/{workspace_id}/fhir/{resource_type}/{resource_id} endpoints now accept an optional data_source_id field (UUID) in the request body. When provided, the emitted world event is tagged with the data source for provenance tracking. The data source must belong to the caller's workspace; an unrecognized or cross-workspace ID returns 422 (not 404, to avoid leaking whether a foreign ID exists).

  • data_source_id on FHIR bundle import - The POST /v1/{workspace_id}/fhir/import endpoint now accepts an optional data_source_id field (UUID) in the request body alongside bundle, source, and source_system. All events emitted from the bundle are tagged with the specified data source.

  • Connector event provenance - Events emitted by the connector sync engine now carry the data source identifier for the connection that produced them. This enables the same cleanup lifecycle for connector-sourced events.

  • Automatic orphan event cleanup - A periodic background process detects world events whose data source no longer exists (the source was deleted via the data source API) and permanently removes them from storage. The process runs in dry-run mode by default and can be enabled for destructive deletes once orphan counts are validated. Each cycle is capped to a configurable number of orphan sources to bound blast radius. Structured audit logs record every cleanup cycle with source identifiers and row counts.

  • Entity data not cascade-deleted - Entity records derived from orphaned events are intentionally preserved. Eventual consistency is the accepted trade-off - entity cleanup for deleted data sources requires a manual refresh or operator action.

No breaking changes. The data_source_id field is optional and defaults to null. Existing requests without it continue to work unchanged.

chevron-rightv0.9.322 - Platform API: Streaming Per-Scenario Session Execution (July 2026)hashtag

Streaming Per-Scenario Session Execution

Simulation runs now start session execution per-scenario as streaming generation delivers each scenario, rather than waiting for all scenarios to finish generating before running any sessions. This collapses perceived run time for large scenario sets.

What changed:

  • Per-scenario session kickoff - Each simulation session now starts as soon as its scenario arrives from the streaming generator. Previously, all scenarios had to finish generating before any sessions began. With generation streams that can take a minute or more, the first session now begins within seconds of the first scenario landing.

  • total_scenarios_requested field on run responses - Simulation run responses now include a total_scenarios_requested field (integer or null). This is set once when streaming generation begins and represents the target scenario count for the run. Clients can compare the length of the scenarios array (the live ready count) against total_scenarios_requested to render generation progress (e.g. "3 of 10 scenarios generated"). The field is null on legacy runs that predate streaming generation.

  • Partial generation resilience - If scenario generation fails partway through after some scenarios have already spawned sessions, those sessions continue running to completion. The run record surfaces both the partial-generation failure and the results from sessions that completed. Previously, a generation failure discarded all progress.

  • scenarios list grows over time - The scenarios array on streaming runs now grows incrementally as scenarios arrive. Polling clients see scenarios appear one by one. The total_scenarios_requested field provides the denominator for progress display.

No breaking changes. The total_scenarios_requested field is additive and null on existing runs.

chevron-rightv0.9.321 - Platform API: Unified Conversation Persistence and Multimodal Content (July 2026)hashtag

Unified Conversation Persistence and Multimodal Content

Conversation persistence is now unified across all text channels. Conversations track which service created them, enforce service ownership on resume, and support structured multimodal content parts on every turn.

What changed:

  • Service binding - Every conversation now records the service that created it. When a client resumes an existing conversation, the platform verifies that the requesting service matches the original service. Requests from a different service are rejected with a not-found error. This prevents cross-service conversation leakage in multi-service workspaces.

  • Multimodal content parts - Turns in a conversation can now include a content array of structured content parts alongside the plain text field. Each content part has a type (e.g. text, file), optional text, url, media_type, provider_id, and metadata fields. This allows messages to carry files, images, and other media without changing the turn structure. The plain text field continues to contain the text transcript for backward compatibility.

  • Content parts on create turn - The POST /v1/{workspace_id}/conversations/{conversation_id}/turns endpoint now accepts optional content (array of content parts, max 20), media_url (string, max 2,048 characters), and media_type (string, max 128 characters) fields in the request body. These are stored on the turn and returned in the response.

  • Content parts in responses - Conversation turns returned by list, detail, and turn response endpoints now include a content array. Each element is a content part object with type, text, url, media_type, provider_id, and metadata fields.

  • Service ID on conversation objects - Conversation summary and detail responses now include a service_id field (UUID) identifying the service that owns the conversation.

  • Turn count tracking - Conversations now track an explicit turn_count that is maintained by the persistence layer. This replaces the previous approach of deriving turn count from conversation state. The turn count is returned on conversation summaries, details, and turn response snapshots.

  • Channel kind filter on list - The GET /v1/{workspace_id}/conversations endpoint now accepts an optional channel_kind query parameter to filter conversations by channel type (web, sms, whatsapp).

  • UUID validation on path and body parameters - conversation_id path parameters and service_id/entity_id body fields are now validated as UUIDs. Invalid values return a 422 error.

  • Service validation on create - Creating a conversation now validates that the provided service_id references an existing service in the workspace. If the service does not exist, the endpoint returns a 404 error.

  • Stricter consent verification for outbound text - Outbound text creation now returns a 503 error if SMS consent cannot be verified due to a temporary service issue, rather than proceeding without verification.

  • WebSocket text stream content parts - WebSocket message frames now accept optional content (array of content parts, max 20), media_url (string, max 2,048 characters), and media_type (string, max 128 characters) fields. These are stored on the conversation turn alongside the text.

  • Text interact content parts - The text interact endpoint now accepts optional content, media_url, and media_type fields in the request body, matching the WebSocket and turn creation interfaces.

Breaking changes:

  • service_id and entity_id fields on conversation creation and text interact requests are now validated as UUIDs. Requests with non-UUID values that previously succeeded will now return 422.

  • conversation_id path parameters on turn creation and close endpoints are now validated as UUIDs.

  • Resuming a conversation from a different service than the one that created it now returns a not-found error instead of succeeding.

chevron-rightv0.9.320 - Platform API: Text Session Cooperative Shutdown (July 2026)hashtag

Text Session Cooperative Shutdown

Text session shutdown now uses a cooperative stop mechanism that ensures conversation state is fully persisted before the session is released. Previously, stopping a text session could cancel in-flight persistence work, which in rare cases led to lost conversation state when a session ended during a save operation.

What changed:

  • Cooperative stop - When a text session is asked to stop (client disconnect, idle timeout, or server-initiated shutdown), the platform now signals the session to wind down gracefully rather than forcibly cancelling it. The session finishes any in-progress work, persists conversation state and intelligence data, and only then releases the session. This eliminates a window where conversation data could be lost during shutdown.

  • Persistence always completes - Conversation state persistence now runs to completion even if the session is force-stopped due to a timeout. The platform waits for persistence to finish before releasing the session lease, so another instance cannot claim the same conversation while a write is still in progress.

  • Timeout fallback - If a session does not exit within a reasonable period after a cooperative stop is requested, the platform falls back to forceful cancellation. This prevents hung sessions from blocking resources indefinitely.

  • Improved shutdown reason tracking - The platform now distinguishes between different shutdown reasons (client disconnect, idle timeout, lease loss) more accurately in logs and metrics. This improves debugging for sessions that end unexpectedly.

No breaking changes. No new API endpoints or parameters. Existing clients are unaffected.

chevron-rightv0.9.319 - Platform API: Stable Text Stream Reconnects (July 2026)hashtag

Stable Text Stream Reconnects

Text streaming WebSocket connections are now more resilient to transient disconnects. The platform sends periodic keepalive pings, supports client-side message deduplication, and serializes outbound frames to prevent interleaved writes.

What changed:

  • Keepalive pings - The server sends periodic ping events over the WebSocket connection. These prevent idle connections from being dropped by proxies or load balancers. Clients should treat ping events as no-ops.

  • Client message deduplication - Client messages can now include an optional client_message_id field (string, 1-128 characters, alphanumeric plus ., _, :, -). If a message with the same client_message_id is received on the same conversation, the server responds with a response_complete event containing "duplicate": true and does not reprocess the message. This makes retries during reconnection safe. If the deduplication store is temporarily unavailable, messages are processed normally to avoid blocking.

  • Serialized outbound writes - Outbound WebSocket frames are now serialized so concurrent sends (typing indicators, events, messages) do not interleave. This eliminates a class of rare protocol errors on high-throughput connections.

  • Improved error observability - Failures to send typing indicators or events over the WebSocket are now logged with context instead of being silently suppressed.

  • Auto-greet behavior on reconnect - When a client reconnects with an existing conversation ID, the agent no longer sends an automatic greeting message. Auto-greet only fires for new conversations.

No breaking changes. Existing clients that do not send client_message_id continue to work as before.

chevron-rightv0.9.318 - Platform API: Dynamic Mid-Call TTS Language Switching (July 2026)hashtag

Dynamic Mid-Call TTS Language Switching

Voice agents configured with a multilingual speech-to-text model now automatically switch their text-to-speech output language to match the caller's detected language during a live call. This enables natural multilingual conversations where the agent responds in the same language the caller is speaking, without requiring a new call or any configuration change.

What changed:

  • Automatic language detection and TTS sync - When the speech-to-text engine consolidates on the caller's dominant language, the platform automatically updates the TTS provider to synthesize speech in that language. The switch happens mid-call with no interruption to the conversation.

  • Works across all supported TTS providers - All TTS providers supported by the platform handle mid-call language updates. Providers that require a connection change to switch languages are reconnected transparently in the background.

  • Multilingual model required - Language detection and automatic switching are only active when the voice agent uses a multilingual speech-to-text model. Agents configured with an English-only model are unaffected.

  • Supported languages - Automatic switching supports English, Spanish, French, German, Portuguese, Japanese, Korean, Chinese, Arabic, Hindi, and Italian. Other detected languages are tracked but do not trigger a TTS switch.

No breaking changes. No new API endpoints or parameters. Voice agents configured with multilingual speech-to-text models automatically benefit from this feature.

chevron-rightv0.9.317 - Platform API: Phone-Based Patient Lookup Returns Full Household (July 2026)hashtag

Phone-Based Patient Lookup Returns Full Household

The patient lookup tool now returns all patients associated with a phone number instead of only the first match. Phone numbers are household identifiers - multiple patients can share the same number (e.g. a parent and child on the same line). Returning only one record caused the agent to miss other household members, preventing proper identity verification when the caller was not the first record returned.

What changed:

  • Full household returned on phone lookup - When the agent looks up a patient by phone number alone (no name or date of birth provided), the lookup now returns every patient record tied to that number. Previously, only a single record was returned, which meant the agent could not see or disambiguate other household members sharing the same phone.

  • Identity verification works for all household members - Because all matching records are now surfaced, the agent's identity verification step (matching by name and date of birth) can correctly identify any member of the household, not just the one who happened to be returned first.

  • No change when other identifiers are provided - Lookups that include a patient ID, or a combination of name and date of birth, continue to work as before. The household expansion only applies to phone-only lookups.

No breaking changes. No new API endpoints or parameters. Agents that perform phone-based patient lookup will automatically benefit from seeing the complete set of household members.

chevron-rightv0.9.316 - Platform API: National Phone Number Support (July 2026)hashtag

National Phone Number Support

The phone number listing and provisioning endpoints now support national (non-geographic) phone numbers as a distinct number type. National numbers are non-geographic numbers that exist in certain countries alongside local, mobile, and toll-free inventory. They are now surfaced as their own category so callers can search for and provision them explicitly.

What changed:

  • New national number type - The number_type parameter on the list available phone numbers and provision phone number endpoints now accepts national in addition to local, mobile, and toll-free. National numbers are non-geographic numbers available in select countries (currently AT, CZ, FR, GB, IL, JP, RO, ZA). Requesting national for a country that does not offer national numbers returns an empty result set rather than an error, so callers can iterate countries uniformly.

  • Clean separation between local and national - When searching for local numbers, national numbers that were previously mixed into the results are now filtered out. Conversely, searching for national returns only non-geographic numbers. This ensures callers get the category they asked for without overlap.

  • Provision-time validation - Provisioning a phone number with number_type=national validates that the phone number matches a known national prefix for the specified country. Attempting to provision a national-prefix number as local is rejected with a 422 error directing you to use number_type=national instead. This ensures the correct regulatory bundle is attached at purchase time.

  • Regulatory compliance - National numbers use their own regulatory compliance regulation lookup. The regulation bundle submission endpoint now handles national as a recognized number type, ensuring the correct compliance requirements are applied.

  • Phone number response - The phone number response model now includes national as a possible value in the number_type field.

No breaking changes. Existing integrations that use local, mobile, or toll-free continue to work as before. The only behavioral difference is that local results no longer include national-prefix numbers that were previously mixed in.

chevron-rightv0.9.315 - Platform API: Outbound Phone Number Resolution at Scheduling Time (July 2026)hashtag

Outbound Phone Number Resolution at Scheduling Time

Outbound tasks now resolve the caller phone number when the task is scheduled rather than at dispatch time. This eliminates a class of failures where outbound calls could not be placed because the phone number lookup failed at the moment of dialing.

What changed:

  • Early phone number resolution - When an outbound task is created, the platform now resolves which phone number to use for the call immediately. Previously, the phone number was looked up at dispatch time, which meant a transient failure during dispatch could prevent an otherwise valid call from going out. Resolving at scheduling time ensures the phone number is locked in before the task enters the dispatch queue.

  • Service-aware caller ID selection - If the outbound task is associated with a specific service, the platform prefers the phone number already assigned to that service as its inbound number. This provides consistent caller ID - patients see the same number calling them as the one they would call back. If no service-specific number is found, the platform falls back to any active phone number with outbound capability in the workspace.

  • Validation at creation time - Phone numbers provided explicitly in the task request are now validated as E.164 format at scheduling time. Invalid phone numbers are rejected immediately with a clear error, rather than failing silently at dispatch.

  • Clearer error messages - If no outbound-capable phone number is configured for the workspace, the task fails at creation time with an explicit error message instead of failing later during dispatch with less context.

No breaking changes. Existing outbound task creation requests work without modification. Tasks that previously relied on dispatch-time phone number resolution will continue to work - the dispatch path retains a fallback lookup during the transition period.

chevron-rightv0.9.314 - Platform API: Extended Text Interaction Timeout (July 2026)hashtag

Extended Text Interaction Timeout

The text interaction endpoint now uses a longer timeout to accommodate full agent reasoning cycles. Previously, text interactions shared the same timeout as lightweight proxy calls, which could cause premature timeouts when the agent needed to execute multi-step tool chains before responding.

What changed:

  • Longer timeout for text interactions - The text interaction endpoint now has a dedicated timeout that matches the audio turn timeout, since both operations involve a full agent reasoning cycle (engagement, tool calls, and final response generation). Previously, text interactions used the shorter generic proxy timeout, which was designed for simple forwarding calls and could expire before the agent completed complex reasoning chains.

  • Other voice agent proxy calls unchanged - All other proxy calls to the voice agent continue to use the existing shorter timeout. Only the text interaction endpoint is affected.

No breaking changes. No new API endpoints or parameters. Integrations that previously experienced intermittent timeouts on text interactions with complex tool-calling agents should see improved reliability.

chevron-rightv0.9.313 - Platform API: Immediate Session Revocation on Role and Membership Changes (July 2026)hashtag

Immediate Session Revocation on Role and Membership Changes

When a workspace member's role is changed, their membership is removed, or workspace ownership is transferred, all active sessions for the affected members are now revoked immediately. Previously, role and membership changes took effect only after existing sessions expired naturally, which could leave stale permissions active for an extended period.

What changed:

  • Role changes revoke sessions - When an admin updates a workspace member's role, all of that member's active sessions are revoked immediately. The member must re-authenticate to obtain new credentials reflecting their updated role. This ensures permission changes are enforced without delay.

  • Membership removal revokes sessions - When a member is removed from a workspace, their active sessions are revoked as part of the removal. The member loses access immediately rather than retaining access until their existing session expires.

  • Ownership transfer revokes sessions for both parties - When workspace ownership is transferred, active sessions for both the previous owner and the new owner are revoked. Both users must re-authenticate to receive credentials reflecting their new roles.

  • Audit trail includes revocation count - The audit log entry for role changes now includes the number of sessions that were revoked as part of the operation, providing visibility into enforcement actions.

No breaking changes. No new API endpoints or parameters. Existing role change, membership removal, and ownership transfer endpoints behave the same from a request/response perspective - the only difference is that permission changes now take effect immediately instead of at next session renewal.

chevron-rightv0.9.312 - Platform API: Increased Surface Fields Limit (July 2026)hashtag

Increased Surface Fields Limit

The maximum number of fields allowed on a surface has been increased from 100 to 200. This applies to both creating and updating surfaces.

What changed:

  • Higher fields cap - The fields array on surface create and update requests now accepts up to 200 fields, up from the previous limit of 100. The minimum of 1 field is unchanged. This supports more complex data collection forms - such as multi-section intake questionnaires or detailed clinical assessments - without requiring customers to split content across multiple surfaces.

No breaking changes. Existing surfaces with 100 or fewer fields continue to work without modification.

chevron-rightv0.9.311 - Platform API: Linear Comment Reply Handling (July 2026)hashtag

Linear Comment Reply Handling

The Linear integration now handles comment replies on issues that Ami is working on. When someone replies to a comment on a Linear issue linked to an Ami task, the reply is added as a follow-up user message on the existing task. This enables back-and-forth collaboration with Ami directly from Linear without creating new tasks.

What changed:

  • Comment replies become follow-up messages - When a comment is created on a Linear issue that has a matching Ami task, the comment body is added as a new user message on that task. If the task is in a resumable state, it is automatically re-enqueued for processing. This lets team members provide additional context, corrections, or follow-up instructions without leaving Linear.

  • Reply threading - Comments that are direct replies to Ami's completion comment are matched to the originating task by the parent comment. Comments on the same issue (but not direct replies) are matched by issue ID, finding the most recently created task for that issue.

  • Queuing for in-progress tasks - If a comment arrives while the task is actively running, it is queued and automatically processed when the current run completes. Multiple comments that arrive during a single run are processed in order. This prevents message loss during long-running tasks.

  • Duplicate detection - If the same comment webhook is delivered more than once, the duplicate is detected and ignored. Deduplication checks both processed messages and queued comments.

  • Self-comment filtering - Comments authored by Ami itself are ignored, preventing feedback loops.

No breaking changes. Existing Linear issue assignment behavior is unchanged. The new comment handling is automatic for any workspace with a configured Linear integration.

chevron-rightv0.9.310 - Platform API: Clinical Data Intake CSV Compatibility Fix (July 2026)hashtag

Clinical Data Intake CSV Compatibility Fix

The clinical data intake pipeline now correctly parses CSV files that use RFC 4180 quoting conventions. Previously, CSV files containing structured data in cell values (such as JSON arrays or objects) could be corrupted during parsing because the reader misinterpreted doubled-quote escape sequences. This caused cell boundaries to shift, splicing fragments of one column into the next and producing garbled data downstream.

What changed:

  • RFC 4180 compliant CSV parsing - The intake file reader now uses standard doubled-quote escape semantics ("" to represent a literal ") as defined by RFC 4180. Previously, the reader used a backslash-based escape convention that is incompatible with most CSV producers, including the files generated by clinical data partners. This fix ensures that cells containing structured data (JSON lists, nested objects, or values with embedded quotes) are parsed correctly with their contents intact.

No breaking changes. No new API endpoints or parameters. Existing intake configurations work without modification. Customers whose CSV files were previously parsed correctly continue to see the same behavior - this fix only affects files that use RFC 4180 doubled-quote escaping.

chevron-rightv0.9.309 - Platform API: Engage Pipeline Resilience for Advanced Models (July 2026)hashtag

Engage Pipeline Resilience for Advanced Models

The engage pipeline now handles advanced reasoning models that consume completion budget on internal reasoning before producing visible content. Previously, conversations using these models could return empty agent replies with no warning, leaving users with a silent turn and no signal in logs or analytics.

What changed:

  • Higher completion budget for reasoning models - When the active model belongs to a family that uses internal reasoning tokens, the platform automatically allocates a larger completion token budget. This ensures the model has enough headroom to produce visible content after reasoning. Models that do not use internal reasoning tokens continue to use the previous budget.

  • Empty response detection and alerting - If the agent produces an empty reply with no tool calls, the platform now logs a structured warning with the model identifier, turn number, finish reason, total completion tokens, reasoning tokens consumed, and the completion budget that was applied. This surfaces a failure mode that was previously silent, making it visible in logs and metrics for alerting and debugging.

  • Metrics instrumentation - Empty response events are now counted in platform metrics, tagged by model. This enables monitoring dashboards and alerts to detect elevated empty response rates before they affect end users.

No breaking changes. No new API endpoints or parameters. Existing agent configurations work without modification - the higher completion budget is applied automatically based on the model family.

chevron-rightv0.9.308 - Platform API: Multi-Tenant Clinical Data Intake (July 2026)hashtag

Multi-Tenant Clinical Data Intake

The customer data intake pipeline now supports multiple customers in a single pipeline run and can ingest structured clinical resources alongside patient demographics. Previously, the intake pipeline handled one customer at a time and only imported patient (member) records. It now processes all configured customers in a single pass and supports six additional clinical resource types.

What changed:

  • Multi-tenant pipeline - The intake pipeline processes all configured customers in one execution cycle. Tenant isolation is enforced at the query level - every intake query binds the workspace identifier explicitly, and deterministic event identifiers encode the customer, so data from different tenants never crosses boundaries.

  • Clinical resource intake - Customer CSVs that include structured clinical data now emit per-resource events into the world model. Each clinical resource becomes a queryable entity linked to its parent patient. Supported resource types: Medication, Observation, Condition, Family History, Questionnaire Response, and Clinical Note.

  • Deterministic resource identifiers - Each clinical resource event receives a deterministic identifier derived from the workspace, patient, and the resource's own identifier. Re-uploads of the same data produce the same event identifiers, so the deduplication logic skips already-emitted events without reprocessing.

  • New entity types - The world model entity resolution layer now recognizes five new standalone entity types from intake: medication statement, observation, family member history, questionnaire response, and clinical note. Conditions continue to link to their parent patient entity rather than creating standalone entities, consistent with the platform-wide convention.

  • Expanded event type filtering - The intake sync process now filters on both patient import events and clinical resource import events when checking for already-emitted data. The previous single-event-type filter has been replaced with a broader match that covers all clinical resource event types.

No breaking changes. Existing single-customer intake configurations continue to work without modification. The new clinical resource types are additive - customers that upload CSV files without clinical data columns see no change in behavior.

chevron-rightv0.9.307 - Platform API: Voice Session Stop Reliability (July 2026)hashtag

Voice Session Stop Reliability

Session shutdown reliability has been improved with two targeted fixes to the voice session lifecycle.

What changed:

  • Scoped resource cleanup - When a session stop is requested, transport closure and audio pipeline shutdown now execute within the same critical section as the stop flag. Previously, these cleanup operations ran outside the critical section, which could allow concurrent stop requests to race and attempt duplicate cleanup.

  • Write-once conference cache - The session identifier stored in the conference cache is now write-once. The first participant to join the conference sets the session identifier; subsequent participants (operators, additional agents) no longer overwrite it. This prevents conference-end callbacks from resolving to the wrong session when multiple participants join and leave.

No breaking changes. No new API endpoints or parameters. This is a reliability improvement to voice session lifecycle management.

chevron-rightv0.9.306 - Platform API: Unified Session Shutdown on Conference End (July 2026)hashtag

Unified Session Shutdown on Conference End

Session shutdown when a conference ends is now handled through a single, idempotent shutdown path. This replaces the previous approach of terminating the agent's call leg via a separate API call and instead closes the session directly, improving reliability and eliminating edge cases where sessions could stall.

What changed:

  • Single shutdown entry point - All session termination triggers (conference end, transport close, agent-initiated hangup, fatal errors) now converge on one idempotent shutdown path. Previously, different triggers used different mechanisms, which could leave sessions in an inconsistent state if multiple triggers fired simultaneously.

  • Direct session close on conference end - When a conference-end event is received, the platform now closes the session's transport directly rather than terminating the agent's call leg through a separate API call. This is more reliable because it does not depend on an external API round-trip to signal the session.

  • Eliminates stalled sessions from race conditions - The previous approach required looking up and terminating the agent's call leg, which could fail silently or race with other shutdown paths. The new approach guarantees the session stops exactly once regardless of how many termination signals arrive.

  • Simplified conference name resolution - Conference-end callbacks that arrive without a call identifier now resolve the associated session from existing conference cache data instead of requiring a separate reverse-lookup cache entry. This removes a class of resolution failures for multi-participant conferences.

No breaking changes. No new API endpoints or parameters. This is a reliability improvement to session lifecycle management.

chevron-rightv0.9.305 - Platform API: Direct Text Interaction Processing (July 2026)hashtag

Direct Text Interaction Processing

Text interactions now process user messages directly within the session lifecycle instead of routing them through an intermediate delivery layer. This reduces latency for text-based conversations and simplifies the processing path.

What changed:

  • Lower latency for text turns - User messages in text conversations are now processed inline by the session actor rather than being queued and consumed asynchronously. This eliminates a round-trip through the message delivery layer, reducing end-to-end response time for each text turn.

  • Simplified error handling - Transient delivery failures that previously surfaced as 503 responses during text interactions are no longer possible. The session processes the message directly, so failures are limited to actual agent processing errors.

  • No API contract changes - The text interaction request and response schemas are unchanged. Existing integrations continue to work without modification.

No breaking changes. No new API endpoints or parameters.

chevron-rightv0.9.304 - Platform API: Automated Outbound Calling Campaigns (July 2026)hashtag

Automated Outbound Calling Campaigns

The platform now supports automated daily outbound calling campaigns that select eligible patients from the world model and initiate calls through the outbound calls API. This enables population-level outreach workflows without manual call list management.

What changed:

  • Automated patient selection - The platform queries the world model for eligible patient entities, applying filters for valid phone numbers, active status, and production data sources. Patients who have been contacted recently or who have reached the maximum attempt threshold are automatically excluded.

  • Configurable attempt limits and cooldowns - Each patient has a maximum number of outbound attempts and a minimum cooldown period between attempts. These limits are enforced automatically based on historical outbound event data, preventing over-contact.

  • Recipient allowlisting - During ramp-up, outbound campaigns can be restricted to a specific set of phone numbers. Only patients whose phone numbers appear in the allowlist are dialed. When the allowlist is cleared, the campaign dials all eligible patients.

  • Idempotent call placement - Each outbound call carries a date-scoped idempotency key derived from the patient entity, preventing duplicate calls if a campaign run is retried or replayed on the same day.

  • Source attribution - Calls placed by automated campaigns carry source tags and metadata identifying them as campaign-originated. This allows analytics to distinguish automated outreach from manually initiated outbound calls.

  • Circuit breaker - If multiple consecutive calls fail, the campaign stops placing new calls to avoid wasting resources against an unavailable API. Partial results are persisted before the run terminates.

  • Manual override - Operators can specify an explicit list of patients to call, bypassing the eligibility query entirely. This supports targeted test runs during initial setup.

No breaking changes to existing API endpoints. The outbound calls endpoint (POST /calls/outbound) is unchanged - this feature automates the selection and submission of calls to that endpoint.

chevron-rightv0.9.303 - Platform API: Agent Call Leg Cleanup on Conference End (July 2026)hashtag

Agent Call Leg Cleanup on Conference End

When a conference ends, the platform now explicitly terminates the agent's call leg so that the agent's media stream receives a proper stop signal. Previously, ending a conference did not always close the agent's underlying call, which could leave the agent's audio stream open indefinitely.

What changed:

  • Automatic agent call leg termination - When a conference-end event is received, the platform now looks up the agent's call leg associated with that conference and hangs it up. This ensures the agent's bidirectional media stream is cleanly closed and receives the expected stop event.

  • Prevents stalled agent sessions - Without this fix, the agent's media stream could remain open after the conference ended, blocking the session from completing. The agent now releases resources immediately when the conference is over.

  • No effect on caller experience - This change only affects the agent's side of the call. The caller's call leg and conference behavior are unchanged. If the agent's call leg has already ended by the time the conference closes, the cleanup is a no-op.

No breaking changes. No new API endpoints or parameters.

chevron-rightv0.9.302 - Platform API: Linear Task Completion Comments (July 2026)hashtag

Linear Task Completion Comments

When an Ami task that originated from a Linear issue reaches a terminal state (completed or failed), the platform now automatically posts a completion comment back to the originating Linear issue. This closes the feedback loop so teams tracking work in Linear can see task outcomes without switching to the Amigo platform.

What changed:

  • Automatic completion comments - When a task created from a Linear issue assignment finishes, Ami posts a comment on the Linear issue summarizing the outcome. The comment includes the task status (completed or failed), links to any pull requests created, error details if the task failed, and a summary of the work performed.

  • Idempotent posting - The platform tracks whether a completion comment has already been posted for a given task. If the comment was already posted (for example, due to a retry or duplicate event), the platform skips posting a second comment. This prevents duplicate comments on Linear issues.

  • Best-effort delivery - Comment posting is best-effort. If the Linear API is unreachable or returns an error, the task update proceeds normally and the failure is logged. The task outcome is never blocked by a comment delivery failure.

  • New environment variable - A LINEAR_API_KEY environment variable is now required for the Ami service to authenticate with the Linear API when posting comments. If the key is not configured, completion comments are skipped silently.

No breaking changes to existing API endpoints. Tasks that do not originate from Linear are unaffected.

chevron-rightv0.9.301 - Platform API: Explicit Role Claim in JWT and Role Change Events (July 2026)hashtag

Explicit Role Claim in JWT and Role Change Events

JWT access tokens now carry the member's workspace role as an explicit claim, and a new SSE event notifies connected clients when a member's role changes.

What changed:

  • role claim in access tokens - Access tokens issued through SSO, device code, Google OAuth, and DPoP-bound refresh flows now include a role claim containing the member's workspace role at the time the token was issued. This removes the need for clients to infer the role from granted scopes. Tokens issued via static API key credentials do not include the claim.

  • workspace.member_role_updated SSE event - When a workspace member's role is updated, the platform publishes a workspace.member_role_updated event on the workspace SSE stream. The event payload includes the member's entity ID, the new role, and the previous role. Clients listening to the workspace event stream can use this to trigger token refresh or update local permission state immediately rather than waiting for the next token renewal cycle.

  • Backward-compatible role resolution - If a token does not contain the role claim (for example, tokens issued before this release or API-key-based tokens), the platform falls back to determining the role from the token's scopes. No action is required from existing integrations.

New SSE event:

Field
Type
Description

event_type

string

workspace.member_role_updated

entity_id

string

Entity ID of the member whose role changed

role

string

New role

previous_role

string

Previous role

No breaking changes. Existing tokens remain valid. The new claim is additive.

chevron-rightv0.9.300 - Platform API: Actor-Owns-State Outbound Dispatch (July 2026)hashtag

Actor-Owns-State Outbound Dispatch

Outbound call dispatch now writes entity state directly rather than relying on multi-hop event projection. This eliminates propagation latency between when an outbound call is scheduled or dispatched and when the entity reflects the updated state. Retry and failure handling are also improved with explicit state transitions at every step.

What changed:

  • Direct entity state writes - When an outbound task is scheduled, dispatched, retried, or fails, the entity's outbound fields are updated immediately. Previously, state changes were written as events and projected asynchronously, introducing latency before the entity reflected the current status. The new approach ensures the entity is always up to date at the moment the action occurs.

  • Per-entity caller ID - Outbound entities now support a caller ID phone number stored on the entity itself. When present, this number is used as the outbound caller ID instead of falling back to the workspace-level default. This enables per-campaign or per-patient caller ID selection.

  • Optimistic concurrency on dispatch - The dispatch step now uses optimistic locking when transitioning an entity from scheduled to dispatched. If another process has already moved the entity out of the scheduled state, the dispatch is safely skipped. This provides an additional layer of protection against double-dispatch across concurrent workers.

  • Explicit failure and retry transitions - When a dispatch attempt fails (missing phone number, no configured caller ID, or a downstream API error), the entity is immediately updated with the failure outcome. If retries remain, the entity is transitioned back to scheduled with a backoff-adjusted next attempt time. If no retries remain, the entity is marked as failed. Previously, some early-exit failure paths could leave the entity in an ambiguous state.

  • Audit events at every transition - Every state change (scheduled, dispatched, failed, retried) emits an audit event to the analytical data store. These events include the attempt count and outcome, providing a complete timeline for debugging and analytics.

No breaking changes to existing API endpoints or webhook payloads. Entity state is now updated faster and more reliably.

chevron-rightv0.9.299 - Platform API: Linear Issue Assignment Webhook (July 2026)hashtag

Linear Issue Assignment Webhook

The Ami service now accepts webhooks from Linear, automatically creating a task when a Linear issue is assigned to the Ami user. This enables teams to trigger Ami investigations directly from their issue tracker by assigning issues to Ami.

What changed:

  • Webhook endpoint - A new POST /webhook/linear endpoint receives Linear webhook payloads. The endpoint validates the request signature and rejects stale deliveries. No authentication token is required - the endpoint uses Linear's webhook signing secret for verification.

  • Automatic task creation on assignment - When a Linear issue is updated and the assignee changes to the configured Ami user, the platform creates a task with the issue details. The task description includes the issue identifier, title, Linear URL, and any Sentry URLs found in the issue description. The task is enqueued for processing immediately after creation.

  • Idempotent delivery - Duplicate webhook deliveries for the same assignment event are detected and ignored. If a task has already been created for a given assignment, subsequent deliveries return the existing task ID without creating a duplicate.

  • Selective processing - Only issue update events where the assignee changed to the Ami user are processed. All other event types and actions are acknowledged but ignored.

New environment variables:

Variable
Required
Description

LINEAR_WEBHOOK_SECRET

Yes

Signing secret for verifying Linear webhook signatures

LINEAR_AMI_USER_ID

Yes

Linear user ID representing Ami - only issues assigned to this user trigger task creation

Response format:

The endpoint returns a JSON object with the following fields:

Field
Type
Description

ok

boolean

Always true on successful processing

task_id

string

ID of the created or existing task (present when a task was created or a duplicate was detected)

ignored

boolean

true when the event was acknowledged but did not match processing criteria

duplicate

boolean

true when the webhook was a duplicate delivery for an already-created task

No breaking changes to existing endpoints or behavior.

chevron-rightv0.9.298 - Platform API: Unified Metering Architecture (July 2026)hashtag

Unified Metering Architecture

Metering and billing now use a unified architecture that cleanly separates usage recording from pricing. Every metered event carries a traffic class (production or simulation), and meters are aggregated and priced independently per traffic class. This replaces the previous approach where simulation meters used a naming prefix convention.

What changed:

  • Traffic class on all metering events - The metering emit endpoint (POST /v1/{workspace_id}/metering/emit) now requires a metering_source field with a value of "production" or "simulation". This determines which pricing tier applies to the event. The field is required on all new metering calls.

  • Optional effective timestamp - The metering emit endpoint now accepts an optional effective_at field (ISO-8601 datetime). When provided, this records when the event actually happened rather than when it was ingested. Useful for batch imports or delayed reporting.

  • Traffic class on billing responses - All billing endpoints that return meter values, usage trends, and invoice line items now include a metering_source field. Meter summaries, usage trend points, invoice line items, and meter value records all carry the traffic class so you can distinguish production from simulation usage in API responses.

  • Independent pricing per traffic class - Price rules are now scoped to a traffic class. The same meter (e.g. voice minutes) can have different rates for production and simulation traffic. Invoices reflect this separation with distinct line items per traffic class.

  • Dashboard scoped to production - The billing dashboard headline metrics now show production usage only. Simulation usage is available through the detailed usage endpoints.

Breaking changes:

  • The metering_source field is now required on POST /v1/{workspace_id}/metering/emit. Requests without this field will receive a 422 validation error. Update your metering calls to include "metering_source": "production" or "metering_source": "simulation".

  • Billing API responses now include metering_source on meter summaries, trend points, invoice line items, and meter value records. Clients that parse these responses strictly should be updated to accept the new field.

chevron-rightv0.9.297 - Platform API: Reliable Conference-End Signal Resolution (July 2026)hashtag

Reliable Conference-End Signal Resolution

Conference-end callbacks now reliably resolve back to the originating call session, fixing a case where the platform could fail to deliver the conference-end signal when the telephony provider omitted the call identifier from the callback.

What changed:

  • Conference name-to-session mapping - When a conference is established, the platform now stores a reverse mapping from the conference name to the originating call session. This ensures that conference lifecycle callbacks can always be resolved to the correct session, even when the telephony provider does not include the call identifier in the callback payload.

  • Fallback resolution on conference end - The conference-end callback handler now uses the stored reverse mapping as a fallback when the call identifier is missing. Previously, if the telephony provider sent a conference-end event without a call identifier, the platform could not determine which session to notify, and the conference-end signal was silently dropped.

No breaking changes to API responses, webhook payloads, or client-facing behavior. Conference lifecycle events are now delivered more reliably in edge cases.

chevron-rightv0.9.296 - Platform API: Hardened Text Session WebSocket Reliability (July 2026)hashtag

Hardened Text Session WebSocket Reliability

Text conversation WebSocket connections now detect and clean up gracefully when the server-side session ends unexpectedly. Previously, if the backend session exited due to idle timeout, maximum duration, or an internal error, the WebSocket read loop could hang indefinitely - the connection appeared alive to the client but no further messages were processed or delivered.

What changed:

  • Session-aware connection lifecycle - The WebSocket connection now monitors the backend session alongside client messages. If the session exits for any reason (idle timeout, maximum duration, lease loss, or conversation completion), the connection detects this immediately and closes cleanly rather than hanging in a silent dead state.

  • Improved exit logging - Text sessions now emit structured log entries at each exit point, including the specific reason the session ended (idle timeout, max duration, lease loss, or conversation completion). This improves observability for diagnosing session lifecycle issues without requiring trace-level debugging.

  • Terminal greeting detection - If the agent's greeting message results in immediate conversation completion (for example, a context graph that resolves on the first turn), the platform now logs a warning at session start. This helps identify misconfigured agents that complete before the user can interact.

No breaking changes to WebSocket message formats, client protocols, or API responses. Existing client integrations benefit from this fix automatically.

chevron-rightv0.9.295 - Platform API: Regulatory Bundle Document Audit Persistence (July 2026)hashtag

Regulatory Bundle Document Audit Persistence

Supporting documents uploaded during regulatory bundle submission are now persisted to a versioned audit store alongside the existing submission to the telephony provider. This ensures every document file is retained for compliance and audit purposes, independent of the telephony provider's own storage.

What changed:

  • Audit-grade document retention - Every supporting document file uploaded through the regulatory bundle submit endpoint is now written to a versioned, append-only audit store before being forwarded to the telephony provider. Files are keyed by bundle and filename. Resubmitting a bundle with updated documents stacks new versions under the same key rather than overwriting, preserving the full history of every file ever submitted for a given bundle.

  • Intentional residue on failure - If a bundle submission fails partway through, any documents already written to the audit store are intentionally retained. The audit store does not support deletion, so partial-submit residue is preserved for compliance review rather than silently discarded.

  • Document filename tracked per entity - Each supporting document entity in a bundle now tracks the filename that was submitted. This filename is visible in bundle detail responses and is used as the audit store key suffix, making it straightforward to correlate a bundle entity with its stored file.

  • Refined entity model - Bundle entities are now distinguished by kind. End user entities and supporting document entities carry distinct fields appropriate to their type. Supporting document entities include the submitted filename. This is a structural refinement - the response shape for existing integrations is unchanged.

  • Stable bundle identity across resubmits - The internal bundle identifier is now allocated before any external calls are made and remains stable across resubmits. This ensures that audit store keys are consistent whether a bundle is submitted for the first time or resubmitted with updated documents.

No breaking changes to existing endpoints or response schemas.

chevron-rightv0.9.294 - Platform API: Overhauled Metrics Overview Dashboard (July 2026)hashtag

Overhauled Metrics Overview Dashboard

The built-in metrics overview dashboard has been redesigned to surface more actionable insights about metric health and scoring activity.

What changed:

  • Metric score leaderboard - A new horizontal bar chart ranks metrics by average score, replacing the previous heatmap visualization. Each bar shows the metric key, average score, value count, and total events on hover. This makes it easier to identify which metrics are scoring high or low at a glance.

  • Daily scored events - A new daily volume chart shows scored event counts over time with the number of active metrics and value points per day. This replaces the previous metric type distribution pie chart and provides a clearer picture of scoring activity trends.

  • Production vs simulation scores - A new bar chart compares average metric scores across sources, with a color scale from low to high scores. This helps teams quickly spot discrepancies between production and simulation scoring.

  • Categorical metric distribution - A new chart breaks down categorical metrics by their category values and event counts, giving visibility into the distribution of non-numerical metric results.

  • Entity-level scoring coverage - A new horizontal bar chart shows how many distinct entities each metric has scored, helping teams identify gaps in per-call or per-entity metric coverage.

  • Per-call metric scores table - The previous entity-scoped metric values table has been replaced with a focused per-call view showing individual call scores, source, event count, and period. The table is limited to entity-level results (excluding workspace aggregates) for more actionable detail.

  • Metric summary row updated - The summary row at the top now includes a count of numerical metrics alongside existing totals for active metrics, value points, scored events, and average confidence.

  • Metric freshness table refined - Column headers are shortened for readability and the row limit is reduced to 25 for faster loading.

No breaking changes to the dashboard API. These are visual and query changes to the built-in metrics overview template.

chevron-rightv0.9.293 - Platform API: Reliable Agent-Initiated Hangup on Outbound Calls (July 2026)hashtag

Reliable Agent-Initiated Hangup on Outbound Calls

Outbound voice calls where the agent initiates the hangup (for example, after delivering a goodbye message upon reaching a terminal state) now terminate reliably. Previously, outbound calls could hang indefinitely after the agent decided to end the conversation.

What changed:

  • Transport connection closed on hangup - When the agent reaches a terminal state and initiates a hangup on a telephony call, the platform now explicitly closes the underlying audio transport connection after ending the callee's call. This ensures the audio receive loop exits immediately. Previously, the receive loop could block indefinitely because the telephony provider's disconnect signal only arrives for inbound caller-initiated disconnects, not for agent-initiated hangups on outbound calls.

  • Consistent cleanup across call directions - The hangup path now follows the same cleanup sequence for both inbound and outbound calls: the callee's call is terminated, the session is marked as stopped, audio playback is halted, and the transport connection is closed. Previously, the transport close step was missing, which caused outbound sessions to remain active after the agent finished.

  • Improved fallback handling - If the telephony hangup request fails, the platform still closes the transport connection as a fallback, ensuring the session does not hang regardless of the hangup outcome.

No breaking changes to existing endpoints or response schemas. This is a reliability fix for outbound call lifecycle management.

chevron-rightv0.9.292 - Platform API: Empty Regulation Filtering for Phone Number Setup (July 2026)hashtag

Empty Regulation Filtering for Phone Number Setup

The regulatory bundle and phone number provisioning flows now correctly handle regulations that exist but have no actual requirements. Some countries return a regulation for a given number type that contains no end user or supporting document requirements - there is nothing for the customer to submit. Previously, these empty regulations were included in the required-bundle filter, which could hide valid bundles or block provisioning for no reason.

What changed:

  • Bundle listing skips empty regulations - When listing setup bundles for a country and number type, the platform now inspects the full regulation requirements before including it in the filter. If the regulation has no end user requirements and no supporting document requirements, it is excluded from the filter set. This prevents the query from constraining on a regulation that no bundle can satisfy, which previously caused valid bundles to be hidden from the results.

  • Provisioning skips empty regulations - When provisioning a phone number, the platform applies the same check. Empty regulations are no longer added to the required-bundle set, so provisioning is not blocked by a regulation the customer cannot fulfill.

  • Structural validation - The platform validates the shape of regulation requirements returned by the telephony provider and raises an error if the structure is unexpected, ensuring early detection of upstream API changes.

No breaking changes to existing endpoints or response schemas. This is a correctness fix for edge cases in specific country and number type combinations.

chevron-rightv0.9.291 - Platform API: Regulatory Bundle Endpoints (July 2026)hashtag

Regulatory Bundle Endpoints

Telephony setup now supports regulatory compliance bundles, which are required for purchasing phone numbers in countries with number registration regulations. Two new endpoints let you look up the regulation requirements for a country and number type, then submit the required entities and documents in a single multipart request.

What changed:

  • Regulation lookup - GET /v1/twilio-setup/{setup_id}/regulation returns the regulation that applies to a given country and number type, including the full requirements breakdown: required end users, required supporting documents, accepted document types for each slot, and the detailed attribute fields for each entity type. Each field includes a value_type (String, Boolean, Date, or Address) so clients know how to render input forms. The Address value type indicates a structured address object that the platform creates automatically from inline fields - clients do not need to manage address resources separately.

  • Regulatory bundle submission - POST /v1/twilio-setup/{setup_id}/bundle/regulatory accepts a multipart form with the regulation SID (from the lookup), JSON-encoded end user and supporting document definitions, and positionally-matched file uploads (JPEG, PNG, or PDF, 5 MiB max per file). The endpoint creates all required entities, attaches them to the bundle, validates the bundle against the regulation, and submits it for review. If any validation fails, the response includes specific failure details.

  • Resubmission support - If a previously submitted regulatory bundle was rejected, submitting again to the same regulation SID resubmits the existing bundle with new entities and documents. The bundle identifier remains stable across resubmissions. Old entities are cleaned up automatically after a successful resubmit. Bundles that are pending review, in review, or approved cannot be resubmitted.

  • Regulatory bundle status webhook - POST /v1/webhook/twilio/regulatory-bundle receives status callbacks for regulatory bundle reviews. The platform mirrors review status transitions to the bundle record. This webhook is separate from the trust hub webhook for independent failure isolation.

  • Customer profile prerequisite - Regulatory bundles can only be submitted after the setup's customer profile is approved. Attempting to submit before approval returns a 409 error.

No breaking changes to existing endpoints. The new endpoints follow the same pattern as the existing SHAKEN/STIR and CNAM bundle endpoints.

chevron-rightv0.9.290 - Platform API: Simulation Call Intelligence Persistence (July 2026)hashtag

Simulation Call Intelligence Persistence

Simulation sessions now persist call intelligence data to the platform's analytical data store, making simulation results available to the same metric evaluation and analytics pipelines used for production calls.

What changed:

  • Simulation intelligence persisted for metric evaluation - When a simulation session ends, the platform computes call intelligence (conversation summary, emotion summary, risk summary, tool summary, quality score, and other dimensions) and writes the result to the analytical data store. Previously, simulation intelligence was only emitted as a real-time event and was not persisted, so metric evaluation could not access it after the session ended.

  • Independent error boundaries - Persistence to the analytical data store and real-time event emission now have separate error boundaries. A failure in one sink does not prevent the other from completing. If the analytical write fails, the real-time event is still emitted, and vice versa.

  • Updated completion reasons - Simulation sessions now report terminal_state when the agent reaches a terminal state in the context graph, and completed otherwise. Previously these were reported as terminal and destroyed.

  • Additional intelligence fields - Simulation call intelligence now includes latency summary, safety summary, and operator summary fields alongside the existing conversation, emotion, risk, and tool summaries.

No breaking changes to API contracts. Existing simulation endpoints, response schemas, and real-time event payloads are unchanged. The additional persistence happens automatically for all simulation sessions.

chevron-rightv0.9.289 - Platform API: Strict All-Fields Patient Lookup Matching (July 2026)hashtag

Strict All-Fields Patient Lookup Matching

The patient lookup tool used by voice agents now enforces strict cross-field verification. When multiple identifying fields are provided (name, date of birth, phone number, identifier), every provided field must match the same patient record for a result to be returned. Previously, a match on a single strong field (such as phone number) could return a patient even when other provided fields contradicted the record, creating a risk of cross-identity bleed in multi-member households.

What changed:

  • Strict all-fields matching - After candidate retrieval, every other provided field is verified against each candidate. Any candidate that fails any field check is dropped. The lookup returns no match if no candidate satisfies all provided inputs. This makes patient lookup an identity-verification primitive rather than a fuzzy search.

  • Phone as household identifier - Phone numbers are treated as household-level identifiers. A phone-only match is returned only when no other identifying field (name, date of birth, identifier) is provided. When a caller provides a phone number along with a name or date of birth, the phone-matched candidate must also match those additional fields.

  • Fuzzy name comparison - Name matching uses token-level fuzzy comparison to handle minor spelling variations and word-order differences. Candidates with names that fall below the similarity threshold are rejected.

  • Empty fields skipped - Fields that are not provided by the caller are not used for filtering. A lookup with only a phone number still works as before; the strict matching only activates for fields that are actually supplied.

No breaking changes to API contracts. The patient lookup tool parameters and response structure are unchanged. Integrations that previously relied on single-field matching may see fewer results when additional fields are provided that do not match the same record - this is the intended behavior to prevent identity mismatches.

chevron-rightv0.9.288 - Platform API: Opt-In Tool Call Events for Text Conversations (July 2026)hashtag

Opt-In Tool Call Events for Text Conversations

Text conversations now support opt-in visibility into the tools the agent calls during a turn. Both the REST turn endpoint and the WebSocket streaming endpoint can return details of each tool invocation, including the tool name, correlation ID, input parameters, result, and success status.

What changed:

  • REST: include_tool_calls query parameter - Pass include_tool_calls=true when creating a turn on a conversation. The response includes a tool_calls array with an entry for each tool the agent invoked. Each entry contains tool_name (string), call_id (string), input (object), result (string), and succeeded (boolean). When the parameter is omitted or false, the field is not present in the response.

  • WebSocket: tool_events query parameter - Pass tool_events=true when connecting to the text streaming WebSocket. The server emits two additional frame types: tool_call_started (with tool_name, call_id, and input) and tool_call_completed (with tool_name, call_id, result, and succeeded). These frames arrive after the tool has executed - both events are post-hoc summaries, so frontends can animate them in sequence but there is no real-time gap between them. When the parameter is omitted or false, no tool call frames are sent.

No breaking changes. Existing REST and WebSocket integrations that do not pass the new parameters continue to work identically. Tool call data is only included when explicitly requested.

chevron-rightv0.9.287 - Platform API: Walk-Based Email Attachment Classifier (July 2026)hashtag

Walk-Based Email Attachment Classifier

Inbound email processing now correctly extracts attachments from deeply nested MIME structures, such as those produced by Apple Mail and iOS Mail. Previously, attachments nested inside alternative branches (e.g., a PDF wrapped inside a multipart/mixed within a multipart/alternative) were silently dropped because the parser only inspected immediate sub-parts of the top-level message.

What changed:

  • Deep MIME tree traversal - The attachment classifier now walks the full MIME tree depth-first instead of only inspecting immediate children. This ensures attachments nested multiple levels deep - common in Apple Mail, iOS Mail, and other clients that wrap HTML and attachments together inside alternative branches - are correctly detected and persisted.

  • Forwarded-as-attachment emails preserved as opaque .eml files - When an email is forwarded as an attachment (enclosed in a message/rfc822 part), the platform now treats it as a single opaque .eml file. The interior of the forwarded message is not recursed into, preventing attachments from a forwarded email from being incorrectly attributed to the outer message.

  • Inline image deduplication via Content-ID - Inline images referenced from the email body via cid: URLs are now identified by matching their Content-ID against references in the HTML body. These images are saved using their Content-ID as the filename, so frontend clients rendering the email body can resolve cid: references directly to the attachment path without an extra lookup. This prevents inline images (such as signature logos and embedded screenshots) from appearing as both rendered body content and separate attachments.

  • Improved filename selection - Attachment filenames are now selected using a priority order: Content-ID (for cid-referenced inline images), the part's own filename (if safe and unique), or a generated fallback. This ensures stable, predictable filenames even for emails with duplicate attachment names across nested parts.

No breaking changes. Existing inbound email endpoints, response schemas, and webhook payloads are unchanged. Emails that were previously processed correctly continue to work identically. This fix affects only emails whose attachments were previously missed due to deep MIME nesting.

chevron-rightv0.9.286 - Platform API: Materialized Outbound Trigger Tasks for Dispatch (July 2026)hashtag

Materialized Outbound Trigger Tasks for Dispatch

Trigger actions can now directly create outbound call tasks in the world model without going through the LLM action loop. When a trigger's action type is configured for outbound calls, the platform writes the outbound task entity and scheduling event deterministically, skipping the agentic tool-call cycle entirely. This reduces latency and removes non-determinism from outbound task creation driven by webhook triggers.

What changed:

  • Deterministic outbound task creation from triggers - Trigger actions configured as outbound call tasks now bypass the LLM reasoning loop and directly create an outbound task entity with a scheduling event. The task is created with all fields from the trigger's input template: destination phone number, reason, goal, priority, scheduled time, retry configuration, business-hours window, and optional patient entity reference. This makes outbound task creation from webhook triggers faster, cheaper, and fully deterministic.

  • Service reference on outbound tasks - Outbound tasks now support an optional service reference field. When provided in the trigger input or scheduling event, the service reference is carried through to dispatch, allowing the voice agent to associate the outbound call with a specific service configuration.

  • Improved next-attempt-at resolution - The scheduling event now accepts an explicit next attempt time, independent of the scheduled time. When provided, this value takes precedence over the scheduled time for determining when the task should first be dispatched. This allows triggers to set a future dispatch time that differs from the logical scheduling timestamp.

  • Refined failure handling for dispatched tasks - When an outbound call fails after being dispatched to the voice agent, the attempt counter is no longer double-incremented. The dispatch step already counts the attempt, so voice-agent-reported failures reuse the same attempt number. Failures that occur before dispatch (such as API errors) continue to increment the attempt counter normally.

  • Deduplicated dispatch events - Outbound dispatch and failure events are now deduplicated to prevent duplicate event writes when concurrent dispatch processes attempt to handle the same task. Each event is identified by a content-based key combining the task, event type, and attempt number. Duplicate writes are silently skipped.

No breaking changes. Existing outbound task workflows, event payloads, and API responses are unchanged. Triggers that were previously using the LLM action loop to create outbound tasks will automatically use the new deterministic path if their action type is configured for outbound calls.

chevron-rightv0.9.285 - Platform API: Underscored Metric Keys in Path Parameters (July 2026)hashtag

Underscored Metric Keys in Path Parameters

Metric key path parameters now accept underscores, matching the format used when creating metrics. Previously, path parameters for metric endpoints only accepted hyphenated slug strings, which caused requests using valid underscore-separated metric keys to be rejected.

What changed:

  • Metric key format expanded - All metric endpoints that take a metric key as a path parameter now accept lowercase alphanumeric strings with underscores (e.g., goal_completion, safety_score). Keys must start with a letter, be between 1 and 64 characters, and contain only lowercase letters, digits, and underscores.

  • Consistent key validation - The accepted metric key format in path parameters now matches the format accepted when creating or updating metrics. Keys that were valid at creation time are now valid in all subsequent API calls that reference them.

No breaking changes. All previously accepted metric key formats continue to work.

chevron-rightv0.9.284 - Platform API: Custom Metrics on Conversation Summaries (July 2026)hashtag

Custom Metrics on Conversation Summaries

Custom AI query metrics can now evaluate conversation summaries from call intelligence, not just raw event data. Metrics configured with a call intelligence source run against post-call conversation summaries - the same data path used by the eleven standard quality metrics - giving you the ability to define organization-specific scoring dimensions that evaluate full conversations.

What changed:

  • Conversation-level custom metrics - Custom AI query metrics can now target call intelligence as their data source. These metrics receive the conversation summary and evaluate it against your prompt, producing numerical, categorical, or boolean results. This lets you score conversations on dimensions specific to your organization (e.g., upsell detection, protocol adherence, disclosure verification) using the same infrastructure as built-in quality metrics.

  • Automatic source routing - The metrics pipeline automatically partitions custom AI query metrics by source. Metrics targeting call intelligence evaluate conversation summaries, while all other metrics continue to evaluate individual events from the world model. No configuration migration is needed for existing metrics.

  • Same output format - Results from conversation-level custom metrics appear in the same metric store tables and dashboards as event-level custom metrics. Entity type, period bucketing, simulation vs. production tagging, and service attribution all work identically.

  • Resilient execution - Individual metric failures are isolated. If one conversation-level metric fails, the remaining metrics continue to execute. The pipeline only raises an error if all conversation-level metrics fail in a single run.

No breaking changes. Existing custom metrics are unaffected. To create a conversation-level custom metric, configure a new AI query metric with the call intelligence source.

chevron-rightv0.9.283 - Platform API: Outbound Task Typed Entity Projection (July 2026)hashtag

Outbound Task Typed Entity Projection

Outbound task entities in the world model now have dedicated typed fields on the entity snapshot instead of storing all task state in an unstructured data blob. This improves query performance for outbound dispatch and makes outbound task data available as first-class columns in data access layers.

What changed:

  • Typed outbound task fields on entity snapshot - Outbound task entities now project the following fields as typed columns: status, destination phone number, reason, goal, priority, scheduled time, next attempt time, maximum attempts, retry backoff interval, patient entity reference, business-hours window, call identifier, outcome, attempt count, and service reference. These fields are available through all data access surfaces (SQL API, Delta Sharing, and entity queries).

  • Status derived from event history - The outbound status field is computed from the most recent outbound event. When a task fails but has remaining attempts, the status automatically resets to scheduled rather than showing as failed. Terminal states (completed, cancelled) reflect the final event.

  • Optimized dispatch queries - Outbound task dispatch now queries typed columns directly instead of parsing nested data at query time. Tasks are filtered by status and next attempt time, then ordered by priority (highest first) and age (oldest first). This reduces dispatch query latency for workspaces with large outbound task volumes.

  • Business-hours window enforcement - The dispatch window is stored as a structured object on the entity, and tasks are only dispatched when the current time falls within the configured business-hours window.

No breaking changes. Existing outbound task workflows, event payloads, and API responses are unchanged. The new fields are additive and appear alongside existing entity data.

chevron-rightv0.9.282 - Platform API: Message Coalescing for SMS and WhatsApp (July 2026)hashtag

Message Coalescing for SMS and WhatsApp

SMS and WhatsApp text sessions now automatically coalesce rapid-fire inbound messages into a single conversational turn. When a user sends multiple messages in quick succession - before the agent has finished processing the first - the platform collects them and joins them into one input. The agent sees and responds to the combined message rather than handling each fragment separately.

What changed:

  • Automatic coalescing on text channels - SMS and WhatsApp conversations now coalesce queued inbound messages before each agent turn. Messages that arrive while the prior turn is being processed are drained from the queue and joined with newline separators into a single turn input.

  • Zero added latency for single messages - When only one message is waiting, the agent processes it immediately with no delay. Coalescing only activates when additional messages have already accumulated.

  • Configurable message cap - Up to 10 messages are coalesced into a single turn by default. Messages beyond the cap, or non-message signals encountered during the drain, are left in the queue for subsequent processing.

  • Non-message signal preservation - If a non-message signal (such as a system event) is encountered while draining queued messages, it is preserved in its original position for the next processing cycle. Coalescing stops at that point to maintain signal ordering.

  • Channel-specific activation - Coalescing is enabled by default for SMS and WhatsApp channels. Other channel types (email, web, etc.) are unaffected.

No breaking changes. Existing SMS and WhatsApp integrations benefit from this behavior automatically. The agent receives the same message content, just combined into fewer turns when messages arrive in bursts.

chevron-rightv0.9.281 - Platform API: Hardened Scribe Long Session Reliability (July 2026)hashtag

Hardened Scribe Long Session Reliability

The Scribe copilot stream now handles long-running clinical sessions more reliably. Sessions lasting 30 minutes or longer previously risked silent disconnection when transient network or transcription delays stalled the WebSocket connection. This release adds application-level heartbeats, buffered audio forwarding, and structured shutdown so that long encounters complete cleanly.

What changed:

  • Application-level heartbeats - The server now sends periodic heartbeat events over the WebSocket connection. Each heartbeat includes a sequence number and elapsed time since session start. If the client connection becomes unresponsive, the server detects the condition and initiates a clean shutdown rather than allowing the session to hang indefinitely.

  • Buffered audio forwarding - Audio frames from the client WebSocket are now decoupled from transcription delivery. Incoming audio is queued and forwarded to the transcription service independently, so transient transcription latency no longer blocks the client receive loop. If the queue fills during a sustained transcription stall, excess frames are dropped with metrics emitted, preserving session stability.

  • Structured shutdown - Sessions now track a specific stop reason (client stop, disconnect, transcription failure, heartbeat timeout, etc.) and include it in the session_end event. The session_end event also reports audio queue drop count and heartbeat failure count, giving integrators visibility into session health.

  • Graceful drain on stop - When the client sends a stop message, already-buffered audio frames are drained to the transcription service (up to a cap) before finalization begins. This preserves final clinical context that was in flight when the clinician ended the session.

  • session_end event enriched - The session_end WebSocket event now includes additional fields:

    • stop_reason - Why the session ended (e.g. client stop, disconnect, transcription failure, heartbeat timeout)

    • audio_queue_drops - Number of audio frames dropped during the session due to transcription backpressure

    • heartbeat_failures - Number of heartbeat send failures detected

    • heartbeat_send_busy_skips - Number of heartbeats skipped because a prior WebSocket send was still in progress

  • heartbeat event (new) - A new WebSocket event type sent periodically by the server:

    • type - Always "heartbeat"

    • sequence - Monotonically increasing integer

    • elapsed_ms - Milliseconds since session start

No breaking changes. Existing clients that ignore unknown event types are unaffected. Clients that parse session_end events will see additional fields but existing fields are unchanged.

chevron-rightv0.9.280 - Platform API: Per-Data-Source Entity Filtering (July 2026)hashtag

Per-Data-Source Entity Filtering

Per-data-source entity views now use precise event-level attribution to determine which entities belong to each data source, replacing the previous identifier-prefix heuristic.

What changed:

  • Exact data source attribution - Each event in the entity timeline now carries the identifier of the data source that produced it. When you list entities for a specific data source, the platform filters using this direct association rather than parsing entity identifiers. This fixes cases where the previous approach returned zero results for data sources whose sync process did not embed a parseable prefix in entity identifiers.

  • Backward-compatible rollout - Entities with timeline events recorded before this change may not yet have data source attribution on their events. For those entities, the platform falls back to the previous identifier-based matching. As new events are recorded, attribution coverage increases automatically.

  • No API contract changes - The request and response schemas for entity list endpoints are unchanged. The improvement is in result accuracy - data sources that previously returned empty entity lists now return the correct entities.

No breaking changes. Existing integrations are not affected.

chevron-rightv0.9.279 - Platform API: Lineage Metadata on Outbound Calls (July 2026)hashtag

Lineage Metadata on Outbound Calls

Outbound calls now require lineage metadata that connects each call to a patient entity in the world model and records why the call is being made. The platform emits a world model event when the call is initiated, creating a traceable link between the outbound call and the patient record.

What changed:

  • patient_entity_id (required) - Every outbound call must reference an existing person entity in the workspace. The platform validates that the entity exists before placing the call. If the entity is not found, the request returns a 404 error.

  • reason (required) - A short label describing why the call is being made (e.g. appointment_reminder, follow_up, lab_results). This is stored with the call and included in the world model event for downstream analytics.

  • goal (optional) - A description of what the call should accomplish. When provided, the goal is injected into the agent's context so the agent understands the purpose of the conversation.

  • tags (optional) - Up to 10 classification tags for analytics. Each tag may be at most 64 characters.

  • metadata (optional) - Arbitrary key-value pairs for correlating the call with external systems. Up to 20 entries, with keys up to 64 characters and values up to 256 characters.

  • derived_from_call_sid (optional) - If this call is a callback from a previous call, pass the prior call SID to establish the relationship.

  • event_id in response - The response now includes the world model event ID for the outbound initiation event, enabling downstream systems to query the event directly.

Breaking changes:

  • patient_entity_id and reason are now required fields on the create outbound call endpoint. Existing integrations that do not send these fields will receive a 422 validation error.

See the Callsarrow-up-right reference for full field details.

chevron-rightv0.9.278 - Platform API: Hardened Webhook-to-Outbound Dispatch Reliability (July 2026)hashtag

Hardened Webhook-to-Outbound Dispatch Reliability

The platform now handles edge cases in webhook-to-outbound action dispatch more reliably, preventing silent failures when database connections are in an unhealthy state and ensuring buffered events are fully flushed before an action is marked complete.

What changed:

  • Connection pool resilience - Database connections that enter an unhealthy state during pool checkout or return are now detected and invalidated automatically. Previously, a bad connection could cause action dispatch to crash mid-execution. The platform now recovers gracefully by discarding the unusable connection and acquiring a new one from the pool.

  • Pre-completion event flush - Before writing the completion marker for a triggered action, the platform now explicitly flushes any buffered events. This ensures that all events produced during action execution are persisted before the action is recorded as complete. If the flush fails, the failure is logged and tracked in operational metrics so it can be investigated without silently dropping events.

  • Improved error isolation - Failures during connection cleanup no longer propagate silently. When a connection cannot be cleanly reset, the platform logs a warning and invalidates the connection rather than returning it to the pool in an unknown state.

No breaking changes to API response schemas, event payloads, or webhook behavior. This is a reliability improvement to the action execution pipeline. Existing integrations are not affected.

chevron-rightv0.9.277 - Platform API: Inbound Email and Voicemail Status Events (July 2026)hashtag

Inbound Email and Voicemail Status Events

The platform now emits real-time events when an inbound email reply is received and when a ringless voicemail delivery status changes. These events flow through the same event infrastructure as existing email status events (delivered, bounced, opened, etc.) and are available via SSE subscriptions.

What changed:

  • channel.email_received event - When an inbound email reply arrives that threads against a previously sent outbound email, the platform emits a channel.email_received event. The event includes the inbound email identifier, the outbound email it replies to, sender and recipient addresses, and the subject line. This lets integrations react to patient replies in real time without polling.

  • channel.voicemail_status event - When a ringless voicemail delivery status updates, the platform emits a channel.voicemail_status event. The event includes the voicemail identifier, the new status (delivered, skipped, failed, or not_delivered), and the recipient phone number. This gives integrations immediate visibility into voicemail delivery outcomes.

  • SSE subscription support - Both new event types are included in the workspace SSE event stream. Clients subscribed to workspace events receive these events alongside existing channel events with no additional configuration.

No breaking changes. These are additive event types. Existing integrations that consume channel events are not affected.

chevron-rightv0.9.276 - Platform API: Compound Emotions in Call Intelligence (July 2026)hashtag

Compound Emotions in Call Intelligence

Call intelligence now includes compound emotion data at both the turn level and the call-level emotional summary. Per-turn compound emotions detected during a conversation are persisted on each turn and aggregated into the call intelligence emotional summary, giving a complete picture of the caller's emotional arc.

What changed:

  • Per-turn compound emotions - Each turn in a call now includes the compound emotion signals detected during that turn. These appear alongside the existing emotion label and valence fields in the turn data.

  • Call-level compound emotion summary - The emotional summary in call intelligence now includes an aggregated compound emotion list. The platform selects the strongest signal for each compound emotion type across all turns in the call and returns the top results, filtered to signals above a minimum confidence threshold. This gives a concise view of the most prominent compound emotions across the entire conversation.

  • Consistent with existing emotion fields - The new compound emotion data uses the same structure as compound emotions elsewhere in the platform (name and score). No changes to existing emotion fields - emotion label, valence, trend, and segment data remain unchanged.

No breaking changes. The compound emotion fields are additive. Existing integrations that consume call intelligence or turn data are not affected.

chevron-rightv0.9.275 - Platform API: Hardened Scribe Session Quality Guardrails (July 2026)hashtag

Hardened Scribe Session Quality Guardrails

Scribe session quality monitoring now distinguishes between aborted or near-empty sessions (mic checks, brief connects) and genuine clinical sessions that fail to produce documentation. This reduces noise from short-lived sessions and improves the accuracy of quality alerts for sessions that matter.

What changed:

  • Abort suppression for short sessions - Sessions that are both very short and contain minimal transcript content are now classified as likely aborts (mic checks, accidental connects). These sessions still emit telemetry for observability, but they no longer trigger low-documentation quality alerts. This prevents on-call teams from being paged for sessions that were never intended to produce clinical output.

  • Separate quality classification - Sessions are now categorized into three outcomes: likely aborts (suppressed from alerting), sessions with sufficient transcript but low documentation output (alert-eligible), and sessions that meet quality expectations. Previously, all sessions with low documentation output were treated the same regardless of session length or transcript volume.

  • Improved quality metric coverage - Sessions that do not trigger alerts and are not classified as aborts now emit an observability signal indicating the reason (insufficient transcript or quality acceptable). This gives analytics dashboards a complete picture of session outcomes without gaps.

  • Reduced PHI exposure in quality logs - Quality alert logs no longer include entity identifiers that could serve as indirect PHI pointers. On-call engineers can correlate session and workspace identifiers to encounter records through existing event trails when investigation is needed.

  • More resilient quality telemetry - If quality metric emission fails, the failure is captured independently so that a telemetry issue does not mask the quality warning or silently drop the session from monitoring.

No breaking changes to API response schemas or event payloads. This change affects internal monitoring behavior only. Integrations that consume Scribe session events or documentation output are not affected.

chevron-rightv0.9.274 - Platform API: Recalibrated Telephony Emotion Detection (July 2026)hashtag

Recalibrated Telephony Emotion Detection

Emotion detection thresholds and compound emotion rules have been recalibrated to reduce false positives on telephony audio. Standard phone calls (8kHz sampling) lack upper-frequency harmonics, which caused the voice emotion model to skew negative and trigger emotion labels on routine, cooperative conversations. This release corrects that bias across dominant emotion classification, compound emotion resolution, and voice-text coherence scoring.

What changed:

  • Improved telephony voice calibration - The voice model's neutral baseline has been corrected for 8kHz telephony characteristics. Calm, neutral speech now produces near-zero valence and arousal readings instead of slightly negative values that previously triggered false Sadness or Fear labels.

  • Cross-channel agreement for negative emotions - Mild negative voice signals no longer produce a Sadness label on their own. The system now requires agreement from the language/text channel before classifying moderate negative voice signals as Sadness. This prevents telephony noise from being misinterpreted as genuine negative emotion.

  • Tighter compound emotion thresholds - Compound emotion signals now require stronger evidence before firing:

    • Resignation requires recent negative sentiment from the text channel in addition to sustained negative valence and low arousal, preventing false triggers on flat telephony audio.

    • Disengagement requires longer silence gaps and lower arousal before activating, avoiding false signals from normal conversational pauses.

    • Trajectory analysis uses stricter valence thresholds to distinguish genuine negative trends from telephony baseline noise.

  • Revised coherence scoring - When the voice signal is near-neutral (ambiguous), the voice-text coherence score now reflects that ambiguity rather than reporting false agreement. This gives downstream systems a more accurate picture of how much to trust the voice channel on any given turn.

  • Adjusted dominant emotion mapping - The valence/arousal quadrant boundaries for dominant emotion classification have been realigned. The Anger, Fear, and Sadness regions now require stronger negative valence, reducing the frequency of negative emotion labels on calls where the speaker is calm or mildly engaged.

No breaking changes to API response schemas. The emotion event payloads retain the same structure and field names. Emotion scores, compound labels, and coherence values will shift toward more conservative (less negative) readings on telephony calls, which may affect downstream rules or analytics that depend on specific threshold values.

chevron-rightv0.9.273 - Platform API: Hardened Text Turn Rendering (July 2026)hashtag

Hardened Text Turn Rendering

The text conversation API now validates turn data more strictly when reading conversation history and returning turn responses. Invalid or corrupted turn data that previously produced silently incorrect output now returns a clear error, making issues visible immediately rather than propagating bad data to clients.

What changed:

  • Strict turn validation - When reading conversation history, each turn is validated for structural correctness. If a turn is not an object or its text field is not a string, the API returns 502 Bad Gateway with "Conversation state invalid" instead of silently coercing the data. This surfaces upstream data corruption immediately rather than returning misleading content.

  • Strict turn validation on create-turn - When the upstream service returns turn data that does not meet structural requirements, the API returns 502 Bad Gateway with "Upstream response invalid" instead of silently normalizing the response.

  • Timestamp validation - Timestamps provided as ISO 8601 strings are now validated for correctness. Strings that cannot be parsed as valid timestamps are discarded rather than passed through. Epoch numeric timestamps and null values continue to be handled as before.

  • Conversation state availability check - After processing a turn, the API now verifies that the conversation record is still available before constructing the response. If the record cannot be retrieved, the API returns 502 Bad Gateway with "Conversation state unavailable" instead of failing with an unhandled error.

  • Improved diagnostic logging - Role normalization warnings now include the type and length of the unrecognized value rather than the raw value itself, reducing the risk of logging sensitive data.

Breaking changes:

Conversation history and create-turn responses that previously returned silently coerced data now return 502 errors when the underlying data is structurally invalid. If your integration was relying on the previous behavior where non-object turns were normalized to empty turns or non-string text was coerced to a string, those responses will now fail. In practice, this only affects conversations with corrupted state data.

chevron-rightv0.9.272 - Platform API: Text Conversation Turn Normalization (July 2026)hashtag

Text Conversation Turn Normalization

The text conversation API now normalizes turn roles, timestamps, and malformed entries when reading conversation history and returning turn responses. This improves consistency when integrating with systems that use different conventions for message roles or timestamp formats.

What changed:

  • Role normalization - Turn roles are mapped to a canonical set of three values: agent, user, and system. Common aliases are accepted and automatically normalized. For example, assistant, ai, and bot all resolve to agent. human resolves to user. tool resolves to system. Unrecognized role values default to user for conversation history and agent for turn output.

  • Timestamp coercion - Timestamps provided as Unix epoch numbers (integer or float) are automatically converted to ISO 8601 strings. Empty strings and null values are treated as absent. Non-string, non-numeric timestamps are discarded.

  • Malformed turn handling - Non-object entries in the turns array are normalized to an empty turn with the default role rather than causing an error. This makes the API resilient to upstream data inconsistencies.

  • Conversation status on create-turn - The create-turn response now reflects the actual conversation status rather than always returning frozen. The status is derived from the current conversation state after the turn is processed.

No breaking changes. Existing integrations continue to work without modification. Clients that already use the canonical role names (agent, user, system) and ISO 8601 timestamps see no difference.

chevron-rightv0.9.271 - Platform API: Text Turn Service Routing Fix (July 2026)hashtag

Text Turn Service Routing Fix

The create-turn endpoint now correctly routes each turn to the service that was specified when the conversation was created. Previously, the service context could be lost between turns, causing requests to fail or be routed incorrectly.

What changed:

  • Service preserved across turns - When you create a conversation with a service ID, all subsequent turns on that conversation are automatically routed to that same service. The service ID no longer needs to be re-resolved on each turn.

  • Stricter validation on create turn - The endpoint now validates that the conversation was created through the REST API and that the associated service still exists in the workspace. Conversations originating from other channels (voice, SMS, WhatsApp) cannot receive turns through this endpoint.

  • New error responses on create turn:

    • 404 Not Found - returned if the service associated with the conversation no longer exists in the workspace.

    • 422 Unprocessable Entity - returned if the conversation was not created through the REST API, or if the conversation ID is malformed.

  • Audit logging for rejected turns - When a turn is rejected due to a missing or invalid service association, the platform records an audit event with the rejection reason. These events are visible in the workspace audit log.

No changes to request or response schemas. Existing integrations that create conversations and send turns through the REST API continue to work without modification.

chevron-rightv0.9.270 - Platform API: Unified Conversations Resource (July 2026)hashtag

Unified Conversations Resource

The conversations API now provides a single resource that spans all channel types. Voice calls and text conversations are accessible through the same endpoints, with consistent response models and filtering. The previous calls endpoints remain available but are deprecated.

What changed:

  • Unified list endpoint - GET /v1/{workspace_id}/conversations now returns both voice and text conversations in a single paginated response, sorted by most recently updated. Use the channel_kind query parameter to filter by channel (voice, sms, whatsapp, web, email). Use the status query parameter to filter by conversation status (active, frozen, closed, completed, in-progress, failed).

  • Unified detail endpoint - GET /v1/{workspace_id}/conversations/{conversation_id} returns detail for any conversation regardless of channel. For voice conversations, the response includes a voice object with recording information, transcript data, emotional analysis, participant details, quality breakdown, latency metrics, tool usage, safety signals, and operator summaries. For text conversations, the response includes the turn history and plan as before.

  • Expanded response model - ConversationSummary now includes channel_kind, direction, duration_seconds, call_sid, caller_id, phone_number, quality_score, has_recording, completion_reason, escalation_status, final_state, source, and service_id. These fields are populated for voice conversations and null for text conversations where not applicable.

  • Expanded status values - Conversation status now includes completed, in-progress, and failed in addition to the existing active, frozen, and closed values. Voice conversations use completed, in-progress, and failed; text conversations continue to use active, frozen, and closed.

  • World model integration for text conversations - Text conversation lifecycle events (started, message, frozen, closed) are now emitted to the world model. This means text conversations appear in entity search, analytics, and the data lake alongside voice conversations.

  • Calls endpoints deprecated - GET /v1/{workspace_id}/calls and GET /v1/{workspace_id}/calls/{call_id} now return Deprecation: true and Sunset: 2026-07-01 headers. These endpoints continue to function but clients should migrate to the unified conversations endpoints.

Migration guide:

Replace calls to /v1/{workspace_id}/calls with /v1/{workspace_id}/conversations?channel_kind=voice. Replace calls to /v1/{workspace_id}/calls/{call_id} with /v1/{workspace_id}/conversations/{conversation_id}. The conversation ID for voice conversations is the same identifier previously used as the call ID.

The voice object on the detail response contains all the data previously available through the calls detail endpoint, reorganized into a structured format.

chevron-rightv0.9.269 - Platform API: Full CRUD Conversations Resource (June 2026)hashtag

Full CRUD Conversations Resource

The text conversation API has been redesigned around a full CRUD resource model. Conversations are now first-class REST resources with dedicated endpoints for creation, listing, detail retrieval, turn-based interaction, and closing.

What changed:

  • Create conversation - POST /v1/{workspace_id}/conversations creates a new conversation with a service ID and optional entity ID. Returns the full conversation detail including status, channel, and timestamps.

  • List conversations - GET /v1/{workspace_id}/conversations returns paginated conversations for a workspace. Supports filtering by status (active, frozen, closed) and pagination via limit and offset query parameters. The response includes total count and a has_more flag.

  • Get conversation detail - GET /v1/{workspace_id}/conversations/{conversation_id} returns a single conversation with its full turn history, including each turn's role, text, and timestamp.

  • Create turn - POST /v1/{workspace_id}/conversations/{conversation_id}/turns replaces the previous message endpoint. Send a message and receive the agent's response. The response includes a turn ID, the user input, agent output messages, and an updated conversation snapshot. Sending a turn to a closed conversation returns 409 Conflict.

  • Close conversation - DELETE /v1/{workspace_id}/conversations/{conversation_id} closes a conversation so it no longer accepts new turns. Returns 204 No Content on success or 404 if the conversation does not exist or is already closed.

Breaking changes:

The previous POST /v1/{workspace_id}/conversations/messages endpoint has been replaced. Clients should migrate to the new create/turn workflow:

  1. Create a conversation with POST /v1/{workspace_id}/conversations

  2. Send messages with POST /v1/{workspace_id}/conversations/{id}/turns

The service_id is now provided at conversation creation rather than with each message. The response models have changed - see the developer guide for updated schemas.

chevron-rightv0.9.268 - Platform API: Scribe Session Quality Guardrails (June 2026)hashtag

Scribe Session Quality Guardrails

The Clinical Copilot (Scribe) now evaluates session output quality at the end of every encounter and emits structured alerts when the generated clinical notes fall below expected thresholds. This enables proactive monitoring of Scribe reliability across workspaces without requiring manual review of every session.

What changed:

  • End-of-session quality evaluation - When a Copilot session ends, the platform evaluates the generated SOAP output against the transcript size. If a session produced meaningful transcript content but the clinical notes are missing, unusually small, or incomplete (too few note sections populated), the platform logs a structured quality alert with the session context. This makes it possible to detect and investigate sessions where the Scribe produced insufficient documentation.

  • Realtime analysis timeout tracking - The platform now tracks how many times realtime clinical analysis timed out during a session. Sessions with excessive analysis timeouts are flagged in the quality evaluation, helping identify patterns where infrastructure or model latency affected documentation quality.

  • Final reconciliation outcome tracking - The final reconciliation pass now tracks whether it produced tool results and how many errors occurred during chunk processing. These signals feed into the end-of-session quality evaluation, distinguishing between sessions where reconciliation succeeded, partially failed, or produced no output.

  • Session-level quality metrics - New session-level metrics report the total SOAP character count, number of populated note sections, transcript character count, and analysis timeout count for each completed session. These metrics support dashboards and alerting for Scribe output quality trends.

Impact:

No breaking changes. Copilot sessions behave identically from the client perspective. The quality evaluation runs after the session has ended and does not affect session duration or output. Workspaces with monitoring configured will begin receiving quality alerts for sessions that produce unexpectedly low documentation output.

chevron-rightv0.9.267 - Platform API: Durable Text Conversation Single-Writer Enforcement (June 2026)hashtag

Durable Text Conversation Single-Writer Enforcement

Durable text conversations now enforce single-writer semantics. Only one active session can process a given conversation at a time, preventing concurrent sessions from corrupting conversation state or producing interleaved agent responses.

What changed:

  • Exclusive conversation locking - When a session begins processing a durable conversation (via REST interact or WebSocket streaming), the platform acquires an exclusive lease for that conversation. If another client attempts to resume the same conversation while it is active, the request is rejected immediately rather than silently creating a second writer.

  • REST conflict response - The /text-interact endpoint returns HTTP 409 Conflict with detail "Conversation is already active" when the requested conversation is already being processed by another session.

  • WebSocket conflict response - The /text-stream endpoint sends an error event with message "Conversation is already active" and closes the connection with code 4409 when the requested conversation is locked.

  • Automatic lease expiry - If a session crashes or becomes unresponsive, the conversation lease expires automatically, allowing the conversation to be resumed by a new session without manual intervention.

  • Inbound message routing during active sessions - For channel-originated conversations (SMS, WhatsApp), inbound messages arriving while an active session holds the lease are routed to the existing session rather than spawning a duplicate actor. This eliminates rare cases where two actors could process the same conversation queue simultaneously.

Impact:

Clients that previously attempted concurrent resume of the same conversation will now receive explicit conflict errors instead of undefined behavior. No changes are required for clients that resume conversations sequentially. The automatic lease expiry ensures conversations are never permanently locked.

chevron-rightv0.9.266 - Platform API: Scribe Diarization Drain Before Final Reconciliation (June 2026)hashtag

Scribe Diarization Drain Before Final Reconciliation

The Clinical Copilot (Scribe) now ensures the medical-grade diarization pipeline is fully drained before running the final reconciliation pass. Previously, ending a session could begin reconciliation while late-arriving speaker-labeled utterances were still in flight, potentially omitting the final seconds of dialogue from the reconciled clinical notes.

What changed:

  • Diarization finalize before reconciliation - When a Copilot session ends, the platform now signals the diarization pipeline to flush any buffered speech into final utterances before closing the stream. The platform waits for outstanding utterances to arrive before proceeding to the final reconciliation pass, so the reconciliation input includes the complete encounter dialogue.

  • Duplicate utterance suppression - Utterances from the diarization pipeline are now deduplicated by their timing, speaker, and content. If the same utterance arrives more than once (for example, as both a streaming result and a finalize result), it is recorded only once. This prevents duplicate lines from appearing in the reconciled transcript.

  • Graceful stream shutdown - The diarization stream now shuts down cooperatively rather than being cancelled immediately. The platform waits briefly for the stream listener to finish processing any remaining events before closing the connection, reducing the chance of lost utterances at session boundaries.

Impact:

No breaking changes. Copilot sessions may capture slightly more dialogue at the tail end of encounters, leading to more complete SOAP documentation and clinical entity extraction. Sessions that previously missed the last few seconds of speech before reconciliation will now include that content.

chevron-rightv0.9.265 - Platform API: Conversation Write Path Consistency (June 2026)hashtag

Conversation Write Path Consistency

Conversation lifecycle write operations - thread materialization, reactivation, state persistence, and failure recovery - now commit changes consistently across all code paths. Previously, certain write paths could return success without durably persisting the result, leading to rare cases where conversation state appeared to be saved but was lost on subsequent reads.

What changed:

  • Durable thread materialization - When a new conversation is created or an existing frozen conversation is reactivated, the write is now committed before the result is returned. Previously, some materialization paths deferred the commit, which could result in the conversation not being visible on immediate subsequent reads.

  • Durable state persistence - Conversation state saves (freeze, close, context updates) are now committed before the platform acknowledges the write. This eliminates a window where the platform reported a successful save but the data had not yet been persisted.

  • Durable failure recovery rollback - When actor-start failure recovery rolls a conversation back to its previous state, the rollback is now committed immediately. Previously, the rollback could be lost if the connection closed before an implicit commit occurred.

Impact:

No breaking changes. This is a reliability improvement. Clients that experienced rare "ghost" conversation states - where a conversation appeared to exist momentarily but then disappeared - should no longer encounter that behavior.

chevron-rightv0.9.264 - Platform API: Scribe Final Reconciliation Pass (June 2026)hashtag

Scribe Final Reconciliation Pass

The Clinical Copilot (Scribe) now runs a final reconciliation pass at the end of each encounter session. During a live session, real-time transcription drives low-latency clinical note updates. At session end, the platform now performs an additional high-accuracy review using the full encounter transcript from the medical-grade diarization pipeline, filling any gaps in SOAP sections, clinical entities, ICD-10 suggestions, and safety alerts that may have been missed during real-time streaming.

What changed:

  • Final reconciliation pass - When a Copilot session ends, the platform reviews the complete encounter transcript and runs a final clinical analysis pass. This pass uses the full diarized transcript rather than the incremental fragments used during real-time streaming, producing more accurate and complete clinical documentation.

  • Medical-grade transcript preference - The final pass prefers the parallel medical-grade diarization transcript when available, as it provides better medical terminology accuracy and speaker separation. If the medical-grade transcript is not available, the system falls back to the real-time streaming transcript.

  • Chunked processing for long encounters - Long encounter transcripts are automatically split into bounded chunks for the final review, ensuring consistent processing quality regardless of encounter length.

  • Gap detection and completion - The reconciliation pass identifies missing SOAP sections, unextracted clinical entities, and absent ICD-10 suggestions, filling gaps without duplicating facts already captured during the real-time session.

  • Safety alert review - The final pass includes a safety review of the complete transcript, catching any clinical safety signals that may not have been apparent from incremental transcript fragments.

  • Results delivered in-session - Reconciliation results are delivered to the Copilot WebSocket connection before the session closes, so clinicians see the completed notes without waiting for offline processing.

  • Encounter update notification - When the reconciliation pass produces updates, an encounter-updated event is published to the workspace, notifying connected clients that the encounter documentation has been refined.

Impact:

No breaking changes. Copilot sessions that previously ended without a final review now automatically receive one. Clinicians may notice more complete SOAP documentation and additional clinical entity extractions appearing at the end of encounters. The reconciliation pass is best-effort - if it fails, the real-time notes captured during the session are preserved unchanged.

chevron-rightv0.9.263 - Platform API: Centralized Text Conversation Write Boundary (June 2026)hashtag

Centralized Text Conversation Write Boundary

Text conversation lifecycle writes - creation, state persistence, and failure recovery - are now coordinated through the platform API's centralized write boundary. Previously, the agent processing layer wrote conversation state directly to the data store. This change moves all durable conversation mutations to the platform API, improving consistency, auditability, and failure handling for text conversations across all channels.

What changed:

  • Centralized conversation materialization - When a new text conversation starts (from any channel - web, SMS, WhatsApp), the platform API now owns the atomic resolve-or-create operation. Simultaneous messages arriving for a new conversation converge on a single durable conversation through the platform API rather than through direct data store writes. This eliminates a class of race conditions where concurrent messages could briefly create duplicate conversation state.

  • Centralized state persistence - Conversation state (turns, context, metadata) is now saved through the platform API's write boundary when a conversation freezes or closes. The agent processing layer sends state to the platform API, which validates, normalizes, and persists it with optimistic concurrency control. State payloads are validated for size (maximum 256 KB) and structural correctness before persistence.

  • Actor start failure recovery - If the platform fails to start a new processing session after resolving a conversation, the rollback (returning the conversation to its previous state) now goes through the platform API. This ensures the rollback is audited and uses the same write coordination as other conversation mutations.

  • Dedicated circuit breakers - Each new write-boundary operation (thread resolution, state persistence, and actor-start failure recovery) has its own circuit breaker with independent failure thresholds and recovery windows. This prevents failures in one operation from cascading to others.

  • New error responses - The text interact (REST) and text-stream (WebSocket) endpoints now return more specific error codes when conversation materialization fails:

    • 403 / WebSocket close 4403: Conversation materialization was rejected for the workspace

    • 409 / WebSocket close 4409: Conversation could not be materialized due to a status conflict

    • 503 / WebSocket close 4203: Conversation materialization service temporarily unavailable

  • Audit trail for all conversation writes - Every conversation mutation (creation, reactivation, state save, failure rollback) now emits an audit event through the platform API, providing a complete audit trail for compliance and operational monitoring.

Impact:

No breaking changes to public APIs. The text conversation REST and WebSocket endpoints continue to work as before. Error responses are more specific in some failure cases - clients that inspect HTTP status codes or WebSocket close codes may want to handle the new codes (403/4403, 409/4409). Conversation state size is now validated server-side with a 256 KB limit; conversations with state payloads exceeding this limit will receive a 422 response during state persistence.

chevron-rightv0.9.262 - Platform API: Hardened Text Conversation Resume (June 2026)hashtag

Hardened Text Conversation Resume

Text conversations can now be resumed by durable conversation ID across both the REST interact endpoint and the WebSocket text-stream endpoint. The resume path validates ownership, entity binding, and channel consistency before reactivating a frozen conversation, with centralized write coordination through the platform API.

What changed:

  • Resume by conversation ID - The text interact (REST) and text-stream (WebSocket) endpoints now accept a conversation_id parameter. When provided, the platform looks up the existing conversation by durable ID instead of creating a new one. The conversation must belong to the same workspace, use the same channel and provider, and not be closed.

  • Entity binding enforcement - Resuming a conversation validates that the requesting entity matches the entity that owns the conversation. Conversations bound to one entity cannot be resumed by a different entity. Unbound conversations cannot be retroactively bound to an entity. Both cases return a not-found response to avoid leaking conversation existence across entity boundaries.

  • Centralized reactivation - When a frozen conversation is resumed, the status transition from frozen to active is performed through the platform API's write boundary rather than directly by the agent processing layer. This ensures consistent ownership semantics and emits audit events for the reactivation. The reactivation endpoint uses row-level locking with a short timeout to prevent contention.

  • Circuit breakers for reactivation - The reactivation path has its own circuit breaker with a lower failure threshold and faster recovery, tuned for the session-initialization critical path. If the reactivation service is unavailable, the client receives a 503 (REST) or 4203 (WebSocket) rather than a generic error.

  • WebSocket subprotocol authentication - The text-stream WebSocket endpoint now accepts authentication via Sec-WebSocket-Protocol: auth, <token> in addition to the existing token query parameter. This supports browser environments where custom headers cannot be set on WebSocket connections.

  • Per-connection rate limiting - Each WebSocket text-stream connection now enforces a message rate limit (configurable window and threshold). Messages exceeding the limit receive an error event. A cross-connection rate limiter keyed by credential is planned for a future release.

  • Message validation - WebSocket text messages are validated for type (must be a string), length (maximum 10,000 characters), and JSON structure. Invalid messages receive descriptive error events instead of being silently dropped. Unknown message types now receive an error event.

  • Improved error specificity - Resume failures now return distinct error codes for invalid conversation ID format, conversation not found, entity mismatch, reactivation unavailable, and reactivation schema drift. The WebSocket endpoint uses custom close codes (4400, 4404, 4203, 4202) to distinguish these cases.

  • Completion reason normalization - Additional call completion reason aliases are now recognized and mapped to canonical values, improving consistency in conversation analytics.

  • Transaction scoping improvements - Database transaction boundaries for conversation operations now use transaction-scoped configuration, reducing the risk of cross-request state leakage under connection pooling.

Impact:

No breaking changes to public APIs. The conversation_id parameter is optional on both endpoints - omitting it preserves the existing behavior of creating a new conversation. WebSocket close code semantics for error cases are more specific than before; clients that inspect close codes may want to handle the new codes.

chevron-rightv0.9.261 - Platform API: Text Conversation Epoch Routing (June 2026)hashtag

Text Conversation Epoch Routing

Text conversation routing now correctly handles the distinction between new conversations, reactivated conversations, and conversations with an existing active session. This fixes an issue where reactivated (previously frozen) conversations could fail to start a new processing session, causing inbound messages to queue without being processed.

What changed:

  • Epoch-aware conversation resolution - When an inbound message arrives on a text channel, the platform now distinguishes three cases: a brand-new conversation, a reactivation of a previously frozen conversation, and a message for an already-active conversation. Both new and reactivated conversations start a fresh processing epoch, ensuring messages are always picked up by an active session.

  • Rollback on session start failure - If the platform fails to start a new processing session after resolving a conversation, the conversation is returned to its frozen state. This allows the next inbound message to retry session creation rather than leaving messages queued with no consumer.

  • Turn metadata - Each conversation turn now includes metadata about the channel, participant type, and conversation direction. This enables richer analytics and audit capabilities for text conversations.

  • Audit events for epoch starts - The platform now emits audit events when a new text conversation epoch begins, whether from a new conversation or a reactivation. These events are available through the data pipeline for compliance and operational monitoring.

  • Graceful shutdown for background tasks - Text channel background tasks are now drained during platform shutdown, reducing the chance of lost audit events or incomplete cleanup during deployments.

Impact:

No breaking changes to public APIs. Existing text conversation endpoints and webhooks continue to work as before. The conversation resolution behavior change fixes a reliability issue where reactivated conversations could silently drop messages.

chevron-rightv0.9.260 - Platform API: Scribe Long-Recording Transcription (June 2026)hashtag

Scribe Long-Recording Transcription

The Scribe clinical copilot now supports transcription of completed clinical recordings of any practical length. Long recordings are automatically split into chunks, transcribed with a medical-optimized speech recognition model, and reassembled into a single transcript with recording-relative segment timing and speaker diarization.

What changed:

  • Recording transcription endpoint - A new POST /v1/{workspace_id}/scribe/recordings/transcribe endpoint accepts a completed audio recording and returns an assembled transcript. The endpoint accepts multipart form data with the audio file, service ID, and optional patient entity ID, language, and medical keyterms. Supported audio formats include WebM, OGG, WAV, MP4, and MP3, up to 512 MB.

  • Automatic chunking - Recordings that exceed the speech recognition service's per-request processing limits are automatically split into shorter chunks. Each chunk is transcribed independently, and the results are reassembled with recording-relative timing so segment timestamps reflect position in the original recording rather than within an individual chunk.

  • Medical keyterm resolution - The platform automatically resolves medical terminology keyterms from multiple sources to improve transcription accuracy: patient context (name, primary diagnosis) when a patient entity ID is provided, service-level keyterms from the service configuration, workspace-level entity data, and request-level keyterms passed in the request body. All keyterm sources are merged and deduplicated before being sent to the speech recognition model.

  • Speaker diarization - The transcription response includes speaker identification for each utterance segment, enabling downstream clinical note generation to distinguish between clinician and patient speech.

  • Language-aware model selection - English recordings use a medical-specialized speech recognition model for improved clinical vocabulary accuracy. Non-English recordings automatically fall back to a general-purpose model.

New endpoint:

Method
Path
Description

POST

/v1/{workspace_id}/scribe/recordings/transcribe

Transcribe a completed clinical recording

Response fields:

Field
Type
Description

transcript

string

Assembled clinical transcript text

confidence

number or null

Duration-weighted transcription confidence

duration_seconds

number

Total recording duration

model

string

Speech recognition model used

language

string

Language used for transcription

chunk_count

integer

Number of audio chunks processed

keyterm_count

integer

Number of keyterms sent

chunks

array

Per-chunk transcription details

segments

array

Utterance-level segments with timing and speaker

Impact:

No breaking changes. Existing Scribe physician review endpoints are unaffected.

chevron-rightv0.9.259 - Platform API: Hardened Text Conversation API (June 2026)hashtag

Hardened Text Conversation API

The text conversation REST and WebSocket APIs now enforce stricter input validation, improve session cleanup reliability, and validate upstream response shapes at the API boundary.

What changed:

  • Non-empty message validation - The message and service_id fields in the POST /v1/{workspace_id}/conversations/messages endpoint now require at least one character. Previously, empty strings were accepted and could produce unexpected agent behavior. Requests with empty messages or service IDs now return a 422 validation error.

  • Upstream response validation - The REST conversation endpoint now validates the shape of the upstream response before returning it to the caller. If the upstream response does not match the expected schema, the endpoint returns a 502 error instead of passing through malformed data. This prevents schema drift from surfacing as confusing client-side errors.

  • WebSocket session cleanup - WebSocket text sessions now guarantee session cleanup in all disconnection scenarios, including unexpected errors during the read loop. Previously, certain error paths could leave orphaned sessions.

  • WebSocket authentication flow - The WebSocket text endpoint now properly accepts the connection before sending close frames for authentication failures, ensuring clients receive the close reason rather than a raw connection rejection.

  • Message delivery error handling - The REST conversation endpoint now returns a 503 error when message delivery to the agent fails due to infrastructure unavailability, instead of silently dropping the message.

Impact:

Clients sending empty message or service_id values to the REST conversation endpoint will now receive 422 validation errors. All other changes are non-breaking improvements to reliability and error reporting.

chevron-rightv0.9.258 - Platform API: Text Conversation REST and WebSocket APIs (June 2026)hashtag

Text Conversation REST and WebSocket APIs

The platform now supports text-based agent conversations through two new interfaces: a synchronous REST endpoint for request-response interactions and a WebSocket endpoint for real-time streaming text chat. Both interfaces share the same conversation persistence, context graph traversal, and agent reasoning used by SMS and WhatsApp channels.

What changed:

  • REST conversation endpoint - A new POST /v1/{workspace_id}/conversations/messages endpoint processes a single text message through the agent and returns the response synchronously. Callers provide a service_id and message; the platform creates a new conversation or resumes an existing one if a conversation_id is provided. The response includes the agent's reply messages, the conversation ID, and the conversation status (active, completed, or error). An optional entity_id parameter loads patient context for the conversation.

  • WebSocket streaming endpoint - A new WebSocket endpoint enables real-time bidirectional text chat. Clients connect with a token, workspace ID, and service ID, then exchange JSON messages. The server sends typing indicators while the agent is composing a response, delivers agent messages as they are generated, and signals session lifecycle events (started, ended). Clients can resume a previous conversation by passing its conversation_id as a query parameter.

  • Cross-mode conversation continuity - Conversations persist across both interaction modes. A conversation started via REST can be resumed over WebSocket and vice versa. When resumed, the agent restores full conversation history, context graph state, and commitments from prior turns.

  • Web channel residency policy - Web-based conversations use their own conversation residency policy with a maximum duration of one hour and an idle timeout of five minutes, consistent with interactive chat usage patterns.

  • WebSocket provider type - A new websocket provider type is available for web channel routing, extending the existing provider model used by SMS, WhatsApp, and email channels.

REST endpoint:

Method
Path
Description

POST

/v1/{workspace_id}/conversations/messages

Send a text message and receive the agent's response

WebSocket endpoint:

Protocol
Path
Description

WS

/agent/text-stream

Real-time bidirectional text chat

WebSocket wire protocol (client to server):

Message type
Description

message

Send a user message ({"type": "message", "text": "..."})

stop

End the conversation gracefully ({"type": "stop"})

WebSocket wire protocol (server to client):

Message type
Description

session_started

Connection established with session_id and conversation_id

message

Agent response with text field

typing

Agent is composing a response

error

Error with message field

session_ended

Conversation ended with reason field

Impact:

No breaking changes. All existing SMS, WhatsApp, and email text session behavior is unaffected. The new endpoints are additive.

chevron-rightv0.9.257 - Platform API: Email Reply-to-Inbound Threading (June 2026)hashtag

Email Reply-to-Inbound Threading

The email send endpoint now supports replying to inbound emails, enabling proper email thread continuity. When sending an email as a reply to a previously received inbound message, the platform sets the correct threading headers so recipient mail clients display the reply in the same conversation thread.

What changed:

  • Reply-to-inbound on email send - The send email endpoint accepts an optional reply_to_inbound_email_id parameter. When provided, the platform validates that the referenced inbound email belongs to the same use case and setup as the outbound send, then constructs the outbound message with proper threading headers (In-Reply-To and References) so recipient mail clients group the reply into the existing conversation. If the referenced inbound email is not found or belongs to a different use case or setup, the request is rejected with a 422 error.

  • References chain tracking - Both outbound and inbound email records now track the RFC 5322 References header chain. For outbound emails, this is the value written on the outgoing message at send time. For inbound emails, the platform canonicalizes the chain at receive time - if the incoming message includes a References header it is stored verbatim; if the header is absent (some mail clients and automated senders strip it), the platform reconstructs the chain from the parent outbound's stored chain. This ensures reply threading works reliably regardless of how the recipient's mail client handles header propagation.

  • New fields on email endpoints:

    • Send email response - now includes replied_to_inbound_email_id indicating which inbound email was replied to (null for fresh sends).

    • Get email response - now includes replied_to_inbound_email_id and references_header (the threading chain written on the outbound message).

    • List emails response - each email item now includes replied_to_inbound_email_id so callers rendering a thread view can stitch outbound emails back to their parent inbound without additional requests.

    • Get inbound email response - now includes references_header (the canonicalized threading chain through the parent outbound).

Impact:

No breaking changes. The reply_to_inbound_email_id parameter on send is optional - omitting it preserves existing behavior (a fresh send with no threading headers). All new response fields are additive.

chevron-rightv0.9.256 - Platform API: WhatsApp Channel Support and Unified Text Channel Architecture (June 2026)hashtag

WhatsApp Channel Support and Unified Text Channel Architecture

The agent engine now supports WhatsApp as an inbound text channel alongside SMS. WhatsApp messages are routed through the same text session infrastructure as SMS, so agents configured for text conversations work across both channels without changes to agent configuration, context graphs, or skills.

What changed:

  • WhatsApp inbound messaging - Agents can now receive and respond to WhatsApp messages from patients. When a patient sends a WhatsApp message to a configured phone number, the platform validates the message signature, resolves the phone number to a workspace and service, and creates or resumes a text session. Responses are sent back through WhatsApp asynchronously, the same pattern used for SMS.

  • Phone number routing for WhatsApp - WhatsApp phone numbers are mapped to workspaces and services through environment configuration. Each WhatsApp-enabled phone number routes to a specific workspace and service. Phone numbers are normalized to E.164 format for consistent matching.

  • Unified text channel architecture - SMS and WhatsApp now share a common signal routing and session lifecycle layer. Each channel handles its own provider-specific concerns (signature validation, payload parsing, message transport) while sharing the session management, signal queuing, and orchestrator lifecycle. This architecture extends to future text channels without duplicating session management logic.

  • Channel-aware session events - Text session started and completed events now include the channel (SMS or WhatsApp) so downstream consumers can distinguish between channel types in analytics, billing, and reporting.

  • Channel-specific conversation residency - Each text channel uses its own conversation residency policy, allowing different session timeout and lifecycle behavior per channel. WhatsApp conversations follow WhatsApp-appropriate session windows.

Configuration:

To enable WhatsApp for a workspace, configure the WhatsApp phone number mapping and messaging provider credentials. Services must have their channel type set to text to accept WhatsApp messages - voice-only services ignore inbound WhatsApp messages, consistent with existing SMS behavior.

Impact:

No breaking changes. Existing SMS text sessions are unaffected. The SMS webhook, status callback, and session lifecycle continue to work as before. WhatsApp support is additive and requires explicit phone number configuration to activate.

chevron-rightv0.9.255 - Platform API: Inbound Email Reply Threading by Message Identifier (June 2026)hashtag

Inbound Email Reply Threading by Message Identifier

Inbound email reply resolution now threads replies using the message identifier assigned by the email delivery service at send time, instead of an application-generated identifier. This aligns thread resolution with how recipient mail clients actually construct their reply headers, improving reliability for inbound threading.

What changed:

  • Reply threading uses delivery-assigned message identifier - When an inbound email arrives, the platform resolves which outbound message it replies to by matching the In-Reply-To header against the message identifier recorded at send time. Previously, the platform set a custom message identifier on outbound emails and expected replies to reference it. However, the email delivery service overwrites custom message identifiers on outbound sends, so recipient mail clients never saw the application-set value. Thread resolution now matches against the delivery-service-assigned identifier that recipients actually receive, eliminating a class of silent threading failures where valid replies were dropped as unresolvable.

  • Broader reply matching - The previous approach required the In-Reply-To local-part to be a valid application-level UUID. Replies from mail clients that copied the delivery service's native identifier format were silently dropped. The new approach accepts any local-part format and matches it directly against stored outbound records, so replies thread correctly regardless of identifier format.

Impact:

No breaking changes to public APIs. Inbound replies that were previously dropped as unresolvable (because the mail client's In-Reply-To header contained the delivery-service-assigned identifier rather than the application-set one) now resolve correctly. No client updates required.

chevron-rightv0.9.254 - Platform API: Inbound Email Message-ID Header and Event Webhook Concurrency (June 2026)hashtag

Inbound Email Message-ID Header and Event Webhook Concurrency

The inbound email read endpoint now returns the RFC 822 Message-ID header from the original message, and the email event webhook handles concurrent delivery retries gracefully instead of returning server errors.

What changed:

  • Message-ID header on inbound emails - The get-inbound-email endpoint now includes a message_id_header field containing the RFC 822 Message-ID header from the original inbound message, preserved verbatim with surrounding angle brackets (e.g. <[email protected]>). Use this value as the In-Reply-To header when sending a reply to the inbound message, enabling proper email threading in recipient mail clients.

  • Concurrent event webhook handling - The email event webhook now returns 409 instead of 500 when concurrent delivery retries from the notification provider race against each other at the database level. This eliminates false-positive server error alerts and stops the provider from continuing to retry deliveries that have already been processed by a competing request. The 409 response signals that another delivery attempt already committed the event successfully.

Impact:

No breaking changes. The message_id_header field is a new addition to the inbound email response. Existing integrations that do not use the field are unaffected. The 409 behavior on the event webhook is an internal reliability improvement - callers that rely on the webhook do not need to take any action.

chevron-rightv0.9.253 - Platform API: Appointment Status Resolution from Color Codes (June 2026)hashtag

Appointment Status Resolution from Color Codes

The appointment normalizer now resolves FHIR appointment statuses from source system color codes when a text-based status is unavailable, improving status accuracy for EHR integrations that rely on color-coded appointment states.

What changed:

  • Color-based status fallback - When an incoming appointment record does not include a recognized text status, the normalizer now inspects the color code associated with the appointment and maps it to the appropriate FHIR appointment status. This covers common color conventions used by source EHR systems to represent states like fulfilled, booked, cancelled, pending, arrived, and waitlisted.

  • Signed visit distinction - For color codes that indicate a completed visit, the normalizer further checks whether the visit has been signed by a provider. Signed visits resolve to fulfilled; unsigned visits resolve to booked. This distinction ensures that appointments marked as complete in the source system are not prematurely recorded as fulfilled before clinical sign-off.

  • Graceful default - If neither a text status nor a recognized color code is present, the appointment status defaults to proposed, consistent with existing behavior for unrecognized statuses.

Impact:

No breaking changes. Appointments that previously fell through to the default proposed status due to missing text-based status fields now resolve to more accurate FHIR statuses based on their color codes. No API changes or client updates required.

chevron-rightv0.9.252 - Platform API: Caller Language Normalization (June 2026)hashtag

Caller Language Normalization

The platform now normalizes caller language preferences at the boundary between the world model and voice components, so downstream speech-to-text and text-to-speech services always receive a valid ISO-639-1 code.

What changed:

  • Automatic language normalization - Language preferences stored in patient demographics can arrive in many formats: full language names ("English", "español"), ISO-639-1 codes ("en"), or regional tags ("en-US", "en_us"). The platform now normalizes all of these to a supported ISO-639-1 code before passing them to voice components. Unrecognized or missing values resolve to an empty string, causing the system to fall back to the default language (typically English) rather than sending an invalid code to a voice provider.

  • Supported languages - Normalization covers the 10 language codes supported by the voice configuration system: English (en), Spanish (es), Arabic (ar), French (fr), German (de), Portuguese (pt), Chinese (zh), Japanese (ja), Korean (ko), and multilingual.

  • Unknown language logging - When a language preference is present but cannot be mapped to a supported code, the platform logs a warning with the workspace and entity context. This helps teams identify upstream data quality issues in connectors or tools that write language values the platform does not recognize.

Impact:

No breaking changes. Callers whose language preference was previously passed through as a raw free-form string now get a normalized code. Sessions that previously may have sent unsupported language values to voice providers will now fall back to the default language instead. No API changes or client updates required.

chevron-rightv0.9.251 - Platform API: Expanded Clinical Tool Filters and LLM-Optimized Result Formatting (June 2026)hashtag

Expanded Clinical Tool Filters and LLM-Optimized Result Formatting

Clinical world tools now accept richer filter parameters across patient lookup, appointment lookup, encounter history, and medication queries. A new result formatter produces compact, token-efficient responses that help the agent narrow broad searches instead of dumping truncated data.

What changed:

  • Patient lookup filters - The patient lookup tool now accepts gender, email, address_state (2-letter code), address_city (partial match), insurance_payer (partial match), and max_results (1-50, default 20). When primary key lookups (name, phone, identifier, birthdate) return no results and broad filters are present, the tool falls back to a filtered search across the patient population.

  • Appointment lookup filters - The appointment lookup tool now supports location_name (partial match) and specialty (partial match on provider specialty), in addition to the existing date, status, provider, and type filters. The tool description has been updated to reflect that searches can be performed by provider, date range, status, type, or location without requiring a patient.

  • Encounter history filters - The encounter history tool now accepts date_from and date_to for date range filtering (inclusive start, exclusive end), provider_name (partial match), and appointment_type (partial match on visit type). The limit parameter maximum has been increased from 20 to 50.

  • Medication filters - The medication lookup tool now supports medication_name (partial match, e.g. "metformin") and prescriber (partial match) filters. The include_inactive parameter now returns both active and historical prescriptions when enabled.

  • Slot search location resolution - The slot search tool now accepts state (US state name or 2-letter code) and location_name (partial match) parameters that auto-resolve to the corresponding facility, removing the need to know a numeric location ID.

  • LLM-optimized result formatting - Tool responses now use a compact format that strips empty fields, includes a summary line describing the result set, and provides guidance when a search is too broad (more than 50 matches with fewer than two filters applied). The guidance tells the agent to add filters rather than working with truncated results.

Impact:

No breaking changes. All new parameters are optional. Existing tool calls continue to work unchanged. Agents that previously required multiple calls or manual filtering can now express richer queries in a single tool invocation. The result formatter improves agent reasoning by reducing token usage and providing actionable guidance on broad searches.

chevron-rightv0.9.250 - Platform API: Conversation Compression on Freeze and Context Restoration on Thaw (June 2026)hashtag

Conversation Compression on Freeze and Context Restoration on Thaw

Text sessions now support automatic conversation compression when a session is frozen and context restoration when the session is thawed, enabling long-running text conversations to resume coherently across idle gaps.

What changed:

  • Compression on freeze - When a text session freezes due to idle timeout and the conversation residency policy has compression enabled, the platform generates a natural-language summary (plan) of the conversation before persisting the frozen state. The summary captures commitments, open questions, and key context from the session. Compression is non-fatal - if it fails or produces no output, the state is saved without a plan and the conversation can still resume from raw turns.

  • Context restoration on thaw - When a patient sends a new message that thaws a frozen session with a compressed plan, the platform injects the plan and recent message history into the reasoning engine before processing the inbound message. The agent resumes with full awareness of prior commitments and context. No outbound greeting is sent - the patient initiated the conversation, so the agent waits for their message and responds naturally.

  • Thaw detection - Sessions that resume from a frozen state with a plan are flagged internally so the greeting flow is skipped in favor of context injection. Sessions without a plan follow the standard greeting flow.

Impact:

No breaking changes. Compression is opt-in via the conversation residency policy. Sessions that do not enable compression continue to behave as before. The thaw context injection is automatic for any frozen session that has a compressed plan. Existing text session integrations require no changes.

chevron-rightv0.9.249 - Platform API: Slot and Appointment Filter Expansion (June 2026)hashtag

Slot and Appointment Filter Expansion

The Slot listing endpoint and appointment lookup tool now support richer filtering, making it easier to find availability by provider, specialty, service type, and date range without client-side post-filtering.

What changed:

  • Slot listing filters - The GET /slots view endpoint now accepts query parameters for status, date (start date, YYYY-MM-DD), days (number of days forward, 1-90, default 7), provider (partial name match), specialty (partial match), service_type (partial match on visit/service type name), and facility_id. When no date is provided, the endpoint defaults to today. Results are sorted by slot start time when no search query is provided.

  • Appointment lookup filters - The appointment lookup tool now supports date_from and date_to for date range filtering (inclusive start, exclusive end), provider_name (partial match), appointment_type (partial match), and a configurable max_results parameter (1-50, default 10).

  • Slot search specialty filter - The slot search tool now accepts a specialty parameter for filtering results by provider specialty (partial match).

  • Entity search provider and service type filters - The search_entities tool now supports provider (partial match on practitioner name) and service_type (partial match on visit type) filters, in addition to the existing typed column filters.

  • Date filtering for Slot resources - FHIR resource search now supports date prefix filtering for Slot resources, matching the existing support for Appointment resources.

  • Improved wildcard escaping - Specialty, provider, and service type partial-match filters now properly escape wildcard characters in filter values, preventing unexpected match behavior when filter values contain special characters.

Impact:

No breaking changes. All new parameters are optional and additive. Existing queries continue to work unchanged. Agents and integrations that previously required multiple search calls or client-side filtering for slot and appointment queries can now express richer filters in a single request.

chevron-rightv0.9.248 - Platform API: Inbound Email Persistence and Read Endpoints (June 2026)hashtag

Inbound Email Persistence and Read Endpoints

The email channel now fully processes inbound email replies, persisting parsed content and exposing read endpoints for listing and retrieving inbound messages.

What changed:

  • Inbound email processing - The inbound email webhook now fully processes incoming replies. When a reply arrives, the platform resolves it to the original outbound email using message threading headers, extracts the canonical body (HTML preferred, plain text fallback), parses attachments with sanitized filenames, and preserves the original raw message. All content is persisted durably. Messages that cannot be resolved to a platform-originated outbound email are dropped silently - cold inbound and replies to external messages remain out of scope.

  • List inbound emails (GET /v1/email/inbound) - Returns a paginated list of inbound emails with cursor-based pagination. At least one filter is required: use case, setup, sender address, or the outbound email being replied to. Results are ordered by receive time (newest first). Each item includes sender, recipient, subject, receive timestamp, and whether attachments are present.

  • Get inbound email (GET /v1/email/inbound/{email_id}) - Returns full detail for a single inbound email including body format (html or text), attachment filenames, and the outbound email it replies to.

  • Get inbound email body (GET /v1/email/inbound/{email_id}/body) - Returns the canonical body content with the appropriate content type (text/html or text/plain).

  • Get inbound email attachment (GET /v1/email/inbound/{email_id}/attachment/{filename}) - Redirects to a short-lived secure URL for downloading a specific attachment. The filename must match one listed on the email.

  • Get inbound email raw (GET /v1/email/inbound/{email_id}/raw) - Redirects to a short-lived secure URL for downloading the original raw email message in RFC 822 format.

  • Idempotent webhook processing - Duplicate delivery of the same inbound notification is handled gracefully. The first delivery persists the message; subsequent deliveries for the same message are acknowledged without creating duplicates.

  • Atomic persistence with rollback - If any step of the inbound processing pipeline fails (content extraction, storage, or database insert), all partial writes are cleaned up automatically so the next retry attempt starts from a clean state.

Impact:

No breaking changes. The inbound webhook endpoint introduced in v0.9.246 now performs full processing instead of logging notifications. Existing outbound email integrations are unaffected. The new read endpoints are additive. Inbound emails inherit use case and setup configuration from the outbound email they reply to, so no additional routing setup is needed.

chevron-rightv0.9.247 - Platform API: Typed Column Filters for Entity Search (June 2026)hashtag

Typed Column Filters for Entity Search

The search_entities tool in the Data Access layer now supports a full set of typed column filters, enabling precise queries across all entity types without falling back to free-text search.

What changed:

  • New filter parameters - Entity search accepts filters for status, location_state (2-letter US state code), facility_id, slot_status, slot_facility_id, slot_start_after, slot_start_before, specialty (case-insensitive partial match), scheduling_eligible (boolean), and npi. These filters are composable - combine any subset to build precise queries.

  • Sort control - A new order_by parameter controls result ordering. Supported values: updated_at (default, descending), created_at (descending), display_name (ascending), and slot_start (ascending).

  • Multi-hop query pattern - For queries that span entity types (e.g. finding available slots in a specific state), first search place entities by location_state to retrieve facility IDs, then search slot entities by slot_facility_id. The tool description now documents this pattern explicitly.

  • Expanded entity type guidance - The entity_type filter description now lists all supported types: person, place, slot, appointment, organization, and call.

  • ISO 8601 datetime validation - The slot_start_after and slot_start_before parameters require ISO 8601 format (e.g. 2026-05-01T00:00:00Z). Invalid values return a descriptive error message.

Impact:

No breaking changes. Existing queries using entity_type, display_name, canonical_id, and limit continue to work unchanged. The new filters are additive - omit them to get the previous behavior. Agents and tools that previously required multiple search calls or client-side filtering can now express the query in a single request.

chevron-rightv0.9.246 - Platform API: Inbound Email Webhook and Outbound Message Threading (June 2026)hashtag

Inbound Email Webhook and Outbound Message Threading

The email channel now supports inbound email reception via a new webhook endpoint and sets explicit message identifiers on outbound emails to enable reply threading.

What changed:

  • Inbound email webhook - A new webhook endpoint accepts inbound email notifications from the platform's email infrastructure. This is the first step toward full inbound email processing. The endpoint handles subscription confirmation automatically and logs inbound email notifications. Full inbound processing - thread resolution, content extraction, and conversation routing - will follow in a subsequent release. Until then, raw inbound email payloads are retained temporarily for reprocessing.

  • Outbound message threading - Outbound emails now include an explicit message identifier header tied to the platform's internal email ID. When a recipient replies, their email client includes this identifier in the reply headers, enabling the platform to correlate inbound replies back to the original outbound message. This is the foundation for threaded email conversations where the agent can maintain context across a multi-message exchange.

Impact:

No breaking API changes. Existing email send integrations continue to work without modification. The outbound message identifier is set automatically on all new outbound emails. Inbound email processing is not yet active - notifications are acknowledged but not routed to conversations. Operators deploying inbound email infrastructure should ensure the webhook endpoint is live before creating the inbound notification subscription, as the subscription confirmation is sent exactly once at creation time.

chevron-rightv0.9.245 - Platform API: Channel-Neutral Conversation Directory and Residency Policies (June 2026)hashtag

Channel-Neutral Conversation Directory and Residency Policies

Text conversations are now managed through a channel-neutral conversation directory with per-channel residency policies, replacing the SMS-specific session manager.

What changed:

The text session orchestrator now persists conversation state durably and routes inbound messages through a unified conversation directory rather than an SMS-specific session lookup. This is the foundation for multi-channel text support (WhatsApp, email) using the same routing and lifecycle infrastructure.

Conversations now follow a three-state lifecycle:

Status
Description

active

Conversation is in progress and accepting messages

frozen

Conversation is idle but retains full state; reactivated automatically on next inbound message

closed

Conversation is complete; new inbound messages start a fresh conversation

When a frozen conversation receives a new message, the platform thaws it automatically - restoring the prior turn history, reasoning context, and plan - so the agent continues where it left off.

Each channel has a residency policy that controls active duration, idle timeout, and maximum session length:

Channel
Active Window
Idle Timeout
Max Duration

SMS

2 hours

30 minutes

2 hours

WhatsApp

24 hours

1 hour

24 hours

Email

5 minutes

5 minutes

Unlimited

Conversation state is saved with optimistic concurrency control. Each save checks that no other actor has modified the conversation since it was last read, preventing silent overwrites in concurrent-processing edge cases.

The platform uses a hot cache for low-latency routing of active conversations, with automatic fallback to the durable store on cache errors. Turn history is accumulated on the conversation state and persisted on freeze or close, ensuring no data loss even during infrastructure restarts.

Impact:

No breaking API changes. Existing SMS integrations continue to work without modification. The routing key format used by SMS webhooks and status callbacks is unchanged. Conversation state is now persisted durably across session restarts, so conversations interrupted by infrastructure events (deployments, scaling) resume with full context instead of starting over.

chevron-rightv0.9.244 - Platform API: Notification Email on Direct Member Add (June 2026)hashtag

Notification Email on Direct Member Add

When a workspace admin adds an existing platform user to a workspace directly (rather than sending an invitation), the platform now sends a notification email to the new member informing them of the access grant.

What changed:

Previously, when an admin granted workspace access to someone who already had a platform account, the user was added silently - no email was sent. The user had no way of knowing they had been added to a new workspace unless they checked the console manually. Only invitation-based flows (for users without an existing account) triggered an email.

The grant-access endpoint now sends a notification email to the member whenever they are added directly. The email includes the workspace name, the role they were assigned, and a link to open the console. This applies to all roles: viewer, member, operator, and admin.

If the email notification service is not configured for the deployment, the member is still added successfully - the email is best-effort and does not block the access grant.

Impact:

No breaking API changes. The grant-access endpoint response shape is unchanged. Existing integrations that add members programmatically will now trigger notification emails automatically. There is no way to suppress the notification email per-request - it is sent whenever a direct add occurs and the notification service is enabled.

chevron-rightv0.9.243 - Platform API: Channel Delivery Events via Real-Time Event Pipeline (June 2026)hashtag

Channel Delivery Events via Real-Time Event Pipeline

Email delivery status events are now emitted through the platform's real-time event pipeline and published as SSE events for live UI updates.

What changed:

When the platform sends email on behalf of a workspace, delivery status updates - delivered, bounced, complained, rejected, delayed, opened, and clicked - are now routed through the event pipeline. The platform resolves the workspace automatically from the channel setup, so downstream consumers receive workspace-scoped events without any additional configuration.

Each delivery status is published as a typed SSE event on the workspace event stream:

SSE Event Type
Description

channel.email_delivered

Email was successfully delivered to the recipient

channel.email_bounced

Email bounced (includes bounce type and subtype)

channel.email_complained

Recipient marked the email as spam

channel.email_rejected

Email was rejected before delivery

channel.email_delayed

Delivery is delayed but still being retried

channel.email_opened

Recipient opened the email

channel.email_clicked

Recipient clicked a link in the email

All email events include email_id and to_address fields. Delivery, bounce, complaint, rejection, and delay events also include from_address. Bounce events additionally carry bounce_type and bounce_subtype for diagnosing delivery failures.

These events also flow into the workspace event store, so they are available through the data access layer for analytics, dashboards, and historical queries.

Workspace-to-channel bindings are recorded automatically when a use case is created. No manual binding step is required.

Impact:

No breaking API changes. Existing SSE consumers will see new event types on the workspace event stream. If your integration filters events by type, add the channel.email_* types to your allow list to receive delivery status updates. Use cases created before this release will not have bindings recorded - only newly created use cases are bound automatically.

chevron-rightv0.9.242 - Platform API: Auto-Provision Workspace on Self-Service Creation (June 2026)hashtag

Auto-Provision Workspace on Self-Service Creation

Workspaces created through the self-service creation flow are now automatically provisioned, removing the need for a separate provisioning step after creation.

What changed:

Previously, creating a workspace through the self-service endpoint returned a workspace record that was not yet provisioned. Teams had to trigger provisioning separately before the workspace was fully operational. This added an extra step to onboarding and could cause confusion when newly created workspaces appeared inactive.

The self-service workspace creation endpoint now provisions the workspace automatically as part of the creation flow. When you create a workspace, the platform attempts to provision it immediately after the workspace record is created. The workspace is returned to the caller as before - provisioning happens in the background as a best-effort step.

If auto-provisioning encounters an error, the workspace is still created and usable. A warning is logged, and provisioning can be retried later. This ensures that workspace creation never fails due to a transient provisioning issue.

Impact:

No breaking API changes. The create workspace response shape is unchanged. Existing integrations that already trigger provisioning separately will continue to work - re-provisioning an already-provisioned workspace is a no-op. New integrations can rely on the workspace being provisioned immediately after creation without an additional API call.

chevron-rightv0.9.241 - Platform API: DMARC Quarantine Default and Unsubscribe Provenance (June 2026)hashtag

DMARC Quarantine Default and Unsubscribe Provenance

Email channel setup now defaults to a stricter DMARC policy, and unsubscribe records now track which send triggered the opt-out.

What changed:

  • DMARC policy upgraded to quarantine - New and existing email setups now return a DMARC DNS record with p=quarantine instead of p=none. The quarantine policy instructs receiving mail servers to treat unauthenticated messages as suspicious rather than delivering them normally. This improves deliverability reputation and aligns with bulk-sender requirements from major mailbox providers. If you have already published a _dmarc TXT record for your sending domain, update it to match the new value shown in the setup DNS records.

  • Unsubscribe records include originating send - When a recipient unsubscribes (via one-click link or complaint), the platform now records which specific send triggered the opt-out. This lets you answer "which template or subject line caused this unsubscribe" when auditing opt-out trends. The originating send identifier is cryptographically signed into the unsubscribe link at send time, preventing tampering.

DNS record change:

Record
Previous Value
New Value

_dmarc.<your-domain> TXT

v=DMARC1; p=none;

v=DMARC1; p=quarantine;

If you previously published the p=none record, update it to p=quarantine to match the platform's new default. Existing setups will show the updated value when you retrieve the setup's DNS records.

Impact:

No breaking API changes. The unsubscribe provenance data is recorded automatically - no changes to your integration are required. If you consume unsubscribe data through the platform's data access layer, the originating send identifier will appear on new unsubscribe records going forward.

chevron-rightv0.9.240 - Platform API: Workspace Creation Persists Environment and Region (June 2026)hashtag

Workspace Creation Persists Environment and Region

The workspace creation endpoint now persists environment and region values when provided in the request body.

What changed:

Previously, creating a workspace did not carry the caller-supplied environment and region values through to the workspace record. The workspace always received default values regardless of what was passed in the request. This caused workspaces intended for staging or non-default regions to appear as production workspaces in the Developer Console sidebar, workspace listings, and any downstream features that rely on these fields for filtering or routing.

The create workspace endpoint now accepts two optional fields:

Field
Type
Required
Description

environment

string

No

Environment designation for the workspace (e.g., production, staging). Defaults to production when omitted.

region

string

No

Region where the workspace operates. Defaults to the platform default region when omitted.

When provided, these values are stored on the workspace record and reflected in all read endpoints, the Developer Console sidebar selector, and workspace listings.

Impact:

No breaking changes. Existing integrations that do not pass environment or region continue to receive the same default behavior. If you are creating staging or non-default-region workspaces, pass these fields explicitly to ensure the workspace is labeled correctly.

chevron-rightv0.9.239 - Platform API: Trust Hub Edit Gating on Rejected Status (June 2026)hashtag

Trust Hub Bundle Edits Restricted to Rejected Status

Trust Hub bundle editing is now gated exclusively on the rejected status. Previously, some endpoints allowed edits when a bundle was in other post-review states. This release tightens the rules so that bundles can only be modified after they have been explicitly rejected.

What changed:

  • CNAM bundle updates - The CNAM submission endpoint now returns 409 for any bundle that is not in a rejected state. Previously, bundles in approved or other post-review states could accept display name changes. Now, only rejected bundles accept a new display name and trigger a fresh evaluation cycle.

  • Customer profile data updates - The customer profile update endpoint now requires the customer profile to be in a rejected state before accepting data changes. Previously, approved profiles could be edited. Approved bundles are now locked, and in-review or pending-review bundles cannot be interrupted mid-evaluation.

  • Consistent error messaging - Both endpoints return 409 with a message indicating that Trust Hub bundles can only be edited while rejected, replacing the previous status-specific messages.

Impact:

If you have automation that edits CNAM display names or customer profile data on approved bundles, those requests will now return 409. Update your integration to only submit edits after receiving a rejection status via webhook.

chevron-rightv0.9.238 - Platform API: RFC 8058 Email Unsubscribe (June 2026)hashtag

Email Unsubscribe Surface

Email use cases now support built-in unsubscribe management compliant with RFC 8058, CAN-SPAM, and bulk-sender requirements from major mailbox providers.

Use case configuration:

The email use case creation endpoint accepts a new required field:

Field
Type
Required
Description

unsubscribable

boolean

Yes

Whether the use case exposes unsubscribe headers and footer links, and gates sends on the per-use-case unsubscribe list. Marketing use cases must be true. Transactional use cases may set false for must-send flows (password resets, verification codes).

The use case response includes the unsubscribable field in both create and list endpoints.

Body template contract:

The body_html field in the send email endpoint is now validated as a Jinja2 template:

  • Unsubscribable use cases: body_html must reference exactly two variables - {{ unsubscribe_link }} and {{ unsubscribe_from_all_link }}. The platform renders these with signed, per-recipient URLs. Missing or extra variables return 422.

  • Non-unsubscribable use cases: body_html must contain no Jinja variables. Any {{ ... }} references return 422.

Outbound headers:

When sending through an unsubscribable use case, the platform automatically adds List-Unsubscribe and List-Unsubscribe-Post headers to the outbound message. Mail clients that support RFC 8058 (Gmail, Apple Mail) render a native unsubscribe button in their UI.

Unsubscribe flow:

Two new public endpoints handle the recipient-facing unsubscribe experience:

Method
Path
Description

GET

/v1/email/unsubscribe/{token}

Renders a confirmation page. Does not mutate state (safe against email security scanners that pre-fetch URLs).

POST

/v1/email/unsubscribe/{token}

Records the unsubscribe. Idempotent - duplicate submissions are no-ops.

Unsubscribe tokens are signed per-recipient and per-scope. Two scopes are supported:

  • Use-case scope: Unsubscribes the recipient from a specific use case. Future sends from that use case to the recipient return 422.

  • Setup scope: Unsubscribes the recipient from all email under the sender setup. Future sends from any use case under that setup return 422, including transactional use cases.

Tokens that fail signature verification return 403 with no information about whether the referenced resources exist.

Complaint handling:

When a complaint event is received (recipient marked message as spam), the platform now automatically records a use-case-level unsubscribe for the recipient. This prevents further sends from that use case without requiring the recipient to click an unsubscribe link. Complaints are not projected to the setup-level ban list - they represent list-specific signal, not a domain-wide opt-out.

Send pre-flight checks:

The send email endpoint now checks unsubscribe status before sending:

  1. Setup-level ban list is always checked, regardless of the unsubscribable flag. A banned recipient returns 422.

  2. Use-case-level unsubscribe list is checked when unsubscribable is true. An unsubscribed recipient returns 422.

chevron-rightv0.9.237 - Platform API: Unified Grant-Access Endpoint, Bulk Invite, and Self-Profile (June 2026)hashtag

Unified Grant-Access Endpoint

Workspaces now have a single endpoint for granting access to new or existing users. Instead of choosing between adding a member and sending an invitation, callers provide an email and role, and the platform resolves the correct outcome automatically. If the email belongs to an existing platform user, they are added (or reactivated) as a workspace member immediately. If the email is not recognized, an invitation is created and sent.

New endpoints:

Method
Path
Description

POST

/{workspace_id}/grant-access

Grant workspace access to a single email

POST

/{workspace_id}/grant-access/bulk

Grant workspace access to up to 50 emails in one request

Single grant-access request body:

Field
Type
Required
Description

email

string

Yes

Email address of the person to grant access to

role

string

No

One of viewer, member, operator, admin. Defaults to viewer

Single grant-access response:

Field
Type
Description

action

string

Always granted on success

member

object or null

Workspace member details if the user was added directly

invitation

object or null

Invitation details if an invitation was sent

Exactly one of member or invitation is populated in a successful response.

Bulk grant-access request body:

Field
Type
Required
Description

entries

array

Yes

1 to 50 entries, each with email (string, required) and role (string, optional, defaults to viewer)

Bulk grant-access response:

Field
Type
Description

results

array

Per-email results, each with email, action (granted or error), optional error message, and optional member or invitation

summary

object

Counts: members_added, invitations_sent, errors

Behavior notes:

  • The caller must have a manager-level role (admin or owner) in the workspace.

  • Granting access to your own email returns a validation error.

  • If the email matches multiple platform users, the endpoint returns a conflict error directing the caller to use the members API with an explicit entity ID.

  • If a pending invitation already exists for the email, the invitation is resent with an extended expiration rather than creating a duplicate.

  • Emails are normalized to lowercase before processing.

Self-Profile Endpoint

A new endpoint returns the authenticated user's identity and access across all workspaces.

Method
Path
Description

GET

/self/profile

Get the current user's profile, workspace memberships, and pending invitations

Response:

Field
Type
Description

entity_id

string (UUID)

The user's entity identifier

email

string or null

The user's email address

name

string or null

The user's display name

workspaces

array

Active workspace memberships with role, scopes, and workspace summary

pending_invitations

array

Pending invitations the user has not yet accepted, with workspace summary

Workspace memberships and pending invitations are sorted alphabetically by workspace name.

New Workspace SSE Events

Three new server-sent event types are emitted on the workspace event stream:

Event Type
Description
Key Fields

workspace.member_added

A user was added to the workspace

entity_id, role

workspace.invitation_sent

An invitation was created or resent

invitation_id, role, resent

workspace.invitation_accepted

A user accepted a workspace invitation

entity_id, role

These events fire for both single and bulk grant-access operations, and when an invitation is accepted through the existing invitation acceptance flow.

No breaking changes. All existing workspace, member, and invitation endpoints continue to work as before.

chevron-rightv0.9.236 - Platform API: Device Code Flow for CLI Authentication (June 2026)hashtag

Device Code Flow for CLI Authentication

The identity service now supports the OAuth 2.0 Device Authorization Grant (RFC 8628), enabling CLI tools like Agent Forge to authenticate through a browser-based approval flow without requiring API keys or manual token management.

What changed:

  • New device authorization endpoint - POST /device/code issues a device code and user code. The endpoint is unauthenticated and rate-limited by IP. The response includes a verification_uri where the user completes authorization in a browser, a short user_code to enter, and a verification_uri_complete with the code pre-filled.

  • Device approval endpoint - POST /device/approve lets an authenticated user approve or deny a pending device code. Requires a valid Bearer JWT. Bootstrap tokens are not permitted to approve device codes.

  • New device_code grant type on the token endpoint - POST /token with grant_type=device_code polls for the authorization result. While the user has not acted, the endpoint returns authorization_pending. Once approved, it returns a standard token response with access and refresh tokens. The grant respects workspace IP allowlists and MFA requirements.

  • OpenID discovery updated - The .well-known/openid-configuration response now includes device_authorization_endpoint and lists urn:ietf:params:oauth:grant-type:device_code in grant_types_supported.

  • Device code response model:

Field
Type
Description

device_code

string

Opaque code used to poll the token endpoint

user_code

string

Short code the user enters in the browser (format: XXXX-XXXX)

verification_uri

string

URL where the user authorizes the device

verification_uri_complete

string

Verification URL with the user code pre-filled

expires_in

integer

Seconds until the device code expires

interval

integer

Minimum seconds the client should wait between polling requests

  • Polling error responses:

Error
Description

authorization_pending

User has not yet completed authorization

slow_down

Client is polling too frequently

expired_token

Device code has expired

access_denied

User denied the request

  • Audit events - Device code issuance, approval, denial, consumption, and exchange are all logged as audit events.

No breaking changes. Existing authentication methods continue to work as before.

chevron-rightv0.9.235 - Platform API: Configurable Per-Service Escalation Policy (June 2026)hashtag

Configurable Per-Service Escalation Policy

Services now support an optional escalation_policy that controls what happens when the platform detects an escalation trigger during a call. Previously, all engine-detected escalations followed a single path: notify the operator dashboard and wait for a human to join. With this release, each trigger source can be independently routed to a different action.

What changed:

  • New escalation_policy field on Service - The Service object now accepts an optional escalation_policy object on create and update. When set, it overrides the default operator-only behavior for engine-detected escalations. When null (the default), existing behavior is preserved.

  • Three escalation actions - Each trigger source maps to one of three actions:

Action
Behavior

operator

Notify the command center and wait for a human operator to join (default, existing behavior).

forward

Cold-transfer the caller to the forwarding destination configured on the inbound phone number. If no forwarding destination is configured, falls back to operator handoff.

hangup

End the call gracefully.

  • Three trigger sources - The following trigger sources can be independently configured:

Trigger Source
Description

context_window_exhaustion

The conversation has consumed most of the available context window.

risk_scorer

The composite risk score crossed the auto-escalation threshold.

conversation_monitor

Sentiment or topic analysis flagged the call for handoff.

  • Partial policies - You can set actions for individual trigger sources without specifying all three. Any trigger source not explicitly set defaults to operator.

  • Example - To forward calls on context window exhaustion while keeping operator handoff for other triggers:

  • Audit events unchanged - Escalation audit events and real-time notifications are emitted for every escalation regardless of the configured action. The policy only controls the caller-facing response.

  • Applies to new calls only - Policy changes take effect on calls started after the update. Calls already in progress continue using the policy that was active when the call started.

No breaking changes. Existing services without an escalation policy continue to use operator handoff for all escalation triggers.

chevron-rightv0.9.234 - Platform API: Frozen Conversation Schema and Compression Fidelity (June 2026)hashtag

Frozen Conversation Schema and Compression Fidelity

Text conversations now persist as a durable, immutable value that preserves full conversation context across freeze/thaw cycles. This enables agents to resume idle conversations with complete awareness of prior commitments, participant context, and unresolved items - even after extended periods of inactivity.

What changed:

  • Conversation state model - Each text conversation is now stored as a single value containing three components: a natural-language plan (compressed outcome state), recent verbatim turns (up to 200), and a channel-specific cursor. The plan is written in plain language so it remains readable across platform versions without schema migration.

  • Immutable value semantics - Conversation state is treated as an immutable value. Adding a turn produces a new state rather than mutating the existing one. This enforces the design principle that conversations are values threaded through function applications, not mutable containers.

  • Compression for frozen conversations - When a conversation freezes, the platform compresses its history into a plan that captures participant identities, commitments made, current status, expected next actions, and unresolved questions. The compression prompt is designed so that a future agent version can read the plan months later and resume coherently.

  • Thaw context assembly - When a new inbound message arrives on a frozen conversation, the platform assembles a resumption context combining the compressed plan, the most recent turns, and the new message. The agent resumes with full prior context and honors all previous commitments.

  • Turn limit - Conversations retain up to 200 verbatim turns. When the limit is reached, the oldest turns are dropped as new ones are added. Compressed plans preserve the semantic content of dropped turns.

No breaking changes. Existing text conversations are unaffected.

chevron-rightv0.9.233 - Platform API: Test Call Engine Initialization Error Reporting (June 2026)hashtag

Test Call Engine Initialization Error Reporting

The test-call playground WebSocket now surfaces typed errors when the voice agent engine fails to initialize, instead of silently falling back to a degraded session. This gives developers immediate, actionable feedback when their service configuration is incomplete or invalid.

What changed:

  • Typed initialization errors - When a test call fails to start because of a configuration problem, the WebSocket connection now rejects with a structured error that includes a stable error code and a human-readable reason. Previously, these failures were silently absorbed and the session would start in a degraded fallback mode with no indication of what went wrong.

  • Stable error codes - The following error codes may be returned when a test call cannot initialize:

Code
Meaning

missing_agent_version

The service references an agent with no published versions

missing_context_graph_version

The service references a context graph with no published versions

service_not_found

The specified service does not exist in the workspace

version_set_not_found

The requested version set is not configured on the service

service_config_unavailable

The platform could not retrieve the service configuration

service_config_timeout

The service configuration request timed out

  • Frontend integration - Clients connected to the test-call WebSocket receive the error code and reason in the connection rejection payload, enabling UI banners or error dialogs that tell the developer exactly what to fix.

  • Production calls unaffected - This change only affects the test-call playground WebSocket. Production inbound and outbound calls continue to use existing fallback behavior.

No breaking changes. Existing test-call integrations that do not inspect rejection payloads continue to work as before.

chevron-rightv0.9.232 - Platform API: Surface Field Limit Increased to 200 (June 2026)hashtag

Surface Field Limit Increased to 200

The maximum number of fields allowed in a surface specification has been increased from 100 to 200, matching the limit already supported by form templates.

What changed:

  • Higher field cap - Surface specifications now accept up to 200 fields per surface (previously 100). This aligns the surface field limit with the form template limit, removing a mismatch that could cause validation failures when a form template with more than 100 fields was used to create a surface.

  • Minimum unchanged - The minimum of 1 field per surface is unchanged.

No breaking changes. Existing surfaces with 100 or fewer fields continue to work without modification.

chevron-rightv0.9.230 - Platform API: Conversation Billing Meters and Per-Conversation Billing Detail (June 2026)hashtag

Conversation Billing Meters and Per-Conversation Billing Detail

The billing pipeline now tracks three new engagement meters - messages, actions, and conversations - and provides a per-conversation billing breakdown for audit and dispute resolution. Simulation usage is metered separately from production usage across all meters.

What changed:

  • Message count meter - Tracks the number of user-facing messages sent by the agent during conversations. Available as both a production meter and a simulation meter.

  • Action count meter - Tracks the number of tool executions performed during conversations. Each tool invocation within a voice call or companion agent execution counts as one action. Available as both a production meter and a simulation meter.

  • Conversation count meter - Tracks the number of distinct conversations (call sessions and companion agent executions). Available as both a production meter and a simulation meter.

  • Simulation meter separation - All billing meters now have corresponding simulation variants. Simulation usage is identified automatically based on session origin and tracked under separate meter keys prefixed with sim_. This gives customers clear visibility into production vs. simulation costs.

  • Per-conversation billing detail - A new conversation-level billing breakdown replaces the previous per-call attribution view. Each conversation now shows message count, action count, voice minutes, token usage, quality score, completion reason, direction, and time range. This provides the detail needed for billing audits and dispute resolution without requiring manual event correlation.

  • Tool count tracking - Voice calls and companion agent executions now report the number of tool invocations per turn, enabling accurate action-based metering.

No breaking changes. Existing meter values for voice minutes, call count, tokens, SMS, recordings, completed calls, quality-weighted calls, and surface submissions continue to work unchanged.

chevron-rightv0.9.229 - Platform API: Self-Image Briefs for Cohort, Workspace, and Geographic Targets (June 2026)hashtag

Self-Image Briefs for Cohort, Workspace, and Geographic Targets

Self-Image briefs now support cohort, workspace, territory, emirate, and district targets in addition to patient entities. Each target type uses a dedicated prompt tuned for its scope, and higher-scope targets (workspace and geographic levels) use a more capable model for richer synthesis.

What changed:

  • Cohort briefs - Generate narrative briefs scoped to a cohort entity. Cohort briefs summarize trends and patterns across the cohort's member population using the same latency-optimized model as patient briefs.

  • Workspace briefs - A new workspace-scope brief endpoint (POST /v1/{workspace_id}/brief and GET /v1/{workspace_id}/brief) generates a single narrative brief for the entire workspace. Workspace briefs use a higher-capability model to handle the denser, full-workspace evidence set. The workspace UUID is used as both the scope and the target identifier.

  • Geographic briefs - Territory, emirate, and district entities can now receive briefs. All three geographic levels share a single prompt template that generalizes across administrative boundaries. Geographic briefs use the same higher-capability model as workspace briefs.

  • Model routing by target type - Patient and cohort briefs route to a fast, low-latency model. Workspace and geographic briefs route to a higher-capability model better suited for synthesizing broader evidence sets. Model selection is automatic based on the target type.

  • Audit logging - Brief generation requests now emit an audit event (self_image.brief_requested) before dispatching to the model. The audit entry records the workspace, target entity, target type, and requesting credential. Audit logging is non-blocking and does not affect brief generation latency.

  • PHI region enforcement - The brief generation service now validates at startup that it is configured for a PHI-covered region. Misconfiguration that would route briefs outside the compliance perimeter is rejected immediately rather than failing silently at request time.

New endpoints:

Method
Path
Description

POST

/v1/{workspace_id}/brief

Generate a workspace-level Self-Image brief

GET

/v1/{workspace_id}/brief

Retrieve the latest workspace-level brief (null shape if none exists)

Updated endpoints:

Method
Path
Change

POST

/v1/{workspace_id}/entities/{entity_id}/brief

Now accepts cohort, territory, emirate, and district entities in addition to patient

GET

/v1/{workspace_id}/entities/{entity_id}/brief

Now accepts cohort, territory, emirate, and district entities in addition to patient

The target_entity_type field in brief responses now returns one of: patient, cohort, workspace, territory, emirate, or district.

No breaking changes. Existing patient brief endpoints continue to work unchanged.

chevron-rightv0.9.228 - Platform API: Improved Visit Type Resolution for Scheduling Slots (June 2026)hashtag

Improved Visit Type Resolution for Scheduling Slots

Scheduling slots now resolve visit type information more reliably from provider booking preferences, eliminating cases where the provider's medical specialty (e.g., "Psychiatry") was incorrectly surfaced as the visit type for a slot.

What changed:

  • Robust visit type extraction - The platform now recognizes multiple field naming conventions used by EHR systems when reporting allowed visit types in booking preferences. Previously, only one naming convention was handled, which caused visit type data to be silently dropped for some provider configurations. Slots for those providers would then fall back to displaying the provider's specialty as the visit type, which is incorrect - a provider specializing in psychiatry may offer visit types like "New Patient Evaluation" or "Follow-Up", and those are what callers need to see.

  • Eager visit type resolution - When a scheduling availability poll finds no cached visit type data for a provider, the platform now fetches the provider's booking preferences immediately before emitting the slot batch. Previously, visit type data was only available if a separate background sync had already cached it, meaning the first availability poll for a provider could emit slots without visit type information.

  • Specialty and visit type separation - Provider specialty and visit type are now treated as independent fields throughout the data pipeline. Specialty is no longer used as a fallback value for visit type. If a provider has no configured visit types, the visit type fields remain empty rather than being populated with the specialty.

No breaking changes. Existing slot search queries and FHIR Slot projections continue to work. Slots that previously displayed provider specialty as the visit type will now either show the correct visit type (if booking preferences are configured) or have empty visit type fields.

chevron-rightv0.9.227 - Platform API: Slot Search Spacing, Precise Time Filtering, and Search Metadata (June 2026)hashtag

Slot Search Spacing, Precise Time Filtering, and Search Metadata

The slot_search tool now returns diversified results with intelligent spacing, supports precise clock-time filtering alongside the existing time-of-day buckets, and includes structured search metadata so agents can communicate availability honestly to callers.

What changed:

  • Spacing-greedy results - Returned slots are now spaced at least 30 minutes apart by default (configurable via min_spacing_minutes, 0-1440). This prevents tight clusters like 11:50 / 11:50 / 12:00 and gives callers meaningfully different options. Pass min_spacing_minutes: 0 to disable spacing.

  • Precise clock-time filtering - Two new parameters, time and time_direction, enable exact clock-time queries like "after 2 PM" or "before noon". Pass time in HH:MM 24-hour format (e.g. 14:00) and time_direction as after (slots at or after that time) or before (slots strictly before). Both parameters must be set together. This complements the existing time_preference bucket filter (morning/afternoon/evening) and composes with it - when both are set, results are the intersection.

  • Auto-relax with honest reporting - When a precise time filter returns no results, the search automatically relaxes to the time-of-day bucket containing the requested time, then to an adjacent bucket if still empty. The agent sees exactly what happened via search_metadata.relaxed_filter so it can tell the caller "No slots after 4 PM, but here are evening options" rather than silently returning unrelated times.

  • Structured search metadata - Every response now includes a search_metadata object with: requested_filter (what was asked for), relaxed_filter (set when auto-relax fired, null otherwise), total_matched (matches before spacing), total_after_spacing (matches that survived the spacing rule), total_returned (count in this response), and truncated (whether the candidate set was capped before in-memory filtering). When total_after_spacing exceeds the returned count, the agent can offer more slots by re-calling with a larger max_results.

  • Default and max results updated - max_results now defaults to 5 (previously 3) and accepts values 1-10.

  • Input validation - The time parameter validates HH:MM 24-hour format strictly (hours 00-23, minutes 00-59). Malformed values like 2 PM or 14:00:00 return a structured error so the agent can self-correct. The date parameter now validates YYYY-MM-DD format.

  • Observer events - New observer events slot_search_filter_relaxed and slot_search_completed are emitted for audit visibility into filter relaxation and search outcomes.

No breaking changes. Existing slot_search calls without the new parameters continue to work. The time_preference bucket filter, appointment_type, provider_name, and location_id parameters are unchanged.

chevron-rightv0.9.226 - Platform API: Computer Use Execution Tier for Skills (June 2026)hashtag

Computer Use Execution Tier for Skills

Skills now support a computer_use execution tier in addition to the existing direct, orchestrated, and autonomous tiers. This tier enables skills that interact with desktop and browser-based applications through visual understanding and input simulation.

What changed:

  • New execution tier - The computer_use execution tier is now accepted when creating or updating skills. This tier is designed for skills that need to operate software interfaces visually - navigating screens, reading on-screen content, clicking buttons, and filling forms in applications that lack API integrations.

  • Backward-compatible - Existing skills using direct, orchestrated, or autonomous tiers are unaffected. The new tier is opt-in and only applies to skills explicitly configured with computer_use.

No breaking changes. All existing skill configurations continue to work without modification.

chevron-rightv0.9.225 - Platform API: Per-Disease Risk Scores in Patient Topology (June 2026)hashtag

Per-Disease Risk Scores in Patient Topology

The patient topology endpoint now surfaces individual disease risk scores alongside the existing composite score, giving population health dashboards granular visibility into per-condition predicted risk.

What changed:

  • New per-disease risk score fields - The patient topology response now includes predicted risk scores for hypertension (1-year), congestive heart failure (90-day), asthma (12-month), chronic kidney disease (1-year), and COPD (12-month), in addition to the existing type 2 diabetes (1-year) and composite scores. All scores are floats between 0.0 and 1.0.

  • Backward-compatible rollout - Workspaces whose data pipelines have not yet produced the new score columns will receive null values for the new fields. Existing fields are unaffected. As pipelines are updated, the new scores appear automatically with no API or client changes required.

  • Graceful degradation - If the platform cannot determine which score columns are available for a workspace, the topology endpoint still returns all other patient data. The new score fields will be null rather than causing an error.

No breaking changes. Existing integrations continue to work without modification.

chevron-rightv0.9.224 - Platform API: Metering SDK and HTTP Endpoint (June 2026)hashtag

Metering SDK and HTTP Endpoint

A new metering layer lets you emit usage events from any environment - inside platform services or from external scripts and notebooks - without needing infrastructure credentials. Metering records what happened; the billing layer prices it.

What changed:

  • New metering endpoint - POST /v1/{workspace_id}/metering/emit accepts a usage event with an event type, quantity, optional unit, and optional metadata. The endpoint is workspace-scoped and authenticated with a standard workspace API key. Returns 202 on success. The event type is a free-form lowercase string (validated against ^[a-z][a-z0-9._]*$, max 64 characters). Quantity must be zero or positive. Unit is an optional string (max 32 characters) describing what the quantity represents (e.g., "pages", "minutes", "tokens"). Metadata is an optional key-value object for audit context.

  • Metering client for external environments - A new synchronous client in the platform SDK emits metering events via HTTP for code running outside platform services (laptops, notebooks, CI pipelines). Requires a workspace API key (via AMIGO_API_KEY environment variable or parameter) and optionally a platform URL override (via AMIGO_PLATFORM_URL). No infrastructure credentials required.

  • In-process metering SDK - For code running inside a platform service with a wired event emitter, a new async helper emits metering events directly without the HTTP round-trip. Accepts the same parameters as the HTTP endpoint. Passing a null emitter is a safe no-op for tests and early startup.

  • Billing module clarified - The billing layer documentation now explicitly distinguishes between metering (recording events) and billing (pricing events). The two layers are separate: metering records usage, billing decides what to charge based on metered usage.

  • Fire-and-forget semantics - Metering emission has no built-in deduplication. If retry logic around an emit call causes a duplicate delivery, the event is recorded twice. Callers that need idempotency should track emitted events at the call site.

No breaking changes. Existing billing endpoints are unaffected.

chevron-rightv0.9.223 - Platform API: Superscribe Clinical Settings End-to-End (June 2026)hashtag

Superscribe Clinical Settings End-to-End

The Superscribe settings API now exposes the full clinical configuration surface - language, vocabulary, specialty, custom instructions, and tool selection - and the copilot stream consumes these settings at session start.

What changed:

  • Language configuration - Superscribe settings now include a language field (BCP-47 tag or auto) that controls the speech-to-text model selection. English-only sessions use a dedicated English model for lowest error rate. Non-English or multilingual sessions automatically select the multilingual model with appropriate language hints. The copilot stream resolves the effective language from the configured language, patient language, or defaults to English.

  • Custom vocabulary (keyterms) - A new keyterms field accepts up to 100 domain-specific terms (each up to 80 characters) that are boosted during speech recognition. Keyterms from workspace settings, service configuration, patient medical terms, and environment configuration are merged in priority order, deduplicated case-insensitively, and capped at the recognition engine's limit. The copilot stream now loads service-level vocabulary in addition to workspace-level terms.

  • Specialty and custom instructions - New optional specialty (up to 120 characters) and custom_instructions (up to 4000 characters) fields allow workspaces to specify clinical specialty context and free-form instructions that shape copilot behavior.

  • Tool selection - A new tools_enabled field controls which clinical tools are available during a copilot session. Supported tools include SOAP updates, ICD-10 suggestions, clinical alerts, encounter entities, note polishing, and order preparation. The copilot stream now derives the active tool set from settings, respecting CDS and safety toggles - for example, disabling ICD-10 auto-suggest in the CDS config removes the suggestion tool, and disabling all safety rules removes the clinical alert tool.

  • Safety rule configuration updated - Safety rules now use descriptive identifiers (allergy_cross_reference, drug_interaction_checking, vital_range_alerting, crisis_detection) with backward compatibility for previous field names. The prompt builder resolves both current and legacy field names when determining which safety checks to enable.

  • Settings merge with legacy configuration - The settings API and copilot stream now merge legacy copilot configuration with current Superscribe settings, with the Superscribe settings taking precedence. This ensures a smooth transition for workspaces that have existing copilot configuration.

  • Response model expanded - The GET and PUT Superscribe settings endpoints now return language, keyterms, specialty, custom_instructions, and tools_enabled fields alongside the existing safety, CDS, and post-encounter configuration.

  • Input validation - Language values are normalized to lowercase BCP-47 format. Keyterms are deduplicated, trimmed, and validated against length limits. Tool names are validated against the supported set. Specialty and custom instruction fields are trimmed with empty strings converted to null.

No breaking changes. Existing settings payloads without the new fields continue to work with defaults (language en, empty keyterms, no specialty, no custom instructions, default tool set).

chevron-rightv0.9.222 - Platform API: Population Health Tables for Insights Agent (June 2026)hashtag

Population Health Tables for Insights Agent

The platform insights agent now surfaces population health tables for the labs demo workspace, giving the insights schema introspection tool visibility into synthetic population health data.

What changed:

  • Population health tables exposed in schema introspection - The insights agent's schema tool now includes population health tables when queried from the labs demo workspace. These tables contain synthetic population health data used for demonstration and evaluation purposes. Other workspaces are unaffected and do not see these tables.

  • Workspace-scoped access enforcement - SQL queries that reference demo tables are rejected with a clear error message when executed from any workspace other than the labs demo workspace. This prevents accidental cross-workspace data access.

  • Automatic table discovery - The set of population health tables exposed to the insights agent is derived from the platform's internal catalog. Adding new tables to the population health pipeline automatically extends what the insights agent can see in the labs workspace, with no manual configuration required.

No API contract changes. This feature is scoped to the labs demo workspace only.

chevron-rightv0.9.221 - Platform API: Default Universal Metric Store Dashboards (June 2026)hashtag

Default Universal Metric Store Dashboards

The platform now ships a built-in "Universal Metric Store" dashboard that provides out-of-the-box visibility into production and simulation metrics without any configuration.

What changed:

  • New built-in metrics dashboard - A new default dashboard titled "Universal Metric Store" is now available in the metrics page context. It includes six panels covering metric store summary statistics, a heatmap of numerical and boolean metric intensity over time, metric type distribution, value volume broken down by source and scope, a staleness table showing the least-recently-computed metrics, and a detailed table of recent entity-scoped metric values.

  • Dashboard filters - The metrics dashboard supports four filters: a date-range window (7d, 30d, 90d, 1y), a source selector (production, simulation, or all), a scope selector (all, workspace aggregate, or entity scoped), and a metric type selector (all, numerical, categorical, or boolean). Filters apply across all panels.

  • Freshness tracking - The staleness panel shows each metric's last computation time, latest period end, total value count, and minutes since last computation, ordered by stalest first. This helps teams identify metrics that may have stopped updating.

  • Entity-scoped detail - The entity-scoped values table shows the most recent metric values broken down by entity, including source, entity type, entity ID, service, run, session, display value, event count, and period end. This gives operators visibility into per-entity metric behavior.

  • Expanded data catalog access - Dashboard templates can now query metric value and freshness data from registered data catalogs, enabling the new metrics panels to render automatically once the workspace has metric data ingested.

  • Immutable built-in dashboard references - Built-in dashboard templates are now returned as independent copies when listed or retrieved by ID or slug. This prevents unintended mutation of shared template state when dashboards are customized per-request.

No API contract changes. The new dashboard appears automatically for all workspaces. Dashboard slug: metrics-overview.

chevron-rightv0.9.220 - Platform API: Expanded Data Access for Dashboard Templates (June 2026)hashtag

Expanded Data Access for Dashboard Templates

The platform API now has access to additional data catalogs used by built-in dashboard templates, enabling richer operational insights out of the box.

What changed:

  • Dashboard templates can query entity data from additional catalogs - Built-in dashboard templates now read entity data from a broader set of data sources. Previously, dashboards were limited to analytics, clinical, and core entity data. Dashboard templates can now also query entity records from registered data catalogs, enabling richer cross-catalog visualizations without requiring customers to configure additional data access.

  • Schema-level access controls - Data access grants are now scoped to specific schemas within each catalog rather than defaulting to a single schema. This provides more precise access control and supports catalogs that organize data across multiple schemas.

No API contract changes. Dashboard templates that depend on cross-catalog entity data will render automatically once the workspace has the relevant data ingested.

chevron-rightv0.9.219 - Platform API: Hardened Workspace Invitation Acceptance (June 2026)hashtag

Hardened Workspace Invitation Acceptance

The workspace invitation acceptance flow is now more resilient to concurrent requests and edge cases, with clearer error messages and expanded audit logging.

What changed:

  • Atomic invitation acceptance - Accepting a workspace invitation now uses an atomic state transition that prevents race conditions when multiple requests attempt to accept the same invitation simultaneously. Previously, concurrent acceptance requests could result in duplicate memberships or inconsistent invitation state.

  • Idempotent acceptance - If a user accepts an invitation they have already accepted, the endpoint returns the existing membership rather than failing. This prevents errors when clients retry acceptance requests.

  • Improved conflict handling - If an invitation was already accepted by a different account, the endpoint now returns a specific error message ("That invitation was already accepted by another account") instead of a generic "no longer active" message.

  • Race condition recovery - When concurrent requests cause a conflict during membership creation, the system automatically recovers by detecting and returning the membership created by the winning request, rather than failing with an internal error.

  • Stricter re-invitation logic - Re-sending a workspace invitation now only updates an existing invitation if it is still pending and not expired. Previously, expired or already-accepted invitations could be inadvertently reactivated.

  • Expanded audit logging - Invitation acceptance now emits detailed audit events covering idempotent accepts, race condition recoveries, denial reasons, and membership activation failures. These events appear in the workspace audit log with structured metadata describing the outcome.

chevron-rightv0.9.218 - Platform API: Data Browser Resource Label Polish (June 2026)hashtag

Data Browser Resource Label Polish

The built-in data browser dashboard now uses clearer, more descriptive labels for resources and specialties.

What changed:

  • Resource capacity chart renamed - The "Provider capacity" chart in the data browser dashboard is now titled "Resource capacity" and displays resources by type (provider, facility, or unassigned availability) rather than only by provider name. Resources without a named provider now show facility names or a descriptive "Unassigned availability" label instead of "Unknown".

  • Specialty labels improved - The facility bottleneck table now shows "Unspecified specialty" instead of "Unknown" for slots that do not have a specialty assigned, making it clearer that the data is missing rather than unrecognized.

chevron-rightv0.9.217 - Platform API: Data Browser Dashboard Improvements and Entity Graph Response (June 2026)hashtag

Data Browser Dashboard Improvements and Entity Graph Response

The built-in data browser dashboard now queries slot data directly from the world model instead of pre-aggregated views, and the entity intelligence graph endpoint returns a richer response shape that supports full graph visualization.

What changed:

  • Dashboard queries use live entity data - The data browser insights dashboard (availability summary, heatmap, facility map, provider capacity, and bottleneck table) now queries slot entities directly from the world model rather than relying on pre-aggregated analytical views. This means dashboard results reflect the latest ingested data without waiting for analytical pipeline refreshes. Filter behavior (time window, slot status) is unchanged.

  • Entity graph response includes full node list - The entity intelligence graph endpoint now returns a nodes array containing all entities in the graph (the center entity and all connected neighbors), plus an entity_id field identifying the center entity. Each node includes id, entity_type, and display_name. This replaces the previous response shape where neighbor metadata was embedded inside each edge, making it easier for clients to render graph visualizations where nodes and edges are separate concepts.

  • Edge format updated - Each edge in the graph response now includes source and target fields (entity IDs as strings) and a relationship field, instead of the previous type and nested target object. The confidence, match_reason, and created_at fields remain unchanged.

Updated entity graph response shape:

Field
Type
Description

entity

object

Center entity with id, entity_type, display_name

entity_id

string

ID of the center entity

nodes

array

All entities in the graph (center + neighbors)

edges

array

Relationships between entities

total_edges

number

Total number of edges returned

Node object:

Field
Type
Description

id

string

Entity ID

entity_type

string

Type of entity

display_name

string or null

Human-readable name

Edge object (updated):

Field
Type
Description

source

string

Source entity ID

target

string

Target entity ID

relationship

string

Relationship type

confidence

number

Match confidence score

match_reason

string or null

Reason for the relationship

created_at

string or null

ISO 8601 timestamp

  • Dashboard theming uses design tokens - The embedded dashboard components now use CSS custom property design tokens (with sensible fallbacks) instead of hardcoded color values. Dashboards embedded in host applications that define standard design tokens (e.g., --foreground, --border, --primary) will automatically match the host theme.

chevron-rightv0.9.216 - Platform API: Call Playback Timeline Endpoint (June 2026)hashtag

Call Playback Timeline Endpoint

A new endpoint exposes the playback timeline for a call directly, without requiring clients to fetch the full call detail response.

What changed:

  • New GET /calls/{call_id}/timeline endpoint - Returns the canonical playback timeline for a call, including conversation turns, segments, and total duration. This is the same timeline model available within the call detail response, exposed as a standalone resource for clients that only need timeline data - such as playback visualizations or timeline-only UI components.

  • Shared call resolution - The timeline endpoint uses the same call resolution logic as the existing call detail endpoint, checking live calls, simulation sessions, and stored call data in sequence. Tenant isolation rules apply identically.

Detail
Value

Method

GET

Path

/calls/{call_id}/timeline

Response model

PlaybackTimeline

Auth

Workspace-scoped, read access required

Rate limited

Yes

The PlaybackTimeline response includes:

Field
Type
Description

turns

array

Conversation turns in chronological order

segments

array

Timeline segments for playback visualization

duration_seconds

number

Total call duration in seconds

If the call exists but has no timeline data, the endpoint returns an empty timeline with the call's duration.

chevron-rightv0.9.215 - Platform API: Dashboard-Backed Browser Insights and Location Enrichment (June 2026)hashtag

Dashboard-Backed Browser Insights and Location Enrichment

The platform now ships built-in operational dashboards for the data browser and enriches location entities with structured address and geographic fields. These changes give teams immediate visibility into provider availability, facility capacity, and slot distribution without creating custom dashboards.

What changed:

  • Built-in data browser dashboard - A new "Data Browser Insights" dashboard is available automatically on the data page context. It includes an availability summary (total slots, active providers, active facilities, next available slot), a slot availability heatmap by day and hour, a geographic facility availability map, a provider capacity bar chart, and a facility/specialty bottleneck table. The dashboard uses parameterized filters for time window and slot status, and refreshes every five minutes.

  • New data page context - The dashboard listing endpoint now accepts data as a valid page context, alongside the existing contexts (home, patients, calls, analytics, pipeline, operators). Dashboards scoped to the data context appear in the data browser section of the Developer Console.

  • Built-in dashboard fallback - When listing or fetching dashboards, the platform now returns built-in template dashboards alongside workspace-specific ones. If a workspace has not customized a built-in dashboard, the template version is returned. Workspace-specific dashboards with the same slug take precedence over built-in templates.

  • Enriched location entity fields - The FHIR Location view now includes structured address components and geographic coordinates:

Field
Type
Description

address_line

string

Street address line

city

string

City

state

string

State or province

postal_code

string

Postal or ZIP code

country

string

Country code

latitude

number

Geographic latitude

longitude

number

Geographic longitude

timezone

string

IANA timezone identifier

facility_id

string

Associated facility identifier

All new fields are optional and nullable. The existing address object field is retained for backward compatibility.

  • Trace encoding for dashboard charts - Dashboard chart definitions now support a declarative encoding property on Plotly traces. Instead of pre-populating axis arrays, traces can reference query result columns by name (e.g., {"x": "hour_label", "y": "day_name", "z": "slot_count"}). The charting layer maps query results into the appropriate Plotly data structures at render time, including heatmap matrix construction, geographic coordinates, marker color/size, and custom hover data.

  • Panel row limits - Dashboard panel definitions now support a max_rows property that caps the number of query result rows sent to the chart. This prevents large result sets from degrading chart rendering performance.

  • Slot availability data pipeline - The analytics pipeline now processes slot availability data from FHIR Slot resources, extracting provider, facility, specialty, and schedule information. A pre-aggregated availability heatmap provides slot counts grouped by day, hour, facility, provider, and specialty - optimized for the dashboard queries described above.

chevron-rightv0.9.214 - Platform API: Stable Entity Timeline Event Identifiers (June 2026)hashtag

Stable Entity Timeline Event Identifiers

Entity event timeline entries now use deterministic, content-derived identifiers instead of source-assigned ones. This means the same event always produces the same identifier regardless of when or how many times it is processed, eliminating duplicate entries and ensuring consistent references across sync cycles.

What changed:

  • Deterministic event identifiers - Timeline event identifiers are now derived from the event's content - including workspace, entity, domain, event type, resource references, source, timestamps, and data payload. Two processing runs over the same source data produce identical identifiers, so downstream consumers can safely deduplicate and cache timeline entries.

  • Workspace-scoped deduplication - The pipeline now removes duplicate timeline events within each workspace before persisting results. Combined with deterministic identifiers, this prevents the same event from appearing multiple times in an entity's timeline.

  • Resilient sync lock release - The observability sync pipeline now handles connection interruptions during lock release gracefully. If the connection is closed before the lock can be explicitly released, the platform logs a warning and continues rather than raising an error. The lock is automatically released on disconnect, so no manual intervention is required.

These changes improve data consistency for entity event timelines and reduce duplicate entries for workspaces with frequent sync cycles. No API contract changes - these are backend data integrity improvements.

chevron-rightv0.9.213 - Platform API: Observability Timeline Source Quality Validation (June 2026)hashtag

Observability Timeline Source Quality Validation

The observability data sync pipeline now validates the quality of entity event timeline sources before syncing data to the platform's operational store. This prevents corrupted or malformed source data from propagating into resolved entity timelines.

What changed:

  • Source quality validation - Before syncing entity event timeline data, the pipeline now checks the source for invalid identifiers and duplicate records. If the primary source fails validation, the pipeline automatically falls back to an alternative source. If no valid source is available, the sync fails with a clear error rather than ingesting bad data.

  • Adaptive page sizing - Timeline data pagination now automatically reduces page size when a page exceeds the data platform's inline result byte limit. This prevents large pages from causing sync failures, particularly for workspaces with dense event timelines. Pages shrink progressively until results fit within platform constraints.

These changes improve data integrity for entity event timelines and reduce sync failures for workspaces with large or complex event histories. No API contract changes - these are backend reliability improvements.

chevron-rightv0.9.212 - Platform API: Canonical Call Playback Timeline Contract (June 2026)hashtag

Canonical Call Playback Timeline Contract

The call detail response now includes a fully normalized playback timeline with a canonical timebase, lane model, and ordered segments. This gives frontend clients a single, stable contract for rendering call timelines instead of reconstructing layout from raw turn data.

What changed:

  • Canonical timebase - The playback timeline now includes a timebase object that defines the zero point, unit (always seconds), and visible time range. All segment offsets are relative to this shared timebase, so waveform overlays, seek state, zoom, and scroll transforms share consistent coordinates.

  • Lane model - The timeline introduces a lanes array that defines the canonical set of actor and system lanes. Each lane has a stable id, a display label, a high-level track for styling and grouping, a vertical order, and an optional actor. Segments reference lanes by lane_id rather than inferring layout from segment type.

  • Segment normalization - Every segment now carries a canonical lane_id, a stable order within the timeline, and normalized start/end offsets rounded to millisecond precision. When duration_ms is not provided, it is computed from the segment interval. Segments are sorted by start time, track, lane, and order for deterministic rendering.

  • Automatic timeline construction - When a call detail response includes turns but no pre-built timeline, the platform now constructs the playback timeline automatically from turn data, barge-in events, and call duration. This ensures every call detail response includes a renderable timeline.

  • New segment fields - Timeline segments now support call_id, parent_call_id, integration_name, endpoint_name, and protocol fields for richer tool call attribution.

  • Lane derivation - When no lanes are provided, the platform derives them from the segment data. Lanes are ordered by track priority (caller, agent, operator, tool, system) and then by first appearance. Tool lanes are further distinguished by integration and endpoint names.

New response fields on PlaybackTimeline:

Field
Type
Description

timebase

object

Canonical timebase with unit, origin, start, and end

lanes

array

Ordered lane definitions with id, track, label, order, and optional actor

New fields on TimelineSegment:

Field
Type
Description

lane_id

string

Canonical lane id matching a lane in the lanes array

order

integer

Stable event order after normalization

call_id

string

Call identifier for tool call segments

parent_call_id

string

Parent call identifier for nested tool calls

integration_name

string

Integration name for tool call segments

endpoint_name

string

Endpoint name for tool call segments

protocol

string

Protocol used for tool call segments

New types:

Type
Description

TimelineLaneDefinition

Lane definition with id, track, label, order, and optional actor

TimelineTimebase

Timebase definition with unit, origin, start, and end

Backward compatibility - All new fields have defaults. Existing clients that consume PlaybackTimeline without reading timebase or lanes continue to work. The segments array now includes lane_id and order on every segment, but these are additive fields. The StateTransition model now also accepts from_state/to_state as input aliases for previous_state/next_state.

chevron-rightv0.9.211 - Platform API: Resolved Entity Timelines and Entity Sync Improvements (June 2026)hashtag

Resolved Entity Timelines

Entity event timelines now use fully resolved event data instead of raw ingestion data. Timelines reflect the platform's best understanding of each entity - after entity linking, deduplication, and confidence scoring - rather than unprocessed events.

What changed:

  • Resolved timeline source - Entity timelines are now built from resolved events with entity IDs filled from entity resolution signals. This means timeline entries show accurate entity associations and deduplicated event data.

  • Automatic fallback - If the resolved timeline source is temporarily unavailable (for example, during initial provisioning of a new workspace), the platform falls back to the legacy timeline source automatically. A warning is logged but the API response is unaffected.

  • 90-day window - Timelines include events from the most recent 90 days, with up to 200 events per entity. Events are ordered by effective time (most recent first), with ingestion time as a tiebreaker.

  • Entity sync improvements - The entity sync process now updates existing entities in place before attempting inserts, reducing duplicate processing and improving sync throughput for workspaces with high entity volumes.

Backward compatibility - Timeline API responses use the same schema as before. The change affects data freshness and accuracy, not response shape. No client changes are required.

chevron-rightv0.9.210 - Platform API: Call Metric Values and On-Demand Metric Evaluation (June 2026)hashtag

Call Metric Values and On-Demand Metric Evaluation

Two new capabilities for the Universal Metric Store: per-call metric retrieval from the call detail sidebar and on-demand metric evaluation without persisting results.

New endpoint: List call metric values

GET /calls/{call_id}/metrics

Returns the latest per-call metric values for a specific call. This powers the call detail sidebar in the Developer Console and is useful for inspecting metric results tied to a single conversation.

Parameter
Type
Default
Description

limit

integer

100

Max metric values to return (1-100)

The response uses the same MetricListResponse shape as other metric endpoints.

The call identifier can be a conversation UUID, a telephony call SID, or a simulation session ID. The endpoint matches against both entity and session identifiers stored in the metric store.

New endpoint: Evaluate a metric on demand

POST /metrics/{metric_key}/evaluate

Executes a single metric definition against a specific call without writing results to the metric store. This is intended for previewing metric behavior during development and debugging - production metric values continue to come exclusively from the metrics pipeline.

Request body:

Field
Type
Required
Description

subject_id

string

Yes

Call SID, call UUID, or simulation session ID

as_of

datetime

No

Point-in-time cutoff for selecting the call intelligence snapshot

persist

false

No

Always false - on-demand evaluation never writes to the metric store

Response:

Field
Type
Description

metric

MetricValueResponse

The evaluated metric value

persisted

false

Always false

evaluated_at

datetime

When the evaluation was performed

On-demand evaluation currently supports AI query metrics over call intelligence data. Other extraction modes return a 422 error.

Error responses:

Status
Condition

404

Metric definition not found, or call intelligence data not available for the subject

422

Metric type does not support on-demand evaluation

429

Rate limited

502

Metric evaluation query failed

503

Analytics warehouse not configured for this environment

Recording fix - Call detail recording retrieval now correctly resolves the conversation identity when persisting recording metadata, fixing cases where recordings could fail to associate with their call.

Backward compatibility - All changes are additive. Existing metric endpoints and responses are unchanged.

chevron-rightv0.9.209 - Platform API: Universal Metric Scope Contract (June 2026)hashtag

Universal Metric Scope Contract

Metric query endpoints now accept an entity_type filter parameter alongside the existing entity_id, service_id, run_id, and session_id filters. This lets you query metrics for a specific entity type (e.g. all call-level metrics) without knowing individual entity identifiers.

New query parameter on all metric endpoints (GET /metrics, GET /metrics/{metric_key}, GET /metrics/{metric_key}/trend):

Parameter
Type
Default
Description

entity_type

string

-

Filter to metrics for a specific entity type (e.g. workspace, call)

Scope resolution improvements - When any scope identifier (entity_type, entity_id, service_id, run_id, or session_id) is provided, the API now returns matching rows directly instead of falling back to the default aggregate-only filter. This means simulation queries that specify a run_id or session_id no longer need to also set scope=entity to see per-entity results.

Data quality enforcement - The metric pipeline now enforces stricter validation rules on metric scope fields:

  • The source field must be production or simulation. Rows with other values are dropped during pipeline processing.

  • Every metric row must carry a non-empty entity_type.

  • Workspace-scoped rows (where entity_type is workspace) must have an empty entity_id. Per-entity rows must have a non-empty entity_id.

These rules are enforced at the pipeline level. API consumers do not need to change anything - invalid rows are filtered before they reach the metric store.

MCP tool description updates - The get_metrics MCP tool now explicitly documents that it returns production workspace-aggregate metrics by default. Use the metrics API directly for simulation or entity/run/session-scoped reads.

Backward compatibility - All new parameters are optional. Existing integrations that do not pass entity_type continue to work identically. The default source=production and scope=aggregate behavior is unchanged.

chevron-rightv0.9.208 - Platform API: World Read Model Boundary Hardening (June 2026)hashtag

World Read Model Boundary Hardening

Event velocity and pipeline status endpoints now return null instead of 0 when the underlying read model is empty or unavailable. This makes it possible to distinguish between "no data has been synced yet" and "the read model is synced and reports zero events."

Affected response fields:

Endpoint
Field
Previous Default
New Default

Pipeline status

total_events

0

null

World dashboard

events_24h

0

null

World dashboard

events_7d

null

null

All three fields are now typed as integer or null. A null value means the read model has not synced or is temporarily unavailable. A zero value means the read model is ready and contains no matching events.

The event_read_model_status field on both endpoints continues to report the underlying state (empty, ready, or unavailable), so callers can distinguish between the three conditions programmatically.

Backward compatibility - Callers that treat null and zero equivalently require no changes. Callers that display event counts should handle null values explicitly - for example, by showing a "not yet available" indicator instead of "0".

Entity appointment resolution - The world model pipeline now scopes appointment participant display resolution by workspace, preventing cross-workspace data from appearing in entity snapshots. This fix is internal to the data pipeline and does not change any API request or response shapes.

chevron-rightv0.9.207 - Platform API: Entity and Simulation Scoped Metrics (June 2026)hashtag

Entity and Simulation Scoped Metrics

Metric values are now scoped by source and entity, enabling independent tracking of production and simulation metrics and drill-down from workspace-level aggregates to individual call or session scores.

Source scoping - Every metric value is now tagged as either production or simulation. Simulation runs generate their own metric values that are stored separately from production data. When querying metrics, use the source parameter (production, simulation, or all) to control which values are returned. The default is production, so existing integrations see no change.

Entity scoping - Metric values can now be stored at two levels: workspace-level aggregates and per-entity (per-call or per-session) values. Use the scope parameter (aggregate, entity, or all) to control which level is returned. The default is aggregate, preserving existing behavior.

New query parameters on all metric endpoints (GET /metrics, GET /metrics/{metric_key}, GET /metrics/{metric_key}/trend):

Parameter
Type
Default
Description

source

string

production

Filter by metric source: production, simulation, or all

scope

string

aggregate

Filter by entity scope: aggregate, entity, or all

entity_id

string

-

Filter to a specific entity

service_id

string

-

Filter to metrics from a specific service

run_id

string

-

Filter to a specific simulation run

session_id

string

-

Filter to a specific session

New response fields on all metric value objects:

Field
Type
Description

source

string

production or simulation

entity_type

string or null

Entity type (e.g. workspace, call)

entity_id

string or null

Entity identifier, null for aggregate rows

service_id

string or null

Service that produced the metric value

run_id

string or null

Simulation run identifier

session_id

string or null

Session identifier

Simulation call intelligence - Simulation sessions now emit call intelligence events through the same pipeline as production calls. This means simulation conversations are scored by all configured metrics - quality scores, completion rates, custom metrics - producing per-session metric values that can be queried by run_id or session_id.

Backward compatibility - All new parameters have defaults that preserve existing behavior. Callers that do not pass source or scope receive production aggregate metrics, exactly as before.

chevron-rightv0.9.206 - Platform API: External User Login via Invitations and Workspace Isolation Hardening (June 2026)hashtag

External User Login via Workspace Invitations

Users who have been invited to a workspace but do not belong to an auto-provisioning domain can now log in through Google OAuth and receive a bootstrap token. Previously, users whose email domain was not covered by an auto-provisioning policy were rejected at login even if a workspace admin had already sent them an invitation.

The login flow now checks for pending workspace invitations after auto-provisioning is attempted. If one or more pending invitations exist for the user's verified email address, a federation identity is created and a bootstrap token is issued. The bootstrap token carries no workspace scopes - the user must accept a specific invitation through the Developer Console before receiving a workspace-scoped token.

This is idempotent: if the user already has a federation identity from a previous login, the existing identity is reused.

Invitation Email Notifications

Workspace admins who create or resend an invitation now trigger an email notification to the invited user. The email includes the workspace name, assigned role, and an accept link that directs the user to the Developer Console. Email delivery is asynchronous and fail-open - if delivery fails, the invitation is still created and the invite link is returned to the admin for manual sharing.

Email notifications require two environment-level configuration values: a sender email address and the console base URL. When the sender email is not configured, email delivery is disabled and invitations work as before (link returned to admin only).

Workspace Isolation Hardening

  • Audit log access - Non-admin callers querying the audit log are now restricted to their own workspace. Previously, callers with the audit:read scope could query audit entries across workspaces if they supplied a different workspace ID. Admin-scoped callers retain cross-workspace access.

  • Member info credential filtering - The workspace member info endpoint now returns only credentials that belong to the queried workspace. Previously, credentials from other workspaces could appear in member info responses if the underlying identity had memberships in multiple workspaces.

  • Invitation listing - The pending invitations endpoint now uses a cross-workspace lookup scoped to the caller's verified email, consistent with the bootstrap login flow. Workspace-admin list endpoints continue to use workspace-scoped queries.

chevron-rightv0.9.205 - Platform API: World Event Read Models for Faster API Reads (June 2026)hashtag

World Event Read Models

API endpoints that previously queried the analytical data warehouse on every request now read from pre-computed serving tables that are continuously refreshed by the data platform. This change affects several areas of the Platform API:

  • Entity event timelines - The entity timeline endpoint, trigger execution history, and webhook delivery history now read from a bounded, pre-materialized timeline instead of querying the full event ledger. Timeline results are limited to the most recent 200 events per entity within a 90-day window, ordered by effective time.

  • Event type registry - The event type summary endpoint returns pre-aggregated counts, domains, and sources per event type. Previously, each request scanned the event ledger to compute these aggregates.

  • Enrichment audit trail - The enrichment history endpoint for a given entity and enrichment key now reads from the pre-materialized timeline, filtering to entity.enriched events for the requested key.

  • Review queue diffs - The review diff endpoint now reads from pre-computed correction pairs that link original events to their correcting replacements. Previously, the endpoint issued multiple analytical queries to locate superseding events. Diff results include original and corrected event types, data payloads, confidence scores, review statuses, and timestamps.

  • Sensorium loop latency - The loop latency endpoint now reads from pre-computed sense-to-act pairs with per-hour aggregation computed at query time against the serving table. The truncated field in the response is now always false since the serving table contains all matched pairs rather than a row-limited sample.

These changes improve response times for read-heavy API paths and eliminate direct dependencies on the analytical query engine for request-path reads. Write paths (event ingestion, entity updates) are unchanged.

chevron-rightv0.9.204 - Platform API: Appointment Participant Resolution and Slot Location Matching (June 2026)hashtag

Appointment Participant Display Resolution

Appointment entities now resolve display names for all three participant roles - patient, practitioner, and location - by cross-referencing related entities in the world model. Previously, only the patient display name was resolved from linked entities; practitioner and location names relied solely on raw data from the connected EHR. If the EHR payload omitted those names, appointments appeared with blank participant labels.

The resolution now works for all three roles:

  • Patient display - resolved from the linked patient entity when the appointment data does not include a patient name (existing behavior, now improved).

  • Practitioner display - resolved from the linked practitioner entity when the appointment data does not include a practitioner name.

  • Location display - resolved from the linked location entity when the appointment data does not include a location name.

Resolution uses both direct entity references and source-system-specific identifiers, so appointments ingested from different connector types (voice-agent-created vs. EHR-synced) are handled correctly.

If the appointment already contains a non-empty display name for a participant, that value is preserved. Resolution only fills in missing or blank values.

Improved Appointment Patient Lookup

The appointment_lookup tool now matches patient references across multiple identifier formats. Previously, looking up appointments for a patient required an exact match on a single reference format. Appointments ingested through different paths (EHR connectors vs. voice agent) could use different reference formats for the same patient, causing some appointments to be missed.

The tool now automatically resolves the patient entity to all known reference formats and matches against any of them, ensuring complete appointment results regardless of how the appointment was originally created.

Slot Search Location Matching

Slot search now matches locations using both the facility identifier on the slot and the schedule-based resolution path. Previously, location filtering relied solely on schedule references, which not all EHR systems populate. Slots that carry a direct facility identifier are now matched immediately, with schedule-based resolution as a fallback. This improves slot availability accuracy for workspaces where slots include facility identifiers.

chevron-rightv0.9.203 - Platform API: Improved Scheduling Data Fidelity (June 2026)hashtag

Improved Patient Scheduling Data Fidelity

The EHR data normalization pipeline and FHIR projection layer now handle a broader range of field naming variations from connected EHR systems, improving accuracy for appointment, patient, slot, and practitioner records. This update primarily affects workspaces connected to Charm-based EHR systems but applies to any connector that produces similar field variations.

Appointments:

  • Appointment start/end times now resolve correctly when the EHR returns datetime values under alternative field names. Previously, some list-vs-detail response variations caused appointment times to be missing or malformed.

  • Appointment participant references (patient, practitioner, location) are now projected into the FHIR Appointment resource from structured entity fields, ensuring participant data appears even when not embedded in the raw EHR payload.

  • Appointment reason, cancellation reason, modality, and duration are now resolved from additional field name variants, reducing data gaps.

  • The FHIR projection now includes description and cancelationReason fields on Appointment resources when the underlying data is available.

Patients:

  • Patient address, phone, and email fields are now resolved from nested contact detail structures in addition to top-level fields. Practices that store contact information in a grouped structure no longer see missing phone numbers or addresses.

  • The patient active status now recognizes additional truthy values (yes, 1) beyond the previous true-only check.

  • Patient address data stored in structured entity columns is now projected into the FHIR Patient resource, providing address information even when demographic state has not yet been populated.

  • The patient list endpoint now uses improved practitioner-vs-patient classification. Practitioners are more reliably excluded from patient list results, preventing provider records from appearing as patients in multi-entity workspaces.

Slots:

  • Slot FHIR projections now include provider name, provider ID, facility ID, specialty, and allowed visit type information as extensions, giving downstream consumers richer context for availability display and scheduling decisions.

  • Visit type names and IDs on slots are projected into both serviceType and structured extensions, supporting both simple and detailed slot rendering.

Practitioners:

  • Practitioner phone resolution now checks additional field name variants, reducing missing contact information.

  • Licensed state lists that arrive as structured objects (with state codes or names) are now normalized correctly, in addition to the existing CSV and flat-list formats.

  • Practitioner records now include an EHR-specific member identifier when available, projected as an additional identifier on the FHIR Practitioner resource.

Patient lookup:

  • Patient search by date of birth now matches against both structured entity fields and legacy demographic state, improving recall for workspaces with mixed data vintages.

Appointment lookup:

  • The appointment_lookup tool now supports filtering by date (YYYY-MM-DD format) in addition to the existing status filter.

  • The patient parameter is now accepted as an alias for patient_entity_id for consistency with other tool interfaces.

Slot search results:

  • Slot search results now include provider_id, location_id, and template_id fields when available, giving agents and downstream tools the identifiers needed to book appointments without additional lookups.

  • Appointment type names are now always included in slot results when available, regardless of whether a template ID was resolved.

Insurance tools:

  • The insurance_create tool now accepts payer_name as an alias for carrier_name, practice_payer_id for specifying the practice-specific payer identifier, policyholder_name and policyholder_dob for simplified policyholder specification, and policyholder_relationship as an alias for the relationship parameter.

  • The carrier_name field is no longer strictly required in the tool schema when payer_name is provided instead. At least one of the two must be present.

  • Policyholder information is now recorded for all relationships (including "self"), not only for non-self relationships.

Patient create/update tools:

  • The patient_create, patient_update, and save_patient tools now accept zip_code as an alias for postal_code, matching the terminology callers and agents commonly use.

World model entity fields:

The world model entity schema has been expanded with additional structured fields for patients, appointments, locations, slots, and practitioners. These fields support richer FHIR projections and more accurate tool behavior without requiring data to be extracted from unstructured state blobs. Key additions include:

Category
New Fields

Patient

Address components, marital status, preferred language, race, ethnicity, emergency contact, primary insurance details

Appointment

Participant references and display names, modality, duration, timezone, provider credentials, series and encounter IDs, cancel/visit reason

Location

Address components, coordinates, timezone, facility ID

Slot

Practitioner display/ID, facility ID, specialty, visit type IDs and names

Practitioner

EHR member ID

chevron-rightv0.9.202 - Platform API: Soft-Delete for Channel Identities (June 2026)hashtag

Soft-Delete for Channel Identities

Deleting a use case or communication setup now performs a soft-delete instead of a hard delete. Deleted records are retained for audit trail purposes, and all list and detail responses include a deleted_at timestamp field indicating when the resource was removed. Historical references from sent emails and voicemails remain intact.

Use cases (DELETE /use-case/{id}):

  • The use case and its channel binding are marked as deleted rather than permanently removed.

  • External resources (configuration sets, tenant associations) are still torn down at delete time - soft-delete preserves the database record, not the external resource.

  • Re-deleting an already-deleted use case returns 404.

  • A deleted use case's name becomes available for reuse under the same entity.

Communication setups (DELETE /ses-setup/{id}):

  • The setup is marked as deleted rather than permanently removed.

  • External identities and tenants are still torn down at delete time.

  • Only live (non-deleted) use case bindings block setup deletion. Previously deleted bindings no longer prevent cleanup.

  • Re-deleting an already-deleted setup returns 404.

List endpoints (GET /use-case, GET /ses-setup):

  • A new include_deleted query parameter (default false) controls whether soft-deleted records appear in list results.

  • When include_deleted=true, deleted items appear alongside live items with their deleted_at field populated.

Detail endpoint (GET /ses-setup/{id}):

  • Returns both live and deleted setups. Deleted setups include deleted_at in the response.

  • For deleted setups, the live DNS verification refresh is skipped since the external identity has been removed. The dns_records[].verified flags reflect the last cached state before deletion.

New response fields:

Endpoint
Field
Type
Description

GET /use-case

deleted_at

datetime or null

Soft-delete timestamp. null for live use cases.

GET /ses-setup

deleted_at

datetime or null

Soft-delete timestamp. null for live setups.

GET /ses-setup/{id}

deleted_at

datetime or null

Soft-delete timestamp. null for live setups.

New query parameters:

Endpoint
Parameter
Type
Default
Description

GET /use-case

include_deleted

boolean

false

Include soft-deleted use cases in the response.

GET /ses-setup

include_deleted

boolean

false

Include soft-deleted setups in the response.

All action endpoints (send-email, send-ringless-voicemail, select-phone-number, assign-phone-number, provision-phone-number) now return 404 for deleted use cases, consistent with the resource no longer being active.

Paginated Voicemail Listing

The GET /ringless-voicemail endpoint now supports cursor-based pagination and requires at least one scoping filter.

Breaking changes:

  • At least one of use_case_id or setup_id is now required. Requests without either return a validation error.

  • The status query parameter now uses set semantics - duplicate values are collapsed.

New query parameters:

Parameter
Type
Default
Description

limit

integer (1-200)

50

Maximum number of voicemails to return.

continuation_token

string

null

Opaque token from a prior response to fetch the next page.

New response fields:

Field
Type
Description

has_more

boolean

Whether additional pages of results exist.

continuation_token

string or null

Opaque token to pass on the next request. null when no more results.

Results are ordered by creation time (newest first) with stable pagination across concurrent inserts.

chevron-rightv0.9.201 - Platform API: Typed Metric Values (June 2026)hashtag

Typed Metric Values

Metric value responses now return strongly typed value fields based on the metric type, instead of returning all values as untyped data. The metric_type field acts as a discriminator that determines the shape of value:

Metric Type

value Type

numerical

number or null

categorical

string or null

boolean

boolean or null

The period_start, period_end, and computed_at fields are now returned as ISO 8601 datetime strings with consistent formatting.

This applies to all metric value endpoints: list metrics, get metric, and get metric trend. Existing integrations that treated value as an opaque field continue to work. Integrations that parse value can now use metric_type to determine the expected type without inspecting the value itself.

chevron-rightv0.9.200 - Platform API: Read Model Status on Dashboard and Pipeline Endpoints (June 2026)hashtag

Read Model Status on Dashboard and Pipeline Endpoints

The world dashboard, pipeline status, and connector health endpoints now include read model status fields that indicate the freshness and availability of the underlying data projections.

World dashboard (GET /world/dashboard):

The response is now a structured object with explicit fields. Two new fields indicate whether the event velocity summary is current:

Field
Type
Description

event_read_model_status

string

ready, empty, or unavailable

event_read_model_synced_at

datetime or null

Timestamp of the last successful data projection sync

Pipeline status (GET /pipeline/status):

Two new fields on the pipeline status response:

Field
Type
Description

event_read_model_status

string

ready, empty, or unavailable

event_read_model_synced_at

datetime or null

Timestamp of the last successful data projection sync

Connector health (GET /sensorium/connector-health):

Two new fields on the connector health response:

Field
Type
Description

read_model_status

string

ready, empty, or unavailable

read_model_synced_at

datetime or null

Most recent sync timestamp across sources in the response

Status values:

  • ready - Data projection returned current data

  • empty - No summary data available yet for this workspace

  • unavailable - The data projection could not be read (transient error)

These fields let clients distinguish between "no data exists yet" and "data exists but the projection is temporarily unreachable," enabling appropriate UI treatment (e.g., showing a stale-data indicator rather than zero counts).

chevron-rightv0.9.199 - Platform API: Aligned Builtin Tool Validation for Context Graphs (June 2026)hashtag

Aligned Builtin Tool Validation for Context Graphs

Context graph validation now recognizes the full set of builtin tools available at runtime, including clinical documentation tools (polish_note, prepare_orders, learn_style) and all surface, voice system, and platform function tools. Previously, saving a context graph that referenced certain builtin tools could produce spurious validation warnings indicating the tool required a skill, even though the tool is provided by the platform automatically.

Additionally, platform function tools (tools with the fn_ prefix) are now recognized during validation without requiring a skill binding. The fn_ namespace is reserved for platform functions that are discovered dynamically at runtime, so context graphs can reference any fn_-prefixed tool without a corresponding skill.

No API changes. Graphs that previously triggered false warnings will now validate cleanly.

chevron-rightv0.9.198 - Platform API: Email Channel - Send, Track, and Query Emails (June 2026)hashtag

Email Channel - Send, Track, and Query Emails

The Platform API now supports sending emails through configured email use cases, with full delivery and engagement tracking. Emails are sent through the email channel infrastructure provisioned via use case creation, and delivery events (delivery confirmations, bounces, complaints, opens, clicks) are tracked automatically.

New endpoints:

Emails (/v1/{workspace_id}/email)

Method
Path
Description

POST

/email/send

Send an email

GET

/email

List emails with filters

GET

/email/event

List email delivery and engagement events

GET

/email/{email_id}

Get full email detail

GET

/email/{email_id}/body

Get the HTML body of an email

GET

/email/{email_id}/attachment/{filename}

Download an email attachment

Send email - Send an email via multipart form data. Fields: use_case_id (UUID), to_address (email address), subject (1-998 characters), body_html (HTML content, max 1 MB), and optional attachments (up to 5 files, max 5 MB each). Attachment filenames must be unique within a single send and conform to safe filename rules (no path separators, reserved names, or control characters). The total assembled message must not exceed 39 MB. Returns the email id, message_id (the provider-assigned correlation key), sent_at timestamp, and attachment_filenames. Requires Channel.send permission.

The email use case's domain must have verified DNS before sending. If DNS is not verified, the endpoint returns 409 Conflict with guidance to publish the required records.

List emails - List emails scoped to a use case and/or email setup. At least one of use_case_id or setup_id is required. Optional filters: to_address (repeatable, any match), sent_after (inclusive), sent_before (exclusive), state (repeatable, any match). States are derived from delivery events: sent, delivered, bounced, complained, rejected (precedence: complained > bounced > rejected > delivered > sent). Paginated via opaque continuation_token. Returns slim email summaries with id, use_case_id, setup_id, from_address, to_address, subject, state, sent_at, has_attachment, open_count, and click_count. Default limit 50, max 200. Requires Channel.view permission.

List email events - List delivery and engagement events scoped to a use case and/or setup. At least one of use_case_id or setup_id is required. Optional filters: email_id (repeatable), event_type (repeatable; values: Reject, Delivery, Bounce, Complaint, DeliveryDelay, Open, Click), event_at_after (inclusive), event_at_before (exclusive). Paginated via opaque continuation_token. Returns event records with id, email_id, event_type, event_at, and received_at. Default limit 50, max 200. Requires Channel.view permission.

Get email - Get the full detail of a single email by ID. Returns all fields from the list endpoint plus: message_id, email_type, tier (reputation lane at send time), attachment_filenames, per-event timestamps (delivered_at, bounced_at, bounce_type, bounce_subtype, complained_at, rejected_at, delivery_delay_at), engagement timestamps (first_open_at, last_open_at, first_click_at, last_click_at), raw engagement counts (open_count, click_count), and updated_at. Requires Channel.view permission.

Get email body - Returns the HTML body of a sent email. Response content type is text/html. Returns 404 if the email does not exist. Requires Channel.view permission.

Get email attachment - Redirects (307) to a short-lived download URL for the named attachment. The filename must match one of the filenames recorded at send time; requests for unrecognized filenames return 404. The download URL includes a content-disposition header for browser-friendly downloading, with full support for non-ASCII filenames. Requires Channel.view permission.

Email delivery and engagement tracking:

Email events are tracked automatically after sending. The platform receives delivery notifications from the email provider and projects them onto email records:

  • Delivery - Email accepted by the recipient's mail server

  • Bounce - Email bounced (includes bounce type and subtype)

  • Complaint - Recipient marked the email as spam

  • Reject - Email rejected before delivery

  • Delivery Delay - Temporary delivery delay

  • Open - Recipient opened the email (raw count; subject to pixel-loading behavior)

  • Click - Recipient clicked a link in the email

Event processing is idempotent - duplicate notifications are silently deduplicated.

Email use case creation updates:

When creating an email use case, the platform now automatically configures event tracking for the full set of delivery and engagement event types (Reject, Delivery, Bounce, Complaint, DeliveryDelay, Open, Click). No additional setup is required.

New environment configuration: Email use case creation requires an event notification topic to be provisioned in the deployment environment.

Error responses:

  • Send email: 404 (use case not found or not an email use case), 409 (DNS not verified), 413 (attachment or total message too large), 422 (invalid filename, empty attachment, duplicate filenames, message rejected by provider)

  • List emails / events: 422 (missing required scope filter)

  • Get email / body / attachment: 404 (email or attachment not found)

chevron-rightv0.9.197 - Platform API: Use Case and Voicemail Channel Management (June 2026)hashtag

Use Case and Voicemail Channel Management

The Platform API now exposes use case management and ringless voicemail endpoints, enabling direct management of voice and email use cases and voicemail delivery without interacting with internal channel infrastructure separately.

New endpoints:

Use Cases (/v1/{workspace_id}/use-cases)

Method
Path
Description

POST

/use-cases

Create a voice or email use case

GET

/use-cases

List use cases with optional filters

DELETE

/use-cases/{use_case_id}

Delete a use case

  • Create use case - Create a use case for a specific channel. The request body is a discriminated union on the channel field. Voice channels (outbound_voice, inbound_voice, ringless_voicemail) require a setup_id referencing an existing telephony setup. Email channel requires setup_id (referencing an email setup), sender_email_address, and email_type (transactional or marketing). Both types accept entity_name, name, and optional description. Returns the created use case with assigned ID, resolved configuration, tier, and timestamps. Requires Channel.create permission.

  • List use cases - List use cases with optional query filters: entity_name, channel (outbound_voice, inbound_voice, ringless_voicemail, email), and setup_id. When filtering by setup_id, the channel filter is required. Returns an items array of use case objects. Requires Channel.view permission.

  • Delete use case - Delete a use case by ID. Fails with 409 Conflict if a voice use case still has phone number assignments. Requires Channel.delete permission.

Voicemail (/v1/{workspace_id}/voicemail)

Method
Path
Description

POST

/voicemail

Send a ringless voicemail

GET

/voicemail

List voicemail records

  • Send voicemail - Send a ringless voicemail via multipart form. Fields: use_case_id (UUID), recipient_phone_number (US E.164 format, +1 followed by 10 digits), and audio (MP3 file, max 8 MB). Returns the voicemail_id and the sender_phone_number selected for delivery. Requires Channel.send permission.

  • List voicemails - List voicemail records with optional query filters: use_case_id, setup_id, status (repeatable), and recipient_phone_number. Returns an items array of voicemail objects with status, timestamps, and associated use case and setup IDs. Requires Channel.view permission.

New permissions:

Permission
Viewer
Member
Admin

Channel.view

Yes

Yes

Yes

Channel.create

No

Yes

Yes

Channel.send

No

Yes

Yes

Channel.delete

No

No

Yes

Use case response fields: id, channel, entity_name, name, description, setup_id, configuration_set_name, sender_email_address, email_type, tier, created_at, updated_at.

Voicemail response fields: voicemail_id, setup_id, use_case_id, recipient_phone_number, status, created_at, updated_at.

Error responses:

  • Use case creation: 404 (setup not found), 409 (already exists or setup not approved), 422 (invalid configuration), 502 (upstream unavailable), 504 (timeout).

  • Use case deletion: 404 (not found), 409 (has active phone assignments), 502, 504.

  • Send voicemail: 404 (use case not found or no phone assigned), 413 (audio exceeds 8 MB), 422 (invalid audio or configuration), 502, 504.

chevron-rightv0.9.196 - Platform API: Channel-Manager Federation for Outbound Calls and Phone Number Binding (June 2026)hashtag

Channel-Manager Federation for Outbound Calls and Phone Number Binding

Outbound calls can now be placed using a use-case-based phone number selection model, and phone numbers provisioned through the channel manager can be bound to a workspace in a single step via a new dedicated endpoint.

Outbound call changes:

  • Use-case-based caller ID selection - The POST /calls/outbound endpoint now accepts an optional use_case_id field (UUID). When provided, the platform selects the optimal outbound phone number for the given use case rather than requiring an explicit phone_from. Exactly one of phone_from or use_case_id must be provided - they are mutually exclusive.

  • phone_from is now optional - The phone_from field on the outbound call request body is now optional (was required). When use_case_id is provided, caller ID is resolved automatically.

  • New response fields - The outbound call response now includes phone_from (the resolved caller ID, useful when use_case_id was used) and setup_id (the channel-manager setup ID used for number selection, or null when phone_from was provided directly).

  • New error responses - 404 Not Found is returned when no phone number is available for the specified use case. The 403 Forbidden error message for unregistered caller IDs has been generalized.

Phone number binding:

  • New endpoint: POST /phone-numbers/bind - Binds a channel-manager-provisioned phone number to a workspace in one operation. The endpoint looks up the phone number from the channel manager by setup ID and phone number ID, then creates the workspace registration with the correct sub-account association for automatic credential resolution. Accepts setup_id, channel_phone_id, optional inbound_service_id, forwarding configuration, capabilities, display_name, and notes. Returns the standard phone number response. Requires PhoneNumber.create permission.

  • Bind endpoint error responses - Returns 404 if the setup or phone number is not found in the channel manager, 409 if the phone number is already registered, 403 for insufficient permissions.

Impact on integrations:

  • The phone_from field on POST /calls/outbound changing from required to optional is a breaking change for clients that rely on strict schema validation. Clients that already send phone_from are unaffected.

  • New response fields (phone_from, setup_id) on the outbound call response are additive.

  • The bind endpoint is new and does not affect existing phone number creation flows.

chevron-rightv0.9.195 - Platform API: Enriched Call Detail and Call List (June 2026)hashtag

Enriched Call Detail and Call List

Call detail and call list endpoints now return significantly richer data, including per-turn transcripts, timing information, recording availability, call analysis, and emotional summaries. Previously, historical call detail was limited to entity projection data and quality scores. The endpoints now draw from the full conversation record when available, with entity and intelligence data used for enrichment.

What changed:

  • Call list endpoint - GET /calls now returns caller_id, phone_number, has_recording (boolean), and uses the actual call start time when available instead of the entity creation time for the started_at field. Recording availability is now determined from actual recording data rather than always returning null.

  • Call detail endpoint - GET /calls/{id} now returns a comprehensive response with per-turn transcripts (turns), context graph states visited (states_visited), call timing (call_start_time, call_end_time, call_duration_seconds, media_start_time), recording details (has_recording), emotional summary, forwarding details, conference and participant information, barge-in events, call analysis, verified transcript data with accuracy scores, and voice configuration used for the call.

  • Call ID resolution - The call detail endpoint now accepts entity UUIDs, conversation UUIDs, or telephony call SIDs as the {id} parameter, resolving across identifier types to find the correct call record.

  • Enrichment layers - Call detail is assembled from up to three data sources: the full conversation record (transcripts, timing, recording, analysis), entity projection (escalation status, safety concerns, human operator segments), and call intelligence (quality scores, conversation and safety summaries). When the full conversation record is not yet available, the endpoint falls back to entity and intelligence data.

  • New response fields - error, call_start_time, call_end_time, call_duration_seconds, media_start_time, config, turns, states_visited, triggered_behaviors, emotional_summary, forwarding, conference_sid, participants, barge_in_events, has_recording, verified_transcript, verified_words, transcript_accuracy, per_turn_accuracy, call_analysis, safety, and service_id are now included in the call detail response.

  • Renamed fields - started_at is now call_start_time in the detail response. duration_seconds is now call_duration_seconds. emotion_summary is now emotional_summary.

  • Removed fields - event_count is no longer included in the call detail response.

Impact on integrations:

  • The call list response shape is backward compatible - new fields are additive and has_recording changes from nullable to always-present boolean.

  • The call detail response has renamed and restructured fields. Integrations that read started_at, duration_seconds, emotion_summary, or event_count from the detail response should update to the new field names.

  • The turns field now contains full per-turn transcript data (array of objects) rather than a turn count. Integrations that expected a number should handle the array format.

chevron-rightv0.9.194 - Platform API: Channel-Manager Phone Number Federation (June 2026)hashtag

Channel-Manager Phone Number Federation

Phone numbers can now be linked to an external channel management service for credential resolution. When a phone number is provisioned through the channel manager, the platform stores the association and uses it to resolve telephony credentials automatically - both for inbound signature verification and outbound call placement.

This introduces a dual-path credential resolution model: numbers linked to the channel manager resolve credentials through that path, while existing numbers continue using the legacy per-workspace credential configuration. The two paths coexist transparently - no migration is required for existing numbers.

What changed:

  • Phone number create endpoint - POST /phone-numbers now accepts optional channel_phone_id (UUID) and sub_account_sid (string, Twilio SID format AC followed by 32 hex characters) fields. These fields associate the phone number with a channel-manager-provisioned number and its telephony sub-account.

  • Phone number update endpoint - PATCH /phone-numbers/{id} now accepts optional channel_phone_id and sub_account_sid fields for updating the channel manager association on existing numbers.

  • Phone number response - GET /phone-numbers and GET /phone-numbers/{id} responses now include a channel_phone_id field (UUID or null) indicating whether the number is linked to the channel manager.

  • Inbound call credential resolution - Inbound calls to channel-manager-linked numbers now resolve telephony credentials through the channel manager path. Signature verification uses the resolved credentials. Numbers without a channel manager link continue using the existing credential resolution path.

  • Outbound call credential resolution - Outbound calls placed from channel-manager-linked numbers now resolve telephony credentials through the channel manager path. Numbers without a channel manager link continue using the existing credential resolution path.

Impact on integrations:

  • No breaking changes. The new fields are optional on create and update, and the response field is nullable.

  • Existing phone numbers are unaffected. The channel manager association is null by default.

  • Integrations that provision phone numbers through the channel manager can now pass the association at creation time, enabling automatic credential resolution without per-workspace credential configuration.

chevron-rightv0.9.193 - Platform API: Graceful FHIR Browser Fallback (June 2026)hashtag

Graceful FHIR Browser Fallback

FHIR browser endpoints now return empty results instead of errors when the analytical data layer is unavailable. Previously, FHIR resource queries that depend on the analytical query engine returned a service unavailable error if the engine was not configured or was temporarily unreachable. These endpoints now return empty result sets (empty arrays with zero totals for searches, null for single-resource lookups, zero for counts) and log a warning internally.

This affects FHIR resource search, single resource retrieval, resource history, resource counts, data-source-scoped searches, and multi-type count aggregations. Entity-backed FHIR types (Patient, Practitioner, Appointment, Slot, Location) are unaffected because they read from the primary data store.

What changed:

  • FHIR resource endpoints - All FHIR browser endpoints that read from the analytical layer now fail open. When the analytical engine is unavailable or returns an error, the endpoints return empty results instead of a 503 error.

  • No API surface changes - Response shapes are unchanged. The only behavioral difference is that callers receive empty results instead of errors during analytical layer downtime.

Impact on integrations:

  • No breaking changes. Clients that previously handled 503 errors from FHIR endpoints will now receive successful responses with empty data.

  • Clients should not assume that empty results always mean no data exists - during analytical layer downtime, results may be incomplete. The FHIR browser in the Developer Console already handles this gracefully.

chevron-rightv0.9.192 - Platform API: Progressive Scenario Streaming (June 2026)hashtag

Progressive Scenario Streaming

Simulation scenario generation now streams results progressively. As each scenario finishes generating, it is persisted to the simulation run immediately rather than waiting for the entire batch to complete. UI clients polling the run see scenarios appear one at a time, which provides faster visual feedback - especially for large scenario sets where full generation can take over a minute.

The final set of scenarios is validated identically to the previous non-streaming path, so there is no change in output quality or error handling. If generation is interrupted or hits a token limit, the same errors are raised as before.

What changed:

  • Simulation runs - Scenario generation for simulation bridge runs now persists each scenario to the run as it is produced, enabling progressive rendering in the Developer Console and any integration polling run status.

  • No API surface changes - The simulation run response shape is unchanged. The scenarios field on a run continues to be a list of scenario objects. The only behavioral difference is that this list grows incrementally during generation rather than appearing all at once.

Impact on integrations:

  • No breaking changes. Clients polling simulation run status will see scenarios appear progressively instead of all at once.

  • The final run state and scenario list are identical to the previous behavior.

  • No client-side changes are required.

chevron-rightv0.9.191 - Platform API: Historical Call Detail Fallback (June 2026)hashtag

Historical Call Detail Fallback

The call detail endpoint now returns complete call data for historical calls that are no longer held in the real-time voice layer. Previously, requesting detail for a call after it aged out of the live call store returned a 404 error. The endpoint now falls back to durable platform storage, reconstructing the call detail from persisted call state and post-call intelligence data.

This means call detail is available for the full retention period of your workspace, not just while calls remain in the real-time layer. Historical call details are returned with a source value of historical so clients can distinguish them from live or recently completed calls.

What changed:

  • Call detail endpoint - GET /calls/{call_id} now returns call detail for historical calls by falling back to durable storage when the call is no longer available in the real-time layer. The response includes the same fields as live call detail (direction, phone number, caller ID, started timestamp, status, escalation, duration, quality score, conversation summary, and other intelligence fields) sourced from persisted call state and post-call intelligence records.

  • Historical source indicator - Responses for historical calls include "source": "historical" to distinguish them from live calls ("source": "live") and simulation calls.

  • Intelligence data included - When post-call intelligence data is available, the response includes duration, quality score, final state, completion reason, emotion summary, conversation summary, and safety summary. When intelligence data has not yet been computed, duration and final state are populated from the call state record where available.

Impact on integrations:

  • No breaking changes. The call detail endpoint retains its existing response shape.

  • Calls that previously returned 404 after aging out of the real-time layer now return successfully with full detail.

  • Clients can check the source field to determine whether the call detail came from the live layer or durable storage.

  • No client-side changes are required.

chevron-rightv0.9.189 - Platform API: Analytics Stability Fixes (June 2026)hashtag

Analytics Stability Fixes

Fixed a class of server errors (HTTP 500) across several analytics and event query endpoints caused by internal column mismatches between the query layer and the underlying analytical data store. These mismatches could cause failures when querying event timelines, entity histories, FHIR resource views, data source event listings, and outbound sync summaries.

Additionally, the trace analysis model for decision factors now accepts a wider range of category values, preventing validation errors that could occur when the intelligence pipeline returned categories outside the previously restricted set.

What changed:

  • Event queries - Several event listing and detail endpoints now correctly reference the available columns in the analytical store, eliminating 500 errors that occurred when requesting events by entity, by ID, or by data source.

  • Analytics aggregations - Time-series, confidence distribution, and review status aggregation queries now use the correct timestamp field for filtering and grouping, fixing errors in the event breakdown, confidence analytics, and quality trend endpoints.

  • Superseding event lookup - The endpoint that finds the event superseding a given event ID now returns the correct timestamp field.

  • FHIR resource queries - Paginated FHIR resource event listings and resource history endpoints now select the correct columns, fixing errors when browsing FHIR data through the console or API.

  • Data source event queries - Event count, listing, and outbound sync summary queries for data sources now filter on the correct identifier column.

  • Decision factor validation - The trace analysis model for call decision factors now accepts any string category value instead of requiring a fixed set, preventing validation failures on unexpected category values from the analysis pipeline.

  • Date formatting in memory analytics - The memory dimension analytics endpoint now handles both pre-formatted and raw date values correctly, preventing serialization errors in the response.

Impact on integrations:

  • No API surface changes. All endpoints retain their existing request and response shapes.

  • Integrations that were receiving intermittent 500 errors from analytics or event query endpoints should see those errors resolved.

  • No client-side changes are required.

chevron-rightv0.9.188 - Platform API: Graceful Analytics Fallback (June 2026)hashtag

Graceful Analytics Fallback

All analytics endpoints now return structured empty responses instead of errors when the analytical data layer is temporarily unavailable. Previously, if the analytical layer was unreachable, these endpoints could return server errors. They now return valid response objects with empty result sets and zero counts, allowing clients to handle unavailability gracefully.

Affected endpoints:

  • Usage summary - Returns an empty buckets array and total_events: 0 when the analytical layer is unavailable.

  • Call stats - Returns zero values for total_calls, total_duration_seconds, and avg_duration_seconds, and an empty calls_by_date array when the analytical layer is unavailable.

  • Event breakdown - Returns empty by_type and by_source arrays and total_events: 0 when the analytical layer is unavailable.

Impact on integrations:

  • No API surface changes. All endpoints retain their existing response shapes.

  • Clients that previously received HTTP 5xx errors during analytical layer outages will now receive HTTP 200 responses with empty data. If your integration distinguishes between "no data" and "service error," be aware that temporary unavailability now looks like an empty result set.

chevron-rightv0.9.187 - Platform API: Observability OLTP Layer, Review Audit Trail, and Review Diff (June 2026)hashtag

Observability OLTP Layer

The platform now maintains pre-computed operational summaries that are periodically synced from the analytical layer into the transactional database. Several endpoints that previously relied on direct analytical queries now read from these local summaries first, falling back to the analytical layer only when summary data is not yet available. This reduces typical response times from seconds to sub-millisecond for affected endpoints.

Affected endpoints:

  • World dashboard event stats - Event velocity (24-hour and 7-day counts, average confidence) is now served from the transactional database when available, with automatic fallback to the analytical layer.

  • Connector health (Sensorium) - Per-source event counts, events-per-minute rates, and freshness indicators are now read from the transactional database first, falling back to the analytical layer if no summary data exists.

  • Pipeline status - Event counts in the pipeline status response now prefer the transactional summary, falling back to analytical queries when the summary is empty.

Review Queue Audit Trail

All review queue actions - approve, reject, and correct - now emit audit trail events. Each audit event records the action taken, the review item, the associated entity, the reviewer, and the related event identifiers. These audit events are written to the platform's event stream and are available through the standard event query interfaces.

Review Diff Endpoint Restored

The review diff endpoint (GET /review-queue/{id}/diff) is now functional. For corrected review items, it returns the original events alongside the corrected (superseding) events, enabling before-and-after comparison of corrections. The endpoint requires the analytical query layer to be available and returns HTTP 503 if it is not configured.

Impact on integrations:

  • No API surface changes. All endpoints retain their existing request and response shapes.

  • The review diff endpoint, previously returning HTTP 503 unconditionally, now returns diff data for corrected items. Integrations that were handling the 503 response should be updated to process the diff payload.

  • Audit trail events for review actions are additive. Existing event consumers will see new review.approve, review.reject, and review.correct events in the audit domain.

chevron-rightv0.9.186 - Platform API: Restore Delta-Backed Features (June 2026)hashtag

Restored Delta-Backed Features

Nine features that were temporarily returning empty results have been restored with full data backing. These features previously returned placeholder or zero values after an internal data migration. They now query the platform's analytical data layer and return live results.

What changed:

  • World dashboard event stats - The world model dashboard now returns real values for 24-hour and 7-day event counts and average confidence scores, instead of zeros and nulls.

  • Phone call volume - The GET /calls/phone-volume endpoint now returns per-phone-number call volume with inbound/outbound breakdowns, average duration, and daily counts. Previously returned an empty list.

  • Memory analytics - The memory analytics endpoint now returns event type statistics, recent event counts (24h, 7d, 30d), and top data sources. Previously returned empty stats.

  • Connector health (Sensorium) - The connector health strip now returns per-source event counts, events-per-minute rates, and freshness status. Previously returned an empty list.

  • Pipeline event history - Pipeline source history, source events, throughput time series, outbound summary, and outbound log endpoints now return live data. Previously returned empty results.

  • Pipeline status and source overview - Pipeline status and source overview now include accurate event counts from the analytical layer. Previously reported zero.

  • Entity timeline - Entity timeline queries now return event history. Previously returned an empty list.

  • Narrative projector - The self-image narrative projector now loads entity events and briefs from the analytical layer, enabling brief generation and retrieval. Previously returned empty.

  • Review queue operations - Review queue approve, reject, correct, and batch operations are re-enabled. The correction schema endpoint is also restored. The review diff endpoint remains unavailable and returns a service-unavailable status.

  • Surface analytics - Surface analytics endpoints (completion rates, channel effectiveness, field abandonment, entity surface history) now return computed results from lifecycle data instead of zeros and empty lists.

Impact on integrations:

  • No API surface changes. All endpoints retain their existing request and response shapes.

  • Integrations that were handling empty/zero responses should now expect populated data.

  • The review diff endpoint (GET /review-queue/{id}/diff) was unavailable in this release and returned HTTP 503. It has been restored in v0.9.187.

chevron-rightv0.9.185 - Platform API: Cross-Provider Voice ID Isolation (June 2026)hashtag

Cross-Provider Voice ID Isolation

The TTS configuration merge pipeline now prevents voice IDs from one provider being applied when a different provider is resolved for the session. Previously, an agent-level voice ID configured for one TTS provider could leak into sessions where a different provider was active - for example, a voice ID intended for one provider being passed to a different provider, causing unexpected voice selection or errors.

What changed:

  • Provider-aware voice ID resolution - When merging TTS configuration across workspace, agent, and service levels, the platform now compares the agent-level TTS provider against the resolved session provider. An agent-level voice ID is only applied when the providers match, or when no provider is explicitly set at one of the levels. This prevents cross-provider voice ID leakage without affecting configurations where providers are consistent.

  • No breaking changes. Configurations where the agent and service use the same TTS provider behave exactly as before. Only the incorrect cross-provider override is blocked.

Impact on integrations:

  • No API surface changes. This is a behavioral fix to the TTS configuration merge logic.

  • If you previously relied on an agent-level voice ID overriding a different service-level provider, you should configure the correct voice ID at the service level or through per-language TTS provider routing.

chevron-rightv0.9.184 - Platform API: Per-Language TTS Provider Routing (June 2026)hashtag

Per-Language TTS Provider Routing

Voice settings now support per-language TTS provider routing. You can configure different text-to-speech providers for different caller languages, so each language is served by the provider and voice best suited for it.

What changed:

  • New language_providers field on voice settings - The voice settings request and response models now include a language_providers field. Each key is a BCP-47 language code (en, es, ar, fr, de, pt, zh, ja, ko) or multilingual. Each value specifies a TTS provider (cartesia, elevenlabs, or groq) and an optional provider-specific config object.

  • Language-aware provider resolution - When a caller's language is detected, the platform resolves the TTS provider through a priority matrix. It checks for an exact language match first (e.g., ar-SA), then a base language match (e.g., ar), then a multilingual fallback. At each level, service configuration takes priority over agent, which takes priority over workspace. If no language-specific entry matches, the flat tts_provider field is used as before.

  • Isolated per-language config - When a per-language provider is matched, only that entry's config is used. Base tts_config from a different provider is not merged in, preventing cross-provider configuration leaks (e.g., a Cartesia voice ID being passed to Groq).

  • Service and agent-level support - The language_providers field is available at workspace level (voice settings), agent level (voice config on agent versions), and service level (service voice config). The resolution matrix scans all three levels.

  • Validation - Language keys are validated against the supported set. At most 10 language entries are permitted. Sending null clears the map; an empty object is rejected.

Example configuration:

Impact on integrations:

  • New optional field. Existing integrations are unaffected - language_providers defaults to null.

  • Voice settings GET response now includes language_providers when configured.

  • No breaking changes. All existing TTS provider selection behavior is preserved when language_providers is not set.

chevron-rightv0.9.183 - Platform API: Entity-Only Tool Reads and Semantic Search Improvements (June 2026)hashtag

Entity-Only Tool Reads and Semantic Search Improvements

All agent tools now read exclusively from the entity data model. Previously deprecated event-based search tools have been fully removed, and the semantic search tool has been updated with new filtering capabilities. Voiceprint verification now reads enrollment data directly from entity state instead of requiring a separate lookup.

What changed:

  • Event search tools removed - The search_events and semantic_search_events MCP tools now return an error directing callers to use search_entities and semantic_search_entities instead. These tools were previously deprecated and returning empty results.

  • Semantic entity search improvements - The semantic_event_search tool has been updated to search world model entities instead of events. It now supports an optional entity_type filter parameter (e.g., person, appointment, call) in addition to the existing entity_id filter. Results now return entity metadata (display name, canonical ID, source, confidence, last activity timestamp, and available state keys) instead of event data.

  • Voiceprint verification reads from entity state - Caller identity verification now reads voiceprint enrollment and embedding data directly from entity state. Previously, this required a separate data lookup that was returning empty results after the event data migration. Verification is skipped with a warning when embedding data is not yet available in entity state.

  • Ad-hoc query scope updated - The ad-hoc SQL query tool description no longer references the deprecated events table. Queryable tables include entities, call intelligence, billing analytics, patient memory, metrics, scheduling, and registered functions.

  • Supersede chain resolution - Appointment event writes no longer attempt local supersede chain resolution. This resolution now happens in the downstream data processing pipeline, which is the authoritative source for event lineage.

Impact on integrations:

  • No API contract changes. All endpoints, request shapes, and response shapes remain identical.

  • Tool behavior change: If your agent logic depends on search_events or semantic_search_events, switch to the entity-based equivalents. The event tools now return errors instead of empty results.

  • Semantic search results shape change: The semantic_event_search tool now returns entity-shaped results with different field names. If you parse tool results programmatically, update your parsing logic.

chevron-rightv0.9.182 - Platform API: Multi-Region Deployment and Environment Safety (June 2026)hashtag

Multi-Region Deployment and Environment Safety

The platform now enforces explicit region configuration in deployed environments and adds safety checks that prevent services from starting with incorrect environment settings. These changes are prerequisites for multi-region deployments and eliminate a class of silent misconfiguration bugs.

What changed:

  • Mandatory region configuration in deployed environments - Services running in staging or production now require an explicit deployment region. Previously, services without a configured region silently defaulted to a single region, which could cause requests to route to the wrong regional endpoint. Services that do not have a region configured will now fail to start with a clear error message instead of running with an incorrect default.

  • Environment detection safety checks - Services now validate that their environment setting is consistent with the deployment context. A service running in a container orchestration environment without an explicit environment setting will fail to start immediately, rather than silently falling back to local-development defaults. This prevents accidental deployment of services with development-mode settings that disable security controls and open test-only endpoints.

  • AI model provider region validation - Services that use cloud-hosted AI model providers now validate that a provider region is configured when a provider project is set. Previously, an empty region with a configured project caused cryptic errors at request time. The platform now fails fast at startup with a clear message identifying the misconfiguration.

  • Direct stream endpoint restricted - The direct audio streaming endpoint (used for testing voice-to-voice without telephony) is now disabled in both staging and production environments. Previously it was only disabled in production. This endpoint is intended for local development and testing only.

  • Removed deprecated configuration fallback - The deprecated GPT_AUDIO_MAX_TOKENS fallback (announced in v0.9.180) has been removed. Services must use the current configuration name. The deprecation warning is no longer emitted.

  • Removed redundant service-specific environment variables - Several services had their own environment name variables (e.g., separate settings for the voice agent environment or bridge environment) that duplicated the platform-wide environment setting. These have been consolidated to use the single platform-wide environment setting. Services that previously read from a service-specific environment variable now use the shared setting automatically.

  • Prompt logging restricted to non-production - Detailed prompt logging in the voice agent is now enabled only outside production environments. Previously it was controlled by a separate service-specific environment variable.

Impact on integrations:

  • No API contract changes. All endpoints, request shapes, and response shapes remain identical.

  • Self-hosted deployments: Verify that your deployment configuration explicitly sets the deployment region for all services in staging and production. Services without an explicit region will fail to start.

  • AI model provider users: If you have configured a cloud AI model provider project, ensure the corresponding region is also set. Services will fail to start if a project is configured without a region.

  • Direct stream users: If you were using the direct audio streaming endpoint in staging for testing, switch to using it in local or test environments only.

  • GPT_AUDIO_MAX_TOKENS users: If you have not yet migrated to CARTESIA_MAX_COMPLETION_TOKENS, you must do so before upgrading. The old name is no longer recognized.

chevron-rightv0.9.181 - Platform API: TTS Provider Enhancements - SDK-Based Streaming and Arabic Voice Support (June 2026)hashtag

TTS Provider Enhancements - SDK-Based Streaming and Arabic Voice Support

The voice agent's text-to-speech pipeline adds SDK-based audio streaming for the ElevenLabs provider and dedicated Arabic voice model support for the Groq provider. These changes improve audio delivery reliability and expand language coverage for Middle East deployments.

What changed:

  • ElevenLabs SDK streaming - The ElevenLabs TTS provider now supports streaming audio through the official SDK in addition to the existing WebSocket transport. When an SDK client is configured, filler audio (short spoken phrases played while the agent processes a request) uses HTTP-based streaming for simpler connection management. The WebSocket transport remains available as a fallback. Main turn-level TTS continues to use the persistent WebSocket connection for lowest latency.

  • Groq Arabic voice model - The Groq TTS provider now supports a dedicated Arabic voice model for Middle East deployments. When the conversation language is Arabic, the provider automatically selects the configured Arabic model instead of the default English model. The Arabic model can be configured per-service through the voice settings tts_config field using the arabic_model key.

  • Groq default model update - The default Groq TTS model has been updated. Existing services that explicitly set a model in their voice settings are not affected.

  • Voice settings tts_config expansion - The tts_config configuration object for the Groq provider now accepts an arabic_model key to specify the Arabic TTS model. This is optional and falls back to the platform default when not set.

Impact on integrations:

  • No API contract changes. All endpoints and response shapes remain identical.

  • ElevenLabs users: If an ElevenLabs API key is configured, the SDK client is initialized automatically. No configuration changes are needed.

  • Groq Arabic TTS: To use Arabic voice synthesis, set the conversation language to Arabic. The provider selects the appropriate model automatically. To override the default Arabic model, include arabic_model in the service's tts_config.

chevron-rightv0.9.180 - Platform API: Feature Flags, Multi-Region Readiness, and Environment Variable Cleanup (June 2026)hashtag

Feature Flags, Multi-Region Readiness, and Environment Variable Cleanup

Feature flags for several platform capabilities have been migrated from static environment variables to the dynamic feature flag system. Operators can now toggle these capabilities at runtime - per workspace or globally - without redeploying services. The platform also adds multi-region awareness to service initialization, and cleans up deprecated configuration names.

What changed:

  • Runtime feature flag control - The following capabilities are now controlled via the platform's feature flag system with environment-variable fallback. Operators can toggle these dynamically without service restarts:

    • Companion skills (agent engine)

    • Async task execution (agent engine)

    • Agent SDK mode (agent engine)

    • Fuzzy entity resolution (connector runner, per-workspace)

    • Review loop kill switch (connector runner)

    • Trigger scheduler (platform API)

    When the feature flag service is unavailable, each flag falls back to its existing environment variable default, so there is no disruption during rollout.

  • Review loop runtime kill switch - The review loop now re-evaluates its kill switch periodically at runtime. Previously, the loop could only be disabled at startup. Operators can now disable a running review loop without restarting the service.

  • Multi-region readiness - Services now read the deployment region from environment configuration instead of hardcoding a default. This is a prerequisite for multi-region deployments. Services that do not have an explicit region configured will log a warning in staging and production environments and fall back to the default region.

  • Deprecated: GPT_AUDIO_MAX_TOKENS - The GPT_AUDIO_MAX_TOKENS configuration has been renamed to CARTESIA_MAX_COMPLETION_TOKENS to reflect the current text-to-speech provider. The old name continues to work as a fallback but will be removed in a future release. Services using the old name will log a deprecation warning at startup.

  • Speculative navigation env var removed - The SPECULATIVE_NAV_ENABLED environment variable has been removed from the agent engine. Speculative navigation is now controlled exclusively through the feature flag system.

  • Health check configuration - The database health check skip mechanism now uses explicit parameters instead of reading from an environment variable directly. The skip is still restricted to preview, development, local, and test environments - it cannot be used in staging or production.

  • Desktop connection API key propagation - The desktop connection helper now accepts an explicit API key parameter, improving reliability when connections are established from subprocess contexts.

Impact on integrations:

  • No API contract changes. All endpoints and response shapes remain identical.

  • Rename GPT_AUDIO_MAX_TOKENS to CARTESIA_MAX_COMPLETION_TOKENS in your environment configuration at your convenience. The old name still works but will be removed in a future release.

  • SPECULATIVE_NAV_ENABLED can be removed from environment configuration. It is no longer read.

  • LAKEBASE_HEALTHCHECK_SKIP environment variable is no longer read directly by the health check system. Services that pass this configuration do so through their own startup logic.

chevron-rightv0.9.179 - Platform API: Agent Engine - Query Safety and Performance Improvements (June 2026)hashtag

Agent Engine - Query Safety and Performance Improvements

The agent engine now uses exact-match lookups for patient references in appointment, encounter, and payer queries instead of partial string matching. This improves query performance and eliminates false-positive matches where one patient's data could surface in another patient's results due to substring collisions.

What changed:

  • Appointment and encounter lookups - Patient filtering in appointment lookup, encounter history, patient context loading (recent encounters, upcoming appointments), and slot search now uses exact patient reference matching. Previously, these queries used partial string matching, which could return incorrect results when one patient identifier was a substring of another.

  • Payer search - Payer name filtering is now pushed to the database layer for both payer entity and patient insurance searches. Previously, the engine loaded all payer or patient entities into memory and filtered client-side, which scaled poorly for workspaces with large entity counts. The fuzzy name matching logic is unchanged - only the initial candidate set is now pre-filtered.

  • Location schedule resolution - Location matching for schedule lookups now uses exact facility identifier matching and validates location identifier format before querying. Previously, partial string matching on location identifiers could return unrelated locations.

  • Encounter deduplication - Encounter history results are now deduplicated across data sources. When the same encounter appears in both the patient's clinical record and the appointment history, it is returned once instead of twice.

  • Error logging - All agent tool error logging now uses synchronous structured logging, improving reliability of error capture during exception handling.

Impact on integrations:

  • No API contract changes. All tool response shapes remain identical.

  • More precise results. Appointment, encounter, and payer queries may return fewer results than before if previous results included false-positive matches from partial string collisions. This is the correct behavior.

  • Improved performance for payer search. Workspaces with large numbers of payer or patient entities will see faster payer search responses due to database-side filtering.

chevron-rightv0.9.178 - Platform API: World Model - Read Path Migration to Entity State (June 2026)hashtag

World Model - Read Path Migration to Entity State

All read operations that previously queried the world model event stream now read from entity state projections and dedicated platform tables instead. This completes a multi-release migration that moves the platform's read paths away from the append-only event log and onto materialized, query-optimized storage.

What changed:

The following read operations have been migrated:

  • Patient context loading - Recent encounters, upcoming appointments, call history, and data quality metrics for patient context during voice calls now resolve from entity state. Previously, these queries scanned the event stream with time-windowed filters.

  • Appointment, encounter, medication, and payer lookups - Agent tools that search clinical data now read from entity state projections populated by the streaming data pipeline. Previously, these tools queried the event stream directly with FHIR resource type filters.

  • Voiceprint embeddings - Speaker verification embeddings are being migrated to a dedicated table. During the transition, voiceprint lookup returns empty (no enrolled voiceprints) until the new storage path is fully wired.

  • Semantic event search - Vector similarity search on event embeddings now returns empty results. Semantic search over clinical data will be served by the analytical query service in a future release.

  • Entity resolution batch loop - The background entity resolution reconciliation loop no longer scans for unlinked events. Entity resolution is now fully handled by the real-time subscriber path. The batch loop remains as a no-op safety net.

  • Gap scanner entity filtering - The gap detection scanner no longer uses event-stream subqueries to exclude test data or detect upcoming appointments. Entity state projections from the streaming data pipeline already filter non-production sources and include appointment status.

  • Outbound sync reconciliation - The outbound sync reconciliation loop no longer scans the event stream for unsynced events. Outbound sync is fully handled by the real-time subscriber path.

  • Review loop - The low-confidence event review loop no longer scans the event stream. Review queue population will be handled by the streaming data pipeline.

  • Patient type detection - Determining whether a patient is new or returning now checks entity state for completed appointment history instead of querying appointment events through relationship graphs.

  • Surface lifecycle stats - Surface creation, completion, and channel preference stats now return zeroed values. These metrics will be served by the analytical pipeline in a future release.

Impact on integrations:

  • No API contract changes. All endpoints return the same response shapes. Tools that previously returned clinical data now return empty result sets until entity state projections are fully populated for the workspace.

  • Temporary data gaps. Workspaces that rely on appointment lookup, encounter history, medication lists, payer search, or voiceprint verification through agent tools will see empty results during the transition period. Data will become available as entity state projections backfill.

  • Monitor concepts and safety policies continue to read from their dedicated tables (migrated in v0.9.176) and are not affected.

Why this matters:

Reading from entity state instead of the event stream reduces query latency for clinical data lookups and eliminates the dependency on the append-only event log for real-time read operations. This is a prerequisite for scaling the world model to higher event volumes without degrading read performance.

chevron-rightv0.9.177 - Platform API: Voice Agent - Multi-Provider TTS Support (June 2026)hashtag

Voice Agent - Multi-Provider TTS Support

The voice agent now supports multiple text-to-speech providers, giving workspaces control over which TTS engine powers agent speech. Previously, a single TTS provider was available. You can now choose between three providers, each with different characteristics for latency, voice quality, and language support.

Provider selection:

The TTS provider is configured at the workspace level through voice settings, or via environment-level defaults. The provider determines which speech synthesis engine converts agent text to audio during voice calls.

Provider
Strengths
Audio Output

Default provider

Low-latency WebSocket streaming, emotion-aware speech, pronunciation dictionaries

16 kHz PCM

Provider B

Multi-stream WebSocket with per-turn isolation, word-level alignment data, regional endpoint support (US, EU, India)

16 kHz PCM

Provider C

Ultra-fast REST-based synthesis, sentence-level pipelining, vocal direction tags for expressive delivery, Arabic language auto-detection

24 kHz PCM

Configuration:

  • Set tts_provider in workspace voice settings to select the provider. Valid values: the three provider identifiers.

  • Each provider has its own set of tunable parameters (voice, model, speed, and provider-specific quality settings) configurable through the tts_config object in voice settings.

  • Per-agent voice overrides (voice selection) continue to work across all providers.

  • Per-service pipeline settings (response length caps, buffer delays) apply regardless of provider.

Provider-specific capabilities:

  • Provider B maintains a persistent WebSocket connection across turns within a session, with each turn isolated by a unique context. It supports tunable stability, similarity, and style parameters, and returns word-level timing alignment with audio chunks.

  • Provider C pipelines sentences to the TTS engine as they arrive from the text model, so audio playback begins before the full response is generated. It supports vocal direction tags (e.g., cheerful, whisper, calm, dramatic) for expressive delivery in English, and automatically selects the appropriate model variant for Arabic input.

Resilience:

Each provider has its own circuit breaker with independent failure thresholds and recovery windows. Provider failures are isolated - a degradation in one provider does not affect others. If an unknown provider is configured, the system falls back to the default provider with a warning.

No API contract changes. Voice call endpoints, session management, and call recordings work identically regardless of provider. The provider selection is transparent to callers and API consumers.

chevron-rightv0.9.176 - Platform API: Monitor Concepts and Safety Policies - Dedicated Storage (June 2026)hashtag

Monitor Concepts and Safety Policies - Dedicated Storage

Monitor concepts and safety policies now have their own dedicated storage, separate from the general-purpose event stream. Previously, these entities were stored as tagged events in the world model event stream. They are now first-class platform resources with purpose-built schemas.

What changed:

  • Monitor concepts are stored in a dedicated table with native fields for name, description, tags, and vector embeddings. This replaces the previous pattern of encoding concept data inside generic event payloads.

  • Safety policies are stored per-workspace with upsert semantics. Updating a workspace's safety policy now overwrites the existing record in place rather than appending a new event and marking the previous one as superseded.

  • No API contract changes. All monitor concept and safety policy endpoints return the same response shapes as before. Existing integrations do not need to change.

Benefits:

  • Faster reads for monitor concepts and safety policies - queries no longer scan the event stream.

  • Cleaner separation between configuration data (concepts, policies) and runtime event data.

  • Safety policy updates are atomic single-row upserts instead of two-step event supersession.

chevron-rightv0.9.175 - Platform API: World Event Pipeline - Streaming-First Event Writes (June 2026)hashtag

World Event Pipeline - Streaming-First Event Writes

The world model event write path now uses a fully streaming architecture. Events are emitted asynchronously to the streaming data pipeline, which processes them into entity state projections continuously. This replaces the previous dual-write approach where events were written to both a transactional store and the streaming pipeline.

What changed:

  • Event writes are now fire-and-forget to the streaming pipeline. Events flow through the data pipeline to entity state projections with eventual consistency. Entity lifecycle operations (creating entities, managing relationships) and configuration tables remain transactional.

  • FHIR event deduplication moved downstream. Content-based deduplication for FHIR resource events is now handled by the streaming pipeline rather than at the API layer. The upsert_fhir_event operation no longer returns "skipped" - all events are emitted and deduplicated downstream.

  • Enrichment supersedes resolution uses cache. When writing enrichment events, the supersedes chain (which previous enrichment event is being replaced) is now resolved atomically via a distributed cache instead of querying the event store. This is faster and avoids read-after-write consistency issues.

  • Entity linking is a no-op. The link_events_to_entity and link_event_to_entity operations are now no-ops. Entity resolution is fully handled by the entity.resolved signal flowing through the streaming pipeline. Callers should migrate to using emit_entity_resolved() only.

Impact on API consumers:

  • If you rely on the "skipped" action from FHIR event upserts, note that all events now return "created". Deduplication still occurs but is handled downstream.

  • Event timestamps (ingested_at, created_at, updated_at) on returned event objects are now client-generated rather than database-generated. The authoritative timestamps are set when events are processed by the pipeline.

  • No changes to request schemas or authentication.

chevron-rightv0.9.174 - Platform API: Voice Agent - Session Cleanup on Terminal Turns (June 2026)hashtag

Voice Agent - Session Cleanup on Terminal Turns

When a voice agent conversation reaches a terminal state (the agent ends the call), the platform now clears the caller's session immediately instead of letting it expire on its own. Previously, if the same caller phoned back shortly after a completed conversation, the agent could resume from the old conversation's state rather than starting fresh. This was most visible after a context graph publish - the agent would appear to run the previous graph version until the old session expired.

With this fix, every call after a terminal turn starts cleanly from the context graph's initial state with no carryover from the prior conversation.

The session time-to-live for active (non-terminal) conversations has also been shortened to better match the near-synchronous nature of voice interactions, reducing the window in which stale state can affect a follow-up call.

No client changes are required.

chevron-rightv0.9.173 - Platform API: Voice Pipeline - Tool Result Persistence, Context Window Management, and Silence Timing (June 2026)hashtag

Voice Pipeline - Tool Result Persistence, Context Window Management, and Silence Timing

This release includes three voice pipeline improvements that affect long-running conversations and conversations with polling tools.

Tool result persistence mode

Tool call specs now support a result_persistence field that controls how repeated tool results appear in the agent's prompt context. The default mode (accumulate) preserves all results. The new override mode keeps only the latest result per tool name, reducing context growth from tools that are called repeatedly (such as status-checking or polling tools).

Field
Type
Default
Description

result_persistence

string

accumulate

How repeated results appear in prompt context. accumulate keeps all results. override keeps only the latest result per tool name.

Context window management

The voice agent engine now monitors cumulative token usage across a call and applies automatic safeguards as the context window fills:

  • When utilization crosses a warning threshold, the engine automatically reduces the prompt history window to prevent context overflow.

  • When utilization crosses an escalation threshold, the engine triggers an escalation to a human operator.

Three new environment-level configuration parameters control these thresholds:

Parameter
Type
Default
Description

context_window_size

integer

200000

Total context window size in tokens

context_window_warning_ratio

float

0.6

Utilization ratio at which prompt history is automatically reduced

context_window_escalation_ratio

float

0.8

Utilization ratio at which escalation to a human operator is triggered

Silence detection timing

Silence detection after agent speech now accounts for remaining audio playback time. Previously, the silence window started when audio bytes finished streaming to the transport layer. Now the silence window starts from when the caller actually hears the end of the response, preventing premature silence check-ins on longer responses.

Greeting cache improvements

Greeting text caching is now cross-pod, so greeting latency savings persist across service restarts and are shared across all instances serving the same workspace and service.

No client changes are required.

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

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.

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

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.

chevron-rightv0.9.170 - Platform API: Slot Practitioner and Facility Identifiers (May 2026)hashtag

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.

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

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.

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

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.

chevron-rightv0.9.167 - Platform API: Outbound Call Creation API (May 2026)hashtag

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).

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

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.

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

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.

chevron-rightv0.9.164 - Platform API: Policyholder DOB, Slot Practitioner Display, and Appointment Participant Fallback (May 2026)hashtag

Policyholder DOB, Slot Practitioner Display, and Appointment Participant Fallback

The world model now surfaces additional fields for insurance verification and scheduling display, and the appointment view resolves participant names more reliably.

What changed:

  • Policyholder date of birth. Patient entities now include the policyholder's date of birth when it differs from the patient's own. This supports eligibility and identity-match flows where the voice agent confirms the insured person's date of birth during a call. The value is sourced from the EHR's primary insurance record.

  • Slot practitioner display name. Slot entities now include the practitioner's display name directly, so the booking UI and voice agent can present slots as "Dr. Smith's 10:00 AM slot" without requiring a separate lookup of the practitioner or schedule entity.

  • Appointment participant resolution. The appointment view now resolves participant display names (patient, practitioner, location) through a multi-tier fallback chain: typed entity fields first, then nested state data, then the raw FHIR resource blob. This ensures participant names appear reliably on older entities that predate the current projection pipeline, and on entities that have only partial data.

  • Appointment reason fallback. The appointment reason field now prefers the typed entity field when available and falls back to the state blob only when the typed field is absent, preventing stale cached values from shadowing corrected data.

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

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

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.

chevron-rightv0.9.162 - Platform API: Desktop Integration Protocol (May 2026)hashtag

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.

chevron-rightv0.9.161 - Platform API: Reliable Surface Creation (May 2026)hashtag

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.

chevron-rightv0.9.160 - Platform API: Dedicated Connector Configuration Storage (May 2026)hashtag

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.

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

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 diagn