---
title: "Connect an agent"
method: POST
path: "/agents"
tags: ["Agents"]
---

# Connect an agent

`POST /agents`

## Request

- Base URL: `https://api.coval.dev/v1`
- URL: `https://api.coval.dev/v1/agents`
- Auth: API key in header `x-api-key`

Connect an agent to coval by providing the agent's configuration.

## Request body

- CreateAgentRequest
  - `display_name` string, required: Human-readable agent name
  - `model_type` 'MODEL_TYPE_VOICE' | 'MODEL_TYPE_OUTBOUND_VOICE' | 'MODEL_TYPE_CHAT' | 'MODEL_TYPE_CHAT_A2A' | 'MODEL_TYPE_CHAT_WEBSOCKET' | 'MODEL_TYPE_EMAIL' | 'MODEL_TYPE_SMS' | 'MODEL_TYPE_WEBSOCKET' | 'MODEL_TYPE_SDK_WEBSOCKET' | 'MODEL_TYPE_LIVEKIT' | 'MODEL_TYPE_DAILY' | 'MODEL_TYPE_OPENAI_REALTIME' | 'MODEL_TYPE_GEMINI_REALTIME' | 'MODEL_TYPE_GROK_REALTIME' | 'MODEL_TYPE_DEEPGRAM_REALTIME', required: Agent type. Active types that can be created via the v1 API: - **MODEL_TYPE_VOICE**: Inbound voice calls (requires phone_number in E.164 format or SIP address) - **MODEL_TYPE_OUTBOUND_VOICE**: Outbound voice calls (requires endpoint webhook URL) - **MODEL_TYPE_CHAT**: Text-based chat agents (requires metadata.chat_endpoint) - **MODEL_TYPE_CHAT_A2A**: A2A JSON-RPC chat agents (requires metadata.chat_endpoint) - **MODEL_TYPE_CHAT_WEBSOCKET**: Text chat over WebSocket (requires metadata.endpoint in direct mode) - **MODEL_TYPE_EMAIL**: Email-based text agents - **MODEL_TYPE_SMS**: SMS messaging agents (requires phone_number in E.164 format) - **MODEL_TYPE_WEBSOCKET**: WebSocket voice agents (requires metadata.endpoint wss:// URL in direct mode; metadata.initialization_json is optional) - **MODEL_TYPE_SDK_WEBSOCKET**: Voice agents that connect outbound to the Cloudflare Durable Object relay using Coval Agent SDK. - **MODEL_TYPE_LIVEKIT**: LiveKit agents (requires metadata.generate_token_endpoint and metadata.livekit_url) - **MODEL_TYPE_DAILY**: Pipecat Cloud agents (requires metadata.pipecat_api_key and metadata.agent_name) - **MODEL_TYPE_OPENAI_REALTIME**: OpenAI Realtime voice-to-voice agents - **MODEL_TYPE_GEMINI_REALTIME**: Gemini Live voice-to-voice agents - **MODEL_TYPE_GROK_REALTIME**: Grok (xAI) Voice Agent voice-to-voice agents - **MODEL_TYPE_DEEPGRAM_REALTIME**: Deepgram Voice Agent voice-to-voice agents
  - `phone_number` string, nullable: Phone number in E.164 format (e.g., +12345678901) or SIP address (e.g., sip:user@domain.com). **Required for:** - MODEL_TYPE_VOICE agents (E.164 or SIP) - MODEL_TYPE_SMS agents (E.164 only) Optional for other agent types.
  - `endpoint` string, nullable: Webhook endpoint URL that Coval will POST to. **Required for MODEL_TYPE_OUTBOUND_VOICE agents.** Must be a valid HTTP/HTTPS URL.
  - `prompt` string, nullable: Agent instructions/system prompt
  - `customer_agent_id` string, nullable: Your own external id for this agent. Defaults to the generated agent id when omitted.
  - `language` string, nullable: Primary language for the agent
  - `attributes` object, nullable: Free-form agent attributes; referenceable in metric prompts as `{{agent.<key>}}`.
  - `metadata` object: Simulator-specific configuration (JSONB, max 10MB). **For CHAT agents:** *Required:* - `chat_endpoint` - Chat endpoint URL (validated, no private IPs/localhost) *Authentication:* - `authorization_header` - Auth header (Bearer, X-API-Key, etc.) *Initialization:* - `initialization_endpoint` - Init endpoint called before chat (validated URL) - `initialization_payload` - JSON payload for init request (max 16KB) *Custom Data:* - `custom_data` - Organization/agent-level data (max 32KB JSON string) - `custom_persona_data` - Persona-specific data (max 16KB JSON string) *Headers & Format:* - `custom_headers` - Additional headers with template variables, as a JSON object or JSON-encoded object string (max 16KB when encoded) - `response_format` - "chat_completions" (default) or "responses" *Request/Response Processing:* - `input_template` - Custom JSON template for requests (validated JSON) - `payload_wrapper` - Wrapper field name (e.g., "data", "request") - `response_message_path` - Dot notation path to extract message - `strip_message_timestamps` - Remove timestamp fields (boolean, default: false) *Tool Calls:* - `tool_call_extraction_config` - Configuration for extracting tool calls from custom responses *Dynamic Configuration:* - `persona_id` - Reference persona for parameter substitution (22-char ShortUUID) *Template Variables:* `{{sessionId}}`, `{{simulation_output_id}}`, `{{init_response.path}}`, `{{persona.field}}`, `{{messages}}`, `{{latest_message}}`, `{{custom_data.field}}` **For OUTBOUND_VOICE agents:** - `trigger_call_headers` - JSON string with HTTP headers - `trigger_call_payload` - JSON string with base payload - `phone_number_key` - Field name for phone number (default: "phone_number") **For LIVEKIT agents:** *Required:* - `generate_token_endpoint` - HTTP/HTTPS endpoint Coval calls to create a participant token - `livekit_url` - LiveKit server URL using ws, wss, http, or https *Optional:* - `generate_token_headers` - Token-request headers as a JSON object or encoded object string - `token_request_payload` - Fields merged into the token request as a JSON object or encoded object string - `content_type` - Convenience value for the token-request `Content-Type` header - `livekit_agent_name` - Agent dispatch name **For DAILY (Pipecat Cloud) agents:** *Required:* - `pipecat_api_key` - Pipecat Cloud API key - `agent_name` - Pipecat Cloud agent name *Optional:* - `custom_data` - JSON-encoded object with string keys and string values (max 16KB) **For WEBSOCKET agents:** *Required:* - `endpoint` - WebSocket endpoint URL (must be wss://, validated). Required in `direct` connection mode. *Connection mode:* - `connection_mode` - `direct` (default), `http_first`, or `twiml_webhook`. - `http_url`, `http_method`, `http_request_body`, `http_headers`, `websocket_url_response_path` - HTTP-first setup fields when `connection_mode=http_first`. - `voice_url`, `voice_http_method`, `voice_http_headers`, `voice_form_fields`, `twilio_account_sid`, `twilio_from_number`, `twilio_to_number` - TwiML voice-webhook fields when `connection_mode=twiml_webhook`. *Authentication (optional):* - `authorization_header` - Auth header sent during the WebSocket handshake. Supports: - `"Bearer <token>"` → sent as `Authorization: Bearer <token>` - `"Basic <base64-credentials>"` → sent as `Authorization: Basic <base64-credentials>` - `"X-API-Key <key>"` → sent as `X-API-Key: <key>` - `custom_headers` - JSON object or JSON-encoded object string of additional HTTP headers for the WebSocket handshake. *Initialization & handshake (optional):* - `initialization_json` - JSON object or JSON string payload sent after the WebSocket upgrade and before any ready-message wait. - `handshake_ready_message_type` - Message type to wait for before streaming audio (default `session_ready` in direct mode and empty in `http_first` and `twiml_webhook`; empty string skips the ready-message wait). - `handshake_requires_session_id` - Whether the ready message must include `session_id` (default `true` in direct mode and `false` in `http_first` and `twiml_webhook`). - `handshake_timeout_seconds` - Seconds Coval waits for the ready message (default `30`). *Audio format (optional):* - `send_audio_template` - JSON template for outbound audio. Must contain `{{audio_data}}`. Setting it exactly to `{{audio_data}}` sends raw PCM bytes (default `{"type":"audio_chunk","data":"{{audio_data}}"}`). - `message_type_path` - Dot-notation path to the field naming the inbound message kind (default `type`). - `audio_message_type_value` - Value identifying an audio frame; use `*` to treat every JSON message as audio (default `audio_chunk`). - `audio_data_path` - Dot-notation path to the inbound base64 audio payload (default `data`). - `audio_encoding` - JSON audio payload encoding: `pcm` (default), `mp3`, or `ulaw`. MP3 is inbound-only; `ulaw` sends and receives G.711 mu-law audio. - `receive_audio_channels` - `1` for mono inbound JSON PCM or `2` for legacy stereo-to-mono averaging (default `2`). - `send_sample_rate_hertz` - Outbound sample rate. One of 8000, 16000, 24000, 48000 (default 16000). - `receive_sample_rate_hertz` - Inbound sample rate. One of 8000, 16000, 24000, 48000 (default 48000). - `pipeline_sample_rate_hertz` - Pipeline-internal rate; must remain 16000. - `pace_inbound_binary_audio` - Boolean, paces inbound binary PCM at real-time. Defaults on when outbound audio is configured for raw PCM bytes, off for JSON templates. - `send_media_template` - Outbound template for image attachments. Must contain `{{media_data}}`; may also include `{{media_name}}` and `{{mime_type}}`. Set exactly to `{{media_data}}` to send raw bytes, otherwise Coval base64-encodes the image into the JSON template. - `send_dtmf_template` - Outbound template for keypad digits. Must contain `{{digit}}`. *Per-simulation placeholders:* - Connection setup fields support `{{run_id}}`, `{{simulation_output_id}}` (legacy alias `{{simulation_id}}`), `{{stream_sid}}`, `{{call_sid}}`, `{{agent.*}}`, `{{test_case.*}}`, `{{sim_wrapper.*}}`, and `{{run_metadata.*}}`. - Connection setup fields are `initialization_json` in direct and HTTP-first modes; `custom_headers` in every mode; `http_request_body` and `http_headers` in HTTP-first mode; and `voice_form_fields` and `voice_http_headers` in TwiML webhook mode. - `{{stream_sid}}` and `{{call_sid}}` also resolve in `send_audio_template`, `send_media_template`, and `send_dtmf_template`. Coval generates fresh Twilio-shaped values for every simulation. *Non-audio event capture (optional):* - `non_audio_event_message_types` - List of message-type values to emit as `WebsocketEventFrame`s instead of dropping. Each match carries the message type, optional `event` name, and original payload. Useful for cart updates, transcript fragments, or session telemetry. *Compatibility profile (optional):* - `websocket_compat_profile` - One of `generic` or `json_audio`. Forces the simulator routing decision. Use `json_audio` for the JSON audio preset shape.
  - `workflows` object: Workflow configuration (JSONB, max 10MB)
  - `metric_ids` string[]: Associated metric IDs (22-char IDs)
  - `test_set_ids` string[]: Associated test set IDs (8-char IDs)
  - `tags` string[], nullable: Tags to associate with this agent. Null or omitted creates the agent with no tags. Pass [] for an empty tag list.

## Response `201`

Agent created successfully

- CreateAgentResponse
  - `agent` AgentResource, required: Agent configuration resource. Note: The `active` field (soft delete status) is managed internally and not exposed in API responses.
    - `created_at` string, date-time, nullable, required: Authoring timestamp; null when unknown.
    - `created_by` string, nullable, required: Canonical author user ID; null when unknown.
    - `updated_at` string, date-time, nullable, required: Authoring timestamp; null when unknown.
    - `updated_by` string, nullable, required: Canonical author user ID; null when unknown.
    - `id` string, required: Agent resource ID
    - `customer_agent_id` string, required: Customer-supplied external id for the agent. Defaults to `id` when not set at creation.
    - `display_name` string, required: Human-readable agent name
    - `model_type` 'MODEL_TYPE_VOICE' | 'MODEL_TYPE_OUTBOUND_VOICE' | 'MODEL_TYPE_CHAT' | 'MODEL_TYPE_CHAT_A2A' | 'MODEL_TYPE_CHAT_WEBSOCKET' | 'MODEL_TYPE_EMAIL' | 'MODEL_TYPE_SMS' | 'MODEL_TYPE_WEBSOCKET' | 'MODEL_TYPE_SDK_WEBSOCKET' | 'MODEL_TYPE_OPENAI_REALTIME' | 'MODEL_TYPE_GEMINI_REALTIME' | 'MODEL_TYPE_GROK_REALTIME' | 'MODEL_TYPE_DEEPGRAM_REALTIME' | 'MODEL_TYPE_TEXT' | 'MODEL_TYPE_LIVEKIT' | 'MODEL_TYPE_DAILY' | 'MODEL_TYPE_NOOP' | 'MODEL_TYPE_OPENAI_ENDPOINT' | 'MODEL_TYPE_TRANSCRIPTION' | 'MODEL_TYPE_TTS' | 'MODEL_TYPE_VOICE_TO_VOICE', required: Agent type returned by the API. Responses can include active types as well as legacy types retained for existing agents. Only values in `SimulatorType` can be supplied when creating or changing an agent type.
    - `phone_number` string, nullable: Phone number in E.164 format or SIP address for voice/SMS agents
    - `endpoint` string, nullable: Custom API endpoint URL
    - `prompt` string, nullable: Agent instructions/system prompt
    - `language` string, nullable: Primary language for the agent
    - `attributes` object, nullable: Free-form agent attributes; referenceable in metric prompts as `{{agent.<key>}}`.
    - `metadata` object: Simulator-specific configuration (JSONB)
    - `workflows` object: Workflow configuration (JSONB)
    - `metric_ids` string[]: Associated metric IDs
    - `test_set_ids` string[]: Associated test set IDs
    - `knowledge_base_ids` string[]: Associated knowledge base entry IDs (read-only, derived from reverse FK)
    - `tags` string[]: Tags associated with this agent
    - `create_time` string, date-time, required: Creation timestamp (ISO 8601)
    - `update_time` string, date-time, nullable: Last update timestamp (ISO 8601)

## Other responses

- `400`: Invalid request body or validation failed
- `401`: Authentication failed
- `500`: Internal server error

---

[API](https://skmtc.dev/coval/apis/coval-agents-api.md) - [All operations](https://skmtc.dev/coval/apis/coval-agents-api/llms.txt) - [OpenAPI document](https://skmtc.dev/coval/apis/coval-agents-api/revisions/ba0291fe3911?raw)
