# Services

## List services

> List services in a workspace with pagination. Requires \`Service.view\` permission.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"SearchString":{"type":"string","maxLength":200,"minLength":1},"PaginatedResponse_ServiceResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ServiceResponse"},"type":"array","title":"Items"},"has_more":{"type":"boolean","title":"Has More"},"continuation_token":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Continuation Token"},"total":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total"}},"type":"object","required":["items","has_more"],"title":"PaginatedResponse[ServiceResponse]"},"ServiceResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"agent_id":{"type":"string","format":"uuid","title":"Agent Id"},"context_graph_id":{"type":"string","format":"uuid","title":"Context Graph Id"},"agent_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agent Name"},"context_graph_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Context Graph Name"},"keyterms":{"items":{"type":"string"},"type":"array","title":"Keyterms"},"is_active":{"type":"boolean","title":"Is Active"},"version_sets":{"additionalProperties":{"$ref":"#/components/schemas/VersionSet-Output"},"type":"object","title":"Version Sets"},"tags":{"items":{"$ref":"#/components/schemas/ServiceTag"},"type":"array","title":"Tags"},"tool_capacity":{"type":"integer","title":"Tool Capacity"},"safety_filters_enabled":{"type":"boolean","title":"Safety Filters Enabled","default":true},"channel_type":{"type":"string","enum":["voice","text"],"title":"Channel Type","default":"voice"},"environment":{"type":"string","enum":["sandbox","production"],"title":"Environment","default":"production"},"voice_config":{"anyOf":[{"$ref":"#/components/schemas/ServiceVoiceConfig-Output"},{"type":"null"}]},"escalation_policy":{"anyOf":[{"$ref":"#/components/schemas/EscalationPolicy"},{"type":"null"}]},"is_system":{"type":"boolean","title":"Is System","default":false},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","workspace_id","name","description","agent_id","context_graph_id","keyterms","is_active","version_sets","tags","tool_capacity","created_at","updated_at"],"title":"ServiceResponse"},"VersionSet-Output":{"properties":{"agent_version_number":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Agent Version Number"},"context_graph_version_number":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Context Graph Version Number"},"llm_model_preferences":{"additionalProperties":{"$ref":"#/components/schemas/LLMConfig"},"type":"object","title":"Llm Model Preferences"}},"type":"object","title":"VersionSet","description":"Pins agent, state machine, and LLM model versions for a service."},"LLMConfig":{"properties":{"llm_name":{"type":"string","title":"Llm Name"},"params":{"additionalProperties":true,"type":"object","title":"Params"},"experience_controls":{"anyOf":[{"$ref":"#/components/schemas/LLMExperienceControls"},{"type":"null"}]}},"type":"object","required":["llm_name"],"title":"LLMConfig"},"LLMExperienceControls":{"properties":{"verbosity":{"anyOf":[{"type":"string","enum":["low","medium","high"]},{"type":"null"}],"title":"Verbosity"},"reasoning_effort":{"anyOf":[{"type":"string","enum":["none","minimal","low","medium","high","xhigh"]},{"type":"null"}],"title":"Reasoning Effort"},"temperature":{"anyOf":[{"type":"number","maximum":2,"minimum":0},{"type":"null"}],"title":"Temperature"},"top_p":{"anyOf":[{"type":"number","maximum":1,"minimum":0},{"type":"null"}],"title":"Top P"},"presence_penalty":{"anyOf":[{"type":"number","maximum":2,"minimum":-2},{"type":"null"}],"title":"Presence Penalty"},"frequency_penalty":{"anyOf":[{"type":"number","maximum":2,"minimum":-2},{"type":"null"}],"title":"Frequency Penalty"},"response_format":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Response Format"},"seed":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Seed"},"stop":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Stop"},"logit_bias":{"anyOf":[{"additionalProperties":{"type":"number","maximum":100,"minimum":-100},"type":"object"},{"type":"null"}],"title":"Logit Bias"},"logprobs":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Logprobs"},"top_logprobs":{"anyOf":[{"type":"integer","maximum":20,"minimum":0},{"type":"null"}],"title":"Top Logprobs"},"parallel_tool_calls":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Parallel Tool Calls"},"service_tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service Tier"},"prompt_cache_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt Cache Key"},"prompt_cache_retention":{"anyOf":[{"type":"string","enum":["in-memory","24h"]},{"type":"null"}],"title":"Prompt Cache Retention"},"safety_identifier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Safety Identifier"},"store":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Store"},"metadata":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Metadata"}},"additionalProperties":false,"type":"object","title":"LLMExperienceControls","description":"First-class chat experience controls for consumer-facing agents.\n\n``params`` remains available as a provider-specific escape hatch. These\nfields cover the OpenAI Chat Completions controls that most directly shape\nresponse tone, feel, determinism, latency, and structured output behavior.\nToken budgets are intentionally excluded so version sets do not reintroduce\naccidental response truncation."},"ServiceTag":{"properties":{"key":{"type":"string","title":"Key"},"value":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Value"}},"type":"object","required":["key"],"title":"ServiceTag"},"ServiceVoiceConfig-Output":{"properties":{"tts_model":{"anyOf":[{"type":"string","enum":["sonic-turbo","sonic-3"]},{"type":"null"}],"title":"Tts Model"},"max_buffer_delay_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Buffer Delay Ms"},"eager_eot_threshold":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Eager Eot Threshold"},"eot_timeout_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Eot Timeout Ms"},"filler_style":{"type":"string","enum":["backchannel","phrase","silent"],"title":"Filler Style","default":"backchannel"},"filler_vocabulary":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Filler Vocabulary"},"backchannel_delay_ms":{"type":"integer","title":"Backchannel Delay Ms","default":400},"max_response_sentences":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Response Sentences"},"max_response_words":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Response Words"},"barge_in_min_speech_s":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Barge In Min Speech S"},"barge_in_cooldown_s":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Barge In Cooldown S"},"min_tts_speed":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Tts Speed"},"post_eot_pause_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Post Eot Pause Ms"},"transition_deadline_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Transition Deadline Ms"},"progress_interval_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Progress Interval Ms"},"empathy_hold_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Empathy Hold Ms"},"filler_cooldown_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Filler Cooldown Ms"},"progress_vocabulary":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Progress Vocabulary"},"tts_provider":{"anyOf":[{"type":"string","enum":["cartesia","elevenlabs","groq"]},{"type":"null"}],"title":"Tts Provider"},"tts_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Tts Config"},"language_providers":{"anyOf":[{"additionalProperties":{"$ref":"#/components/schemas/LanguageProviderEntry"},"type":"object","maxProperties":10},{"type":"null"}],"title":"Language Providers"},"forward_call_enabled":{"type":"boolean","title":"Forward Call Enabled","default":false},"forwarding":{"anyOf":[{"$ref":"#/components/schemas/ServiceForwardingConfig"},{"type":"null"}]}},"type":"object","title":"ServiceVoiceConfig","description":"Per-service voice pipeline tuning. Overrides workspace/env defaults.\n\nEach field is optional — None means inherit from the layer above\n(workspace VoiceSettings → env vars → hardcoded defaults)."},"LanguageProviderEntry":{"properties":{"provider":{"type":"string","enum":["cartesia","elevenlabs","groq"],"title":"Provider"},"config":{"additionalProperties":true,"type":"object","maxProperties":20,"title":"Config"}},"type":"object","required":["provider"],"title":"LanguageProviderEntry","description":"Per-language TTS provider configuration."},"ServiceForwardingConfig":{"properties":{"forward_to":{"$ref":"#/components/schemas/PhoneE164"},"should_disconnect":{"type":"boolean","title":"Should Disconnect","default":true},"warm_transfer":{"type":"boolean","title":"Warm Transfer","default":true}},"type":"object","required":["forward_to"],"title":"ServiceForwardingConfig","description":"Per-service call-forwarding destination + transfer mechanism.\n\nRead by:\n  - LLM-driven ``forward_call`` tool (tier 3 fallback when the LLM doesn't\n    pass an explicit ``phone_number`` and no EHR location is configured).\n  - ``EscalationPolicy.ForwardAction`` — engine-fired escalation with no\n    overrides falls through to the same path.\n\nDistinct from ``platform_lib.phone_numbers.ForwardingConfig`` (per-phone\nlegacy shape with ``enabled``); per-service forwarding is a binary\npresence — set means tier 3 resolves to it, None means tier 3 has no\nstatic target."},"PhoneE164":{"type":"string","maxLength":16,"minLength":2},"EscalationPolicy":{"properties":{"context_window_exhaustion":{"oneOf":[{"$ref":"#/components/schemas/OperatorAction"},{"$ref":"#/components/schemas/ForwardAction"},{"$ref":"#/components/schemas/HangupAction"}],"title":"Context Window Exhaustion","discriminator":{"propertyName":"type","mapping":{"forward":"#/components/schemas/ForwardAction","hangup":"#/components/schemas/HangupAction","operator":"#/components/schemas/OperatorAction"}}},"risk_scorer":{"oneOf":[{"$ref":"#/components/schemas/OperatorAction"},{"$ref":"#/components/schemas/ForwardAction"},{"$ref":"#/components/schemas/HangupAction"}],"title":"Risk Scorer","discriminator":{"propertyName":"type","mapping":{"forward":"#/components/schemas/ForwardAction","hangup":"#/components/schemas/HangupAction","operator":"#/components/schemas/OperatorAction"}}},"conversation_monitor":{"oneOf":[{"$ref":"#/components/schemas/OperatorAction"},{"$ref":"#/components/schemas/ForwardAction"},{"$ref":"#/components/schemas/HangupAction"}],"title":"Conversation Monitor","discriminator":{"propertyName":"type","mapping":{"forward":"#/components/schemas/ForwardAction","hangup":"#/components/schemas/HangupAction","operator":"#/components/schemas/OperatorAction"}}}},"type":"object","title":"EscalationPolicy","description":"Per-service routing for engine-detected escalation triggers.\n\nEach trigger source maps to one EscalationAction. The three enumerated\nfields below are the trigger_sources actually emitted by the agent-engine\ntoday; new triggers can be added as fields without breaking back-compat.\n\nPartial policies are intentional: every field defaults to OperatorAction,\nso a PUT body like ``{\"context_window_exhaustion\": {\"type\": \"forward\"}}``\noverrides only that trigger and leaves the others on the operator default.\nTo opt the entire service back to today's behavior, set\n``Service.escalation_policy = None`` (caveat: the platform-api Service\nupdate path uses ``exclude_none=True`` and currently has no clears-via-null\nbranch, so this requires a direct config edit; see follow-up issue).\n\nResolution lookup is done against ``model_fields``: a trigger_source that\nis not an enumerated field name falls through to OperatorAction, never\na non-Action Pydantic internal."},"OperatorAction":{"properties":{"type":{"type":"string","const":"operator","title":"Type","default":"operator"}},"type":"object","title":"OperatorAction","description":"Today's behavior — write escalation.requested + publish SSE, wait for a\nhuman operator to join via the dashboard. No-op if no operators are staffed."},"ForwardAction":{"properties":{"type":{"type":"string","const":"forward","title":"Type","default":"forward"}},"type":"object","title":"ForwardAction","description":"Cold-transfer the caller to the service's configured forwarding\ndestination (set via ``Service.voice_config.forwarding``).\n\nNo agent-side decision and no operator dashboard required — the engine\ninvokes the same forwarding callback used by the LLM-driven\n``forward_call`` tool, with no location override, which falls through to\nthe per-service ``ServiceForwardingConfig``.\n\nIf ``voice_config.forwarding`` is unset, the dispatcher falls back to the\noperator path (audit event + SSE only)."},"HangupAction":{"properties":{"type":{"type":"string","const":"hangup","title":"Type","default":"hangup"}},"type":"object","title":"HangupAction","description":"End the call gracefully via the existing speaker-drain hangup path."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}},"paths":{"/v1/{workspace_id}/services":{"get":{"tags":["Services"],"summary":"List services","description":"List services in a workspace with pagination. Requires `Service.view` permission.","operationId":"list-services","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SearchString"},{"type":"null"}],"title":"Search"}},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sort By"}},{"name":"is_active","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"exclusiveMinimum":0,"default":10,"title":"Limit"}},{"name":"continuation_token","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Continuation Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_ServiceResponse_"}}}},"401":{"description":"Missing or invalid API key."},"403":{"description":"Insufficient permissions."},"404":{"description":"Not found."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}}}
```

