{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://jambonz.org/schema/jambonz-app",
  "title": "jambonz Application",
  "description": "A jambonz application is an array of verbs that are executed sequentially to control a phone call. Each verb performs an action: speaking text, playing audio, collecting input, dialing a number, connecting to an AI model, etc. When a webhook (actionHook) is invoked, it must return a new verb array to continue call processing.\n\nThe execution model is simple: verbs execute one after another, top to bottom. When a verb with an actionHook completes (e.g. gather collects input), the actionHook is called and its response replaces the remaining verb stack. If the verb array is exhausted without a hangup, the call is terminated.\n\nThere are two transport modes for delivering verb arrays to jambonz:\n- **Webhook**: Your HTTP server receives POST/GET requests with call data and returns JSON verb arrays in the response body.\n- **WebSocket**: Your server maintains a persistent websocket connection with jambonz and sends/receives verb arrays as JSON messages. Required for real-time features like LLM conversations.\n\nThe verb schemas and JSON structure are identical regardless of transport mode.",
  "type": "array",
  "items": {
    "$ref": "#/$defs/Verb"
  },
  "minItems": 1,
  "$defs": {
    "Verb": {
      "oneOf": [
        { "$ref": "verbs/answer" },
        { "$ref": "verbs/alert" },
        { "$ref": "verbs/config" },
        { "$ref": "verbs/say" },
        { "$ref": "verbs/play" },
        { "$ref": "verbs/gather" },
        { "$ref": "verbs/dial" },
        { "$ref": "verbs/listen" },
        { "$ref": "verbs/stream" },
        { "$ref": "verbs/llm" },
        { "$ref": "verbs/s2s" },
        { "$ref": "verbs/openai_s2s" },
        { "$ref": "verbs/google_s2s" },
        { "$ref": "verbs/elevenlabs_s2s" },
        { "$ref": "verbs/deepgram_s2s" },
        { "$ref": "verbs/ultravox_s2s" },
        { "$ref": "verbs/qwen_s2s" },
        { "$ref": "verbs/gptlive_s2s" },
        { "$ref": "verbs/voicelive_s2s" },
        { "$ref": "verbs/nova_s2s" },
        { "$ref": "verbs/dialogflow" },
        { "$ref": "verbs/agent" },
        { "$ref": "verbs/transfer" },
        { "$ref": "verbs/conference" },
        { "$ref": "verbs/transcribe" },
        { "$ref": "verbs/enqueue" },
        { "$ref": "verbs/dequeue" },
        { "$ref": "verbs/dtmf" },
        { "$ref": "verbs/dub" },
        { "$ref": "verbs/hangup" },
        { "$ref": "verbs/leave" },
        { "$ref": "verbs/message" },
        { "$ref": "verbs/pause" },
        { "$ref": "verbs/redirect" },
        { "$ref": "verbs/tag" },
        { "$ref": "verbs/sip:decline" },
        { "$ref": "verbs/sip:request" },
        { "$ref": "verbs/sip:refer" },
        { "$ref": "verbs/rest:dial" }
      ],
      "discriminator": {
        "propertyName": "verb"
      }
    }
  },
  "examples": [
    [
      {
        "verb": "config",
        "synthesizer": { "vendor": "elevenlabs", "voice": "EXAVITQu4vr4xnSDxMaL", "language": "en-US" },
        "recognizer": { "vendor": "deepgram", "language": "en-US" }
      },
      {
        "verb": "say",
        "text": "Hello! Welcome to Acme Corp. How can I help you today?"
      },
      {
        "verb": "gather",
        "input": ["speech"],
        "actionHook": "/process-input",
        "timeout": 15,
        "say": { "text": "I'm listening." }
      }
    ],
    [
      {
        "verb": "say",
        "text": "Please hold while I connect you to an agent."
      },
      {
        "verb": "dial",
        "target": [{ "type": "phone", "number": "+15085551212" }],
        "answerOnBridge": true,
        "timeout": 30,
        "actionHook": "/dial-complete"
      },
      {
        "verb": "say",
        "text": "Sorry, the agent is not available. Please try again later."
      },
      {
        "verb": "hangup"
      }
    ],
    [
      {
        "verb": "config",
        "synthesizer": { "vendor": "cartesia", "voice": "sonic-english" },
        "recognizer": { "vendor": "deepgram", "language": "en-US" }
      },
      {
        "verb": "openai_s2s",
        "model": "gpt-4o",
        "llmOptions": {
          "messages": [
            { "role": "system", "content": "You are a helpful customer service agent for Acme Corp. Be concise and friendly." }
          ],
          "temperature": 0.7
        },
        "actionHook": "/llm-complete",
        "toolHook": "/llm-tool"
      }
    ]
  ]
}
