{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://api.forgeling.io/schemas/events/turn.completed.json",
  "title": "turn.completed",
  "description": "A turn ended with an answer. The sandbox reports status, stop_reason, output, result, result_error, usage and duration_ms; the API fills turn_id, idempotency_key and metadata and re-validates result against the turn's output_schema. Source platform only for a turn that reached the front of the queue with no budget left.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "turn_id",
    "idempotency_key",
    "status",
    "stop_reason",
    "output",
    "result",
    "result_error",
    "usage",
    "metadata",
    "duration_ms"
  ],
  "properties": {
    "turn_id": {
      "type": "string",
      "pattern": "^trn_[0-9A-HJKMNP-TV-Z]{26}$"
    },
    "idempotency_key": {
      "type": [
        "string",
        "null"
      ],
      "description": "The Idempotency-Key the turn was posted with."
    },
    "status": {
      "const": "completed"
    },
    "stop_reason": {
      "enum": [
        "end_turn",
        "budget_reached"
      ]
    },
    "output": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "text"
      ],
      "properties": {
        "text": {
          "type": "string",
          "description": "The agent's final text."
        }
      }
    },
    "result": {
      "description": "The value the agent submitted for the turn's output_schema; any JSON value, null when none was submitted."
    },
    "result_error": {
      "enum": [
        null,
        "not_submitted",
        "invalid"
      ],
      "description": "Why result is null although the turn had an output_schema."
    },
    "usage": {
      "$ref": "https://api.forgeling.io/schemas/defs/usage.json"
    },
    "metadata": {
      "type": "object",
      "additionalProperties": true,
      "description": "The turn's metadata, echoed as the app sent it."
    },
    "duration_ms": {
      "type": "integer",
      "minimum": 0
    }
  }
}