## Create a service

> Create a new service linking an agent and HSM. Validates that agent\_id and context\_graph\_id exist in the workspace. Requires \`Service.create\` permission.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"CreateServiceRequest":{"properties":{"name":{"$ref":"#/components/schemas/NameString"},"description":{"$ref":"#/components/schemas/DescriptionString","default":""},"agent_id":{"type":"string","format":"uuid","title":"Agent Id"},"context_graph_id":{"type":"string","format":"uuid","title":"Context Graph Id"},"keyterms":{"items":{"type":"string","maxLength":128,"minLength":1},"type":"array","maxItems":500,"title":"Keyterms"},"is_active":{"type":"boolean","title":"Is Active","default":true},"version_sets":{"additionalProperties":{"$ref":"#/components/schemas/VersionSet-Input"},"type":"object","title":"Version Sets","default":{}},"tags":{"items":{"$ref":"#/components/schemas/ServiceTag"},"type":"array","maxItems":50,"title":"Tags"},"tool_capacity":{"type":"integer","maximum":10,"minimum":1,"title":"Tool Capacity","default":3},"safety_filters_enabled":{"type":"boolean","title":"Safety Filters Enabled","default":true},"channel_type":{"type":"string","enum":["voice","text"],"title":"Channel Type","default":"voice"},"environment":{"type":"string","enum":["sandbox","production"],"title":"Environment","default":"production"},"voice_config":{"anyOf":[{"$ref":"#/components/schemas/ServiceVoiceConfig-Input"},{"type":"null"}]},"escalation_policy":{"anyOf":[{"$ref":"#/components/schemas/EscalationPolicy"},{"type":"null"}]}},"type":"object","required":["name","agent_id","context_graph_id"],"title":"CreateServiceRequest"},"NameString":{"type":"string","maxLength":256,"minLength":1},"DescriptionString":{"type":"string","maxLength":2000},"VersionSet-Input":{"properties":{"agent_version_number":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Agent Version Number"},"context_graph_version_number":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Context Graph Version Number"},"llm_model_preferences":{"additionalProperties":{"$ref":"#/components/schemas/LLMConfig"},"type":"object","title":"Llm Model Preferences"}},"type":"object","title":"VersionSet","description":"Pins agent, state machine, and LLM model versions for a service."},"LLMConfig":{"properties":{"llm_name":{"type":"string","title":"Llm Name"},"params":{"additionalProperties":true,"type":"object","title":"Params"},"experience_controls":{"anyOf":[{"$ref":"#/components/schemas/LLMExperienceControls"},{"type":"null"}]}},"type":"object","required":["llm_name"],"title":"LLMConfig"},"LLMExperienceControls":{"properties":{"verbosity":{"anyOf":[{"type":"string","enum":["low","medium","high"]},{"type":"null"}],"title":"Verbosity"},"reasoning_effort":{"anyOf":[{"type":"string","enum":["none","minimal","low","medium","high","xhigh"]},{"type":"null"}],"title":"Reasoning Effort"},"temperature":{"anyOf":[{"type":"number","maximum":2,"minimum":0},{"type":"null"}],"title":"Temperature"},"top_p":{"anyOf":[{"type":"number","maximum":1,"minimum":0},{"type":"null"}],"title":"Top P"},"presence_penalty":{"anyOf":[{"type":"number","maximum":2,"minimum":-2},{"type":"null"}],"title":"Presence Penalty"},"frequency_penalty":{"anyOf":[{"type":"number","maximum":2,"minimum":-2},{"type":"null"}],"title":"Frequency Penalty"},"response_format":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Response Format"},"seed":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Seed"},"stop":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Stop"},"logit_bias":{"anyOf":[{"additionalProperties":{"type":"number","maximum":100,"minimum":-100},"type":"object"},{"type":"null"}],"title":"Logit Bias"},"logprobs":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Logprobs"},"top_logprobs":{"anyOf":[{"type":"integer","maximum":20,"minimum":0},{"type":"null"}],"title":"Top Logprobs"},"parallel_tool_calls":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Parallel Tool Calls"},"service_tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service Tier"},"prompt_cache_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt Cache Key"},"prompt_cache_retention":{"anyOf":[{"type":"string","enum":["in-memory","24h"]},{"type":"null"}],"title":"Prompt Cache Retention"},"safety_identifier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Safety Identifier"},"store":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Store"},"metadata":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Metadata"}},"additionalProperties":false,"type":"object","title":"LLMExperienceControls","description":"First-class chat experience controls for consumer-facing agents.\n\n``params`` remains available as a provider-specific escape hatch. These\nfields cover the OpenAI Chat Completions controls that most directly shape\nresponse tone, feel, determinism, latency, and structured output behavior.\nToken budgets are intentionally excluded so version sets do not reintroduce\naccidental response truncation."},"ServiceTag":{"properties":{"key":{"type":"string","title":"Key"},"value":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Value"}},"type":"object","required":["key"],"title":"ServiceTag"},"ServiceVoiceConfig-Input":{"properties":{"tts_model":{"anyOf":[{"type":"string","enum":["sonic-turbo","sonic-3"]},{"type":"null"}],"title":"Tts Model"},"max_buffer_delay_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Buffer Delay Ms"},"eager_eot_threshold":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Eager Eot Threshold"},"eot_timeout_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Eot Timeout Ms"},"filler_style":{"type":"string","enum":["backchannel","phrase","silent"],"title":"Filler Style","default":"backchannel"},"filler_vocabulary":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Filler Vocabulary"},"backchannel_delay_ms":{"type":"integer","title":"Backchannel Delay Ms","default":400},"max_response_sentences":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Response Sentences"},"max_response_words":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Response Words"},"barge_in_min_speech_s":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Barge In Min Speech S"},"barge_in_cooldown_s":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Barge In Cooldown S"},"min_tts_speed":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Tts Speed"},"post_eot_pause_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Post Eot Pause Ms"},"transition_deadline_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Transition Deadline Ms"},"progress_interval_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Progress Interval Ms"},"empathy_hold_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Empathy Hold Ms"},"filler_cooldown_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Filler Cooldown Ms"},"progress_vocabulary":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Progress Vocabulary"},"tts_provider":{"anyOf":[{"type":"string","enum":["cartesia","elevenlabs","groq"]},{"type":"null"}],"title":"Tts Provider"},"tts_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Tts Config"},"language_providers":{"anyOf":[{"additionalProperties":{"$ref":"#/components/schemas/LanguageProviderEntry"},"type":"object","maxProperties":10},{"type":"null"}],"title":"Language Providers"},"forward_call_enabled":{"type":"boolean","title":"Forward Call Enabled","default":false},"forwarding":{"anyOf":[{"$ref":"#/components/schemas/ServiceForwardingConfig"},{"type":"null"}]}},"type":"object","title":"ServiceVoiceConfig","description":"Per-service voice pipeline tuning. Overrides workspace/env defaults.\n\nEach field is optional — None means inherit from the layer above\n(workspace VoiceSettings → env vars → hardcoded defaults)."},"LanguageProviderEntry":{"properties":{"provider":{"type":"string","enum":["cartesia","elevenlabs","groq"],"title":"Provider"},"config":{"additionalProperties":true,"type":"object","maxProperties":20,"title":"Config"}},"type":"object","required":["provider"],"title":"LanguageProviderEntry","description":"Per-language TTS provider configuration."},"ServiceForwardingConfig":{"properties":{"forward_to":{"$ref":"#/components/schemas/PhoneE164"},"should_disconnect":{"type":"boolean","title":"Should Disconnect","default":true},"warm_transfer":{"type":"boolean","title":"Warm Transfer","default":true}},"type":"object","required":["forward_to"],"title":"ServiceForwardingConfig","description":"Per-service call-forwarding destination + transfer mechanism.\n\nRead by:\n  - LLM-driven ``forward_call`` tool (tier 3 fallback when the LLM doesn't\n    pass an explicit ``phone_number`` and no EHR location is configured).\n  - ``EscalationPolicy.ForwardAction`` — engine-fired escalation with no\n    overrides falls through to the same path.\n\nDistinct from ``platform_lib.phone_numbers.ForwardingConfig`` (per-phone\nlegacy shape with ``enabled``); per-service forwarding is a binary\npresence — set means tier 3 resolves to it, None means tier 3 has no\nstatic target."},"PhoneE164":{"type":"string","maxLength":16,"minLength":2},"EscalationPolicy":{"properties":{"context_window_exhaustion":{"oneOf":[{"$ref":"#/components/schemas/OperatorAction"},{"$ref":"#/components/schemas/ForwardAction"},{"$ref":"#/components/schemas/HangupAction"}],"title":"Context Window Exhaustion","discriminator":{"propertyName":"type","mapping":{"forward":"#/components/schemas/ForwardAction","hangup":"#/components/schemas/HangupAction","operator":"#/components/schemas/OperatorAction"}}},"risk_scorer":{"oneOf":[{"$ref":"#/components/schemas/OperatorAction"},{"$ref":"#/components/schemas/ForwardAction"},{"$ref":"#/components/schemas/HangupAction"}],"title":"Risk Scorer","discriminator":{"propertyName":"type","mapping":{"forward":"#/components/schemas/ForwardAction","hangup":"#/components/schemas/HangupAction","operator":"#/components/schemas/OperatorAction"}}},"conversation_monitor":{"oneOf":[{"$ref":"#/components/schemas/OperatorAction"},{"$ref":"#/components/schemas/ForwardAction"},{"$ref":"#/components/schemas/HangupAction"}],"title":"Conversation Monitor","discriminator":{"propertyName":"type","mapping":{"forward":"#/components/schemas/ForwardAction","hangup":"#/components/schemas/HangupAction","operator":"#/components/schemas/OperatorAction"}}}},"type":"object","title":"EscalationPolicy","description":"Per-service routing for engine-detected escalation triggers.\n\nEach trigger source maps to one EscalationAction. The three enumerated\nfields below are the trigger_sources actually emitted by the agent-engine\ntoday; new triggers can be added as fields without breaking back-compat.\n\nPartial policies are intentional: every field defaults to OperatorAction,\nso a PUT body like ``{\"context_window_exhaustion\": {\"type\": \"forward\"}}``\noverrides only that trigger and leaves the others on the operator default.\nTo opt the entire service back to today's behavior, set\n``Service.escalation_policy = None`` (caveat: the platform-api Service\nupdate path uses ``exclude_none=True`` and currently has no clears-via-null\nbranch, so this requires a direct config edit; see follow-up issue).\n\nResolution lookup is done against ``model_fields``: a trigger_source that\nis not an enumerated field name falls through to OperatorAction, never\na non-Action Pydantic internal."},"OperatorAction":{"properties":{"type":{"type":"string","const":"operator","title":"Type","default":"operator"}},"type":"object","title":"OperatorAction","description":"Today's behavior — write escalation.requested + publish SSE, wait for a\nhuman operator to join via the dashboard. No-op if no operators are staffed."},"ForwardAction":{"properties":{"type":{"type":"string","const":"forward","title":"Type","default":"forward"}},"type":"object","title":"ForwardAction","description":"Cold-transfer the caller to the service's configured forwarding\ndestination (set via ``Service.voice_config.forwarding``).\n\nNo agent-side decision and no operator dashboard required — the engine\ninvokes the same forwarding callback used by the LLM-driven\n``forward_call`` tool, with no location override, which falls through to\nthe per-service ``ServiceForwardingConfig``.\n\nIf ``voice_config.forwarding`` is unset, the dispatcher falls back to the\noperator path (audit event + SSE only)."},"HangupAction":{"properties":{"type":{"type":"string","const":"hangup","title":"Type","default":"hangup"}},"type":"object","title":"HangupAction","description":"End the call gracefully via the existing speaker-drain hangup path."},"ServiceResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"agent_id":{"type":"string","format":"uuid","title":"Agent Id"},"context_graph_id":{"type":"string","format":"uuid","title":"Context Graph Id"},"agent_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agent Name"},"context_graph_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Context Graph Name"},"keyterms":{"items":{"type":"string"},"type":"array","title":"Keyterms"},"is_active":{"type":"boolean","title":"Is Active"},"version_sets":{"additionalProperties":{"$ref":"#/components/schemas/VersionSet-Output"},"type":"object","title":"Version Sets"},"tags":{"items":{"$ref":"#/components/schemas/ServiceTag"},"type":"array","title":"Tags"},"tool_capacity":{"type":"integer","title":"Tool Capacity"},"safety_filters_enabled":{"type":"boolean","title":"Safety Filters Enabled","default":true},"channel_type":{"type":"string","enum":["voice","text"],"title":"Channel Type","default":"voice"},"environment":{"type":"string","enum":["sandbox","production"],"title":"Environment","default":"production"},"voice_config":{"anyOf":[{"$ref":"#/components/schemas/ServiceVoiceConfig-Output"},{"type":"null"}]},"escalation_policy":{"anyOf":[{"$ref":"#/components/schemas/EscalationPolicy"},{"type":"null"}]},"is_system":{"type":"boolean","title":"Is System","default":false},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","workspace_id","name","description","agent_id","context_graph_id","keyterms","is_active","version_sets","tags","tool_capacity","created_at","updated_at"],"title":"ServiceResponse"},"VersionSet-Output":{"properties":{"agent_version_number":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Agent Version Number"},"context_graph_version_number":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Context Graph Version Number"},"llm_model_preferences":{"additionalProperties":{"$ref":"#/components/schemas/LLMConfig"},"type":"object","title":"Llm Model Preferences"}},"type":"object","title":"VersionSet","description":"Pins agent, state machine, and LLM model versions for a service."},"ServiceVoiceConfig-Output":{"properties":{"tts_model":{"anyOf":[{"type":"string","enum":["sonic-turbo","sonic-3"]},{"type":"null"}],"title":"Tts Model"},"max_buffer_delay_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Buffer Delay Ms"},"eager_eot_threshold":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Eager Eot Threshold"},"eot_timeout_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Eot Timeout Ms"},"filler_style":{"type":"string","enum":["backchannel","phrase","silent"],"title":"Filler Style","default":"backchannel"},"filler_vocabulary":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Filler Vocabulary"},"backchannel_delay_ms":{"type":"integer","title":"Backchannel Delay Ms","default":400},"max_response_sentences":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Response Sentences"},"max_response_words":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Response Words"},"barge_in_min_speech_s":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Barge In Min Speech S"},"barge_in_cooldown_s":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Barge In Cooldown S"},"min_tts_speed":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Tts Speed"},"post_eot_pause_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Post Eot Pause Ms"},"transition_deadline_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Transition Deadline Ms"},"progress_interval_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Progress Interval Ms"},"empathy_hold_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Empathy Hold Ms"},"filler_cooldown_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Filler Cooldown Ms"},"progress_vocabulary":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Progress Vocabulary"},"tts_provider":{"anyOf":[{"type":"string","enum":["cartesia","elevenlabs","groq"]},{"type":"null"}],"title":"Tts Provider"},"tts_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Tts Config"},"language_providers":{"anyOf":[{"additionalProperties":{"$ref":"#/components/schemas/LanguageProviderEntry"},"type":"object","maxProperties":10},{"type":"null"}],"title":"Language Providers"},"forward_call_enabled":{"type":"boolean","title":"Forward Call Enabled","default":false},"forwarding":{"anyOf":[{"$ref":"#/components/schemas/ServiceForwardingConfig"},{"type":"null"}]}},"type":"object","title":"ServiceVoiceConfig","description":"Per-service voice pipeline tuning. Overrides workspace/env defaults.\n\nEach field is optional — None means inherit from the layer above\n(workspace VoiceSettings → env vars → hardcoded defaults)."}}},"paths":{"/v1/{workspace_id}/services":{"post":{"tags":["Services"],"summary":"Create a service","description":"Create a new service linking an agent and HSM. Validates that agent_id and context_graph_id exist in the workspace. Requires `Service.create` permission.","operationId":"create-service","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateServiceRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"}}}},"401":{"description":"Missing or invalid API key."},"403":{"description":"Insufficient permissions."},"404":{"description":"Not found."},"409":{"description":"Name already taken."},"422":{"description":"Invalid request body."}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}]}}}}
```

