{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/anjal-app/json-schema/anjal-app-cadence-step-input-schema.json",
  "title": "CadenceStepInput",
  "x-generated": "2026-11-01",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/anjal-app-openapi.yaml#/components/schemas/CadenceStepInput",
  "type": "object",
  "required": [
    "kind",
    "delayDays"
  ],
  "properties": {
    "kind": {
      "type": "string",
      "enum": [
        "linkedin_connect",
        "linkedin_message",
        "email",
        "wait"
      ]
    },
    "delayDays": {
      "type": "number",
      "minimum": 0,
      "maximum": 365,
      "description": "Days after the previous step's completion. 0 = fire on enrollment for step 0; 0.25 = 6 hours."
    },
    "condition": {
      "type": [
        "string",
        "null"
      ],
      "enum": [
        "after_accept",
        "no_reply_to_prev",
        "never_replied"
      ]
    },
    "draftStrategy": {
      "type": "string",
      "enum": [
        "static",
        "webhook"
      ],
      "default": "static",
      "description": "How the runner gets the rendered content for this step.\n\n- `static`  — Use `staticBody` (+ `staticSubject` for email) as\n              the message verbatim, with `{{name}}`,\n              `{{first_name}}`, `{{email}}` token\n              substitution. Predictable; zero external deps.\n- `webhook` — At fire-time, the runner POSTs a\n              `cadence.step.draft.requested` event to the\n              cadence's `webhookUrl` and waits up to 30s for\n              a JSON response of\n              `{ body, subject?, skip?, defer? }`. The\n              customer's app brings the actual content with\n              its own business context, its own LLM if it\n              wants one, its own thread memory. Anjal never\n              generates copy on the customer's behalf.\n\nThe legacy `\"ai\"` value was REMOVED 2026-05-19 — Anjal no\nlonger drafts content server-side. New cadences passing\n`\"ai\"` get a `VALIDATION_ERROR` with a migration hint\npointing here. Pre-existing rows with `\"ai\"` will surface\n`AI_STRATEGY_REMOVED` as the per-enrollment `lastError.code`\nwhen the runner tries to fire them — fix by updating the\nstep to `static` (with `staticBody`) or `webhook` (with the\ncadence's `webhookUrl` set).\n"
    },
    "staticSubject": {
      "type": [
        "string",
        "null"
      ],
      "description": "Email-only. The literal subject line for static-strategy email steps. Supports `{{name}}` / `{{first_name}}` / `{{email}}` tokens."
    },
    "staticBody": {
      "type": [
        "string",
        "null"
      ],
      "description": "The literal message body for static-strategy steps. Supports `{{name}}` / `{{first_name}}` / `{{email}}` tokens. Required when `draftStrategy: \"static\"`."
    },
    "promptHint": {
      "type": [
        "string",
        "null"
      ],
      "description": "Free-text hint for the step. Anjal does not read this — it's\npassed through verbatim in the `cadence.step.draft.requested`\nwebhook payload (`step.promptHint`) so the customer's draft\nhandler can use it as per-step context. Ignored by static\nstrategy.\n"
    },
    "notes": {
      "type": [
        "string",
        "null"
      ],
      "description": "Operator notes — not sent anywhere, just stored for the customer's reference."
    }
  }
}