{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://jambonz.org/schema/callbacks/agent-turn",
  "title": "Agent EventHook Events",
  "description": "Events sent to the agent verb's eventHook during a conversation. These are sent as 'agent:event' messages over the WebSocket connection.",
  "type": "object",
  "oneOf": [
    {
      "properties": {
        "type": {
          "const": "turn_end",
          "description": "Sent at the end of each conversational turn."
        },
        "transcript": {
          "type": "string",
          "description": "The user's final speech-to-text transcript for this turn."
        },
        "response": {
          "type": "string",
          "description": "The assistant's text response for this turn. May be trimmed to what was actually spoken if the turn was interrupted and alignment tracking is enabled."
        },
        "interrupted": {
          "type": "boolean",
          "description": "True if the user interrupted the assistant before it finished speaking.",
          "default": false
        },
        "latency": {
          "type": "object",
          "description": "Latency metrics for this turn, all in milliseconds. Fields are absent when not applicable.",
          "properties": {
            "transcriber_latency": {
              "type": "integer",
              "description": "STT processing latency: time from user stops talking until final transcript received, in milliseconds."
            },
            "turn_detection_latency": {
              "type": "integer",
              "description": "Additional wait after final transcript for end-of-turn detection, in milliseconds. Absent when EOT fires before or with the transcript."
            },
            "model_latency": {
              "type": "integer",
              "description": "LLM latency: time spent waiting for the first LLM token after the system is ready to prompt, in milliseconds. Absent on a preflight hit."
            },
            "voice_latency": {
              "type": "integer",
              "description": "TTS engine latency: time from first text sent to the TTS engine until first audio received back, in milliseconds."
            },
            "preflight": {
              "type": "object",
              "description": "Early generation (preflight) metrics. Only present when earlyGeneration is enabled.",
              "properties": {
                "result": {
                  "type": "string",
                  "enum": ["hit", "miss", "pending"],
                  "description": "Whether the speculative preflight transcript matched the final transcript ('hit'), did not match ('miss'), or was still in progress ('pending')."
                },
                "tokens": {
                  "type": "integer",
                  "description": "Number of preflight tokens that were buffered. Only present on a 'hit'."
                }
              },
              "additionalProperties": false
            }
          },
          "additionalProperties": false
        }
      },
      "required": ["type", "transcript", "response", "interrupted", "latency"],
      "additionalProperties": false
    },
    {
      "properties": {
        "type": {
          "const": "user_transcript",
          "description": "Sent when the user's final transcript is available and the system is proceeding to prompt the LLM. This indicates the end of the user's speech input for the current turn."
        },
        "transcript": {
          "type": "string",
          "description": "The user's final speech-to-text transcript."
        }
      },
      "required": ["type", "transcript"],
      "additionalProperties": false
    },
    {
      "properties": {
        "type": {
          "const": "llm_response",
          "description": "Sent when the LLM has finished generating its response for the current turn. Contains the complete response text."
        },
        "response": {
          "type": "string",
          "description": "The assistant's complete text response."
        }
      },
      "required": ["type", "response"],
      "additionalProperties": false
    },
    {
      "properties": {
        "type": {
          "const": "user_interruption",
          "description": "Sent when the user barges in (interrupts) while the assistant is speaking. This event has no additional data."
        }
      },
      "required": ["type"],
      "additionalProperties": false
    }
  ]
}