## Get a service

> Retrieve a service by ID. Requires \`Service.view\` permission.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"ServiceResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"agent_id":{"type":"string","format":"uuid","title":"Agent Id"},"context_graph_id":{"type":"string","format":"uuid","title":"Context Graph Id"},"agent_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agent Name"},"context_graph_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Context Graph Name"},"keyterms":{"items":{"type":"string"},"type":"array","title":"Keyterms"},"is_active":{"type":"boolean","title":"Is Active"},"version_sets":{"additionalProperties":{"$ref":"#/components/schemas/VersionSet-Output"},"type":"object","title":"Version Sets"},"tags":{"items":{"$ref":"#/components/schemas/ServiceTag"},"type":"array","title":"Tags"},"tool_capacity":{"type":"integer","title":"Tool Capacity"},"safety_filters_enabled":{"type":"boolean","title":"Safety Filters Enabled","default":true},"channel_type":{"type":"string","enum":["voice","text"],"title":"Channel Type","default":"voice"},"environment":{"type":"string","enum":["sandbox","production"],"title":"Environment","default":"production"},"voice_config":{"anyOf":[{"$ref":"#/components/schemas/ServiceVoiceConfig-Output"},{"type":"null"}]},"escalation_policy":{"anyOf":[{"$ref":"#/components/schemas/EscalationPolicy"},{"type":"null"}]},"is_system":{"type":"boolean","title":"Is System","default":false},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","workspace_id","name","description","agent_id","context_graph_id","keyterms","is_active","version_sets","tags","tool_capacity","created_at","updated_at"],"title":"ServiceResponse"},"VersionSet-Output":{"properties":{"agent_version_number":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Agent Version Number"},"context_graph_version_number":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Context Graph Version Number"},"llm_model_preferences":{"additionalProperties":{"$ref":"#/components/schemas/LLMConfig"},"type":"object","title":"Llm Model Preferences"}},"type":"object","title":"VersionSet","description":"Pins agent, state machine, and LLM model versions for a service."},"LLMConfig":{"properties":{"llm_name":{"type":"string","title":"Llm Name"},"params":{"additionalProperties":true,"type":"object","title":"Params"},"experience_controls":{"anyOf":[{"$ref":"#/components/schemas/LLMExperienceControls"},{"type":"null"}]}},"type":"object","required":["llm_name"],"title":"LLMConfig"},"LLMExperienceControls":{"properties":{"verbosity":{"anyOf":[{"type":"string","enum":["low","medium","high"]},{"type":"null"}],"title":"Verbosity"},"reasoning_effort":{"anyOf":[{"type":"string","enum":["none","minimal","low","medium","high","xhigh"]},{"type":"null"}],"title":"Reasoning Effort"},"temperature":{"anyOf":[{"type":"number","maximum":2,"minimum":0},{"type":"null"}],"title":"Temperature"},"top_p":{"anyOf":[{"type":"number","maximum":1,"minimum":0},{"type":"null"}],"title":"Top P"},"presence_penalty":{"anyOf":[{"type":"number","maximum":2,"minimum":-2},{"type":"null"}],"title":"Presence Penalty"},"frequency_penalty":{"anyOf":[{"type":"number","maximum":2,"minimum":-2},{"type":"null"}],"title":"Frequency Penalty"},"response_format":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Response Format"},"seed":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Seed"},"stop":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Stop"},"logit_bias":{"anyOf":[{"additionalProperties":{"type":"number","maximum":100,"minimum":-100},"type":"object"},{"type":"null"}],"title":"Logit Bias"},"logprobs":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Logprobs"},"top_logprobs":{"anyOf":[{"type":"integer","maximum":20,"minimum":0},{"type":"null"}],"title":"Top Logprobs"},"parallel_tool_calls":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Parallel Tool Calls"},"service_tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service Tier"},"prompt_cache_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt Cache Key"},"prompt_cache_retention":{"anyOf":[{"type":"string","enum":["in-memory","24h"]},{"type":"null"}],"title":"Prompt Cache Retention"},"safety_identifier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Safety Identifier"},"store":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Store"},"metadata":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Metadata"}},"additionalProperties":false,"type":"object","title":"LLMExperienceControls","description":"First-class chat experience controls for consumer-facing agents.\n\n``params`` remains available as a provider-specific escape hatch. These\nfields cover the OpenAI Chat Completions controls that most directly shape\nresponse tone, feel, determinism, latency, and structured output behavior.\nToken budgets are intentionally excluded so version sets do not reintroduce\naccidental response truncation."},"ServiceTag":{"properties":{"key":{"type":"string","title":"Key"},"value":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Value"}},"type":"object","required":["key"],"title":"ServiceTag"},"ServiceVoiceConfig-Output":{"properties":{"tts_model":{"anyOf":[{"type":"string","enum":["sonic-turbo","sonic-3"]},{"type":"null"}],"title":"Tts Model"},"max_buffer_delay_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Buffer Delay Ms"},"eager_eot_threshold":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Eager Eot Threshold"},"eot_timeout_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Eot Timeout Ms"},"filler_style":{"type":"string","enum":["backchannel","phrase","silent"],"title":"Filler Style","default":"backchannel"},"filler_vocabulary":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Filler Vocabulary"},"backchannel_delay_ms":{"type":"integer","title":"Backchannel Delay Ms","default":400},"max_response_sentences":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Response Sentences"},"max_response_words":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Response Words"},"barge_in_min_speech_s":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Barge In Min Speech S"},"barge_in_cooldown_s":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Barge In Cooldown S"},"min_tts_speed":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Tts Speed"},"post_eot_pause_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Post Eot Pause Ms"},"transition_deadline_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Transition Deadline Ms"},"progress_interval_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Progress Interval Ms"},"empathy_hold_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Empathy Hold Ms"},"filler_cooldown_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Filler Cooldown Ms"},"progress_vocabulary":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Progress Vocabulary"},"tts_provider":{"anyOf":[{"type":"string","enum":["cartesia","elevenlabs","groq"]},{"type":"null"}],"title":"Tts Provider"},"tts_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Tts Config"},"language_providers":{"anyOf":[{"additionalProperties":{"$ref":"#/components/schemas/LanguageProviderEntry"},"type":"object","maxProperties":10},{"type":"null"}],"title":"Language Providers"},"forward_call_enabled":{"type":"boolean","title":"Forward Call Enabled","default":false},"forwarding":{"anyOf":[{"$ref":"#/components/schemas/ServiceForwardingConfig"},{"type":"null"}]}},"type":"object","title":"ServiceVoiceConfig","description":"Per-service voice pipeline tuning. Overrides workspace/env defaults.\n\nEach field is optional — None means inherit from the layer above\n(workspace VoiceSettings → env vars → hardcoded defaults)."},"LanguageProviderEntry":{"properties":{"provider":{"type":"string","enum":["cartesia","elevenlabs","groq"],"title":"Provider"},"config":{"additionalProperties":true,"type":"object","maxProperties":20,"title":"Config"}},"type":"object","required":["provider"],"title":"LanguageProviderEntry","description":"Per-language TTS provider configuration."},"ServiceForwardingConfig":{"properties":{"forward_to":{"$ref":"#/components/schemas/PhoneE164"},"should_disconnect":{"type":"boolean","title":"Should Disconnect","default":true},"warm_transfer":{"type":"boolean","title":"Warm Transfer","default":true}},"type":"object","required":["forward_to"],"title":"ServiceForwardingConfig","description":"Per-service call-forwarding destination + transfer mechanism.\n\nRead by:\n  - LLM-driven ``forward_call`` tool (tier 3 fallback when the LLM doesn't\n    pass an explicit ``phone_number`` and no EHR location is configured).\n  - ``EscalationPolicy.ForwardAction`` — engine-fired escalation with no\n    overrides falls through to the same path.\n\nDistinct from ``platform_lib.phone_numbers.ForwardingConfig`` (per-phone\nlegacy shape with ``enabled``); per-service forwarding is a binary\npresence — set means tier 3 resolves to it, None means tier 3 has no\nstatic target."},"PhoneE164":{"type":"string","maxLength":16,"minLength":2},"EscalationPolicy":{"properties":{"context_window_exhaustion":{"oneOf":[{"$ref":"#/components/schemas/OperatorAction"},{"$ref":"#/components/schemas/ForwardAction"},{"$ref":"#/components/schemas/HangupAction"}],"title":"Context Window Exhaustion","discriminator":{"propertyName":"type","mapping":{"forward":"#/components/schemas/ForwardAction","hangup":"#/components/schemas/HangupAction","operator":"#/components/schemas/OperatorAction"}}},"risk_scorer":{"oneOf":[{"$ref":"#/components/schemas/OperatorAction"},{"$ref":"#/components/schemas/ForwardAction"},{"$ref":"#/components/schemas/HangupAction"}],"title":"Risk Scorer","discriminator":{"propertyName":"type","mapping":{"forward":"#/components/schemas/ForwardAction","hangup":"#/components/schemas/HangupAction","operator":"#/components/schemas/OperatorAction"}}},"conversation_monitor":{"oneOf":[{"$ref":"#/components/schemas/OperatorAction"},{"$ref":"#/components/schemas/ForwardAction"},{"$ref":"#/components/schemas/HangupAction"}],"title":"Conversation Monitor","discriminator":{"propertyName":"type","mapping":{"forward":"#/components/schemas/ForwardAction","hangup":"#/components/schemas/HangupAction","operator":"#/components/schemas/OperatorAction"}}}},"type":"object","title":"EscalationPolicy","description":"Per-service routing for engine-detected escalation triggers.\n\nEach trigger source maps to one EscalationAction. The three enumerated\nfields below are the trigger_sources actually emitted by the agent-engine\ntoday; new triggers can be added as fields without breaking back-compat.\n\nPartial policies are intentional: every field defaults to OperatorAction,\nso a PUT body like ``{\"context_window_exhaustion\": {\"type\": \"forward\"}}``\noverrides only that trigger and leaves the others on the operator default.\nTo opt the entire service back to today's behavior, set\n``Service.escalation_policy = None`` (caveat: the platform-api Service\nupdate path uses ``exclude_none=True`` and currently has no clears-via-null\nbranch, so this requires a direct config edit; see follow-up issue).\n\nResolution lookup is done against ``model_fields``: a trigger_source that\nis not an enumerated field name falls through to OperatorAction, never\na non-Action Pydantic internal."},"OperatorAction":{"properties":{"type":{"type":"string","const":"operator","title":"Type","default":"operator"}},"type":"object","title":"OperatorAction","description":"Today's behavior — write escalation.requested + publish SSE, wait for a\nhuman operator to join via the dashboard. No-op if no operators are staffed."},"ForwardAction":{"properties":{"type":{"type":"string","const":"forward","title":"Type","default":"forward"}},"type":"object","title":"ForwardAction","description":"Cold-transfer the caller to the service's configured forwarding\ndestination (set via ``Service.voice_config.forwarding``).\n\nNo agent-side decision and no operator dashboard required — the engine\ninvokes the same forwarding callback used by the LLM-driven\n``forward_call`` tool, with no location override, which falls through to\nthe per-service ``ServiceForwardingConfig``.\n\nIf ``voice_config.forwarding`` is unset, the dispatcher falls back to the\noperator path (audit event + SSE only)."},"HangupAction":{"properties":{"type":{"type":"string","const":"hangup","title":"Type","default":"hangup"}},"type":"object","title":"HangupAction","description":"End the call gracefully via the existing speaker-drain hangup path."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}},"paths":{"/v1/{workspace_id}/services/{service_id}":{"get":{"tags":["Services"],"summary":"Get a service","description":"Retrieve a service by ID. Requires `Service.view` permission.","operationId":"get-service","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"service_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Service Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"}}}},"401":{"description":"Missing or invalid API key."},"403":{"description":"Insufficient permissions."},"404":{"description":"Not found."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}}}
```

