{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://jambonz.org/schema/verbs/say",
  "minVersion": "0.9.6",
  "title": "Say",
  "description": "Speaks text to the caller using text-to-speech. The text can be plain text or SSML. Optionally streams TTS output incrementally for lower latency. This is one of the most commonly used verbs in jambonz applications.",
  "type": "object",
  "properties": {
    "verb": {
      "const": "say",
      "description": "The verb name."
    },
    "id": {
      "type": "string",
      "description": "An optional unique identifier for this verb instance. Can be used to reference it in other contexts."
    },
    "text": {
      "oneOf": [
        {
          "type": "string"
        },
        {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      ],
      "description": "The text to speak. Can be plain text or SSML markup. If an array is provided, one entry is selected at random (useful for variety in prompts).",
      "examples": [
        "Hello, welcome to our service.",
        "<speak>Hello <break time='500ms'/> welcome.</speak>",
        [
          "Hello!",
          "Hi there!",
          "Welcome!"
        ]
      ]
    },
    "instructions": {
      "type": "string",
      "description": "Natural language instructions to guide TTS expression and delivery. Supported by vendors that offer instruction-based synthesis (e.g. ElevenLabs, some OpenAI models).",
      "examples": [
        "Speak in a warm, friendly tone",
        "Sound excited and energetic"
      ]
    },
    "stream": {
      "type": "boolean",
      "description": "If true, stream TTS audio to the caller incrementally as it is generated, rather than waiting for the complete audio. Reduces time-to-first-byte for long utterances. Requires a vendor that supports streaming synthesis."
    },
    "loop": {
      "oneOf": [
        {
          "type": "number"
        },
        {
          "type": "string"
        }
      ],
      "description": "Number of times to repeat the speech. Use 0 or 'forever' to loop indefinitely until interrupted.",
      "examples": [
        2,
        "forever"
      ]
    },
    "synthesizer": {
      "$ref": "../components/synthesizer",
      "description": "Override the session-level TTS configuration for this specific utterance."
    },
    "earlyMedia": {
      "type": "boolean",
      "description": "If true, play the audio as early media (before the call is answered). Used for playing announcements or prompts to the caller before the call is formally connected."
    },
    "disableTtsCache": {
      "type": "boolean",
      "description": "If true, bypass the TTS cache and always generate fresh audio. Useful when the same text should be re-synthesized (e.g. with different SSML or when the voice has been updated)."
    },
    "closeStreamOnEmpty": {
      "type": "boolean",
      "description": "If true, close the TTS stream when an empty text string is received. Only applies when stream is true."
    }
  },
  "examples": [
    {
      "verb": "say",
      "text": "Hello, welcome to Acme Corp. How can I help you today?"
    },
    {
      "verb": "say",
      "text": "Please hold while I transfer your call.",
      "synthesizer": {
        "vendor": "elevenlabs",
        "voice": "Rachel"
      }
    },
    {
      "verb": "say",
      "text": [
        "Hello!",
        "Hi there!",
        "Welcome!"
      ],
      "loop": 1
    }
  ]
}
