Services
Bind agents and context graphs into deployable services, manage version sets, and configure voice behavior for conversations across supported channels.
A service binds an agent, a context graph, and version sets into a deployable unit. Services are the entry point for conversations: when a user calls a phone number or starts a chat, the platform resolves the service to determine which agent persona, conversation flow, and model configuration to use.
Key Concepts
Agent and context graph binding: every service links to one agent and one context graph.
Version sets: named configurations that pin specific agent and context graph versions and LLM model preferences.
Tags: key-value metadata stored with the service.
Channel type: the separate
channel_typefield declares whether the service is forvoiceortextconversations.Tool capacity: maximum concurrent tool executions per conversation (1-10, default 3).
Accepted conversation context: the
accepted_contextschema declares which string and number values callers may supply when starting a conversation.
Endpoints
Create a Service
Create a new service linking an agent and a context graph. Validates that agent_id and context_graph_id exist in the workspace and that every version set name and pinned version is valid. Requires Service.create permission.
API key issued via POST /v1/{workspace_id}/api-keys. Pass the returned api_key value as a Bearer token.
""true3voicePossible values: productionPossible values: Successful Response
voicePossible values: productionPossible values: falseMissing or invalid API key.
Insufficient permissions.
Not found.
Name already taken.
Invalid request body.
POST /v1/{workspace_id}/services HTTP/1.1
Host: platform.api-us.concurrence.com
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 1910
{
"name": "text",
"description": "",
"agent_id": "123e4567-e89b-12d3-a456-426614174000",
"context_graph_id": "123e4567-e89b-12d3-a456-426614174000",
"keyterms": [
"text"
],
"is_active": true,
"version_sets": {
"ANY_ADDITIONAL_PROPERTY": {
"agent_version_number": 1,
"context_graph_version_number": 1,
"llm_model_preferences": {
"ANY_ADDITIONAL_PROPERTY": {
"llm_name": "text",
"params": {
"ANY_ADDITIONAL_PROPERTY": "anything"
},
"experience_controls": {
"reasoning_effort": "none",
"temperature": 1,
"top_p": 1
}
}
}
}
},
"tags": [
{
"key": "text",
"value": "text"
}
],
"tool_capacity": 3,
"channel_type": "voice",
"environment": "production",
"voice_config": {
"max_buffer_delay_ms": 1,
"eager_eot_threshold": 1,
"eot_timeout_ms": 1,
"filler_style": "backchannel",
"filler_vocabulary": [
"text"
],
"backchannel_delay_ms": 400,
"max_response_sentences": 1,
"max_response_words": 1,
"barge_in_min_speech_s": 1,
"barge_in_cooldown_s": 1,
"min_tts_speed": 1,
"post_eot_pause_ms": 1,
"transition_deadline_ms": 1,
"progress_interval_ms": 1,
"empathy_hold_ms": 1,
"filler_cooldown_ms": 1,
"progress_vocabulary": [
"text"
],
"tts_provider": "cartesia",
"tts_config": {
"ANY_ADDITIONAL_PROPERTY": "anything"
},
"language_providers": {
"ANY_ADDITIONAL_PROPERTY": {
"provider": "cartesia",
"config": {
"ANY_ADDITIONAL_PROPERTY": "anything"
}
}
},
"session_provider": "amigo",
"realtime": {
"model": "gpt-realtime-2.1",
"voice": "alloy",
"speed": 1,
"noise_reduction": "near_field",
"transcription": {
"model": "gpt-transcribe",
"language": "text",
"prompt": "text"
},
"turn_detection": {
"type": "server_vad",
"threshold": 1,
"prefix_padding_ms": 1,
"silence_duration_ms": 1,
"idle_timeout_ms": 1
},
"reasoning_effort": "low",
"max_output_tokens": 1,
"truncation": {
"type": "auto",
"retention_ratio": 1,
"post_instructions_tokens": 1
},
"required_tool_on_first_caller_turn": "text"
},
"forwarding": {
"forward_to": "text",
"warm_transfer": true,
"approved_destinations": {
"ANY_ADDITIONAL_PROPERTY": "text"
}
}
},
"accepted_context": [
{
"key": "text",
"type": "string",
"description": "text",
"required": true
}
]
}{
"id": "123e4567-e89b-12d3-a456-426614174000",
"workspace_id": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"description": "text",
"agent_id": "123e4567-e89b-12d3-a456-426614174000",
"context_graph_id": "123e4567-e89b-12d3-a456-426614174000",
"agent_name": "text",
"context_graph_name": "text",
"keyterms": [
"text"
],
"is_active": true,
"version_sets": {
"ANY_ADDITIONAL_PROPERTY": {
"agent_version_number": 1,
"context_graph_version_number": 1,
"llm_model_preferences": {
"ANY_ADDITIONAL_PROPERTY": {
"llm_name": "text",
"params": {
"ANY_ADDITIONAL_PROPERTY": "anything"
},
"experience_controls": {
"reasoning_effort": "none",
"temperature": 1,
"top_p": 1
}
}
}
}
},
"tags": [
{
"key": "text",
"value": "text"
}
],
"tool_capacity": 1,
"channel_type": "voice",
"environment": "production",
"voice_config": {
"max_buffer_delay_ms": 1,
"eager_eot_threshold": 1,
"eot_timeout_ms": 1,
"filler_style": "backchannel",
"filler_vocabulary": [
"text"
],
"backchannel_delay_ms": 400,
"max_response_sentences": 1,
"max_response_words": 1,
"barge_in_min_speech_s": 1,
"barge_in_cooldown_s": 1,
"min_tts_speed": 1,
"post_eot_pause_ms": 1,
"transition_deadline_ms": 1,
"progress_interval_ms": 1,
"empathy_hold_ms": 1,
"filler_cooldown_ms": 1,
"progress_vocabulary": [
"text"
],
"tts_provider": "cartesia",
"tts_config": {
"ANY_ADDITIONAL_PROPERTY": "anything"
},
"language_providers": {
"ANY_ADDITIONAL_PROPERTY": {
"provider": "cartesia",
"config": {
"ANY_ADDITIONAL_PROPERTY": "anything"
}
}
},
"session_provider": "amigo",
"realtime": {
"model": "gpt-realtime-2.1",
"voice": "alloy",
"speed": 1,
"noise_reduction": "near_field",
"transcription": {
"model": "gpt-transcribe",
"language": "text",
"prompt": "text"
},
"turn_detection": {
"type": "server_vad",
"threshold": 1,
"prefix_padding_ms": 1,
"silence_duration_ms": 1,
"idle_timeout_ms": 1
},
"reasoning_effort": "low",
"max_output_tokens": 1,
"truncation": {
"type": "auto",
"retention_ratio": 1,
"post_instructions_tokens": 1
},
"required_tool_on_first_caller_turn": "text"
},
"forwarding": {
"forward_to": "text",
"warm_transfer": true,
"approved_destinations": {
"ANY_ADDITIONAL_PROPERTY": "text"
}
}
},
"accepted_context": [
{
"key": "text",
"type": "string",
"description": "text",
"required": true
}
],
"is_system": false,
"created_at": "2026-01-01T00:00:00.000Z",
"updated_at": "2026-01-01T00:00:00.000Z"
}List Services
Filter by agent_id or context_graph_id to find the services that run a given agent or Context Graph. Filters apply before pagination.
List services in a workspace with pagination. Filter by agent_id or context_graph_id to list the services on an agent or context graph. Requires Service.view permission.
API key issued via POST /v1/{workspace_id}/api-keys. Pass the returned api_key value as a Bearer token.
[]50Only services on this agent. Each version set pins a version of its service's agent.
Only services on this context graph. Each version set pins a version of its service's context graph.
Successful Response
Missing or invalid API key.
Insufficient permissions.
Not found.
Validation Error
GET /v1/{workspace_id}/services HTTP/1.1
Host: platform.api-us.concurrence.com
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"items": [
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"workspace_id": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"description": "text",
"agent_id": "123e4567-e89b-12d3-a456-426614174000",
"context_graph_id": "123e4567-e89b-12d3-a456-426614174000",
"agent_name": "text",
"context_graph_name": "text",
"keyterms": [
"text"
],
"is_active": true,
"version_sets": {
"ANY_ADDITIONAL_PROPERTY": {
"agent_version_number": 1,
"context_graph_version_number": 1,
"llm_model_preferences": {
"ANY_ADDITIONAL_PROPERTY": {
"llm_name": "text",
"params": {
"ANY_ADDITIONAL_PROPERTY": "anything"
},
"experience_controls": {
"reasoning_effort": "none",
"temperature": 1,
"top_p": 1
}
}
}
}
},
"tags": [
{
"key": "text",
"value": "text"
}
],
"tool_capacity": 1,
"channel_type": "voice",
"environment": "production",
"voice_config": {
"max_buffer_delay_ms": 1,
"eager_eot_threshold": 1,
"eot_timeout_ms": 1,
"filler_style": "backchannel",
"filler_vocabulary": [
"text"
],
"backchannel_delay_ms": 400,
"max_response_sentences": 1,
"max_response_words": 1,
"barge_in_min_speech_s": 1,
"barge_in_cooldown_s": 1,
"min_tts_speed": 1,
"post_eot_pause_ms": 1,
"transition_deadline_ms": 1,
"progress_interval_ms": 1,
"empathy_hold_ms": 1,
"filler_cooldown_ms": 1,
"progress_vocabulary": [
"text"
],
"tts_provider": "cartesia",
"tts_config": {
"ANY_ADDITIONAL_PROPERTY": "anything"
},
"language_providers": {
"ANY_ADDITIONAL_PROPERTY": {
"provider": "cartesia",
"config": {
"ANY_ADDITIONAL_PROPERTY": "anything"
}
}
},
"session_provider": "amigo",
"realtime": {
"model": "gpt-realtime-2.1",
"voice": "alloy",
"speed": 1,
"noise_reduction": "near_field",
"transcription": {
"model": "gpt-transcribe",
"language": "text",
"prompt": "text"
},
"turn_detection": {
"type": "server_vad",
"threshold": 1,
"prefix_padding_ms": 1,
"silence_duration_ms": 1,
"idle_timeout_ms": 1
},
"reasoning_effort": "low",
"max_output_tokens": 1,
"truncation": {
"type": "auto",
"retention_ratio": 1,
"post_instructions_tokens": 1
},
"required_tool_on_first_caller_turn": "text"
},
"forwarding": {
"forward_to": "text",
"warm_transfer": true,
"approved_destinations": {
"ANY_ADDITIONAL_PROPERTY": "text"
}
}
},
"accepted_context": [
{
"key": "text",
"type": "string",
"description": "text",
"required": true
}
],
"is_system": false,
"created_at": "2026-01-01T00:00:00.000Z",
"updated_at": "2026-01-01T00:00:00.000Z"
}
],
"has_more": true,
"continuation_token": null
}Get a Service
Retrieve a service by ID. Requires Service.view permission.
API key issued via POST /v1/{workspace_id}/api-keys. Pass the returned api_key value as a Bearer token.
Successful Response
voicePossible values: productionPossible values: falseMissing or invalid API key.
Insufficient permissions.
Not found.
Validation Error
GET /v1/{workspace_id}/services/{service_id} HTTP/1.1
Host: platform.api-us.concurrence.com
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"workspace_id": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"description": "text",
"agent_id": "123e4567-e89b-12d3-a456-426614174000",
"context_graph_id": "123e4567-e89b-12d3-a456-426614174000",
"agent_name": "text",
"context_graph_name": "text",
"keyterms": [
"text"
],
"is_active": true,
"version_sets": {
"ANY_ADDITIONAL_PROPERTY": {
"agent_version_number": 1,
"context_graph_version_number": 1,
"llm_model_preferences": {
"ANY_ADDITIONAL_PROPERTY": {
"llm_name": "text",
"params": {
"ANY_ADDITIONAL_PROPERTY": "anything"
},
"experience_controls": {
"reasoning_effort": "none",
"temperature": 1,
"top_p": 1
}
}
}
}
},
"tags": [
{
"key": "text",
"value": "text"
}
],
"tool_capacity": 1,
"channel_type": "voice",
"environment": "production",
"voice_config": {
"max_buffer_delay_ms": 1,
"eager_eot_threshold": 1,
"eot_timeout_ms": 1,
"filler_style": "backchannel",
"filler_vocabulary": [
"text"
],
"backchannel_delay_ms": 400,
"max_response_sentences": 1,
"max_response_words": 1,
"barge_in_min_speech_s": 1,
"barge_in_cooldown_s": 1,
"min_tts_speed": 1,
"post_eot_pause_ms": 1,
"transition_deadline_ms": 1,
"progress_interval_ms": 1,
"empathy_hold_ms": 1,
"filler_cooldown_ms": 1,
"progress_vocabulary": [
"text"
],
"tts_provider": "cartesia",
"tts_config": {
"ANY_ADDITIONAL_PROPERTY": "anything"
},
"language_providers": {
"ANY_ADDITIONAL_PROPERTY": {
"provider": "cartesia",
"config": {
"ANY_ADDITIONAL_PROPERTY": "anything"
}
}
},
"session_provider": "amigo",
"realtime": {
"model": "gpt-realtime-2.1",
"voice": "alloy",
"speed": 1,
"noise_reduction": "near_field",
"transcription": {
"model": "gpt-transcribe",
"language": "text",
"prompt": "text"
},
"turn_detection": {
"type": "server_vad",
"threshold": 1,
"prefix_padding_ms": 1,
"silence_duration_ms": 1,
"idle_timeout_ms": 1
},
"reasoning_effort": "low",
"max_output_tokens": 1,
"truncation": {
"type": "auto",
"retention_ratio": 1,
"post_instructions_tokens": 1
},
"required_tool_on_first_caller_turn": "text"
},
"forwarding": {
"forward_to": "text",
"warm_transfer": true,
"approved_destinations": {
"ANY_ADDITIONAL_PROPERTY": "text"
}
}
},
"accepted_context": [
{
"key": "text",
"type": "string",
"description": "text",
"required": true
}
],
"is_system": false,
"created_at": "2026-01-01T00:00:00.000Z",
"updated_at": "2026-01-01T00:00:00.000Z"
}Update a Service
Omitted top-level fields and fields sent as null leave their stored values unchanged. Explicit non-null values, including an empty description, is_active: false, or empty keyterms and tags lists, are applied when valid for the field.
A supplied voice_config object replaces the stored voice configuration. Nested nulls accepted by its schema are preserved, including forwarding.forward_to: null for dynamic forwarding. Sending voice_config: null leaves the existing configuration unchanged. Read the current configuration first and resend the complete object when changing it.
Update a service's configuration. Requires Service.update permission.
API key issued via POST /v1/{workspace_id}/api-keys. Pass the returned api_key value as a Bearer token.
Successful Response
voicePossible values: productionPossible values: falseMissing or invalid API key.
Insufficient permissions.
Not found.
Name already taken.
Invalid request body.
PUT /v1/{workspace_id}/services/{service_id} HTTP/1.1
Host: platform.api-us.concurrence.com
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 1911
{
"name": "text",
"description": "text",
"agent_id": "123e4567-e89b-12d3-a456-426614174000",
"context_graph_id": "123e4567-e89b-12d3-a456-426614174000",
"keyterms": [
"text"
],
"is_active": true,
"version_sets": {
"ANY_ADDITIONAL_PROPERTY": {
"agent_version_number": 1,
"context_graph_version_number": 1,
"llm_model_preferences": {
"ANY_ADDITIONAL_PROPERTY": {
"llm_name": "text",
"params": {
"ANY_ADDITIONAL_PROPERTY": "anything"
},
"experience_controls": {
"reasoning_effort": "none",
"temperature": 1,
"top_p": 1
}
}
}
}
},
"tags": [
{
"key": "text",
"value": "text"
}
],
"tool_capacity": 1,
"channel_type": "voice",
"environment": "sandbox",
"voice_config": {
"max_buffer_delay_ms": 1,
"eager_eot_threshold": 1,
"eot_timeout_ms": 1,
"filler_style": "backchannel",
"filler_vocabulary": [
"text"
],
"backchannel_delay_ms": 400,
"max_response_sentences": 1,
"max_response_words": 1,
"barge_in_min_speech_s": 1,
"barge_in_cooldown_s": 1,
"min_tts_speed": 1,
"post_eot_pause_ms": 1,
"transition_deadline_ms": 1,
"progress_interval_ms": 1,
"empathy_hold_ms": 1,
"filler_cooldown_ms": 1,
"progress_vocabulary": [
"text"
],
"tts_provider": "cartesia",
"tts_config": {
"ANY_ADDITIONAL_PROPERTY": "anything"
},
"language_providers": {
"ANY_ADDITIONAL_PROPERTY": {
"provider": "cartesia",
"config": {
"ANY_ADDITIONAL_PROPERTY": "anything"
}
}
},
"session_provider": "amigo",
"realtime": {
"model": "gpt-realtime-2.1",
"voice": "alloy",
"speed": 1,
"noise_reduction": "near_field",
"transcription": {
"model": "gpt-transcribe",
"language": "text",
"prompt": "text"
},
"turn_detection": {
"type": "server_vad",
"threshold": 1,
"prefix_padding_ms": 1,
"silence_duration_ms": 1,
"idle_timeout_ms": 1
},
"reasoning_effort": "low",
"max_output_tokens": 1,
"truncation": {
"type": "auto",
"retention_ratio": 1,
"post_instructions_tokens": 1
},
"required_tool_on_first_caller_turn": "text"
},
"forwarding": {
"forward_to": "text",
"warm_transfer": true,
"approved_destinations": {
"ANY_ADDITIONAL_PROPERTY": "text"
}
}
},
"accepted_context": [
{
"key": "text",
"type": "string",
"description": "text",
"required": true
}
]
}{
"id": "123e4567-e89b-12d3-a456-426614174000",
"workspace_id": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"description": "text",
"agent_id": "123e4567-e89b-12d3-a456-426614174000",
"context_graph_id": "123e4567-e89b-12d3-a456-426614174000",
"agent_name": "text",
"context_graph_name": "text",
"keyterms": [
"text"
],
"is_active": true,
"version_sets": {
"ANY_ADDITIONAL_PROPERTY": {
"agent_version_number": 1,
"context_graph_version_number": 1,
"llm_model_preferences": {
"ANY_ADDITIONAL_PROPERTY": {
"llm_name": "text",
"params": {
"ANY_ADDITIONAL_PROPERTY": "anything"
},
"experience_controls": {
"reasoning_effort": "none",
"temperature": 1,
"top_p": 1
}
}
}
}
},
"tags": [
{
"key": "text",
"value": "text"
}
],
"tool_capacity": 1,
"channel_type": "voice",
"environment": "production",
"voice_config": {
"max_buffer_delay_ms": 1,
"eager_eot_threshold": 1,
"eot_timeout_ms": 1,
"filler_style": "backchannel",
"filler_vocabulary": [
"text"
],
"backchannel_delay_ms": 400,
"max_response_sentences": 1,
"max_response_words": 1,
"barge_in_min_speech_s": 1,
"barge_in_cooldown_s": 1,
"min_tts_speed": 1,
"post_eot_pause_ms": 1,
"transition_deadline_ms": 1,
"progress_interval_ms": 1,
"empathy_hold_ms": 1,
"filler_cooldown_ms": 1,
"progress_vocabulary": [
"text"
],
"tts_provider": "cartesia",
"tts_config": {
"ANY_ADDITIONAL_PROPERTY": "anything"
},
"language_providers": {
"ANY_ADDITIONAL_PROPERTY": {
"provider": "cartesia",
"config": {
"ANY_ADDITIONAL_PROPERTY": "anything"
}
}
},
"session_provider": "amigo",
"realtime": {
"model": "gpt-realtime-2.1",
"voice": "alloy",
"speed": 1,
"noise_reduction": "near_field",
"transcription": {
"model": "gpt-transcribe",
"language": "text",
"prompt": "text"
},
"turn_detection": {
"type": "server_vad",
"threshold": 1,
"prefix_padding_ms": 1,
"silence_duration_ms": 1,
"idle_timeout_ms": 1
},
"reasoning_effort": "low",
"max_output_tokens": 1,
"truncation": {
"type": "auto",
"retention_ratio": 1,
"post_instructions_tokens": 1
},
"required_tool_on_first_caller_turn": "text"
},
"forwarding": {
"forward_to": "text",
"warm_transfer": true,
"approved_destinations": {
"ANY_ADDITIONAL_PROPERTY": "text"
}
}
},
"accepted_context": [
{
"key": "text",
"type": "string",
"description": "text",
"required": true
}
],
"is_system": false,
"created_at": "2026-01-01T00:00:00.000Z",
"updated_at": "2026-01-01T00:00:00.000Z"
}Delete a Service
Delete a service. Requires Service.delete permission.
API key issued via POST /v1/{workspace_id}/api-keys. Pass the returned api_key value as a Bearer token.
Successful Response
No content
Missing or invalid API key.
Insufficient permissions.
Not found.
Validation Error
DELETE /v1/{workspace_id}/services/{service_id} HTTP/1.1
Host: platform.api-us.concurrence.com
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
No content
Upsert a Version Set
Replace or create a named version set on a service. The name and pinned agent and context graph versions are validated.
API key issued via POST /v1/{workspace_id}/api-keys. Pass the returned api_key value as a Bearer token.
Version set name (e.g. 'release')
Successful Response
No content
Missing or invalid API key.
Insufficient permissions.
Not found.
Name already taken.
Invalid request body.
PUT /v1/{workspace_id}/services/{service_id}/version-sets/{name} HTTP/1.1
Host: platform.api-us.concurrence.com
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 271
{
"version_set": {
"agent_version_number": 1,
"context_graph_version_number": 1,
"llm_model_preferences": {
"ANY_ADDITIONAL_PROPERTY": {
"llm_name": "text",
"params": {
"ANY_ADDITIONAL_PROPERTY": "anything"
},
"experience_controls": {
"reasoning_effort": "none",
"temperature": 1,
"top_p": 1
}
}
}
}
}No content
Process a Voice-Note Turn
Run one WhatsApp-style voice-note turn against the service's agent.
Accepts OGG Opus audio (or any format Deepgram's prerecorded endpoint
accepts). Server keys the conversation on (workspace, service, phone_number) and returns the agent's spoken reply as OGG Opus — or WAV
PCM16 when the Accept header prefers audio/wav.
API key issued via POST /v1/{workspace_id}/api-keys. Pass the returned api_key value as a Bearer token.
^\+[1-9]\d{1,14}$Agent spoken reply — OGG Opus by default, WAV PCM16 (16 kHz mono) when the request's Accept header prefers audio/wav
Agent elected silence
Concurrent voice turn in progress for this speaker
Validation Error
POST /v1/{workspace_id}/services/{service_id}/voice-turn HTTP/1.1
Host: platform.api-us.concurrence.com
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: multipart/form-data
Accept: */*
Content-Length: 38
{
"audio": "text",
"phone_number": "text"
}No content
Text Conversations
The former service text-turn endpoint has been removed. Use Conversations for application-hosted text and the managed channel integrations for SMS and WhatsApp.
Accepted Conversation Context
Declare accepted_context on the service's create or update request. Each entry specifies a unique key, a type of string or number, a description, and a required flag. Conversation creation validates its parsed context map against this schema; unknown keys, missing required keys, and values that fail this validation return 422. The guide below also covers a boolean-coercion edge case in request parsing.
Update the service with PUT /v1/{workspace_id}/services/{service_id}. A supplied accepted_context list replaces the entire previous list. Omission or null preserves it; [] accepts no caller-supplied context keys. Coordinate newly required keys with callers before changing a shared service.
The service declares the schema; the active Context Graph's state-to-tool specification declares context_bindings. Follow Pass Context to Tool Parameters for a complete setup, supported tool paths, and mapped parameter names and automatic channel-id prerequisites.
The same declaration governs values a trusted backend sets on a live voice call. Declare such a key with required: false; on voice, a tool bound to it refuses to run until it is set. See Set Context on a Live Voice Call.
Version Sets
Creating a service, updating it, and upserting a version set all check the version sets they write. A version set name must match [A-Za-z0-9_-]{1,40}, or the request returns 422. Each pinned agent and Context Graph version must exist for the service's agent and graph, or the request returns 404. Changing a service's agent_id or context_graph_id checks its stored pins against the new target.
Version sets support an optional llm_model_preferences map that overrides the default models used for context graph navigation and conversational engagement. Each key identifies a model role: use nav for navigation and engage for response generation. Each value specifies the preferred model and optional parameters for that role. When omitted, sessions use the platform defaults.
This lets you pin specific agent versions to specific models for controlled rollouts, A/B testing, or compliance requirements that mandate a fixed model version.
Model preference resolution order
Version set override - If the active version set has an
llm_model_preferencesentry for the relevant role, that model is used.Platform default - If no override is configured, the platform default model is used.
The resolved model is applied consistently across voice sessions, text sessions, and simulation runs.
Tool Turns and Reasoning Effort
On gpt-5.4, gpt-5.5, gpt-5.6, and gpt-6 engage models, a turn that offers the model tools is sent at reasoning_effort none, the only effort those models accept with tools. A turn without tools uses the configured effort.
Because a higher effort would not be honored on tool turns, creating or updating a service, or upserting a version set, returns 422 when an engage preference for one of these models sets reasoning_effort above none in params or experience_controls. The message names the version set, the preference, and the model. Leave the effort unset or set it to none. A version set saved before this check still loads, but its next save fails until the effort is fixed.
Version sets enable safe iteration, like Git branches for your service configuration:
release: the required default version set used when clients do not specify one. Service creation adds an unpinnedreleaseset whenversion_setsis omitted or empty.Custom sets: create named sets (for example,
personal-dev,test, orpreview) for your promotion workflow. Leaving a version number unset resolves the latest available version at runtime.
The recommended promotion path: personal-dev → test → preview → release
Manage Platform version sets through service updates or the single-version upsert endpoint. Agent Forge also provides forge platform version-set commands for listing, inspecting, upserting, comparing, promoting, and rolling back sets. Mutating commands are dry-run by default and require --apply to execute.
Structured Actions
Context Graph action states use a structured Action model. Each action and exit condition can carry a filler_hint, a semantic direction that guides the voice pipeline's filler generation alongside emotional context and latency state.
Voice Configuration
Session Provider
The voice_config.session_provider field controls which voice session runtime drives calls for a service. Supported values:
amigo
Concurrence's own voice pipeline (STT, reasoning, TTS). The default.
gpt_realtime
GPT realtime speech-to-speech model family
When the service field is unset, it inherits the agent-level provider and then the environment default, which is normally amigo. The session provider can also be set on the service detail page in the Console.
The platform resolves the session provider with the following precedence: service > agent > environment default.
voice_config is an optional field on the service model that controls how the voice pipeline behaves for that service. It covers latency tuning, filler behavior, response length, barge-in sensitivity, and tool access. If omitted, the service has no service-level overrides. See Voice Configuration for field-level inheritance and defaults.
Fields
Latency
max_buffer_delay_ms
int (200 to 1000)
500
How long the pipeline buffers text before sending to TTS. Lower values feel snappier but may produce choppier speech.
eager_eot_threshold
float (0.0 to 1.0)
-
End-of-turn sensitivity. Higher values make the system more aggressive about detecting when the caller has stopped talking.
eot_timeout_ms
int
-
Hard timeout for end-of-turn detection in milliseconds.
Fillers
filler_style
"backchannel", "phrase", or "silent"
"backchannel"
Only silent changes runtime behavior: it mutes the agent's autonomous backchannels. backchannel and phrase are currently advisory, and Context Graph progress phrases still play under silent. See Voice Configuration.
filler_vocabulary
list[str]
-
Custom words for the short acknowledgment played when navigation is skipped. Tool-wait phrases come from progress_vocabulary or Context Graph progress phrases.
backchannel_delay_ms
int
400
Delay before emitting a backchannel filler when navigation is skipped. Controls how quickly the agent acknowledges the caller.
Response
max_response_sentences
int
-
Streamed-response sentence cap. Counting is approximate across streamed fragments.
max_response_words
int
-
Streamed-response word cap, enforced while consuming generated text.
Barge-in
barge_in_min_speech_s
float
0.5
Minimum speech duration before the caller can interrupt the agent. Lower values make barge-in more sensitive. Setting this too low causes false interrupts from breath sounds or "um".
barge_in_cooldown_s
float
1.5
Cooldown period after a barge-in before another one can trigger. Prevents rapid-fire interruptions.
Speed
min_tts_speed
float (0.5 to 1.0)
-
Minimum TTS speed multiplier. When the emotion engine reduces speech rate in response to caller distress, it cannot go below this value. The empathy formula produces speeds in the 0.85-0.97 range; set this somewhere in that band if the agent sounds unnaturally slow after emotional turns. Omit to use the default unclamped behavior.
Call Forwarding
Configure forwarding in voice_config.forwarding. Omitting that block or setting it to null leaves the forwarding tool unavailable. When present, choose warm or cold transfer explicitly and configure either a fixed destination or dynamic destination mode. There is no workspace-number fallback.
Dynamic mode (forward_to: null) dials only the numbers listed in approved_destinations, a map of E.164 number to label with up to 50 entries. A dynamic block with no approved destinations offers no forward_call tool, and approved_destinations with a fixed forward_to returns 422. See Call Forwarding for an example.
The removed forward_call_enabled flag is not the current enablement control. The embedded service schema is authoritative for the forwarding object. Active turn policy can further restrict forwarding. See Call Forwarding for the hold and answer-handling sequence.
Presets
Agent Forge provides four named presets:
ultra_low_latency
200ms
backchannel
400ms
1 sentence
balanced
500ms
defaults
defaults
-
quality
500ms
phrase
defaults
-
gpt_realtime
n/a
n/a
n/a
n/a
Presets no longer select a Cartesia model. The service tts_model field they set was removed on October 9, 2026, so a sent value is ignored. Pin a model in tts_config.model; see Default TTS Model.
Example
Include voice_config when creating or updating a service:
CLI
Apply a preset:
Set config fields (the body replaces the stored voice config as a whole - read the current config first and include every field you want to keep):
Read current config:
API
Use Update a Service with the voice_config field in the request body. The field replaces the stored voice config as a whole. Omitted fields resolve through their field-specific defaults or inheritance rules. Read the current config first (--get or Get a Service) and resend the full object with your changes.
Turn-Level Emotion
On each turn, the voice pipeline selects an emotional tone alongside the state transition and applies it to the entire utterance - filler and main response share the same tone, so the whole turn has consistent prosody with no mid-sentence shifts. See Voice Configuration for the available emotions and how the empathy system can override the selection, and Voice Agent for the emotional adaptation behavior.
Last updated
Was this helpful?