## Update a service

> Update a service's configuration. Requires \`Service.update\` permission.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"UpdateServiceRequest":{"properties":{"name":{"anyOf":[{"$ref":"#/components/schemas/NameString"},{"type":"null"}]},"description":{"anyOf":[{"$ref":"#/components/schemas/DescriptionString"},{"type":"null"}]},"agent_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Agent Id"},"context_graph_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Context Graph Id"},"keyterms":{"anyOf":[{"items":{"type":"string","maxLength":128,"minLength":1},"type":"array","maxItems":500},{"type":"null"}],"title":"Keyterms"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"},"version_sets":{"anyOf":[{"additionalProperties":{"$ref":"#/components/schemas/VersionSet-Input"},"type":"object"},{"type":"null"}],"title":"Version Sets"},"tags":{"anyOf":[{"items":{"$ref":"#/components/schemas/ServiceTag"},"type":"array","maxItems":50},{"type":"null"}],"title":"Tags"},"tool_capacity":{"anyOf":[{"type":"integer","maximum":10,"minimum":1},{"type":"null"}],"title":"Tool Capacity"},"safety_filters_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Safety Filters Enabled"},"channel_type":{"anyOf":[{"type":"string","enum":["voice","text"]},{"type":"null"}],"title":"Channel Type"},"environment":{"anyOf":[{"type":"string","enum":["sandbox","production"]},{"type":"null"}],"title":"Environment"},"voice_config":{"anyOf":[{"$ref":"#/components/schemas/ServiceVoiceConfig-Input"},{"type":"null"}]},"escalation_policy":{"anyOf":[{"$ref":"#/components/schemas/EscalationPolicy"},{"type":"null"}]}},"type":"object","title":"UpdateServiceRequest"},"NameString":{"type":"string","maxLength":256,"minLength":1},"DescriptionString":{"type":"string","maxLength":2000},"VersionSet-Input":{"properties":{"agent_version_number":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Agent Version Number"},"context_graph_version_number":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Context Graph Version Number"},"llm_model_preferences":{"additionalProperties":{"$ref":"#/components/schemas/LLMConfig"},"type":"object","title":"Llm Model Preferences"}},"type":"object","title":"VersionSet","description":"Pins agent, state machine, and LLM model versions for a service."},"LLMConfig":{"properties":{"llm_name":{"type":"string","title":"Llm Name"},"params":{"additionalProperties":true,"type":"object","title":"Params"},"experience_controls":{"anyOf":[{"$ref":"#/components/schemas/LLMExperienceControls"},{"type":"null"}]}},"type":"object","required":["llm_name"],"title":"LLMConfig"},"LLMExperienceControls":{"properties":{"verbosity":{"anyOf":[{"type":"string","enum":["low","medium","high"]},{"type":"null"}],"title":"Verbosity"},"reasoning_effort":{"anyOf":[{"type":"string","enum":["none","minimal","low","medium","high","xhigh"]},{"type":"null"}],"title":"Reasoning Effort"},"temperature":{"anyOf":[{"type":"number","maximum":2,"minimum":0},{"type":"null"}],"title":"Temperature"},"top_p":{"anyOf":[{"type":"number","maximum":1,"minimum":0},{"type":"null"}],"title":"Top P"},"presence_penalty":{"anyOf":[{"type":"number","maximum":2,"minimum":-2},{"type":"null"}],"title":"Presence Penalty"},"frequency_penalty":{"anyOf":[{"type":"number","maximum":2,"minimum":-2},{"type":"null"}],"title":"Frequency Penalty"},"response_format":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Response Format"},"seed":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Seed"},"stop":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Stop"},"logit_bias":{"anyOf":[{"additionalProperties":{"type":"number","maximum":100,"minimum":-100},"type":"object"},{"type":"null"}],"title":"Logit Bias"},"logprobs":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Logprobs"},"top_logprobs":{"anyOf":[{"type":"integer","maximum":20,"minimum":0},{"type":"null"}],"title":"Top Logprobs"},"parallel_tool_calls":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Parallel Tool Calls"},"service_tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service Tier"},"prompt_cache_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt Cache Key"},"prompt_cache_retention":{"anyOf":[{"type":"string","enum":["in-memory","24h"]},{"type":"null"}],"title":"Prompt Cache Retention"},"safety_identifier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Safety Identifier"},"store":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Store"},"metadata":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Metadata"}},"additionalProperties":false,"type":"object","title":"LLMExperienceControls","description":"First-class chat experience controls for consumer-facing agents.\n\n``params`` remains available as a provider-specific escape hatch. These\nfields cover the OpenAI Chat Completions controls that most directly shape\nresponse tone, feel, determinism, latency, and structured output behavior.\nToken budgets are intentionally excluded so version sets do not reintroduce\naccidental response truncation."},"ServiceTag":{"properties":{"key":{"type":"string","title":"Key"},"value":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Value"}},"type":"object","required":["key"],"title":"ServiceTag"},"ServiceVoiceConfig-Input":{"properties":{"tts_model":{"anyOf":[{"type":"string","enum":["sonic-turbo","sonic-3"]},{"type":"null"}],"title":"Tts Model"},"max_buffer_delay_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Buffer Delay Ms"},"eager_eot_threshold":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Eager Eot Threshold"},"eot_timeout_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Eot Timeout Ms"},"filler_style":{"type":"string","enum":["backchannel","phrase","silent"],"title":"Filler Style","default":"backchannel"},"filler_vocabulary":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Filler Vocabulary"},"backchannel_delay_ms":{"type":"integer","title":"Backchannel Delay Ms","default":400},"max_response_sentences":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Response Sentences"},"max_response_words":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Response Words"},"barge_in_min_speech_s":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Barge In Min Speech S"},"barge_in_cooldown_s":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Barge In Cooldown S"},"min_tts_speed":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Tts Speed"},"post_eot_pause_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Post Eot Pause Ms"},"transition_deadline_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Transition Deadline Ms"},"progress_interval_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Progress Interval Ms"},"empathy_hold_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Empathy Hold Ms"},"filler_cooldown_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Filler Cooldown Ms"},"progress_vocabulary":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Progress Vocabulary"},"tts_provider":{"anyOf":[{"type":"string","enum":["cartesia","elevenlabs","groq"]},{"type":"null"}],"title":"Tts Provider"},"tts_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Tts Config"},"language_providers":{"anyOf":[{"additionalProperties":{"$ref":"#/components/schemas/LanguageProviderEntry"},"type":"object","maxProperties":10},{"type":"null"}],"title":"Language Providers"},"forward_call_enabled":{"type":"boolean","title":"Forward Call Enabled","default":false},"forwarding":{"anyOf":[{"$ref":"#/components/schemas/ServiceForwardingConfig"},{"type":"null"}]}},"type":"object","title":"ServiceVoiceConfig","description":"Per-service voice pipeline tuning. Overrides workspace/env defaults.\n\nEach field is optional — None means inherit from the layer above\n(workspace VoiceSettings → env vars → hardcoded defaults)."},"LanguageProviderEntry":{"properties":{"provider":{"type":"string","enum":["cartesia","elevenlabs","groq"],"title":"Provider"},"config":{"additionalProperties":true,"type":"object","maxProperties":20,"title":"Config"}},"type":"object","required":["provider"],"title":"LanguageProviderEntry","description":"Per-language TTS provider configuration."},"ServiceForwardingConfig":{"properties":{"forward_to":{"$ref":"#/components/schemas/PhoneE164"},"should_disconnect":{"type":"boolean","title":"Should Disconnect","default":true},"warm_transfer":{"type":"boolean","title":"Warm Transfer","default":true}},"type":"object","required":["forward_to"],"title":"ServiceForwardingConfig","description":"Per-service call-forwarding destination + transfer mechanism.\n\nRead by:\n  - LLM-driven ``forward_call`` tool (tier 3 fallback when the LLM doesn't\n    pass an explicit ``phone_number`` and no EHR location is configured).\n  - ``EscalationPolicy.ForwardAction`` — engine-fired escalation with no\n    overrides falls through to the same path.\n\nDistinct from ``platform_lib.phone_numbers.ForwardingConfig`` (per-phone\nlegacy shape with ``enabled``); per-service forwarding is a binary\npresence — set means tier 3 resolves to it, None means tier 3 has no\nstatic target."},"PhoneE164":{"type":"string","maxLength":16,"minLength":2},"EscalationPolicy":{"properties":{"context_window_exhaustion":{"oneOf":[{"$ref":"#/components/schemas/OperatorAction"},{"$ref":"#/components/schemas/ForwardAction"},{"$ref":"#/components/schemas/HangupAction"}],"title":"Context Window Exhaustion","discriminator":{"propertyName":"type","mapping":{"forward":"#/components/schemas/ForwardAction","hangup":"#/components/schemas/HangupAction","operator":"#/components/schemas/OperatorAction"}}},"risk_scorer":{"oneOf":[{"$ref":"#/components/schemas/OperatorAction"},{"$ref":"#/components/schemas/ForwardAction"},{"$ref":"#/components/schemas/HangupAction"}],"title":"Risk Scorer","discriminator":{"propertyName":"type","mapping":{"forward":"#/components/schemas/ForwardAction","hangup":"#/components/schemas/HangupAction","operator":"#/components/schemas/OperatorAction"}}},"conversation_monitor":{"oneOf":[{"$ref":"#/components/schemas/OperatorAction"},{"$ref":"#/components/schemas/ForwardAction"},{"$ref":"#/components/schemas/HangupAction"}],"title":"Conversation Monitor","discriminator":{"propertyName":"type","mapping":{"forward":"#/components/schemas/ForwardAction","hangup":"#/components/schemas/HangupAction","operator":"#/components/schemas/OperatorAction"}}}},"type":"object","title":"EscalationPolicy","description":"Per-service routing for engine-detected escalation triggers.\n\nEach trigger source maps to one EscalationAction. The three enumerated\nfields below are the trigger_sources actually emitted by the agent-engine\ntoday; new triggers can be added as fields without breaking back-compat.\n\nPartial policies are intentional: every field defaults to OperatorAction,\nso a PUT body like ``{\"context_window_exhaustion\": {\"type\": \"forward\"}}``\noverrides only that trigger and leaves the others on the operator default.\nTo opt the entire service back to today's behavior, set\n``Service.escalation_policy = None`` (caveat: the platform-api Service\nupdate path uses ``exclude_none=True`` and currently has no clears-via-null\nbranch, so this requires a direct config edit; see follow-up issue).\n\nResolution lookup is done against ``model_fields``: a trigger_source that\nis not an enumerated field name falls through to OperatorAction, never\na non-Action Pydantic internal."},"OperatorAction":{"properties":{"type":{"type":"string","const":"operator","title":"Type","default":"operator"}},"type":"object","title":"OperatorAction","description":"Today's behavior — write escalation.requested + publish SSE, wait for a\nhuman operator to join via the dashboard. No-op if no operators are staffed."},"ForwardAction":{"properties":{"type":{"type":"string","const":"forward","title":"Type","default":"forward"}},"type":"object","title":"ForwardAction","description":"Cold-transfer the caller to the service's configured forwarding\ndestination (set via ``Service.voice_config.forwarding``).\n\nNo agent-side decision and no operator dashboard required — the engine\ninvokes the same forwarding callback used by the LLM-driven\n``forward_call`` tool, with no location override, which falls through to\nthe per-service ``ServiceForwardingConfig``.\n\nIf ``voice_config.forwarding`` is unset, the dispatcher falls back to the\noperator path (audit event + SSE only)."},"HangupAction":{"properties":{"type":{"type":"string","const":"hangup","title":"Type","default":"hangup"}},"type":"object","title":"HangupAction","description":"End the call gracefully via the existing speaker-drain hangup path."},"ServiceResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"agent_id":{"type":"string","format":"uuid","title":"Agent Id"},"context_graph_id":{"type":"string","format":"uuid","title":"Context Graph Id"},"agent_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agent Name"},"context_graph_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Context Graph Name"},"keyterms":{"items":{"type":"string"},"type":"array","title":"Keyterms"},"is_active":{"type":"boolean","title":"Is Active"},"version_sets":{"additionalProperties":{"$ref":"#/components/schemas/VersionSet-Output"},"type":"object","title":"Version Sets"},"tags":{"items":{"$ref":"#/components/schemas/ServiceTag"},"type":"array","title":"Tags"},"tool_capacity":{"type":"integer","title":"Tool Capacity"},"safety_filters_enabled":{"type":"boolean","title":"Safety Filters Enabled","default":true},"channel_type":{"type":"string","enum":["voice","text"],"title":"Channel Type","default":"voice"},"environment":{"type":"string","enum":["sandbox","production"],"title":"Environment","default":"production"},"voice_config":{"anyOf":[{"$ref":"#/components/schemas/ServiceVoiceConfig-Output"},{"type":"null"}]},"escalation_policy":{"anyOf":[{"$ref":"#/components/schemas/EscalationPolicy"},{"type":"null"}]},"is_system":{"type":"boolean","title":"Is System","default":false},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","workspace_id","name","description","agent_id","context_graph_id","keyterms","is_active","version_sets","tags","tool_capacity","created_at","updated_at"],"title":"ServiceResponse"},"VersionSet-Output":{"properties":{"agent_version_number":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Agent Version Number"},"context_graph_version_number":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Context Graph Version Number"},"llm_model_preferences":{"additionalProperties":{"$ref":"#/components/schemas/LLMConfig"},"type":"object","title":"Llm Model Preferences"}},"type":"object","title":"VersionSet","description":"Pins agent, state machine, and LLM model versions for a service."},"ServiceVoiceConfig-Output":{"properties":{"tts_model":{"anyOf":[{"type":"string","enum":["sonic-turbo","sonic-3"]},{"type":"null"}],"title":"Tts Model"},"max_buffer_delay_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Buffer Delay Ms"},"eager_eot_threshold":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Eager Eot Threshold"},"eot_timeout_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Eot Timeout Ms"},"filler_style":{"type":"string","enum":["backchannel","phrase","silent"],"title":"Filler Style","default":"backchannel"},"filler_vocabulary":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Filler Vocabulary"},"backchannel_delay_ms":{"type":"integer","title":"Backchannel Delay Ms","default":400},"max_response_sentences":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Response Sentences"},"max_response_words":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Response Words"},"barge_in_min_speech_s":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Barge In Min Speech S"},"barge_in_cooldown_s":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Barge In Cooldown S"},"min_tts_speed":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Tts Speed"},"post_eot_pause_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Post Eot Pause Ms"},"transition_deadline_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Transition Deadline Ms"},"progress_interval_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Progress Interval Ms"},"empathy_hold_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Empathy Hold Ms"},"filler_cooldown_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Filler Cooldown Ms"},"progress_vocabulary":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Progress Vocabulary"},"tts_provider":{"anyOf":[{"type":"string","enum":["cartesia","elevenlabs","groq"]},{"type":"null"}],"title":"Tts Provider"},"tts_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Tts Config"},"language_providers":{"anyOf":[{"additionalProperties":{"$ref":"#/components/schemas/LanguageProviderEntry"},"type":"object","maxProperties":10},{"type":"null"}],"title":"Language Providers"},"forward_call_enabled":{"type":"boolean","title":"Forward Call Enabled","default":false},"forwarding":{"anyOf":[{"$ref":"#/components/schemas/ServiceForwardingConfig"},{"type":"null"}]}},"type":"object","title":"ServiceVoiceConfig","description":"Per-service voice pipeline tuning. Overrides workspace/env defaults.\n\nEach field is optional — None means inherit from the layer above\n(workspace VoiceSettings → env vars → hardcoded defaults)."}}},"paths":{"/v1/{workspace_id}/services/{service_id}":{"put":{"tags":["Services"],"summary":"Update a service","description":"Update a service's configuration. Requires `Service.update` permission.","operationId":"update-service","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"service_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Service Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateServiceRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"}}}},"401":{"description":"Missing or invalid API key."},"403":{"description":"Insufficient permissions."},"404":{"description":"Not found."},"409":{"description":"Name already taken."},"422":{"description":"Invalid request body."}}}}}}
```

## Delete a service

> Delete a service. Requires \`Service.delete\` permission.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}},"paths":{"/v1/{workspace_id}/services/{service_id}":{"delete":{"tags":["Services"],"summary":"Delete a service","description":"Delete a service. Requires `Service.delete` permission.","operationId":"delete-service","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"service_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Service Id"}}],"responses":{"204":{"description":"Successful Response"},"401":{"description":"Missing or invalid API key."},"403":{"description":"Insufficient permissions."},"404":{"description":"Not found."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}}}
```

