changedInput schema / properties / node / oneOf
Previous value: -[
- {
- "additionalProperties": false,
- "description": "A LinkedIn connection request. Routes both send outcomes — `accepted` (invite\ntaken) and `already_connected` (a no-op CR on an existing 1st-degree connection) — and\nan optional `timeout` (a held advance, e.g. withdraw after no accept).",
- "properties": {
- "accepted": {
- "type": "string"
- },
- "already_connected": {
- "type": "string"
- },
- "id": {
- "type": "string"
- },
- "kind": {
- "const": "connection_request",
- "type": "string"
- },
- "label": {
- "type": "string"
- },
- "timeout": {
- "anyOf": [
- {
- "additionalProperties": false,
- "description": "A held follow-on anchored on this node's send — always delayed (no instant form).\n ",
- "properties": {
- "delay": {
- "additionalProperties": false,
- "description": "A timed hold: `value` units of `unit`. A `d` (day) hold counts BUSINESS days — Mon–Fri,\nweekends skipped — the outreach default; `cd` counts calendar days (weekends included), as\ndo `w`/`h`/`m`. Validated by construction (no free-form string to parse) and stored\nJSON-natively as `{value, unit}`.",
- "properties": {
- "unit": {
- "enum": [
- "w",
- "cd",
- "d",
- "h",
- "m"
- ],
- "type": "string"
- },
- "value": {
- "exclusiveMinimum": 0,
- "type": "integer"
- }
- },
- "required": [
- "value",
- "unit"
- ],
- "title": "EdgeDelay",
- "type": "object"
- },
- "to": {
- "type": "string"
- }
- },
- "required": [
- "delay",
- "to"
- ],
- "title": "TimedAdvance",
- "type": "object"
- },
- {
- "type": "null"
- }
- ],
- "default": null
- }
- },
- "required": [
- "id",
- "label",
- "kind",
- "accepted",
- "already_connected"
- ],
- "title": "ConnectionRequestNode",
- "type": "object"
- },
- {
- "additionalProperties": false,
- "description": "A repliable send — a LinkedIn message/inmail, or an email. Routes `replied` (a reply\nadvances the prospect off the node) and an optional `follow_up` (a held no-reply canned\nfollow-on, itself just another send reached after the delay).\n\n`message_templates` is input-only: excluded from every dump, so it never lands in the stored\nsequence — the step's templates live in their own rows and are merged back in on read. A step\nwith two is running an A/B test.",
- "properties": {
- "action": {
- "enum": [
- "message",
- "inmail",
- "email"
- ],
- "type": "string"
- },
- "channel": {
- "enum": [
- "linkedin",
- "email"
- ],
- "type": "string"
- },
- "follow_up": {
- "anyOf": [
- {
- "additionalProperties": false,
- "description": "A held follow-on anchored on this node's send — always delayed (no instant form).\n ",
- "properties": {
- "delay": {
- "additionalProperties": false,
- "description": "A timed hold: `value` units of `unit`. A `d` (day) hold counts BUSINESS days — Mon–Fri,\nweekends skipped — the outreach default; `cd` counts calendar days (weekends included), as\ndo `w`/`h`/`m`. Validated by construction (no free-form string to parse) and stored\nJSON-natively as `{value, unit}`.",
- "properties": {
- "unit": {
- "enum": [
- "w",
- "cd",
- "d",
- "h",
- "m"
- ],
- "type": "string"
- },
- "value": {
- "exclusiveMinimum": 0,
- "type": "integer"
- }
- },
- "required": [
- "value",
- "unit"
- ],
- "title": "EdgeDelay",
- "type": "object"
- },
- "to": {
- "type": "string"
- }
- },
- "required": [
- "delay",
- "to"
- ],
- "title": "TimedAdvance",
- "type": "object"
- },
- {
- "type": "null"
- }
- ],
- "default": null
- },
- "id": {
- "type": "string"
- },
- "kind": {
- "const": "send",
- "type": "string"
- },
- "label": {
- "type": "string"
- },
- "message_templates": {
- "anyOf": [
- {
- "items": {
- "type": "string"
- },
- "maxItems": 2,
- "type": "array"
- },
- {
- "type": "null"
- }
- ],
- "default": null
- },
- "replied": {
- "type": "string"
- }
- },
- "required": [
- "id",
- "label",
- "kind",
- "channel",
- "action",
- "replied"
- ],
- "title": "SendNode",
- "type": "object"
- },
- {
- "additionalProperties": false,
- "description": "A bodyless LinkedIn action (follow / withdraw / resolve / comment / reaction) — no\nreply to route. `then` is its single advance: bare (`then.after=None`) flows straight\ninto the next node when the send completes, or held for a delay first.\n\n`notify` applies only to `action='resolve'`: True makes the profile lookup a *visible*\nvisit (\"View Profile\") that notifies the person — a warm-up touch — instead of the\nsilent data lookup. Default False.",
- "properties": {
- "action": {
- "enum": [
- "follow",
- "withdraw",
- "resolve",
- "comment",
- "reaction"
- ],
- "type": "string"
- },
- "channel": {
- "const": "linkedin",
- "type": "string"
- },
- "id": {
- "type": "string"
- },
- "kind": {
- "const": "action",
- "type": "string"
- },
- "label": {
- "type": "string"
- },
- "notify": {
- "default": false,
- "type": "boolean"
- },
- "then": {
- "additionalProperties": false,
- "description": "An unconditional advance onto `to`. `after=None` fires the instant the source send\ncompletes (the send-completion advance); `after` set holds for that delay first (a\ntimed advance anchored on the send's sent_at, or on tracking time off the start node).",
- "properties": {
- "after": {
- "anyOf": [
- {
- "additionalProperties": false,
- "description": "A timed hold: `value` units of `unit`. A `d` (day) hold counts BUSINESS days — Mon–Fri,\nweekends skipped — the outreach default; `cd` counts calendar days (weekends included), as\ndo `w`/`h`/`m`. Validated by construction (no free-form string to parse) and stored\nJSON-natively as `{value, unit}`.",
- "properties": {
- "unit": {
- "enum": [
- "w",
- "cd",
- "d",
- "h",
- "m"
- ],
- "type": "string"
- },
- "value": {
- "exclusiveMinimum": 0,
- "type": "integer"
- }
- },
- "required": [
- "value",
- "unit"
- ],
- "title": "EdgeDelay",
- "type": "object"
- },
- {
- "type": "null"
- }
- ],
- "default": null
- },
- "to": {
- "type": "string"
- }
- },
- "required": [
- "to"
- ],
- "title": "Advance",
- "type": "object"
- }
- },
- "required": [
- "id",
- "label",
- "kind",
- "channel",
- "action",
- "then"
- ],
- "title": "SilentActionNode",
- "type": "object"
- },
- {
- "additionalProperties": false,
- "description": "A step a human performs off-platform that the system surfaces but never enacts (a\ncall, a gift, a recorded note). Entry queues a manual_action_queue row carrying\n`action_description`; the user marking that row done advances the prospect along `then`.\nNo channel and no reply to route; `then` is a single bare advance — completion is\nhuman-paced, so there's no timed hold to anchor on a send's sent_at.",
- "properties": {
- "action_description": {
- "type": "string"
- },
- "id": {
- "type": "string"
- },
- "kind": {
- "const": "manual",
- "type": "string"
- },
- "label": {
- "type": "string"
- },
- "then": {
- "type": "string"
- }
- },
- "required": [
- "id",
- "label",
- "kind",
- "action_description",
- "then"
- ],
- "title": "ManualActionNode",
- "type": "object"
- },
- {
- "additionalProperties": false,
- "description": "An automated side-effect the agent performs on entry — update a CRM, post a\nnotification, tag a record — with no outreach send, then advances along `then`. The\nside-effect itself is authored onto the node's on_enter trigger (a `prompt`, or `code` for\na deterministic one), like a terminal node's hook — not a field here. Unlike a manual node\nit boots an agent run (rather than waiting on a human) and unlike a terminal hook it\nadvances; structurally it is a decision with one implicit 'always' arm — the run does the\nside-effect, then moves each prospect onto `then`. `then` is a single bare\nadvance: a side-effect completes on the run, not a send's sent_at, so there's no timed hold.",
- "properties": {
- "id": {
- "type": "string"
- },
- "kind": {
- "const": "automation",
- "type": "string"
- },
- "label": {
- "type": "string"
- },
- "then": {
- "type": "string"
- }
- },
- "required": [
- "id",
- "label",
- "kind",
- "then"
- ],
- "title": "AutomationNode",
- "type": "object"
- },
- {
- "additionalProperties": false,
- "description": "A natural-language judgment fork. `arms` are the judged routes — each a `case`\ncondition and a target (the default authored as an explicit arm too, e.g. case='else').",
- "properties": {
- "arms": {
- "items": {
- "additionalProperties": false,
- "description": "One judged decision arm: `case` is the natural-language condition (stripped,\nnon-empty — the decision judge needs something to evaluate), `to` its target node.",
- "properties": {
- "case": {
- "minLength": 1,
- "type": "string"
- },
- "to": {
- "type": "string"
- }
- },
- "required": [
- "case",
- "to"
- ],
- "title": "Arm",
- "type": "object"
- },
- "minItems": 1,
- "type": "array"
- },
- "id": {
- "type": "string"
- },
- "kind": {
- "const": "decision",
- "type": "string"
- },
- "label": {
- "type": "string"
- },
- "rule": {
- "type": "string"
- }
- },
- "required": [
- "id",
- "label",
- "kind",
- "rule",
- "arms"
- ],
- "title": "DecisionNode",
- "type": "object"
- },
- {
- "additionalProperties": false,
- "description": "A resting end-state with no further outreach — structurally a sink (no out-edge\nslots). Its human meaning lives in `label`. A terminal can still carry an on_enter hook —\na notify / tag / webhook side-effect on entry, no send and no movement — but that is just\nan on_enter Trigger added to the node with add_trigger, not a field here.",
- "properties": {
- "id": {
- "type": "string"
- },
- "kind": {
- "const": "terminal",
- "type": "string"
- },
- "label": {
- "type": "string"
- }
- },
- "required": [
- "id",
- "label",
- "kind"
- ],
- "title": "TerminalNode",
- "type": "object"
- }
-]New value: +[
+ {
+ "additionalProperties": false,
+ "description": "A LinkedIn connection request. Routes both send outcomes — `accepted` (invite\ntaken) and `already_connected` (a no-op CR on an existing 1st-degree connection) — and\nan optional `timeout` (a held advance, e.g. withdraw after no accept).\n\n`message_templates` is input-only, as on a send node, and holds the request's note (at most\n300 characters): `''` is a version sent without one, so `['', note]` A/B tests a note\nagainst none.",
+ "properties": {
+ "accepted": {
+ "type": "string"
+ },
+ "already_connected": {
+ "type": "string"
+ },
+ "id": {
+ "type": "string"
+ },
+ "kind": {
+ "const": "connection_request",
+ "type": "string"
+ },
+ "label": {
+ "type": "string"
+ },
+ "message_templates": {
+ "anyOf": [
+ {
+ "items": {
+ "maxLength": 300,
+ "type": "string"
+ },
+ "maxItems": 2,
+ "type": "array"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "default": null
+ },
+ "timeout": {
+ "anyOf": [
+ {
+ "additionalProperties": false,
+ "description": "A held follow-on anchored on this node's send — always delayed (no instant form).\n ",
+ "properties": {
+ "delay": {
+ "additionalProperties": false,
+ "description": "A timed hold: `value` units of `unit`. A `d` (day) hold counts BUSINESS days — Mon–Fri,\nweekends skipped — the outreach default; `cd` counts calendar days (weekends included), as\ndo `w`/`h`/`m`. Validated by construction (no free-form string to parse) and stored\nJSON-natively as `{value, unit}`.",
+ "properties": {
+ "unit": {
+ "enum": [
+ "w",
+ "cd",
+ "d",
+ "h",
+ "m"
+ ],
+ "type": "string"
+ },
+ "value": {
+ "exclusiveMinimum": 0,
+ "type": "integer"
+ }
+ },
+ "required": [
+ "value",
+ "unit"
+ ],
+ "title": "EdgeDelay",
+ "type": "object"
+ },
+ "to": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "delay",
+ "to"
+ ],
+ "title": "TimedAdvance",
+ "type": "object"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "default": null
+ }
+ },
+ "required": [
+ "id",
+ "label",
+ "kind",
+ "accepted",
+ "already_connected"
+ ],
+ "title": "ConnectionRequestNode",
+ "type": "object"
+ },
+ {
+ "additionalProperties": false,
+ "description": "A repliable send — a LinkedIn message/inmail, or an email. Routes `replied` (a reply\nadvances the prospect off the node) and an optional `follow_up` (a held no-reply canned\nfollow-on, itself just another send reached after the delay).\n\n`message_templates` is input-only: excluded from every dump, so it never lands in the stored\nsequence — the step's templates live in their own rows and are merged back in on read. A step\nwith two is running an A/B test.",
+ "properties": {
+ "action": {
+ "enum": [
+ "message",
+ "inmail",
+ "email"
+ ],
+ "type": "string"
+ },
+ "channel": {
+ "enum": [
+ "linkedin",
+ "email"
+ ],
+ "type": "string"
+ },
+ "follow_up": {
+ "anyOf": [
+ {
+ "additionalProperties": false,
+ "description": "A held follow-on anchored on this node's send — always delayed (no instant form).\n ",
+ "properties": {
+ "delay": {
+ "additionalProperties": false,
+ "description": "A timed hold: `value` units of `unit`. A `d` (day) hold counts BUSINESS days — Mon–Fri,\nweekends skipped — the outreach default; `cd` counts calendar days (weekends included), as\ndo `w`/`h`/`m`. Validated by construction (no free-form string to parse) and stored\nJSON-natively as `{value, unit}`.",
+ "properties": {
+ "unit": {
+ "enum": [
+ "w",
+ "cd",
+ "d",
+ "h",
+ "m"
+ ],
+ "type": "string"
+ },
+ "value": {
+ "exclusiveMinimum": 0,
+ "type": "integer"
+ }
+ },
+ "required": [
+ "value",
+ "unit"
+ ],
+ "title": "EdgeDelay",
+ "type": "object"
+ },
+ "to": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "delay",
+ "to"
+ ],
+ "title": "TimedAdvance",
+ "type": "object"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "default": null
+ },
+ "id": {
+ "type": "string"
+ },
+ "kind": {
+ "const": "send",
+ "type": "string"
+ },
+ "label": {
+ "type": "string"
+ },
+ "message_templates": {
+ "anyOf": [
+ {
+ "items": {
+ "type": "string"
+ },
+ "maxItems": 2,
+ "type": "array"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "default": null
+ },
+ "replied": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "id",
+ "label",
+ "kind",
+ "channel",
+ "action",
+ "replied"
+ ],
+ "title": "SendNode",
+ "type": "object"
+ },
+ {
+ "additionalProperties": false,
+ "description": "A bodyless LinkedIn action (follow / withdraw / resolve / comment / reaction) — no\nreply to route. `then` is its single advance: bare (`then.after=None`) flows straight\ninto the next node when the send completes, or held for a delay first.\n\n`notify` applies only to `action='resolve'`: True makes the profile lookup a *visible*\nvisit (\"View Profile\") that notifies the person — a warm-up touch — instead of the\nsilent data lookup. Default False.",
+ "properties": {
+ "action": {
+ "enum": [
+ "follow",
+ "withdraw",
+ "resolve",
+ "comment",
+ "reaction"
+ ],
+ "type": "string"
+ },
+ "channel": {
+ "const": "linkedin",
+ "type": "string"
+ },
+ "id": {
+ "type": "string"
+ },
+ "kind": {
+ "const": "action",
+ "type": "string"
+ },
+ "label": {
+ "type": "string"
+ },
+ "notify": {
+ "default": false,
+ "type": "boolean"
+ },
+ "then": {
+ "additionalProperties": false,
+ "description": "An unconditional advance onto `to`. `after=None` fires the instant the source send\ncompletes (the send-completion advance); `after` set holds for that delay first (a\ntimed advance anchored on the send's sent_at, or on tracking time off the start node).",
+ "properties": {
+ "after": {
+ "anyOf": [
+ {
+ "additionalProperties": false,
+ "description": "A timed hold: `value` units of `unit`. A `d` (day) hold counts BUSINESS days — Mon–Fri,\nweekends skipped — the outreach default; `cd` counts calendar days (weekends included), as\ndo `w`/`h`/`m`. Validated by construction (no free-form string to parse) and stored\nJSON-natively as `{value, unit}`.",
+ "properties": {
+ "unit": {
+ "enum": [
+ "w",
+ "cd",
+ "d",
+ "h",
+ "m"
+ ],
+ "type": "string"
+ },
+ "value": {
+ "exclusiveMinimum": 0,
+ "type": "integer"
+ }
+ },
+ "required": [
+ "value",
+ "unit"
+ ],
+ "title": "EdgeDelay",
+ "type": "object"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "default": null
+ },
+ "to": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "to"
+ ],
+ "title": "Advance",
+ "type": "object"
+ }
+ },
+ "required": [
+ "id",
+ "label",
+ "kind",
+ "channel",
+ "action",
+ "then"
+ ],
+ "title": "SilentActionNode",
+ "type": "object"
+ },
+ {
+ "additionalProperties": false,
+ "description": "A step a human performs off-platform that the system surfaces but never enacts (a\ncall, a gift, a recorded note). Entry queues a manual_action_queue row carrying\n`action_description`; the user marking that row done advances the prospect along `then`.\nNo channel and no reply to route; `then` is a single bare advance — completion is\nhuman-paced, so there's no timed hold to anchor on a send's sent_at.",
+ "properties": {
+ "action_description": {
+ "type": "string"
+ },
+ "id": {
+ "type": "string"
+ },
+ "kind": {
+ "const": "manual",
+ "type": "string"
+ },
+ "label": {
+ "type": "string"
+ },
+ "then": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "id",
+ "label",
+ "kind",
+ "action_description",
+ "then"
+ ],
+ "title": "ManualActionNode",
+ "type": "object"
+ },
+ {
+ "additionalProperties": false,
+ "description": "An automated side-effect the agent performs on entry — update a CRM, post a\nnotification, tag a record — with no outreach send, then advances along `then`. The\nside-effect itself is authored onto the node's on_enter trigger (a `prompt`, or `code` for\na deterministic one), like a terminal node's hook — not a field here. Unlike a manual node\nit boots an agent run (rather than waiting on a human) and unlike a terminal hook it\nadvances; structurally it is a decision with one implicit 'always' arm — the run does the\nside-effect, then moves each prospect onto `then`. `then` is a single bare\nadvance: a side-effect completes on the run, not a send's sent_at, so there's no timed hold.",
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "kind": {
+ "const": "automation",
+ "type": "string"
+ },
+ "label": {
+ "type": "string"
+ },
+ "then": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "id",
+ "label",
+ "kind",
+ "then"
+ ],
+ "title": "AutomationNode",
+ "type": "object"
+ },
+ {
+ "additionalProperties": false,
+ "description": "A natural-language judgment fork. `arms` are the judged routes — each a `case`\ncondition and a target (the default authored as an explicit arm too, e.g. case='else').",
+ "properties": {
+ "arms": {
+ "items": {
+ "additionalProperties": false,
+ "description": "One judged decision arm: `case` is the natural-language condition (stripped,\nnon-empty — the decision judge needs something to evaluate), `to` its target node.",
+ "properties": {
+ "case": {
+ "minLength": 1,
+ "type": "string"
+ },
+ "to": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "case",
+ "to"
+ ],
+ "title": "Arm",
+ "type": "object"
+ },
+ "minItems": 1,
+ "type": "array"
+ },
+ "id": {
+ "type": "string"
+ },
+ "kind": {
+ "const": "decision",
+ "type": "string"
+ },
+ "label": {
+ "type": "string"
+ },
+ "rule": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "id",
+ "label",
+ "kind",
+ "rule",
+ "arms"
+ ],
+ "title": "DecisionNode",
+ "type": "object"
+ },
+ {
+ "additionalProperties": false,
+ "description": "A resting end-state with no further outreach — structurally a sink (no out-edge\nslots). Its human meaning lives in `label`. A terminal can still carry an on_enter hook —\na notify / tag / webhook side-effect on entry, no send and no movement — but that is just\nan on_enter Trigger added to the node with add_trigger, not a field here.",
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "kind": {
+ "const": "terminal",
+ "type": "string"
+ },
+ "label": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "id",
+ "label",
+ "kind"
+ ],
+ "title": "TerminalNode",
+ "type": "object"
+ }
+]