## Upsert a service version set

> Replace or create a named version set on a service. Pinned agent/HSM versions are validated.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"UpsertVersionSetRequest":{"properties":{"version_set":{"$ref":"#/components/schemas/VersionSet-Input"}},"type":"object","required":["version_set"],"title":"UpsertVersionSetRequest"},"VersionSet-Input":{"properties":{"agent_version_number":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Agent Version Number"},"context_graph_version_number":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Context Graph Version Number"},"llm_model_preferences":{"additionalProperties":{"$ref":"#/components/schemas/LLMConfig"},"type":"object","title":"Llm Model Preferences"}},"type":"object","title":"VersionSet","description":"Pins agent, state machine, and LLM model versions for a service."},"LLMConfig":{"properties":{"llm_name":{"type":"string","title":"Llm Name"},"params":{"additionalProperties":true,"type":"object","title":"Params"},"experience_controls":{"anyOf":[{"$ref":"#/components/schemas/LLMExperienceControls"},{"type":"null"}]}},"type":"object","required":["llm_name"],"title":"LLMConfig"},"LLMExperienceControls":{"properties":{"verbosity":{"anyOf":[{"type":"string","enum":["low","medium","high"]},{"type":"null"}],"title":"Verbosity"},"reasoning_effort":{"anyOf":[{"type":"string","enum":["none","minimal","low","medium","high","xhigh"]},{"type":"null"}],"title":"Reasoning Effort"},"temperature":{"anyOf":[{"type":"number","maximum":2,"minimum":0},{"type":"null"}],"title":"Temperature"},"top_p":{"anyOf":[{"type":"number","maximum":1,"minimum":0},{"type":"null"}],"title":"Top P"},"presence_penalty":{"anyOf":[{"type":"number","maximum":2,"minimum":-2},{"type":"null"}],"title":"Presence Penalty"},"frequency_penalty":{"anyOf":[{"type":"number","maximum":2,"minimum":-2},{"type":"null"}],"title":"Frequency Penalty"},"response_format":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Response Format"},"seed":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Seed"},"stop":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Stop"},"logit_bias":{"anyOf":[{"additionalProperties":{"type":"number","maximum":100,"minimum":-100},"type":"object"},{"type":"null"}],"title":"Logit Bias"},"logprobs":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Logprobs"},"top_logprobs":{"anyOf":[{"type":"integer","maximum":20,"minimum":0},{"type":"null"}],"title":"Top Logprobs"},"parallel_tool_calls":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Parallel Tool Calls"},"service_tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service Tier"},"prompt_cache_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt Cache Key"},"prompt_cache_retention":{"anyOf":[{"type":"string","enum":["in-memory","24h"]},{"type":"null"}],"title":"Prompt Cache Retention"},"safety_identifier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Safety Identifier"},"store":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Store"},"metadata":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Metadata"}},"additionalProperties":false,"type":"object","title":"LLMExperienceControls","description":"First-class chat experience controls for consumer-facing agents.\n\n``params`` remains available as a provider-specific escape hatch. These\nfields cover the OpenAI Chat Completions controls that most directly shape\nresponse tone, feel, determinism, latency, and structured output behavior.\nToken budgets are intentionally excluded so version sets do not reintroduce\naccidental response truncation."}}},"paths":{"/v1/{workspace_id}/services/{service_id}/version-sets/{name}":{"put":{"tags":["Services"],"summary":"Upsert a service version set","description":"Replace or create a named version set on a service. Pinned agent/HSM versions are validated.","operationId":"upsert-service-version-set","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"service_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Service Id"}},{"name":"name","in":"path","required":true,"schema":{"type":"string","maxLength":40,"description":"Version set name (e.g. 'release')","title":"Name"},"description":"Version set name (e.g. 'release')"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertVersionSetRequest"}}}},"responses":{"204":{"description":"Successful Response"},"401":{"description":"Missing or invalid API key."},"403":{"description":"Insufficient permissions."},"404":{"description":"Not found."},"409":{"description":"Name already taken."},"422":{"description":"Invalid request body."}}}}}}
```

## Voice 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.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"Body_voice-turn":{"properties":{"audio":{"type":"string","contentMediaType":"application/octet-stream","title":"Audio"},"phone_number":{"type":"string","maxLength":16,"pattern":"^\\+[1-9]\\d{1,14}$","title":"Phone Number"}},"type":"object","required":["audio","phone_number"],"title":"Body_voice-turn"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}},"paths":{"/v1/{workspace_id}/services/{service_id}/voice-turn":{"post":{"tags":["Services"],"summary":"Voice Turn","description":"Run one WhatsApp-style voice-note turn against the service's agent.\n\nAccepts OGG Opus audio (or any format Deepgram's prerecorded endpoint\naccepts). Server keys the conversation on ``(workspace, service,\nphone_number)`` and returns the agent's spoken reply as OGG Opus.","operationId":"voice-turn","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"service_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Service Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_voice-turn"}}}},"responses":{"200":{"description":"OGG Opus agent reply","content":{"application/json":{"schema":{}},"audio/ogg":{}}},"204":{"description":"Agent elected silence"},"409":{"description":"Concurrent voice turn in progress for this speaker"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}}}
```

## Text Turn

> Run one WhatsApp-style text turn against the service's agent.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"TextTurnRequest":{"properties":{"phone_number":{"type":"string","maxLength":16,"pattern":"^\\+[1-9]\\d{1,14}$","title":"Phone Number"},"text":{"type":"string","maxLength":8192,"minLength":1,"title":"Text"}},"type":"object","required":["phone_number","text"],"title":"TextTurnRequest","description":"Request body for ``POST /v1/{ws}/services/{service_id}/text-turn``."},"TextTurnResponse":{"properties":{"text":{"type":"string","maxLength":8192,"title":"Text"}},"type":"object","required":["text"],"title":"TextTurnResponse","description":"Response body — the agent's text reply.\n\nReturned only on 200; 204 indicates the engine elected silence."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}},"paths":{"/v1/{workspace_id}/services/{service_id}/text-turn":{"post":{"tags":["Services"],"summary":"Text Turn","description":"Run one WhatsApp-style text turn against the service's agent.","operationId":"text-turn","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"service_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Service Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TextTurnRequest"}}}},"responses":{"200":{"description":"Agent text reply","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TextTurnResponse"}}}},"204":{"description":"Agent elected silence"},"409":{"description":"Concurrent text turn in progress for this speaker"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}}}
```


---

# Agent Instructions: Querying This Documentation

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

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

```
GET https://docs.amigo.ai/api-reference/readme/platform/services.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

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