[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-twilio-twilio-studio-flows":3,"mdc--5wm916-key":33,"related-repo-twilio-twilio-studio-flows":3125,"related-org-twilio-twilio-studio-flows":3230},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":23,"repoUrl":24,"updatedAt":25,"license":26,"forks":27,"topics":28,"repo":29,"sourceUrl":31,"mdContent":32},"twilio-studio-flows","build and deploy Twilio Studio flows","Build and deploy Twilio Studio flows — visual IVR, SMS\u002FWhatsApp, and conversation automation — by authoring the flow definition JSON and managing it through the Studio REST API. Covers the flow envelope, widgets, transitions, Liquid templating, the draft\u002Fpublished lifecycle, and when to use Studio vs. custom TwiML\u002Fcode. Use this skill to create, validate, deploy, or update a Studio flow programmatically.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},"twilio","Twilio","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Ftwilio.png",[12,16,19,22],{"name":13,"slug":14,"type":15},"Automation","automation","tag",{"name":17,"slug":18,"type":15},"Messaging","messaging",{"name":20,"slug":21,"type":15},"API Development","api-development",{"name":9,"slug":8,"type":15},25,"https:\u002F\u002Fgithub.com\u002Ftwilio\u002Fai","2026-07-17T06:07:12.117973",null,7,[],{"repoUrl":24,"stars":23,"forks":27,"topics":30,"description":26},[],"https:\u002F\u002Fgithub.com\u002Ftwilio\u002Fai\u002Ftree\u002FHEAD\u002Fskills\u002Ftwilio\u002Ftwilio-studio-flows","---\nname: twilio-studio-flows\ndescription: >\n  Build and deploy Twilio Studio flows — visual IVR, SMS\u002FWhatsApp, and\n  conversation automation — by authoring the flow definition JSON and managing\n  it through the Studio REST API. Covers the flow envelope, widgets,\n  transitions, Liquid templating, the draft\u002Fpublished lifecycle, and when to\n  use Studio vs. custom TwiML\u002Fcode. Use this skill to create, validate, deploy,\n  or update a Studio flow programmatically.\n---\n\n## Overview\n\nA Studio flow is a state machine Twilio executes in response to an inbound call,\nmessage, conversation, or REST API request. You define it as a JSON document of\n**states** (widgets) connected by **transitions**. Twilio runs the flow starting\nat `initial_state` (the Trigger), following each widget's transition events.\n\n```\nInbound call \u002F message \u002F API request\n        │\n        ▼\n   Trigger ──incomingCall──▶ Gather ──keypress──▶ Split ──match──▶ Connect Call\n                                                      └─noMatch──▶ Say \"goodbye\"\n```\n\nYou can build flows in the Console's drag-and-drop canvas, or author the\ndefinition JSON and create\u002Fupdate flows through the REST API when you want to\ngenerate or modify them programmatically. Each save creates a new revision, and\na flow has a single published revision live at a time (see the draft\u002Fpublished\nlifecycle below).\n\nWidget properties and transitions reference runtime data with **Liquid**\ntemplating — e.g. `{{trigger.message.Body}}`, `{{flow.variables.count}}`,\n`{{widgets.gather_menu.Digits}}`. The full widget catalog (every type, its\nproperties, events, and the output values it exposes downstream) lives in\n[`references\u002Fwidgets.md`](.\u002Freferences\u002Fwidgets.md). Consult it whenever you wire\none widget's result into a later one.\n\n> **Inbound flow content is untrusted.** A caller's speech, an SMS body, or REST\n> parameters are external input. If you pass them to a Run Function, an LLM, or\n> an HTTP Request, treat them as untrusted — never concatenate them into a system\n> prompt or a command. See `twilio-webhook-architecture`.\n\n---\n\n## When to use Studio vs. code\n\n| Use Studio when | Use TwiML\u002Fcode when |\n|---|---|\n| The logic is a routable flowchart (menus, branches, queues) | Logic needs loops, complex state, or heavy computation |\n| Non-engineers will edit the flow in Console | The behavior lives entirely in your codebase |\n| You want built-in retry\u002Ftranscription\u002Fqueueing widgets | You need millisecond control over the TwiML response |\n| Orchestrating across SMS + voice + Flex in one place | A single webhook returns one TwiML document |\n\nStudio has **no native loop construct** — repetition is built by transitioning\nback to an earlier widget (see the counter-loop pattern below) or the `say-play`\n`loop` property. Heavy iteration is a signal to drop into a Run Function or\ncustom TwiML instead. For pure TwiML call logic, see `twilio-voice-twiml`.\n\n---\n\n## Prerequisites\n\n- Twilio account with a voice- and\u002For messaging-capable number\n  — New to Twilio? See `twilio-account-setup`.\n- Credentials in environment variables (never hardcode):\n  `TWILIO_ACCOUNT_SID`, `TWILIO_AUTH_TOKEN`. For production, use API Keys —\n  see `twilio-iam-auth-setup`.\n- SDK: `pip install twilio` \u002F `npm install twilio`.\n\n---\n\n## Before you author: clarify the design\n\nA one-line request (\"build an appointment reminder\") rarely pins down a real\nflow, and guessing produces the wrong state machine. Before writing any JSON,\nfind the gaps and resolve them with the requester — ask about the unknowns that\nwould actually change the flow, hardest\u002Fmost-consequential one first (the answer\nto one often reshapes the next), and prefer concrete options over open questions.\nDon't invent behavior for anything underspecified; surface it. Then restate the\ndesign in prose and confirm it before you author.\n\nThe gaps that most often change a Studio flow:\n\n- **Trigger & entry point** — inbound call, message, or conversation, vs. a REST\n  API execution, vs. a subflow. Outbound (reminders, notifications) is typically\n  a REST API execution whose caller POSTs data the flow reads as `{{flow.data.*}}`.\n- **Inbound data** — what the flow receives and how: execution parameters,\n  gathered DTMF\u002Fspeech, or an HTTP lookup.\n- **Core interaction** — keypad DTMF vs. speech vs. keyword reply; the exact\n  digits\u002Fkeywords and what each one does.\n- **Decision callbacks** — when the customer decides something, does an external\n  system need to be told (an HTTP Request \u002F Run Function), and what are its\n  request shape, auth, and failure behavior?\n- **Unhappy paths** — no input, invalid input, no match, timeouts, and\n  max-retry exhaustion. Re-prompt how many times, then what?\n- **Branching completeness** — every menu option and Split branch accounted for,\n  including the default \u002F `noMatch` fallback.\n- **Terminal states** — how each branch ends: hang up, final message, or hand\n  off to an agent\u002Fqueue.\n- **Dynamic values** — greetings, numbers, URLs, and copy that should come from\n  `flow.*` \u002F `trigger.*` rather than being hard-coded.\n\nAsk only what matters for the flow at hand — a trivial auto-responder may need\nnone; a reminder, IVR, or booking flow usually needs several.\n\n## Quickstart\n\nBuild a minimal SMS auto-responder flow, validate it, and create it as a draft.\n\n**1. Author the flow definition.** Build the JSON as a native object and\nserialize it — never string-concatenate JSON.\n\n**Python**\n```python\nflow_definition = {\n    \"description\": \"SMS auto-responder\",\n    \"states\": [\n        {\n            \"name\": \"Trigger\",\n            \"type\": \"trigger\",\n            \"transitions\": [{\"event\": \"incomingMessage\", \"next\": \"reply\"}],\n            \"properties\": {},\n        },\n        {\n            \"name\": \"reply\",\n            \"type\": \"send-message\",\n            \"transitions\": [{\"event\": \"sent\"}, {\"event\": \"failed\"}],\n            \"properties\": {\n                \"from\": \"{{flow.channel.address}}\",\n                \"to\": \"{{contact.channel.address}}\",\n                \"body\": \"Thanks for your message! We'll be in touch shortly.\",\n            },\n        },\n    ],\n    \"initial_state\": \"Trigger\",\n    \"flags\": {\"allow_concurrent_calls\": True},\n}\n```\n\n**Node.js**\n```node\nconst flowDefinition = {\n  description: \"SMS auto-responder\",\n  states: [\n    {\n      name: \"Trigger\",\n      type: \"trigger\",\n      transitions: [{ event: \"incomingMessage\", next: \"reply\" }],\n      properties: {},\n    },\n    {\n      name: \"reply\",\n      type: \"send-message\",\n      transitions: [{ event: \"sent\" }, { event: \"failed\" }],\n      properties: {\n        from: \"{{flow.channel.address}}\",\n        to: \"{{contact.channel.address}}\",\n        body: \"Thanks for your message! We'll be in touch shortly.\",\n      },\n    },\n  ],\n  initial_state: \"Trigger\",\n  flags: { allow_concurrent_calls: true },\n};\n```\n\n**2. Create the flow as a draft.** Pass the definition, a friendly name, and a\ncommit message. `status=\"draft\"` keeps it off live traffic.\n\n**Python**\n```python\nimport os\nfrom twilio.rest import Client\n\nclient = Client(os.environ[\"TWILIO_ACCOUNT_SID\"], os.environ[\"TWILIO_AUTH_TOKEN\"])\n\nflow = client.studio.v2.flows.create(\n    friendly_name=\"SMS Auto-Responder\",\n    status=\"draft\",\n    definition=flow_definition,          # SDK serializes the dict\n    commit_message=\"Initial draft\",\n)\nprint(f\"Created flow {flow.sid} (status={flow.status})\")\n```\n\n**Node.js**\n```node\nconst client = require(\"twilio\")(\n  process.env.TWILIO_ACCOUNT_SID,\n  process.env.TWILIO_AUTH_TOKEN\n);\n\nconst flow = await client.studio.v2.flows.create({\n  friendlyName: \"SMS Auto-Responder\",\n  status: \"draft\",\n  definition: flowDefinition,\n  commitMessage: \"Initial draft\",\n});\nconsole.log(`Created flow ${flow.sid} (status=${flow.status})`);\n```\n\nTest the draft in the Console (Studio > your flow > Test), then publish it\n(next section). Wire the flow to a number or Messaging Service to take live\ntraffic.\n\n## Key Patterns\n\n### Validate before deploy\n\nTwilio's `FlowValidate` endpoint checks a definition without saving it. The SDK\nexposes it via the `studio.v2.flowValidate` resource. Validate after every edit;\nfix each reported error before deploying.\n\nWhen a definition is invalid the call **raises** (it does not return\n`valid=False`). The exception's `details` carries the specific per-state errors —\na `property_path` like `#\u002Fstates\u002F3\u002Fproperties\u002Fpayment_method` and a message.\nAlways read `details`; the top-level message only says validation failed.\n\n**Python**\n```python\nfrom twilio.base.exceptions import TwilioRestException\n\ntry:\n    result = client.studio.v2.flow_validate.update(\n        friendly_name=\"SMS Auto-Responder\",\n        status=\"draft\",\n        definition=flow_definition,\n    )\n    print(\"valid\" if result.valid else \"invalid\")\nexcept TwilioRestException as e:\n    for err in (e.details or {}).get(\"errors\", []):\n        print(f\"{err['property_path']}: {err['message']}\")\n    raise\n```\n\n**Node.js**\n```node\ntry {\n  const result = await client.studio.v2.flowValidate.update({\n    friendlyName: \"SMS Auto-Responder\",\n    status: \"draft\",\n    definition: flowDefinition,\n  });\n  console.log(result.valid ? \"valid\" : \"invalid\");\n} catch (e) {\n  for (const err of e.details?.errors ?? []) {\n    console.log(`${err.property_path}: ${err.message}`);\n  }\n  throw e;\n}\n```\n\n#### Reading and fixing validation errors\n\nEach error has a `property_path` (e.g. `#\u002Fstates\u002F3\u002Fproperties\u002Ftimeout` points at\nthe `timeout` property of the 4th state — paths are 0-indexed) and a `message`.\nFix one widget at a time, then re-validate. The common messages and their fixes:\n\n| Message | Meaning | Fix |\n|---|---|---|\n| `boolean found, string expected` | A flag must be a quoted string | Send `\"true\"`\u002F`\"false\"`, not `true`\u002F`false` (e.g. `trim`, `play_beep`, `postal_code`, `profanity_filter`, `interruptible`) |\n| `integer found, string expected` | A number must be a quoted string | Quote it: `\"3600\"`, not `3600` (e.g. `timeout`, `time_limit`, `priority`, `machine_detection_timeout`) |\n| `string found, boolean expected` | The reverse — this one wants a real boolean | Send `true`, not `\"true\"` (e.g. `security_code`). Coercion is per-property; trust the message, not a global rule |\n| `does not have a value in the enumeration [...]` | Wrong `type` string, or an out-of-range enum value | Use one of the listed values exactly (this is how you discover the real widget `type`) |\n| `must be a constant value \u003Cx>` (repeated) | A transition `event` name isn't valid for this widget | Use one of the `\u003Cx>` values listed; remove invented events |\n| `is missing but it is required` | A required property\u002Fsub-field is absent | Add it at the named path |\n| `must not be null` | Required property present but unset | Give it a value |\n| `must be a valid, non-liquid flow sid` | A SID field got a Liquid template or bad value | Pass a literal SID |\n| `\u003Cwidget> can only be used in flows triggered by the REST API` | Widget needs an `incomingRequest` trigger | Trigger the flow via the REST API, not a call\u002Fmessage |\n\nWhen the message itself lists the allowed values (enumeration \u002F constant-value\ncases), that list is authoritative — prefer it over any documentation.\n\n### Publish, update, and the full-replace rule\n\nA flow has a **draft** and a **published** revision. `status=\"published\"` makes\nthe flow live to real traffic; `status=\"draft\"` keeps it editable without\naffecting traffic. Each save increments the revision.\n\n**Updating replaces the entire definition — there is no partial patch.** Always\nsend the complete definition JSON, not a diff. To change one widget, fetch the\ncurrent definition, modify it, and send the whole thing back.\n\n**Python**\n```python\nflow = client.studio.v2.flows(flow_sid).update(\n    status=\"published\",\n    definition=flow_definition,      # the COMPLETE definition\n    commit_message=\"Publish auto-responder\",\n)\n```\n\n**Node.js**\n```node\nconst flow = await client.studio.v2.flows(flowSid).update({\n  status: \"published\",\n  definition: flowDefinition,        \u002F\u002F the COMPLETE definition\n  commitMessage: \"Publish auto-responder\",\n});\n```\n\n### List and fetch (round-trip editing)\n\nList flows with `client.studio.v2.flows.list({ limit })`; fetch one with\n`client.studio.v2.flows(flowSid).fetch()` — its `.definition` is the JSON you\nedit and send back via `update`. These are read-only.\n\n### Core widgets at a glance\n\n| Widget | `type` | Use for |\n|---|---|---|\n| Trigger | `trigger` | Flow entry point (call\u002Fmessage\u002Fconversation\u002FREST) |\n| Say\u002FPlay | `say-play` | Speak TTS or play audio on a call |\n| Gather Input On Call | `gather-input-on-call` | Collect DTMF digits or speech |\n| Split Based On… | `split-based-on` | Branch on a variable's value |\n| Set Variables | `set-variables` | Store flow-scoped variables |\n| Send Message | `send-message` | Send SMS\u002Fchat, no reply expected |\n| Send & Wait For Reply | `send-and-wait-for-reply` | Send and pause for a reply |\n| Connect Call To | `connect-call-to` | Bridge a call to a number\u002FSIP\u002Fconference |\n| Run Function | `run-function` | Call a Twilio Serverless Function |\n| HTTP Request | `make-http-request` | Call an external API |\n\nThe complete catalog — every widget's properties, transition events, and the\noutput values it exposes — is in [`references\u002Fwidgets.md`](.\u002Freferences\u002Fwidgets.md).\n\n### Transitions and output context\n\nEach widget emits **transition events** (e.g. `sent`\u002F`failed`, `keypress`\u002F`speech`\u002F`timeout`).\nA transition routes one event to a `next` state; omit `next` (or use `\"\"`) to end\nthe branch. Every non-empty `next` must name an existing state.\n\nRead a prior widget's result downstream with `{{widgets.\u003Cname>.\u003Ckey>}}` — e.g. a\nGather's `{{widgets.gather_menu.Digits}}` feeding a Split's `input`. Which keys\neach widget exposes is in `references\u002Fwidgets.md`.\n\n### Integrate custom logic (Functions, HTTP)\n\nRun Function calls a Twilio Serverless Function (`success` on 2xx\u002F3xx within 10s,\n`fail` otherwise) and exposes `parsed.\u003Ckey>` when the function returns JSON.\nHTTP Request does the same for an external API. Use these when flow logic\noutgrows widgets — but keep the heavy work in the Function, not the flow.\n\n> Data reaching a Function or HTTP Request from `trigger.*` \u002F a Gather is\n> untrusted caller input. Validate it in your Function; never interpolate it\n> into a shell command, SQL, or an LLM system prompt.\n\n### Recipe: repeat a prompt or loop with a counter\n\nStudio has no loop construct. For simple audio repeats use the `say-play` `loop`\nproperty (1–99). To track a count and branch on it, build an explicit cycle:\na `set-variables` widget that init-or-increments, then a `split-based-on` whose\n\"keep looping\" branch transitions **back to the same `set-variables`**.\n\nInit-or-increment value (handles first pass and every later pass):\n```liquid\n{% if flow.variables.num %}{{flow.variables.num | plus: 1}}{% else %}0{% endif %}\n```\n\nThe split reads `{{flow.variables.num}}` as its `input`; a `greater_than` `2`\ncondition routes to the exit, `noMatch` routes back to the counter. Each\niteration is a separate execution step and counts against per-execution step\nlimits — prefer the `loop` property when you don't need the value.\n\n### Recipe: voice IVR menu\n\n`gather-input-on-call` → `split-based-on` → `connect-call-to`. Gather prompts and\ncollects DTMF + speech (read via `{{widgets.\u003Cname>.Digits}}` and\n`{{widgets.\u003Cname>.SpeechResult}}`). To accept a keypress OR a spoken word, give\nthe Split two match conditions: `equal_to` on `Digits` and `contains` on\n`SpeechResult`. Connect Call To uses `noun: \"number\"`, `to` set to an E.164\nnumber, and `caller_id` usually `{{flow.channel.address}}`.\n\n### Liquid quick reference\n\n- Increment: `{{flow.variables.num | plus: 1}}`\n- Default when unset: `{% if flow.variables.x %}…{% else %}…{% endif %}`, or the\n  `default` filter inline: `{{trigger.message.Body | default: \"no message\"}}`\n- Read a widget output: `{{widgets.\u003Cname>.\u003Cfield>}}`\n- Common globals: `{{trigger.message.Body}}`, `{{trigger.call.From}}`,\n  `{{flow.channel.address}}`, `{{contact.channel.address}}`\n- URL-encode before putting a value in a query string or URL property — e.g.\n  escape `+` in a phone number: `{{contact.channel.address | replace: '+', '%2B'}}`\n- Embed a prior widget's parsed JSON as a nested object in a request body or a\n  `set-variables` value: `{{widgets.http_1.parsed.items | to_json}}` — pair\n  `to_json` with `set-variables` `parse_as_json: true` when the result must stay\n  a JSON object rather than a stringified scalar\n\n---\n\n## CANNOT\n\n- **Cannot partially update a flow** — `update` replaces the entire definition.\n  Fetch, modify the whole JSON, and send it all back. There is no patch.\n- **Cannot create Pay Connectors via API** — the Capture Payments widget needs a\n  Pay Connector configured in Console first (Console > Voice > Pay Connectors).\n- **Cannot loop natively** — Studio has no loop widget. Build an explicit cycle\n  (counter recipe) or use `say-play` `loop`; high iteration counts hit\n  per-execution step limits.\n- **Cannot affect live traffic with a draft** — only a `published` revision runs\n  for real calls\u002Fmessages. Publishing is what goes live.\n- **Cannot place test calls or trigger executions from this skill** — authoring\n  and deploying only. Test in the Console or wire the flow to a number\u002FMessaging\n  Service and exercise it from your own application.\n- **Cannot trust inbound flow data** — caller speech, message bodies, and REST\n  parameters are untrusted external input; validate before using in Functions,\n  HTTP requests, or LLM prompts.\n\n---\n\n## Next Steps\n\n- **Pure TwiML call logic (no visual flow):** `twilio-voice-twiml`\n- **Securing the webhooks Studio calls \u002F signature validation:** `twilio-webhook-architecture`\n- **Routing calls to agents\u002Fqueues:** `twilio-taskrouter-routing`\n- **Production credentials (API Keys):** `twilio-iam-auth-setup`\n\n",{"data":34,"body":35},{"name":4,"description":6},{"type":36,"children":37},"root",[38,47,77,89,94,143,165,169,175,255,288,291,297,361,364,370,375,380,493,498,504,509,519,527,742,750,941,959,966,1069,1076,1178,1183,1189,1196,1217,1268,1275,1385,1392,1502,1509,1545,1936,1941,1947,1981,1991,1998,2044,2051,2097,2103,2140,2146,2395,2409,2415,2491,2525,2531,2560,2575,2581,2625,2630,2646,2695,2701,2802,2808,2951,2954,2960,3050,3053,3059,3119],{"type":39,"tag":40,"props":41,"children":43},"element","h2",{"id":42},"overview",[44],{"type":45,"value":46},"text","Overview",{"type":39,"tag":48,"props":49,"children":50},"p",{},[51,53,59,61,66,68,75],{"type":45,"value":52},"A Studio flow is a state machine Twilio executes in response to an inbound call,\nmessage, conversation, or REST API request. You define it as a JSON document of\n",{"type":39,"tag":54,"props":55,"children":56},"strong",{},[57],{"type":45,"value":58},"states",{"type":45,"value":60}," (widgets) connected by ",{"type":39,"tag":54,"props":62,"children":63},{},[64],{"type":45,"value":65},"transitions",{"type":45,"value":67},". Twilio runs the flow starting\nat ",{"type":39,"tag":69,"props":70,"children":72},"code",{"className":71},[],[73],{"type":45,"value":74},"initial_state",{"type":45,"value":76}," (the Trigger), following each widget's transition events.",{"type":39,"tag":78,"props":79,"children":83},"pre",{"className":80,"code":82,"language":45},[81],"language-text","Inbound call \u002F message \u002F API request\n        │\n        ▼\n   Trigger ──incomingCall──▶ Gather ──keypress──▶ Split ──match──▶ Connect Call\n                                                      └─noMatch──▶ Say \"goodbye\"\n",[84],{"type":39,"tag":69,"props":85,"children":87},{"__ignoreMap":86},"",[88],{"type":45,"value":82},{"type":39,"tag":48,"props":90,"children":91},{},[92],{"type":45,"value":93},"You can build flows in the Console's drag-and-drop canvas, or author the\ndefinition JSON and create\u002Fupdate flows through the REST API when you want to\ngenerate or modify them programmatically. Each save creates a new revision, and\na flow has a single published revision live at a time (see the draft\u002Fpublished\nlifecycle below).",{"type":39,"tag":48,"props":95,"children":96},{},[97,99,104,106,112,114,120,122,128,130,141],{"type":45,"value":98},"Widget properties and transitions reference runtime data with ",{"type":39,"tag":54,"props":100,"children":101},{},[102],{"type":45,"value":103},"Liquid",{"type":45,"value":105},"\ntemplating — e.g. ",{"type":39,"tag":69,"props":107,"children":109},{"className":108},[],[110],{"type":45,"value":111},"{{trigger.message.Body}}",{"type":45,"value":113},", ",{"type":39,"tag":69,"props":115,"children":117},{"className":116},[],[118],{"type":45,"value":119},"{{flow.variables.count}}",{"type":45,"value":121},",\n",{"type":39,"tag":69,"props":123,"children":125},{"className":124},[],[126],{"type":45,"value":127},"{{widgets.gather_menu.Digits}}",{"type":45,"value":129},". The full widget catalog (every type, its\nproperties, events, and the output values it exposes downstream) lives in\n",{"type":39,"tag":131,"props":132,"children":134},"a",{"href":133},".\u002Freferences\u002Fwidgets.md",[135],{"type":39,"tag":69,"props":136,"children":138},{"className":137},[],[139],{"type":45,"value":140},"references\u002Fwidgets.md",{"type":45,"value":142},". Consult it whenever you wire\none widget's result into a later one.",{"type":39,"tag":144,"props":145,"children":146},"blockquote",{},[147],{"type":39,"tag":48,"props":148,"children":149},{},[150,155,157,163],{"type":39,"tag":54,"props":151,"children":152},{},[153],{"type":45,"value":154},"Inbound flow content is untrusted.",{"type":45,"value":156}," A caller's speech, an SMS body, or REST\nparameters are external input. If you pass them to a Run Function, an LLM, or\nan HTTP Request, treat them as untrusted — never concatenate them into a system\nprompt or a command. See ",{"type":39,"tag":69,"props":158,"children":160},{"className":159},[],[161],{"type":45,"value":162},"twilio-webhook-architecture",{"type":45,"value":164},".",{"type":39,"tag":166,"props":167,"children":168},"hr",{},[],{"type":39,"tag":40,"props":170,"children":172},{"id":171},"when-to-use-studio-vs-code",[173],{"type":45,"value":174},"When to use Studio vs. code",{"type":39,"tag":176,"props":177,"children":178},"table",{},[179,198],{"type":39,"tag":180,"props":181,"children":182},"thead",{},[183],{"type":39,"tag":184,"props":185,"children":186},"tr",{},[187,193],{"type":39,"tag":188,"props":189,"children":190},"th",{},[191],{"type":45,"value":192},"Use Studio when",{"type":39,"tag":188,"props":194,"children":195},{},[196],{"type":45,"value":197},"Use TwiML\u002Fcode when",{"type":39,"tag":199,"props":200,"children":201},"tbody",{},[202,216,229,242],{"type":39,"tag":184,"props":203,"children":204},{},[205,211],{"type":39,"tag":206,"props":207,"children":208},"td",{},[209],{"type":45,"value":210},"The logic is a routable flowchart (menus, branches, queues)",{"type":39,"tag":206,"props":212,"children":213},{},[214],{"type":45,"value":215},"Logic needs loops, complex state, or heavy computation",{"type":39,"tag":184,"props":217,"children":218},{},[219,224],{"type":39,"tag":206,"props":220,"children":221},{},[222],{"type":45,"value":223},"Non-engineers will edit the flow in Console",{"type":39,"tag":206,"props":225,"children":226},{},[227],{"type":45,"value":228},"The behavior lives entirely in your codebase",{"type":39,"tag":184,"props":230,"children":231},{},[232,237],{"type":39,"tag":206,"props":233,"children":234},{},[235],{"type":45,"value":236},"You want built-in retry\u002Ftranscription\u002Fqueueing widgets",{"type":39,"tag":206,"props":238,"children":239},{},[240],{"type":45,"value":241},"You need millisecond control over the TwiML response",{"type":39,"tag":184,"props":243,"children":244},{},[245,250],{"type":39,"tag":206,"props":246,"children":247},{},[248],{"type":45,"value":249},"Orchestrating across SMS + voice + Flex in one place",{"type":39,"tag":206,"props":251,"children":252},{},[253],{"type":45,"value":254},"A single webhook returns one TwiML document",{"type":39,"tag":48,"props":256,"children":257},{},[258,260,265,267,273,279,281,287],{"type":45,"value":259},"Studio has ",{"type":39,"tag":54,"props":261,"children":262},{},[263],{"type":45,"value":264},"no native loop construct",{"type":45,"value":266}," — repetition is built by transitioning\nback to an earlier widget (see the counter-loop pattern below) or the ",{"type":39,"tag":69,"props":268,"children":270},{"className":269},[],[271],{"type":45,"value":272},"say-play",{"type":39,"tag":69,"props":274,"children":276},{"className":275},[],[277],{"type":45,"value":278},"loop",{"type":45,"value":280}," property. Heavy iteration is a signal to drop into a Run Function or\ncustom TwiML instead. For pure TwiML call logic, see ",{"type":39,"tag":69,"props":282,"children":284},{"className":283},[],[285],{"type":45,"value":286},"twilio-voice-twiml",{"type":45,"value":164},{"type":39,"tag":166,"props":289,"children":290},{},[],{"type":39,"tag":40,"props":292,"children":294},{"id":293},"prerequisites",[295],{"type":45,"value":296},"Prerequisites",{"type":39,"tag":298,"props":299,"children":300},"ul",{},[301,314,341],{"type":39,"tag":302,"props":303,"children":304},"li",{},[305,307,313],{"type":45,"value":306},"Twilio account with a voice- and\u002For messaging-capable number\n— New to Twilio? See ",{"type":39,"tag":69,"props":308,"children":310},{"className":309},[],[311],{"type":45,"value":312},"twilio-account-setup",{"type":45,"value":164},{"type":39,"tag":302,"props":315,"children":316},{},[317,319,325,326,332,334,340],{"type":45,"value":318},"Credentials in environment variables (never hardcode):\n",{"type":39,"tag":69,"props":320,"children":322},{"className":321},[],[323],{"type":45,"value":324},"TWILIO_ACCOUNT_SID",{"type":45,"value":113},{"type":39,"tag":69,"props":327,"children":329},{"className":328},[],[330],{"type":45,"value":331},"TWILIO_AUTH_TOKEN",{"type":45,"value":333},". For production, use API Keys —\nsee ",{"type":39,"tag":69,"props":335,"children":337},{"className":336},[],[338],{"type":45,"value":339},"twilio-iam-auth-setup",{"type":45,"value":164},{"type":39,"tag":302,"props":342,"children":343},{},[344,346,352,354,360],{"type":45,"value":345},"SDK: ",{"type":39,"tag":69,"props":347,"children":349},{"className":348},[],[350],{"type":45,"value":351},"pip install twilio",{"type":45,"value":353}," \u002F ",{"type":39,"tag":69,"props":355,"children":357},{"className":356},[],[358],{"type":45,"value":359},"npm install twilio",{"type":45,"value":164},{"type":39,"tag":166,"props":362,"children":363},{},[],{"type":39,"tag":40,"props":365,"children":367},{"id":366},"before-you-author-clarify-the-design",[368],{"type":45,"value":369},"Before you author: clarify the design",{"type":39,"tag":48,"props":371,"children":372},{},[373],{"type":45,"value":374},"A one-line request (\"build an appointment reminder\") rarely pins down a real\nflow, and guessing produces the wrong state machine. Before writing any JSON,\nfind the gaps and resolve them with the requester — ask about the unknowns that\nwould actually change the flow, hardest\u002Fmost-consequential one first (the answer\nto one often reshapes the next), and prefer concrete options over open questions.\nDon't invent behavior for anything underspecified; surface it. Then restate the\ndesign in prose and confirm it before you author.",{"type":39,"tag":48,"props":376,"children":377},{},[378],{"type":45,"value":379},"The gaps that most often change a Studio flow:",{"type":39,"tag":298,"props":381,"children":382},{},[383,400,410,420,430,440,458,468],{"type":39,"tag":302,"props":384,"children":385},{},[386,391,393,399],{"type":39,"tag":54,"props":387,"children":388},{},[389],{"type":45,"value":390},"Trigger & entry point",{"type":45,"value":392}," — inbound call, message, or conversation, vs. a REST\nAPI execution, vs. a subflow. Outbound (reminders, notifications) is typically\na REST API execution whose caller POSTs data the flow reads as ",{"type":39,"tag":69,"props":394,"children":396},{"className":395},[],[397],{"type":45,"value":398},"{{flow.data.*}}",{"type":45,"value":164},{"type":39,"tag":302,"props":401,"children":402},{},[403,408],{"type":39,"tag":54,"props":404,"children":405},{},[406],{"type":45,"value":407},"Inbound data",{"type":45,"value":409}," — what the flow receives and how: execution parameters,\ngathered DTMF\u002Fspeech, or an HTTP lookup.",{"type":39,"tag":302,"props":411,"children":412},{},[413,418],{"type":39,"tag":54,"props":414,"children":415},{},[416],{"type":45,"value":417},"Core interaction",{"type":45,"value":419}," — keypad DTMF vs. speech vs. keyword reply; the exact\ndigits\u002Fkeywords and what each one does.",{"type":39,"tag":302,"props":421,"children":422},{},[423,428],{"type":39,"tag":54,"props":424,"children":425},{},[426],{"type":45,"value":427},"Decision callbacks",{"type":45,"value":429}," — when the customer decides something, does an external\nsystem need to be told (an HTTP Request \u002F Run Function), and what are its\nrequest shape, auth, and failure behavior?",{"type":39,"tag":302,"props":431,"children":432},{},[433,438],{"type":39,"tag":54,"props":434,"children":435},{},[436],{"type":45,"value":437},"Unhappy paths",{"type":45,"value":439}," — no input, invalid input, no match, timeouts, and\nmax-retry exhaustion. Re-prompt how many times, then what?",{"type":39,"tag":302,"props":441,"children":442},{},[443,448,450,456],{"type":39,"tag":54,"props":444,"children":445},{},[446],{"type":45,"value":447},"Branching completeness",{"type":45,"value":449}," — every menu option and Split branch accounted for,\nincluding the default \u002F ",{"type":39,"tag":69,"props":451,"children":453},{"className":452},[],[454],{"type":45,"value":455},"noMatch",{"type":45,"value":457}," fallback.",{"type":39,"tag":302,"props":459,"children":460},{},[461,466],{"type":39,"tag":54,"props":462,"children":463},{},[464],{"type":45,"value":465},"Terminal states",{"type":45,"value":467}," — how each branch ends: hang up, final message, or hand\noff to an agent\u002Fqueue.",{"type":39,"tag":302,"props":469,"children":470},{},[471,476,478,484,485,491],{"type":39,"tag":54,"props":472,"children":473},{},[474],{"type":45,"value":475},"Dynamic values",{"type":45,"value":477}," — greetings, numbers, URLs, and copy that should come from\n",{"type":39,"tag":69,"props":479,"children":481},{"className":480},[],[482],{"type":45,"value":483},"flow.*",{"type":45,"value":353},{"type":39,"tag":69,"props":486,"children":488},{"className":487},[],[489],{"type":45,"value":490},"trigger.*",{"type":45,"value":492}," rather than being hard-coded.",{"type":39,"tag":48,"props":494,"children":495},{},[496],{"type":45,"value":497},"Ask only what matters for the flow at hand — a trivial auto-responder may need\nnone; a reminder, IVR, or booking flow usually needs several.",{"type":39,"tag":40,"props":499,"children":501},{"id":500},"quickstart",[502],{"type":45,"value":503},"Quickstart",{"type":39,"tag":48,"props":505,"children":506},{},[507],{"type":45,"value":508},"Build a minimal SMS auto-responder flow, validate it, and create it as a draft.",{"type":39,"tag":48,"props":510,"children":511},{},[512,517],{"type":39,"tag":54,"props":513,"children":514},{},[515],{"type":45,"value":516},"1. Author the flow definition.",{"type":45,"value":518}," Build the JSON as a native object and\nserialize it — never string-concatenate JSON.",{"type":39,"tag":48,"props":520,"children":521},{},[522],{"type":39,"tag":54,"props":523,"children":524},{},[525],{"type":45,"value":526},"Python",{"type":39,"tag":78,"props":528,"children":532},{"className":529,"code":530,"language":531,"meta":86,"style":86},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","flow_definition = {\n    \"description\": \"SMS auto-responder\",\n    \"states\": [\n        {\n            \"name\": \"Trigger\",\n            \"type\": \"trigger\",\n            \"transitions\": [{\"event\": \"incomingMessage\", \"next\": \"reply\"}],\n            \"properties\": {},\n        },\n        {\n            \"name\": \"reply\",\n            \"type\": \"send-message\",\n            \"transitions\": [{\"event\": \"sent\"}, {\"event\": \"failed\"}],\n            \"properties\": {\n                \"from\": \"{{flow.channel.address}}\",\n                \"to\": \"{{contact.channel.address}}\",\n                \"body\": \"Thanks for your message! We'll be in touch shortly.\",\n            },\n        },\n    ],\n    \"initial_state\": \"Trigger\",\n    \"flags\": {\"allow_concurrent_calls\": True},\n}\n","python",[533],{"type":39,"tag":69,"props":534,"children":535},{"__ignoreMap":86},[536,547,556,565,574,583,592,600,609,618,626,635,644,653,662,671,680,689,698,706,715,724,733],{"type":39,"tag":537,"props":538,"children":541},"span",{"class":539,"line":540},"line",1,[542],{"type":39,"tag":537,"props":543,"children":544},{},[545],{"type":45,"value":546},"flow_definition = {\n",{"type":39,"tag":537,"props":548,"children":550},{"class":539,"line":549},2,[551],{"type":39,"tag":537,"props":552,"children":553},{},[554],{"type":45,"value":555},"    \"description\": \"SMS auto-responder\",\n",{"type":39,"tag":537,"props":557,"children":559},{"class":539,"line":558},3,[560],{"type":39,"tag":537,"props":561,"children":562},{},[563],{"type":45,"value":564},"    \"states\": [\n",{"type":39,"tag":537,"props":566,"children":568},{"class":539,"line":567},4,[569],{"type":39,"tag":537,"props":570,"children":571},{},[572],{"type":45,"value":573},"        {\n",{"type":39,"tag":537,"props":575,"children":577},{"class":539,"line":576},5,[578],{"type":39,"tag":537,"props":579,"children":580},{},[581],{"type":45,"value":582},"            \"name\": \"Trigger\",\n",{"type":39,"tag":537,"props":584,"children":586},{"class":539,"line":585},6,[587],{"type":39,"tag":537,"props":588,"children":589},{},[590],{"type":45,"value":591},"            \"type\": \"trigger\",\n",{"type":39,"tag":537,"props":593,"children":594},{"class":539,"line":27},[595],{"type":39,"tag":537,"props":596,"children":597},{},[598],{"type":45,"value":599},"            \"transitions\": [{\"event\": \"incomingMessage\", \"next\": \"reply\"}],\n",{"type":39,"tag":537,"props":601,"children":603},{"class":539,"line":602},8,[604],{"type":39,"tag":537,"props":605,"children":606},{},[607],{"type":45,"value":608},"            \"properties\": {},\n",{"type":39,"tag":537,"props":610,"children":612},{"class":539,"line":611},9,[613],{"type":39,"tag":537,"props":614,"children":615},{},[616],{"type":45,"value":617},"        },\n",{"type":39,"tag":537,"props":619,"children":621},{"class":539,"line":620},10,[622],{"type":39,"tag":537,"props":623,"children":624},{},[625],{"type":45,"value":573},{"type":39,"tag":537,"props":627,"children":629},{"class":539,"line":628},11,[630],{"type":39,"tag":537,"props":631,"children":632},{},[633],{"type":45,"value":634},"            \"name\": \"reply\",\n",{"type":39,"tag":537,"props":636,"children":638},{"class":539,"line":637},12,[639],{"type":39,"tag":537,"props":640,"children":641},{},[642],{"type":45,"value":643},"            \"type\": \"send-message\",\n",{"type":39,"tag":537,"props":645,"children":647},{"class":539,"line":646},13,[648],{"type":39,"tag":537,"props":649,"children":650},{},[651],{"type":45,"value":652},"            \"transitions\": [{\"event\": \"sent\"}, {\"event\": \"failed\"}],\n",{"type":39,"tag":537,"props":654,"children":656},{"class":539,"line":655},14,[657],{"type":39,"tag":537,"props":658,"children":659},{},[660],{"type":45,"value":661},"            \"properties\": {\n",{"type":39,"tag":537,"props":663,"children":665},{"class":539,"line":664},15,[666],{"type":39,"tag":537,"props":667,"children":668},{},[669],{"type":45,"value":670},"                \"from\": \"{{flow.channel.address}}\",\n",{"type":39,"tag":537,"props":672,"children":674},{"class":539,"line":673},16,[675],{"type":39,"tag":537,"props":676,"children":677},{},[678],{"type":45,"value":679},"                \"to\": \"{{contact.channel.address}}\",\n",{"type":39,"tag":537,"props":681,"children":683},{"class":539,"line":682},17,[684],{"type":39,"tag":537,"props":685,"children":686},{},[687],{"type":45,"value":688},"                \"body\": \"Thanks for your message! We'll be in touch shortly.\",\n",{"type":39,"tag":537,"props":690,"children":692},{"class":539,"line":691},18,[693],{"type":39,"tag":537,"props":694,"children":695},{},[696],{"type":45,"value":697},"            },\n",{"type":39,"tag":537,"props":699,"children":701},{"class":539,"line":700},19,[702],{"type":39,"tag":537,"props":703,"children":704},{},[705],{"type":45,"value":617},{"type":39,"tag":537,"props":707,"children":709},{"class":539,"line":708},20,[710],{"type":39,"tag":537,"props":711,"children":712},{},[713],{"type":45,"value":714},"    ],\n",{"type":39,"tag":537,"props":716,"children":718},{"class":539,"line":717},21,[719],{"type":39,"tag":537,"props":720,"children":721},{},[722],{"type":45,"value":723},"    \"initial_state\": \"Trigger\",\n",{"type":39,"tag":537,"props":725,"children":727},{"class":539,"line":726},22,[728],{"type":39,"tag":537,"props":729,"children":730},{},[731],{"type":45,"value":732},"    \"flags\": {\"allow_concurrent_calls\": True},\n",{"type":39,"tag":537,"props":734,"children":736},{"class":539,"line":735},23,[737],{"type":39,"tag":537,"props":738,"children":739},{},[740],{"type":45,"value":741},"}\n",{"type":39,"tag":48,"props":743,"children":744},{},[745],{"type":39,"tag":54,"props":746,"children":747},{},[748],{"type":45,"value":749},"Node.js",{"type":39,"tag":78,"props":751,"children":755},{"className":752,"code":753,"language":754,"meta":86,"style":86},"language-node shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","const flowDefinition = {\n  description: \"SMS auto-responder\",\n  states: [\n    {\n      name: \"Trigger\",\n      type: \"trigger\",\n      transitions: [{ event: \"incomingMessage\", next: \"reply\" }],\n      properties: {},\n    },\n    {\n      name: \"reply\",\n      type: \"send-message\",\n      transitions: [{ event: \"sent\" }, { event: \"failed\" }],\n      properties: {\n        from: \"{{flow.channel.address}}\",\n        to: \"{{contact.channel.address}}\",\n        body: \"Thanks for your message! We'll be in touch shortly.\",\n      },\n    },\n  ],\n  initial_state: \"Trigger\",\n  flags: { allow_concurrent_calls: true },\n};\n","node",[756],{"type":39,"tag":69,"props":757,"children":758},{"__ignoreMap":86},[759,767,775,783,791,799,807,815,823,831,838,846,854,862,870,878,886,894,902,909,917,925,933],{"type":39,"tag":537,"props":760,"children":761},{"class":539,"line":540},[762],{"type":39,"tag":537,"props":763,"children":764},{},[765],{"type":45,"value":766},"const flowDefinition = {\n",{"type":39,"tag":537,"props":768,"children":769},{"class":539,"line":549},[770],{"type":39,"tag":537,"props":771,"children":772},{},[773],{"type":45,"value":774},"  description: \"SMS auto-responder\",\n",{"type":39,"tag":537,"props":776,"children":777},{"class":539,"line":558},[778],{"type":39,"tag":537,"props":779,"children":780},{},[781],{"type":45,"value":782},"  states: [\n",{"type":39,"tag":537,"props":784,"children":785},{"class":539,"line":567},[786],{"type":39,"tag":537,"props":787,"children":788},{},[789],{"type":45,"value":790},"    {\n",{"type":39,"tag":537,"props":792,"children":793},{"class":539,"line":576},[794],{"type":39,"tag":537,"props":795,"children":796},{},[797],{"type":45,"value":798},"      name: \"Trigger\",\n",{"type":39,"tag":537,"props":800,"children":801},{"class":539,"line":585},[802],{"type":39,"tag":537,"props":803,"children":804},{},[805],{"type":45,"value":806},"      type: \"trigger\",\n",{"type":39,"tag":537,"props":808,"children":809},{"class":539,"line":27},[810],{"type":39,"tag":537,"props":811,"children":812},{},[813],{"type":45,"value":814},"      transitions: [{ event: \"incomingMessage\", next: \"reply\" }],\n",{"type":39,"tag":537,"props":816,"children":817},{"class":539,"line":602},[818],{"type":39,"tag":537,"props":819,"children":820},{},[821],{"type":45,"value":822},"      properties: {},\n",{"type":39,"tag":537,"props":824,"children":825},{"class":539,"line":611},[826],{"type":39,"tag":537,"props":827,"children":828},{},[829],{"type":45,"value":830},"    },\n",{"type":39,"tag":537,"props":832,"children":833},{"class":539,"line":620},[834],{"type":39,"tag":537,"props":835,"children":836},{},[837],{"type":45,"value":790},{"type":39,"tag":537,"props":839,"children":840},{"class":539,"line":628},[841],{"type":39,"tag":537,"props":842,"children":843},{},[844],{"type":45,"value":845},"      name: \"reply\",\n",{"type":39,"tag":537,"props":847,"children":848},{"class":539,"line":637},[849],{"type":39,"tag":537,"props":850,"children":851},{},[852],{"type":45,"value":853},"      type: \"send-message\",\n",{"type":39,"tag":537,"props":855,"children":856},{"class":539,"line":646},[857],{"type":39,"tag":537,"props":858,"children":859},{},[860],{"type":45,"value":861},"      transitions: [{ event: \"sent\" }, { event: \"failed\" }],\n",{"type":39,"tag":537,"props":863,"children":864},{"class":539,"line":655},[865],{"type":39,"tag":537,"props":866,"children":867},{},[868],{"type":45,"value":869},"      properties: {\n",{"type":39,"tag":537,"props":871,"children":872},{"class":539,"line":664},[873],{"type":39,"tag":537,"props":874,"children":875},{},[876],{"type":45,"value":877},"        from: \"{{flow.channel.address}}\",\n",{"type":39,"tag":537,"props":879,"children":880},{"class":539,"line":673},[881],{"type":39,"tag":537,"props":882,"children":883},{},[884],{"type":45,"value":885},"        to: \"{{contact.channel.address}}\",\n",{"type":39,"tag":537,"props":887,"children":888},{"class":539,"line":682},[889],{"type":39,"tag":537,"props":890,"children":891},{},[892],{"type":45,"value":893},"        body: \"Thanks for your message! We'll be in touch shortly.\",\n",{"type":39,"tag":537,"props":895,"children":896},{"class":539,"line":691},[897],{"type":39,"tag":537,"props":898,"children":899},{},[900],{"type":45,"value":901},"      },\n",{"type":39,"tag":537,"props":903,"children":904},{"class":539,"line":700},[905],{"type":39,"tag":537,"props":906,"children":907},{},[908],{"type":45,"value":830},{"type":39,"tag":537,"props":910,"children":911},{"class":539,"line":708},[912],{"type":39,"tag":537,"props":913,"children":914},{},[915],{"type":45,"value":916},"  ],\n",{"type":39,"tag":537,"props":918,"children":919},{"class":539,"line":717},[920],{"type":39,"tag":537,"props":921,"children":922},{},[923],{"type":45,"value":924},"  initial_state: \"Trigger\",\n",{"type":39,"tag":537,"props":926,"children":927},{"class":539,"line":726},[928],{"type":39,"tag":537,"props":929,"children":930},{},[931],{"type":45,"value":932},"  flags: { allow_concurrent_calls: true },\n",{"type":39,"tag":537,"props":934,"children":935},{"class":539,"line":735},[936],{"type":39,"tag":537,"props":937,"children":938},{},[939],{"type":45,"value":940},"};\n",{"type":39,"tag":48,"props":942,"children":943},{},[944,949,951,957],{"type":39,"tag":54,"props":945,"children":946},{},[947],{"type":45,"value":948},"2. Create the flow as a draft.",{"type":45,"value":950}," Pass the definition, a friendly name, and a\ncommit message. ",{"type":39,"tag":69,"props":952,"children":954},{"className":953},[],[955],{"type":45,"value":956},"status=\"draft\"",{"type":45,"value":958}," keeps it off live traffic.",{"type":39,"tag":48,"props":960,"children":961},{},[962],{"type":39,"tag":54,"props":963,"children":964},{},[965],{"type":45,"value":526},{"type":39,"tag":78,"props":967,"children":969},{"className":529,"code":968,"language":531,"meta":86,"style":86},"import os\nfrom twilio.rest import Client\n\nclient = Client(os.environ[\"TWILIO_ACCOUNT_SID\"], os.environ[\"TWILIO_AUTH_TOKEN\"])\n\nflow = client.studio.v2.flows.create(\n    friendly_name=\"SMS Auto-Responder\",\n    status=\"draft\",\n    definition=flow_definition,          # SDK serializes the dict\n    commit_message=\"Initial draft\",\n)\nprint(f\"Created flow {flow.sid} (status={flow.status})\")\n",[970],{"type":39,"tag":69,"props":971,"children":972},{"__ignoreMap":86},[973,981,989,998,1006,1013,1021,1029,1037,1045,1053,1061],{"type":39,"tag":537,"props":974,"children":975},{"class":539,"line":540},[976],{"type":39,"tag":537,"props":977,"children":978},{},[979],{"type":45,"value":980},"import os\n",{"type":39,"tag":537,"props":982,"children":983},{"class":539,"line":549},[984],{"type":39,"tag":537,"props":985,"children":986},{},[987],{"type":45,"value":988},"from twilio.rest import Client\n",{"type":39,"tag":537,"props":990,"children":991},{"class":539,"line":558},[992],{"type":39,"tag":537,"props":993,"children":995},{"emptyLinePlaceholder":994},true,[996],{"type":45,"value":997},"\n",{"type":39,"tag":537,"props":999,"children":1000},{"class":539,"line":567},[1001],{"type":39,"tag":537,"props":1002,"children":1003},{},[1004],{"type":45,"value":1005},"client = Client(os.environ[\"TWILIO_ACCOUNT_SID\"], os.environ[\"TWILIO_AUTH_TOKEN\"])\n",{"type":39,"tag":537,"props":1007,"children":1008},{"class":539,"line":576},[1009],{"type":39,"tag":537,"props":1010,"children":1011},{"emptyLinePlaceholder":994},[1012],{"type":45,"value":997},{"type":39,"tag":537,"props":1014,"children":1015},{"class":539,"line":585},[1016],{"type":39,"tag":537,"props":1017,"children":1018},{},[1019],{"type":45,"value":1020},"flow = client.studio.v2.flows.create(\n",{"type":39,"tag":537,"props":1022,"children":1023},{"class":539,"line":27},[1024],{"type":39,"tag":537,"props":1025,"children":1026},{},[1027],{"type":45,"value":1028},"    friendly_name=\"SMS Auto-Responder\",\n",{"type":39,"tag":537,"props":1030,"children":1031},{"class":539,"line":602},[1032],{"type":39,"tag":537,"props":1033,"children":1034},{},[1035],{"type":45,"value":1036},"    status=\"draft\",\n",{"type":39,"tag":537,"props":1038,"children":1039},{"class":539,"line":611},[1040],{"type":39,"tag":537,"props":1041,"children":1042},{},[1043],{"type":45,"value":1044},"    definition=flow_definition,          # SDK serializes the dict\n",{"type":39,"tag":537,"props":1046,"children":1047},{"class":539,"line":620},[1048],{"type":39,"tag":537,"props":1049,"children":1050},{},[1051],{"type":45,"value":1052},"    commit_message=\"Initial draft\",\n",{"type":39,"tag":537,"props":1054,"children":1055},{"class":539,"line":628},[1056],{"type":39,"tag":537,"props":1057,"children":1058},{},[1059],{"type":45,"value":1060},")\n",{"type":39,"tag":537,"props":1062,"children":1063},{"class":539,"line":637},[1064],{"type":39,"tag":537,"props":1065,"children":1066},{},[1067],{"type":45,"value":1068},"print(f\"Created flow {flow.sid} (status={flow.status})\")\n",{"type":39,"tag":48,"props":1070,"children":1071},{},[1072],{"type":39,"tag":54,"props":1073,"children":1074},{},[1075],{"type":45,"value":749},{"type":39,"tag":78,"props":1077,"children":1079},{"className":752,"code":1078,"language":754,"meta":86,"style":86},"const client = require(\"twilio\")(\n  process.env.TWILIO_ACCOUNT_SID,\n  process.env.TWILIO_AUTH_TOKEN\n);\n\nconst flow = await client.studio.v2.flows.create({\n  friendlyName: \"SMS Auto-Responder\",\n  status: \"draft\",\n  definition: flowDefinition,\n  commitMessage: \"Initial draft\",\n});\nconsole.log(`Created flow ${flow.sid} (status=${flow.status})`);\n",[1080],{"type":39,"tag":69,"props":1081,"children":1082},{"__ignoreMap":86},[1083,1091,1099,1107,1115,1122,1130,1138,1146,1154,1162,1170],{"type":39,"tag":537,"props":1084,"children":1085},{"class":539,"line":540},[1086],{"type":39,"tag":537,"props":1087,"children":1088},{},[1089],{"type":45,"value":1090},"const client = require(\"twilio\")(\n",{"type":39,"tag":537,"props":1092,"children":1093},{"class":539,"line":549},[1094],{"type":39,"tag":537,"props":1095,"children":1096},{},[1097],{"type":45,"value":1098},"  process.env.TWILIO_ACCOUNT_SID,\n",{"type":39,"tag":537,"props":1100,"children":1101},{"class":539,"line":558},[1102],{"type":39,"tag":537,"props":1103,"children":1104},{},[1105],{"type":45,"value":1106},"  process.env.TWILIO_AUTH_TOKEN\n",{"type":39,"tag":537,"props":1108,"children":1109},{"class":539,"line":567},[1110],{"type":39,"tag":537,"props":1111,"children":1112},{},[1113],{"type":45,"value":1114},");\n",{"type":39,"tag":537,"props":1116,"children":1117},{"class":539,"line":576},[1118],{"type":39,"tag":537,"props":1119,"children":1120},{"emptyLinePlaceholder":994},[1121],{"type":45,"value":997},{"type":39,"tag":537,"props":1123,"children":1124},{"class":539,"line":585},[1125],{"type":39,"tag":537,"props":1126,"children":1127},{},[1128],{"type":45,"value":1129},"const flow = await client.studio.v2.flows.create({\n",{"type":39,"tag":537,"props":1131,"children":1132},{"class":539,"line":27},[1133],{"type":39,"tag":537,"props":1134,"children":1135},{},[1136],{"type":45,"value":1137},"  friendlyName: \"SMS Auto-Responder\",\n",{"type":39,"tag":537,"props":1139,"children":1140},{"class":539,"line":602},[1141],{"type":39,"tag":537,"props":1142,"children":1143},{},[1144],{"type":45,"value":1145},"  status: \"draft\",\n",{"type":39,"tag":537,"props":1147,"children":1148},{"class":539,"line":611},[1149],{"type":39,"tag":537,"props":1150,"children":1151},{},[1152],{"type":45,"value":1153},"  definition: flowDefinition,\n",{"type":39,"tag":537,"props":1155,"children":1156},{"class":539,"line":620},[1157],{"type":39,"tag":537,"props":1158,"children":1159},{},[1160],{"type":45,"value":1161},"  commitMessage: \"Initial draft\",\n",{"type":39,"tag":537,"props":1163,"children":1164},{"class":539,"line":628},[1165],{"type":39,"tag":537,"props":1166,"children":1167},{},[1168],{"type":45,"value":1169},"});\n",{"type":39,"tag":537,"props":1171,"children":1172},{"class":539,"line":637},[1173],{"type":39,"tag":537,"props":1174,"children":1175},{},[1176],{"type":45,"value":1177},"console.log(`Created flow ${flow.sid} (status=${flow.status})`);\n",{"type":39,"tag":48,"props":1179,"children":1180},{},[1181],{"type":45,"value":1182},"Test the draft in the Console (Studio > your flow > Test), then publish it\n(next section). Wire the flow to a number or Messaging Service to take live\ntraffic.",{"type":39,"tag":40,"props":1184,"children":1186},{"id":1185},"key-patterns",[1187],{"type":45,"value":1188},"Key Patterns",{"type":39,"tag":1190,"props":1191,"children":1193},"h3",{"id":1192},"validate-before-deploy",[1194],{"type":45,"value":1195},"Validate before deploy",{"type":39,"tag":48,"props":1197,"children":1198},{},[1199,1201,1207,1209,1215],{"type":45,"value":1200},"Twilio's ",{"type":39,"tag":69,"props":1202,"children":1204},{"className":1203},[],[1205],{"type":45,"value":1206},"FlowValidate",{"type":45,"value":1208}," endpoint checks a definition without saving it. The SDK\nexposes it via the ",{"type":39,"tag":69,"props":1210,"children":1212},{"className":1211},[],[1213],{"type":45,"value":1214},"studio.v2.flowValidate",{"type":45,"value":1216}," resource. Validate after every edit;\nfix each reported error before deploying.",{"type":39,"tag":48,"props":1218,"children":1219},{},[1220,1222,1227,1229,1235,1237,1243,1245,1251,1253,1259,1261,1266],{"type":45,"value":1221},"When a definition is invalid the call ",{"type":39,"tag":54,"props":1223,"children":1224},{},[1225],{"type":45,"value":1226},"raises",{"type":45,"value":1228}," (it does not return\n",{"type":39,"tag":69,"props":1230,"children":1232},{"className":1231},[],[1233],{"type":45,"value":1234},"valid=False",{"type":45,"value":1236},"). The exception's ",{"type":39,"tag":69,"props":1238,"children":1240},{"className":1239},[],[1241],{"type":45,"value":1242},"details",{"type":45,"value":1244}," carries the specific per-state errors —\na ",{"type":39,"tag":69,"props":1246,"children":1248},{"className":1247},[],[1249],{"type":45,"value":1250},"property_path",{"type":45,"value":1252}," like ",{"type":39,"tag":69,"props":1254,"children":1256},{"className":1255},[],[1257],{"type":45,"value":1258},"#\u002Fstates\u002F3\u002Fproperties\u002Fpayment_method",{"type":45,"value":1260}," and a message.\nAlways read ",{"type":39,"tag":69,"props":1262,"children":1264},{"className":1263},[],[1265],{"type":45,"value":1242},{"type":45,"value":1267},"; the top-level message only says validation failed.",{"type":39,"tag":48,"props":1269,"children":1270},{},[1271],{"type":39,"tag":54,"props":1272,"children":1273},{},[1274],{"type":45,"value":526},{"type":39,"tag":78,"props":1276,"children":1278},{"className":529,"code":1277,"language":531,"meta":86,"style":86},"from twilio.base.exceptions import TwilioRestException\n\ntry:\n    result = client.studio.v2.flow_validate.update(\n        friendly_name=\"SMS Auto-Responder\",\n        status=\"draft\",\n        definition=flow_definition,\n    )\n    print(\"valid\" if result.valid else \"invalid\")\nexcept TwilioRestException as e:\n    for err in (e.details or {}).get(\"errors\", []):\n        print(f\"{err['property_path']}: {err['message']}\")\n    raise\n",[1279],{"type":39,"tag":69,"props":1280,"children":1281},{"__ignoreMap":86},[1282,1290,1297,1305,1313,1321,1329,1337,1345,1353,1361,1369,1377],{"type":39,"tag":537,"props":1283,"children":1284},{"class":539,"line":540},[1285],{"type":39,"tag":537,"props":1286,"children":1287},{},[1288],{"type":45,"value":1289},"from twilio.base.exceptions import TwilioRestException\n",{"type":39,"tag":537,"props":1291,"children":1292},{"class":539,"line":549},[1293],{"type":39,"tag":537,"props":1294,"children":1295},{"emptyLinePlaceholder":994},[1296],{"type":45,"value":997},{"type":39,"tag":537,"props":1298,"children":1299},{"class":539,"line":558},[1300],{"type":39,"tag":537,"props":1301,"children":1302},{},[1303],{"type":45,"value":1304},"try:\n",{"type":39,"tag":537,"props":1306,"children":1307},{"class":539,"line":567},[1308],{"type":39,"tag":537,"props":1309,"children":1310},{},[1311],{"type":45,"value":1312},"    result = client.studio.v2.flow_validate.update(\n",{"type":39,"tag":537,"props":1314,"children":1315},{"class":539,"line":576},[1316],{"type":39,"tag":537,"props":1317,"children":1318},{},[1319],{"type":45,"value":1320},"        friendly_name=\"SMS Auto-Responder\",\n",{"type":39,"tag":537,"props":1322,"children":1323},{"class":539,"line":585},[1324],{"type":39,"tag":537,"props":1325,"children":1326},{},[1327],{"type":45,"value":1328},"        status=\"draft\",\n",{"type":39,"tag":537,"props":1330,"children":1331},{"class":539,"line":27},[1332],{"type":39,"tag":537,"props":1333,"children":1334},{},[1335],{"type":45,"value":1336},"        definition=flow_definition,\n",{"type":39,"tag":537,"props":1338,"children":1339},{"class":539,"line":602},[1340],{"type":39,"tag":537,"props":1341,"children":1342},{},[1343],{"type":45,"value":1344},"    )\n",{"type":39,"tag":537,"props":1346,"children":1347},{"class":539,"line":611},[1348],{"type":39,"tag":537,"props":1349,"children":1350},{},[1351],{"type":45,"value":1352},"    print(\"valid\" if result.valid else \"invalid\")\n",{"type":39,"tag":537,"props":1354,"children":1355},{"class":539,"line":620},[1356],{"type":39,"tag":537,"props":1357,"children":1358},{},[1359],{"type":45,"value":1360},"except TwilioRestException as e:\n",{"type":39,"tag":537,"props":1362,"children":1363},{"class":539,"line":628},[1364],{"type":39,"tag":537,"props":1365,"children":1366},{},[1367],{"type":45,"value":1368},"    for err in (e.details or {}).get(\"errors\", []):\n",{"type":39,"tag":537,"props":1370,"children":1371},{"class":539,"line":637},[1372],{"type":39,"tag":537,"props":1373,"children":1374},{},[1375],{"type":45,"value":1376},"        print(f\"{err['property_path']}: {err['message']}\")\n",{"type":39,"tag":537,"props":1378,"children":1379},{"class":539,"line":646},[1380],{"type":39,"tag":537,"props":1381,"children":1382},{},[1383],{"type":45,"value":1384},"    raise\n",{"type":39,"tag":48,"props":1386,"children":1387},{},[1388],{"type":39,"tag":54,"props":1389,"children":1390},{},[1391],{"type":45,"value":749},{"type":39,"tag":78,"props":1393,"children":1395},{"className":752,"code":1394,"language":754,"meta":86,"style":86},"try {\n  const result = await client.studio.v2.flowValidate.update({\n    friendlyName: \"SMS Auto-Responder\",\n    status: \"draft\",\n    definition: flowDefinition,\n  });\n  console.log(result.valid ? \"valid\" : \"invalid\");\n} catch (e) {\n  for (const err of e.details?.errors ?? []) {\n    console.log(`${err.property_path}: ${err.message}`);\n  }\n  throw e;\n}\n",[1396],{"type":39,"tag":69,"props":1397,"children":1398},{"__ignoreMap":86},[1399,1407,1415,1423,1431,1439,1447,1455,1463,1471,1479,1487,1495],{"type":39,"tag":537,"props":1400,"children":1401},{"class":539,"line":540},[1402],{"type":39,"tag":537,"props":1403,"children":1404},{},[1405],{"type":45,"value":1406},"try {\n",{"type":39,"tag":537,"props":1408,"children":1409},{"class":539,"line":549},[1410],{"type":39,"tag":537,"props":1411,"children":1412},{},[1413],{"type":45,"value":1414},"  const result = await client.studio.v2.flowValidate.update({\n",{"type":39,"tag":537,"props":1416,"children":1417},{"class":539,"line":558},[1418],{"type":39,"tag":537,"props":1419,"children":1420},{},[1421],{"type":45,"value":1422},"    friendlyName: \"SMS Auto-Responder\",\n",{"type":39,"tag":537,"props":1424,"children":1425},{"class":539,"line":567},[1426],{"type":39,"tag":537,"props":1427,"children":1428},{},[1429],{"type":45,"value":1430},"    status: \"draft\",\n",{"type":39,"tag":537,"props":1432,"children":1433},{"class":539,"line":576},[1434],{"type":39,"tag":537,"props":1435,"children":1436},{},[1437],{"type":45,"value":1438},"    definition: flowDefinition,\n",{"type":39,"tag":537,"props":1440,"children":1441},{"class":539,"line":585},[1442],{"type":39,"tag":537,"props":1443,"children":1444},{},[1445],{"type":45,"value":1446},"  });\n",{"type":39,"tag":537,"props":1448,"children":1449},{"class":539,"line":27},[1450],{"type":39,"tag":537,"props":1451,"children":1452},{},[1453],{"type":45,"value":1454},"  console.log(result.valid ? \"valid\" : \"invalid\");\n",{"type":39,"tag":537,"props":1456,"children":1457},{"class":539,"line":602},[1458],{"type":39,"tag":537,"props":1459,"children":1460},{},[1461],{"type":45,"value":1462},"} catch (e) {\n",{"type":39,"tag":537,"props":1464,"children":1465},{"class":539,"line":611},[1466],{"type":39,"tag":537,"props":1467,"children":1468},{},[1469],{"type":45,"value":1470},"  for (const err of e.details?.errors ?? []) {\n",{"type":39,"tag":537,"props":1472,"children":1473},{"class":539,"line":620},[1474],{"type":39,"tag":537,"props":1475,"children":1476},{},[1477],{"type":45,"value":1478},"    console.log(`${err.property_path}: ${err.message}`);\n",{"type":39,"tag":537,"props":1480,"children":1481},{"class":539,"line":628},[1482],{"type":39,"tag":537,"props":1483,"children":1484},{},[1485],{"type":45,"value":1486},"  }\n",{"type":39,"tag":537,"props":1488,"children":1489},{"class":539,"line":637},[1490],{"type":39,"tag":537,"props":1491,"children":1492},{},[1493],{"type":45,"value":1494},"  throw e;\n",{"type":39,"tag":537,"props":1496,"children":1497},{"class":539,"line":646},[1498],{"type":39,"tag":537,"props":1499,"children":1500},{},[1501],{"type":45,"value":741},{"type":39,"tag":1503,"props":1504,"children":1506},"h4",{"id":1505},"reading-and-fixing-validation-errors",[1507],{"type":45,"value":1508},"Reading and fixing validation errors",{"type":39,"tag":48,"props":1510,"children":1511},{},[1512,1514,1519,1521,1527,1529,1535,1537,1543],{"type":45,"value":1513},"Each error has a ",{"type":39,"tag":69,"props":1515,"children":1517},{"className":1516},[],[1518],{"type":45,"value":1250},{"type":45,"value":1520}," (e.g. ",{"type":39,"tag":69,"props":1522,"children":1524},{"className":1523},[],[1525],{"type":45,"value":1526},"#\u002Fstates\u002F3\u002Fproperties\u002Ftimeout",{"type":45,"value":1528}," points at\nthe ",{"type":39,"tag":69,"props":1530,"children":1532},{"className":1531},[],[1533],{"type":45,"value":1534},"timeout",{"type":45,"value":1536}," property of the 4th state — paths are 0-indexed) and a ",{"type":39,"tag":69,"props":1538,"children":1540},{"className":1539},[],[1541],{"type":45,"value":1542},"message",{"type":45,"value":1544},".\nFix one widget at a time, then re-validate. The common messages and their fixes:",{"type":39,"tag":176,"props":1546,"children":1547},{},[1548,1569],{"type":39,"tag":180,"props":1549,"children":1550},{},[1551],{"type":39,"tag":184,"props":1552,"children":1553},{},[1554,1559,1564],{"type":39,"tag":188,"props":1555,"children":1556},{},[1557],{"type":45,"value":1558},"Message",{"type":39,"tag":188,"props":1560,"children":1561},{},[1562],{"type":45,"value":1563},"Meaning",{"type":39,"tag":188,"props":1565,"children":1566},{},[1567],{"type":45,"value":1568},"Fix",{"type":39,"tag":199,"props":1570,"children":1571},{},[1572,1660,1723,1764,1800,1840,1862,1884,1906],{"type":39,"tag":184,"props":1573,"children":1574},{},[1575,1584,1589],{"type":39,"tag":206,"props":1576,"children":1577},{},[1578],{"type":39,"tag":69,"props":1579,"children":1581},{"className":1580},[],[1582],{"type":45,"value":1583},"boolean found, string expected",{"type":39,"tag":206,"props":1585,"children":1586},{},[1587],{"type":45,"value":1588},"A flag must be a quoted string",{"type":39,"tag":206,"props":1590,"children":1591},{},[1592,1594,1600,1602,1608,1610,1616,1617,1623,1624,1630,1631,1637,1638,1644,1645,1651,1652,1658],{"type":45,"value":1593},"Send ",{"type":39,"tag":69,"props":1595,"children":1597},{"className":1596},[],[1598],{"type":45,"value":1599},"\"true\"",{"type":45,"value":1601},"\u002F",{"type":39,"tag":69,"props":1603,"children":1605},{"className":1604},[],[1606],{"type":45,"value":1607},"\"false\"",{"type":45,"value":1609},", not ",{"type":39,"tag":69,"props":1611,"children":1613},{"className":1612},[],[1614],{"type":45,"value":1615},"true",{"type":45,"value":1601},{"type":39,"tag":69,"props":1618,"children":1620},{"className":1619},[],[1621],{"type":45,"value":1622},"false",{"type":45,"value":1520},{"type":39,"tag":69,"props":1625,"children":1627},{"className":1626},[],[1628],{"type":45,"value":1629},"trim",{"type":45,"value":113},{"type":39,"tag":69,"props":1632,"children":1634},{"className":1633},[],[1635],{"type":45,"value":1636},"play_beep",{"type":45,"value":113},{"type":39,"tag":69,"props":1639,"children":1641},{"className":1640},[],[1642],{"type":45,"value":1643},"postal_code",{"type":45,"value":113},{"type":39,"tag":69,"props":1646,"children":1648},{"className":1647},[],[1649],{"type":45,"value":1650},"profanity_filter",{"type":45,"value":113},{"type":39,"tag":69,"props":1653,"children":1655},{"className":1654},[],[1656],{"type":45,"value":1657},"interruptible",{"type":45,"value":1659},")",{"type":39,"tag":184,"props":1661,"children":1662},{},[1663,1672,1677],{"type":39,"tag":206,"props":1664,"children":1665},{},[1666],{"type":39,"tag":69,"props":1667,"children":1669},{"className":1668},[],[1670],{"type":45,"value":1671},"integer found, string expected",{"type":39,"tag":206,"props":1673,"children":1674},{},[1675],{"type":45,"value":1676},"A number must be a quoted string",{"type":39,"tag":206,"props":1678,"children":1679},{},[1680,1682,1688,1689,1695,1696,1701,1702,1708,1709,1715,1716,1722],{"type":45,"value":1681},"Quote it: ",{"type":39,"tag":69,"props":1683,"children":1685},{"className":1684},[],[1686],{"type":45,"value":1687},"\"3600\"",{"type":45,"value":1609},{"type":39,"tag":69,"props":1690,"children":1692},{"className":1691},[],[1693],{"type":45,"value":1694},"3600",{"type":45,"value":1520},{"type":39,"tag":69,"props":1697,"children":1699},{"className":1698},[],[1700],{"type":45,"value":1534},{"type":45,"value":113},{"type":39,"tag":69,"props":1703,"children":1705},{"className":1704},[],[1706],{"type":45,"value":1707},"time_limit",{"type":45,"value":113},{"type":39,"tag":69,"props":1710,"children":1712},{"className":1711},[],[1713],{"type":45,"value":1714},"priority",{"type":45,"value":113},{"type":39,"tag":69,"props":1717,"children":1719},{"className":1718},[],[1720],{"type":45,"value":1721},"machine_detection_timeout",{"type":45,"value":1659},{"type":39,"tag":184,"props":1724,"children":1725},{},[1726,1735,1740],{"type":39,"tag":206,"props":1727,"children":1728},{},[1729],{"type":39,"tag":69,"props":1730,"children":1732},{"className":1731},[],[1733],{"type":45,"value":1734},"string found, boolean expected",{"type":39,"tag":206,"props":1736,"children":1737},{},[1738],{"type":45,"value":1739},"The reverse — this one wants a real boolean",{"type":39,"tag":206,"props":1741,"children":1742},{},[1743,1744,1749,1750,1755,1756,1762],{"type":45,"value":1593},{"type":39,"tag":69,"props":1745,"children":1747},{"className":1746},[],[1748],{"type":45,"value":1615},{"type":45,"value":1609},{"type":39,"tag":69,"props":1751,"children":1753},{"className":1752},[],[1754],{"type":45,"value":1599},{"type":45,"value":1520},{"type":39,"tag":69,"props":1757,"children":1759},{"className":1758},[],[1760],{"type":45,"value":1761},"security_code",{"type":45,"value":1763},"). Coercion is per-property; trust the message, not a global rule",{"type":39,"tag":184,"props":1765,"children":1766},{},[1767,1776,1789],{"type":39,"tag":206,"props":1768,"children":1769},{},[1770],{"type":39,"tag":69,"props":1771,"children":1773},{"className":1772},[],[1774],{"type":45,"value":1775},"does not have a value in the enumeration [...]",{"type":39,"tag":206,"props":1777,"children":1778},{},[1779,1781,1787],{"type":45,"value":1780},"Wrong ",{"type":39,"tag":69,"props":1782,"children":1784},{"className":1783},[],[1785],{"type":45,"value":1786},"type",{"type":45,"value":1788}," string, or an out-of-range enum value",{"type":39,"tag":206,"props":1790,"children":1791},{},[1792,1794,1799],{"type":45,"value":1793},"Use one of the listed values exactly (this is how you discover the real widget ",{"type":39,"tag":69,"props":1795,"children":1797},{"className":1796},[],[1798],{"type":45,"value":1786},{"type":45,"value":1659},{"type":39,"tag":184,"props":1801,"children":1802},{},[1803,1814,1827],{"type":39,"tag":206,"props":1804,"children":1805},{},[1806,1812],{"type":39,"tag":69,"props":1807,"children":1809},{"className":1808},[],[1810],{"type":45,"value":1811},"must be a constant value \u003Cx>",{"type":45,"value":1813}," (repeated)",{"type":39,"tag":206,"props":1815,"children":1816},{},[1817,1819,1825],{"type":45,"value":1818},"A transition ",{"type":39,"tag":69,"props":1820,"children":1822},{"className":1821},[],[1823],{"type":45,"value":1824},"event",{"type":45,"value":1826}," name isn't valid for this widget",{"type":39,"tag":206,"props":1828,"children":1829},{},[1830,1832,1838],{"type":45,"value":1831},"Use one of the ",{"type":39,"tag":69,"props":1833,"children":1835},{"className":1834},[],[1836],{"type":45,"value":1837},"\u003Cx>",{"type":45,"value":1839}," values listed; remove invented events",{"type":39,"tag":184,"props":1841,"children":1842},{},[1843,1852,1857],{"type":39,"tag":206,"props":1844,"children":1845},{},[1846],{"type":39,"tag":69,"props":1847,"children":1849},{"className":1848},[],[1850],{"type":45,"value":1851},"is missing but it is required",{"type":39,"tag":206,"props":1853,"children":1854},{},[1855],{"type":45,"value":1856},"A required property\u002Fsub-field is absent",{"type":39,"tag":206,"props":1858,"children":1859},{},[1860],{"type":45,"value":1861},"Add it at the named path",{"type":39,"tag":184,"props":1863,"children":1864},{},[1865,1874,1879],{"type":39,"tag":206,"props":1866,"children":1867},{},[1868],{"type":39,"tag":69,"props":1869,"children":1871},{"className":1870},[],[1872],{"type":45,"value":1873},"must not be null",{"type":39,"tag":206,"props":1875,"children":1876},{},[1877],{"type":45,"value":1878},"Required property present but unset",{"type":39,"tag":206,"props":1880,"children":1881},{},[1882],{"type":45,"value":1883},"Give it a value",{"type":39,"tag":184,"props":1885,"children":1886},{},[1887,1896,1901],{"type":39,"tag":206,"props":1888,"children":1889},{},[1890],{"type":39,"tag":69,"props":1891,"children":1893},{"className":1892},[],[1894],{"type":45,"value":1895},"must be a valid, non-liquid flow sid",{"type":39,"tag":206,"props":1897,"children":1898},{},[1899],{"type":45,"value":1900},"A SID field got a Liquid template or bad value",{"type":39,"tag":206,"props":1902,"children":1903},{},[1904],{"type":45,"value":1905},"Pass a literal SID",{"type":39,"tag":184,"props":1907,"children":1908},{},[1909,1918,1931],{"type":39,"tag":206,"props":1910,"children":1911},{},[1912],{"type":39,"tag":69,"props":1913,"children":1915},{"className":1914},[],[1916],{"type":45,"value":1917},"\u003Cwidget> can only be used in flows triggered by the REST API",{"type":39,"tag":206,"props":1919,"children":1920},{},[1921,1923,1929],{"type":45,"value":1922},"Widget needs an ",{"type":39,"tag":69,"props":1924,"children":1926},{"className":1925},[],[1927],{"type":45,"value":1928},"incomingRequest",{"type":45,"value":1930}," trigger",{"type":39,"tag":206,"props":1932,"children":1933},{},[1934],{"type":45,"value":1935},"Trigger the flow via the REST API, not a call\u002Fmessage",{"type":39,"tag":48,"props":1937,"children":1938},{},[1939],{"type":45,"value":1940},"When the message itself lists the allowed values (enumeration \u002F constant-value\ncases), that list is authoritative — prefer it over any documentation.",{"type":39,"tag":1190,"props":1942,"children":1944},{"id":1943},"publish-update-and-the-full-replace-rule",[1945],{"type":45,"value":1946},"Publish, update, and the full-replace rule",{"type":39,"tag":48,"props":1948,"children":1949},{},[1950,1952,1957,1959,1964,1966,1972,1974,1979],{"type":45,"value":1951},"A flow has a ",{"type":39,"tag":54,"props":1953,"children":1954},{},[1955],{"type":45,"value":1956},"draft",{"type":45,"value":1958}," and a ",{"type":39,"tag":54,"props":1960,"children":1961},{},[1962],{"type":45,"value":1963},"published",{"type":45,"value":1965}," revision. ",{"type":39,"tag":69,"props":1967,"children":1969},{"className":1968},[],[1970],{"type":45,"value":1971},"status=\"published\"",{"type":45,"value":1973}," makes\nthe flow live to real traffic; ",{"type":39,"tag":69,"props":1975,"children":1977},{"className":1976},[],[1978],{"type":45,"value":956},{"type":45,"value":1980}," keeps it editable without\naffecting traffic. Each save increments the revision.",{"type":39,"tag":48,"props":1982,"children":1983},{},[1984,1989],{"type":39,"tag":54,"props":1985,"children":1986},{},[1987],{"type":45,"value":1988},"Updating replaces the entire definition — there is no partial patch.",{"type":45,"value":1990}," Always\nsend the complete definition JSON, not a diff. To change one widget, fetch the\ncurrent definition, modify it, and send the whole thing back.",{"type":39,"tag":48,"props":1992,"children":1993},{},[1994],{"type":39,"tag":54,"props":1995,"children":1996},{},[1997],{"type":45,"value":526},{"type":39,"tag":78,"props":1999,"children":2001},{"className":529,"code":2000,"language":531,"meta":86,"style":86},"flow = client.studio.v2.flows(flow_sid).update(\n    status=\"published\",\n    definition=flow_definition,      # the COMPLETE definition\n    commit_message=\"Publish auto-responder\",\n)\n",[2002],{"type":39,"tag":69,"props":2003,"children":2004},{"__ignoreMap":86},[2005,2013,2021,2029,2037],{"type":39,"tag":537,"props":2006,"children":2007},{"class":539,"line":540},[2008],{"type":39,"tag":537,"props":2009,"children":2010},{},[2011],{"type":45,"value":2012},"flow = client.studio.v2.flows(flow_sid).update(\n",{"type":39,"tag":537,"props":2014,"children":2015},{"class":539,"line":549},[2016],{"type":39,"tag":537,"props":2017,"children":2018},{},[2019],{"type":45,"value":2020},"    status=\"published\",\n",{"type":39,"tag":537,"props":2022,"children":2023},{"class":539,"line":558},[2024],{"type":39,"tag":537,"props":2025,"children":2026},{},[2027],{"type":45,"value":2028},"    definition=flow_definition,      # the COMPLETE definition\n",{"type":39,"tag":537,"props":2030,"children":2031},{"class":539,"line":567},[2032],{"type":39,"tag":537,"props":2033,"children":2034},{},[2035],{"type":45,"value":2036},"    commit_message=\"Publish auto-responder\",\n",{"type":39,"tag":537,"props":2038,"children":2039},{"class":539,"line":576},[2040],{"type":39,"tag":537,"props":2041,"children":2042},{},[2043],{"type":45,"value":1060},{"type":39,"tag":48,"props":2045,"children":2046},{},[2047],{"type":39,"tag":54,"props":2048,"children":2049},{},[2050],{"type":45,"value":749},{"type":39,"tag":78,"props":2052,"children":2054},{"className":752,"code":2053,"language":754,"meta":86,"style":86},"const flow = await client.studio.v2.flows(flowSid).update({\n  status: \"published\",\n  definition: flowDefinition,        \u002F\u002F the COMPLETE definition\n  commitMessage: \"Publish auto-responder\",\n});\n",[2055],{"type":39,"tag":69,"props":2056,"children":2057},{"__ignoreMap":86},[2058,2066,2074,2082,2090],{"type":39,"tag":537,"props":2059,"children":2060},{"class":539,"line":540},[2061],{"type":39,"tag":537,"props":2062,"children":2063},{},[2064],{"type":45,"value":2065},"const flow = await client.studio.v2.flows(flowSid).update({\n",{"type":39,"tag":537,"props":2067,"children":2068},{"class":539,"line":549},[2069],{"type":39,"tag":537,"props":2070,"children":2071},{},[2072],{"type":45,"value":2073},"  status: \"published\",\n",{"type":39,"tag":537,"props":2075,"children":2076},{"class":539,"line":558},[2077],{"type":39,"tag":537,"props":2078,"children":2079},{},[2080],{"type":45,"value":2081},"  definition: flowDefinition,        \u002F\u002F the COMPLETE definition\n",{"type":39,"tag":537,"props":2083,"children":2084},{"class":539,"line":567},[2085],{"type":39,"tag":537,"props":2086,"children":2087},{},[2088],{"type":45,"value":2089},"  commitMessage: \"Publish auto-responder\",\n",{"type":39,"tag":537,"props":2091,"children":2092},{"class":539,"line":576},[2093],{"type":39,"tag":537,"props":2094,"children":2095},{},[2096],{"type":45,"value":1169},{"type":39,"tag":1190,"props":2098,"children":2100},{"id":2099},"list-and-fetch-round-trip-editing",[2101],{"type":45,"value":2102},"List and fetch (round-trip editing)",{"type":39,"tag":48,"props":2104,"children":2105},{},[2106,2108,2114,2116,2122,2124,2130,2132,2138],{"type":45,"value":2107},"List flows with ",{"type":39,"tag":69,"props":2109,"children":2111},{"className":2110},[],[2112],{"type":45,"value":2113},"client.studio.v2.flows.list({ limit })",{"type":45,"value":2115},"; fetch one with\n",{"type":39,"tag":69,"props":2117,"children":2119},{"className":2118},[],[2120],{"type":45,"value":2121},"client.studio.v2.flows(flowSid).fetch()",{"type":45,"value":2123}," — its ",{"type":39,"tag":69,"props":2125,"children":2127},{"className":2126},[],[2128],{"type":45,"value":2129},".definition",{"type":45,"value":2131}," is the JSON you\nedit and send back via ",{"type":39,"tag":69,"props":2133,"children":2135},{"className":2134},[],[2136],{"type":45,"value":2137},"update",{"type":45,"value":2139},". These are read-only.",{"type":39,"tag":1190,"props":2141,"children":2143},{"id":2142},"core-widgets-at-a-glance",[2144],{"type":45,"value":2145},"Core widgets at a glance",{"type":39,"tag":176,"props":2147,"children":2148},{},[2149,2173],{"type":39,"tag":180,"props":2150,"children":2151},{},[2152],{"type":39,"tag":184,"props":2153,"children":2154},{},[2155,2160,2168],{"type":39,"tag":188,"props":2156,"children":2157},{},[2158],{"type":45,"value":2159},"Widget",{"type":39,"tag":188,"props":2161,"children":2162},{},[2163],{"type":39,"tag":69,"props":2164,"children":2166},{"className":2165},[],[2167],{"type":45,"value":1786},{"type":39,"tag":188,"props":2169,"children":2170},{},[2171],{"type":45,"value":2172},"Use for",{"type":39,"tag":199,"props":2174,"children":2175},{},[2176,2198,2219,2241,2263,2285,2307,2329,2351,2373],{"type":39,"tag":184,"props":2177,"children":2178},{},[2179,2184,2193],{"type":39,"tag":206,"props":2180,"children":2181},{},[2182],{"type":45,"value":2183},"Trigger",{"type":39,"tag":206,"props":2185,"children":2186},{},[2187],{"type":39,"tag":69,"props":2188,"children":2190},{"className":2189},[],[2191],{"type":45,"value":2192},"trigger",{"type":39,"tag":206,"props":2194,"children":2195},{},[2196],{"type":45,"value":2197},"Flow entry point (call\u002Fmessage\u002Fconversation\u002FREST)",{"type":39,"tag":184,"props":2199,"children":2200},{},[2201,2206,2214],{"type":39,"tag":206,"props":2202,"children":2203},{},[2204],{"type":45,"value":2205},"Say\u002FPlay",{"type":39,"tag":206,"props":2207,"children":2208},{},[2209],{"type":39,"tag":69,"props":2210,"children":2212},{"className":2211},[],[2213],{"type":45,"value":272},{"type":39,"tag":206,"props":2215,"children":2216},{},[2217],{"type":45,"value":2218},"Speak TTS or play audio on a call",{"type":39,"tag":184,"props":2220,"children":2221},{},[2222,2227,2236],{"type":39,"tag":206,"props":2223,"children":2224},{},[2225],{"type":45,"value":2226},"Gather Input On Call",{"type":39,"tag":206,"props":2228,"children":2229},{},[2230],{"type":39,"tag":69,"props":2231,"children":2233},{"className":2232},[],[2234],{"type":45,"value":2235},"gather-input-on-call",{"type":39,"tag":206,"props":2237,"children":2238},{},[2239],{"type":45,"value":2240},"Collect DTMF digits or speech",{"type":39,"tag":184,"props":2242,"children":2243},{},[2244,2249,2258],{"type":39,"tag":206,"props":2245,"children":2246},{},[2247],{"type":45,"value":2248},"Split Based On…",{"type":39,"tag":206,"props":2250,"children":2251},{},[2252],{"type":39,"tag":69,"props":2253,"children":2255},{"className":2254},[],[2256],{"type":45,"value":2257},"split-based-on",{"type":39,"tag":206,"props":2259,"children":2260},{},[2261],{"type":45,"value":2262},"Branch on a variable's value",{"type":39,"tag":184,"props":2264,"children":2265},{},[2266,2271,2280],{"type":39,"tag":206,"props":2267,"children":2268},{},[2269],{"type":45,"value":2270},"Set Variables",{"type":39,"tag":206,"props":2272,"children":2273},{},[2274],{"type":39,"tag":69,"props":2275,"children":2277},{"className":2276},[],[2278],{"type":45,"value":2279},"set-variables",{"type":39,"tag":206,"props":2281,"children":2282},{},[2283],{"type":45,"value":2284},"Store flow-scoped variables",{"type":39,"tag":184,"props":2286,"children":2287},{},[2288,2293,2302],{"type":39,"tag":206,"props":2289,"children":2290},{},[2291],{"type":45,"value":2292},"Send Message",{"type":39,"tag":206,"props":2294,"children":2295},{},[2296],{"type":39,"tag":69,"props":2297,"children":2299},{"className":2298},[],[2300],{"type":45,"value":2301},"send-message",{"type":39,"tag":206,"props":2303,"children":2304},{},[2305],{"type":45,"value":2306},"Send SMS\u002Fchat, no reply expected",{"type":39,"tag":184,"props":2308,"children":2309},{},[2310,2315,2324],{"type":39,"tag":206,"props":2311,"children":2312},{},[2313],{"type":45,"value":2314},"Send & Wait For Reply",{"type":39,"tag":206,"props":2316,"children":2317},{},[2318],{"type":39,"tag":69,"props":2319,"children":2321},{"className":2320},[],[2322],{"type":45,"value":2323},"send-and-wait-for-reply",{"type":39,"tag":206,"props":2325,"children":2326},{},[2327],{"type":45,"value":2328},"Send and pause for a reply",{"type":39,"tag":184,"props":2330,"children":2331},{},[2332,2337,2346],{"type":39,"tag":206,"props":2333,"children":2334},{},[2335],{"type":45,"value":2336},"Connect Call To",{"type":39,"tag":206,"props":2338,"children":2339},{},[2340],{"type":39,"tag":69,"props":2341,"children":2343},{"className":2342},[],[2344],{"type":45,"value":2345},"connect-call-to",{"type":39,"tag":206,"props":2347,"children":2348},{},[2349],{"type":45,"value":2350},"Bridge a call to a number\u002FSIP\u002Fconference",{"type":39,"tag":184,"props":2352,"children":2353},{},[2354,2359,2368],{"type":39,"tag":206,"props":2355,"children":2356},{},[2357],{"type":45,"value":2358},"Run Function",{"type":39,"tag":206,"props":2360,"children":2361},{},[2362],{"type":39,"tag":69,"props":2363,"children":2365},{"className":2364},[],[2366],{"type":45,"value":2367},"run-function",{"type":39,"tag":206,"props":2369,"children":2370},{},[2371],{"type":45,"value":2372},"Call a Twilio Serverless Function",{"type":39,"tag":184,"props":2374,"children":2375},{},[2376,2381,2390],{"type":39,"tag":206,"props":2377,"children":2378},{},[2379],{"type":45,"value":2380},"HTTP Request",{"type":39,"tag":206,"props":2382,"children":2383},{},[2384],{"type":39,"tag":69,"props":2385,"children":2387},{"className":2386},[],[2388],{"type":45,"value":2389},"make-http-request",{"type":39,"tag":206,"props":2391,"children":2392},{},[2393],{"type":45,"value":2394},"Call an external API",{"type":39,"tag":48,"props":2396,"children":2397},{},[2398,2400,2408],{"type":45,"value":2399},"The complete catalog — every widget's properties, transition events, and the\noutput values it exposes — is in ",{"type":39,"tag":131,"props":2401,"children":2402},{"href":133},[2403],{"type":39,"tag":69,"props":2404,"children":2406},{"className":2405},[],[2407],{"type":45,"value":140},{"type":45,"value":164},{"type":39,"tag":1190,"props":2410,"children":2412},{"id":2411},"transitions-and-output-context",[2413],{"type":45,"value":2414},"Transitions and output context",{"type":39,"tag":48,"props":2416,"children":2417},{},[2418,2420,2425,2426,2432,2433,2439,2440,2446,2447,2453,2454,2459,2461,2467,2469,2474,2476,2482,2484,2489],{"type":45,"value":2419},"Each widget emits ",{"type":39,"tag":54,"props":2421,"children":2422},{},[2423],{"type":45,"value":2424},"transition events",{"type":45,"value":1520},{"type":39,"tag":69,"props":2427,"children":2429},{"className":2428},[],[2430],{"type":45,"value":2431},"sent",{"type":45,"value":1601},{"type":39,"tag":69,"props":2434,"children":2436},{"className":2435},[],[2437],{"type":45,"value":2438},"failed",{"type":45,"value":113},{"type":39,"tag":69,"props":2441,"children":2443},{"className":2442},[],[2444],{"type":45,"value":2445},"keypress",{"type":45,"value":1601},{"type":39,"tag":69,"props":2448,"children":2450},{"className":2449},[],[2451],{"type":45,"value":2452},"speech",{"type":45,"value":1601},{"type":39,"tag":69,"props":2455,"children":2457},{"className":2456},[],[2458],{"type":45,"value":1534},{"type":45,"value":2460},").\nA transition routes one event to a ",{"type":39,"tag":69,"props":2462,"children":2464},{"className":2463},[],[2465],{"type":45,"value":2466},"next",{"type":45,"value":2468}," state; omit ",{"type":39,"tag":69,"props":2470,"children":2472},{"className":2471},[],[2473],{"type":45,"value":2466},{"type":45,"value":2475}," (or use ",{"type":39,"tag":69,"props":2477,"children":2479},{"className":2478},[],[2480],{"type":45,"value":2481},"\"\"",{"type":45,"value":2483},") to end\nthe branch. Every non-empty ",{"type":39,"tag":69,"props":2485,"children":2487},{"className":2486},[],[2488],{"type":45,"value":2466},{"type":45,"value":2490}," must name an existing state.",{"type":39,"tag":48,"props":2492,"children":2493},{},[2494,2496,2502,2504,2509,2511,2517,2519,2524],{"type":45,"value":2495},"Read a prior widget's result downstream with ",{"type":39,"tag":69,"props":2497,"children":2499},{"className":2498},[],[2500],{"type":45,"value":2501},"{{widgets.\u003Cname>.\u003Ckey>}}",{"type":45,"value":2503}," — e.g. a\nGather's ",{"type":39,"tag":69,"props":2505,"children":2507},{"className":2506},[],[2508],{"type":45,"value":127},{"type":45,"value":2510}," feeding a Split's ",{"type":39,"tag":69,"props":2512,"children":2514},{"className":2513},[],[2515],{"type":45,"value":2516},"input",{"type":45,"value":2518},". Which keys\neach widget exposes is in ",{"type":39,"tag":69,"props":2520,"children":2522},{"className":2521},[],[2523],{"type":45,"value":140},{"type":45,"value":164},{"type":39,"tag":1190,"props":2526,"children":2528},{"id":2527},"integrate-custom-logic-functions-http",[2529],{"type":45,"value":2530},"Integrate custom logic (Functions, HTTP)",{"type":39,"tag":48,"props":2532,"children":2533},{},[2534,2536,2542,2544,2550,2552,2558],{"type":45,"value":2535},"Run Function calls a Twilio Serverless Function (",{"type":39,"tag":69,"props":2537,"children":2539},{"className":2538},[],[2540],{"type":45,"value":2541},"success",{"type":45,"value":2543}," on 2xx\u002F3xx within 10s,\n",{"type":39,"tag":69,"props":2545,"children":2547},{"className":2546},[],[2548],{"type":45,"value":2549},"fail",{"type":45,"value":2551}," otherwise) and exposes ",{"type":39,"tag":69,"props":2553,"children":2555},{"className":2554},[],[2556],{"type":45,"value":2557},"parsed.\u003Ckey>",{"type":45,"value":2559}," when the function returns JSON.\nHTTP Request does the same for an external API. Use these when flow logic\noutgrows widgets — but keep the heavy work in the Function, not the flow.",{"type":39,"tag":144,"props":2561,"children":2562},{},[2563],{"type":39,"tag":48,"props":2564,"children":2565},{},[2566,2568,2573],{"type":45,"value":2567},"Data reaching a Function or HTTP Request from ",{"type":39,"tag":69,"props":2569,"children":2571},{"className":2570},[],[2572],{"type":45,"value":490},{"type":45,"value":2574}," \u002F a Gather is\nuntrusted caller input. Validate it in your Function; never interpolate it\ninto a shell command, SQL, or an LLM system prompt.",{"type":39,"tag":1190,"props":2576,"children":2578},{"id":2577},"recipe-repeat-a-prompt-or-loop-with-a-counter",[2579],{"type":45,"value":2580},"Recipe: repeat a prompt or loop with a counter",{"type":39,"tag":48,"props":2582,"children":2583},{},[2584,2586,2591,2593,2598,2600,2605,2607,2612,2614,2624],{"type":45,"value":2585},"Studio has no loop construct. For simple audio repeats use the ",{"type":39,"tag":69,"props":2587,"children":2589},{"className":2588},[],[2590],{"type":45,"value":272},{"type":45,"value":2592}," ",{"type":39,"tag":69,"props":2594,"children":2596},{"className":2595},[],[2597],{"type":45,"value":278},{"type":45,"value":2599},"\nproperty (1–99). To track a count and branch on it, build an explicit cycle:\na ",{"type":39,"tag":69,"props":2601,"children":2603},{"className":2602},[],[2604],{"type":45,"value":2279},{"type":45,"value":2606}," widget that init-or-increments, then a ",{"type":39,"tag":69,"props":2608,"children":2610},{"className":2609},[],[2611],{"type":45,"value":2257},{"type":45,"value":2613}," whose\n\"keep looping\" branch transitions ",{"type":39,"tag":54,"props":2615,"children":2616},{},[2617,2619],{"type":45,"value":2618},"back to the same ",{"type":39,"tag":69,"props":2620,"children":2622},{"className":2621},[],[2623],{"type":45,"value":2279},{"type":45,"value":164},{"type":39,"tag":48,"props":2626,"children":2627},{},[2628],{"type":45,"value":2629},"Init-or-increment value (handles first pass and every later pass):",{"type":39,"tag":78,"props":2631,"children":2635},{"className":2632,"code":2633,"language":2634,"meta":86,"style":86},"language-liquid shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{% if flow.variables.num %}{{flow.variables.num | plus: 1}}{% else %}0{% endif %}\n","liquid",[2636],{"type":39,"tag":69,"props":2637,"children":2638},{"__ignoreMap":86},[2639],{"type":39,"tag":537,"props":2640,"children":2641},{"class":539,"line":540},[2642],{"type":39,"tag":537,"props":2643,"children":2644},{},[2645],{"type":45,"value":2633},{"type":39,"tag":48,"props":2647,"children":2648},{},[2649,2651,2657,2659,2664,2666,2672,2673,2679,2681,2686,2688,2693],{"type":45,"value":2650},"The split reads ",{"type":39,"tag":69,"props":2652,"children":2654},{"className":2653},[],[2655],{"type":45,"value":2656},"{{flow.variables.num}}",{"type":45,"value":2658}," as its ",{"type":39,"tag":69,"props":2660,"children":2662},{"className":2661},[],[2663],{"type":45,"value":2516},{"type":45,"value":2665},"; a ",{"type":39,"tag":69,"props":2667,"children":2669},{"className":2668},[],[2670],{"type":45,"value":2671},"greater_than",{"type":45,"value":2592},{"type":39,"tag":69,"props":2674,"children":2676},{"className":2675},[],[2677],{"type":45,"value":2678},"2",{"type":45,"value":2680},"\ncondition routes to the exit, ",{"type":39,"tag":69,"props":2682,"children":2684},{"className":2683},[],[2685],{"type":45,"value":455},{"type":45,"value":2687}," routes back to the counter. Each\niteration is a separate execution step and counts against per-execution step\nlimits — prefer the ",{"type":39,"tag":69,"props":2689,"children":2691},{"className":2690},[],[2692],{"type":45,"value":278},{"type":45,"value":2694}," property when you don't need the value.",{"type":39,"tag":1190,"props":2696,"children":2698},{"id":2697},"recipe-voice-ivr-menu",[2699],{"type":45,"value":2700},"Recipe: voice IVR menu",{"type":39,"tag":48,"props":2702,"children":2703},{},[2704,2709,2711,2716,2717,2722,2724,2730,2732,2738,2740,2746,2748,2754,2756,2762,2764,2770,2772,2778,2779,2785,2787,2793,2795,2801],{"type":39,"tag":69,"props":2705,"children":2707},{"className":2706},[],[2708],{"type":45,"value":2235},{"type":45,"value":2710}," → ",{"type":39,"tag":69,"props":2712,"children":2714},{"className":2713},[],[2715],{"type":45,"value":2257},{"type":45,"value":2710},{"type":39,"tag":69,"props":2718,"children":2720},{"className":2719},[],[2721],{"type":45,"value":2345},{"type":45,"value":2723},". Gather prompts and\ncollects DTMF + speech (read via ",{"type":39,"tag":69,"props":2725,"children":2727},{"className":2726},[],[2728],{"type":45,"value":2729},"{{widgets.\u003Cname>.Digits}}",{"type":45,"value":2731}," and\n",{"type":39,"tag":69,"props":2733,"children":2735},{"className":2734},[],[2736],{"type":45,"value":2737},"{{widgets.\u003Cname>.SpeechResult}}",{"type":45,"value":2739},"). To accept a keypress OR a spoken word, give\nthe Split two match conditions: ",{"type":39,"tag":69,"props":2741,"children":2743},{"className":2742},[],[2744],{"type":45,"value":2745},"equal_to",{"type":45,"value":2747}," on ",{"type":39,"tag":69,"props":2749,"children":2751},{"className":2750},[],[2752],{"type":45,"value":2753},"Digits",{"type":45,"value":2755}," and ",{"type":39,"tag":69,"props":2757,"children":2759},{"className":2758},[],[2760],{"type":45,"value":2761},"contains",{"type":45,"value":2763}," on\n",{"type":39,"tag":69,"props":2765,"children":2767},{"className":2766},[],[2768],{"type":45,"value":2769},"SpeechResult",{"type":45,"value":2771},". Connect Call To uses ",{"type":39,"tag":69,"props":2773,"children":2775},{"className":2774},[],[2776],{"type":45,"value":2777},"noun: \"number\"",{"type":45,"value":113},{"type":39,"tag":69,"props":2780,"children":2782},{"className":2781},[],[2783],{"type":45,"value":2784},"to",{"type":45,"value":2786}," set to an E.164\nnumber, and ",{"type":39,"tag":69,"props":2788,"children":2790},{"className":2789},[],[2791],{"type":45,"value":2792},"caller_id",{"type":45,"value":2794}," usually ",{"type":39,"tag":69,"props":2796,"children":2798},{"className":2797},[],[2799],{"type":45,"value":2800},"{{flow.channel.address}}",{"type":45,"value":164},{"type":39,"tag":1190,"props":2803,"children":2805},{"id":2804},"liquid-quick-reference",[2806],{"type":45,"value":2807},"Liquid quick reference",{"type":39,"tag":298,"props":2809,"children":2810},{},[2811,2822,2849,2860,2890,2909],{"type":39,"tag":302,"props":2812,"children":2813},{},[2814,2816],{"type":45,"value":2815},"Increment: ",{"type":39,"tag":69,"props":2817,"children":2819},{"className":2818},[],[2820],{"type":45,"value":2821},"{{flow.variables.num | plus: 1}}",{"type":39,"tag":302,"props":2823,"children":2824},{},[2825,2827,2833,2835,2841,2843],{"type":45,"value":2826},"Default when unset: ",{"type":39,"tag":69,"props":2828,"children":2830},{"className":2829},[],[2831],{"type":45,"value":2832},"{% if flow.variables.x %}…{% else %}…{% endif %}",{"type":45,"value":2834},", or the\n",{"type":39,"tag":69,"props":2836,"children":2838},{"className":2837},[],[2839],{"type":45,"value":2840},"default",{"type":45,"value":2842}," filter inline: ",{"type":39,"tag":69,"props":2844,"children":2846},{"className":2845},[],[2847],{"type":45,"value":2848},"{{trigger.message.Body | default: \"no message\"}}",{"type":39,"tag":302,"props":2850,"children":2851},{},[2852,2854],{"type":45,"value":2853},"Read a widget output: ",{"type":39,"tag":69,"props":2855,"children":2857},{"className":2856},[],[2858],{"type":45,"value":2859},"{{widgets.\u003Cname>.\u003Cfield>}}",{"type":39,"tag":302,"props":2861,"children":2862},{},[2863,2865,2870,2871,2877,2878,2883,2884],{"type":45,"value":2864},"Common globals: ",{"type":39,"tag":69,"props":2866,"children":2868},{"className":2867},[],[2869],{"type":45,"value":111},{"type":45,"value":113},{"type":39,"tag":69,"props":2872,"children":2874},{"className":2873},[],[2875],{"type":45,"value":2876},"{{trigger.call.From}}",{"type":45,"value":121},{"type":39,"tag":69,"props":2879,"children":2881},{"className":2880},[],[2882],{"type":45,"value":2800},{"type":45,"value":113},{"type":39,"tag":69,"props":2885,"children":2887},{"className":2886},[],[2888],{"type":45,"value":2889},"{{contact.channel.address}}",{"type":39,"tag":302,"props":2891,"children":2892},{},[2893,2895,2901,2903],{"type":45,"value":2894},"URL-encode before putting a value in a query string or URL property — e.g.\nescape ",{"type":39,"tag":69,"props":2896,"children":2898},{"className":2897},[],[2899],{"type":45,"value":2900},"+",{"type":45,"value":2902}," in a phone number: ",{"type":39,"tag":69,"props":2904,"children":2906},{"className":2905},[],[2907],{"type":45,"value":2908},"{{contact.channel.address | replace: '+', '%2B'}}",{"type":39,"tag":302,"props":2910,"children":2911},{},[2912,2914,2919,2921,2927,2929,2935,2937,2942,2943,2949],{"type":45,"value":2913},"Embed a prior widget's parsed JSON as a nested object in a request body or a\n",{"type":39,"tag":69,"props":2915,"children":2917},{"className":2916},[],[2918],{"type":45,"value":2279},{"type":45,"value":2920}," value: ",{"type":39,"tag":69,"props":2922,"children":2924},{"className":2923},[],[2925],{"type":45,"value":2926},"{{widgets.http_1.parsed.items | to_json}}",{"type":45,"value":2928}," — pair\n",{"type":39,"tag":69,"props":2930,"children":2932},{"className":2931},[],[2933],{"type":45,"value":2934},"to_json",{"type":45,"value":2936}," with ",{"type":39,"tag":69,"props":2938,"children":2940},{"className":2939},[],[2941],{"type":45,"value":2279},{"type":45,"value":2592},{"type":39,"tag":69,"props":2944,"children":2946},{"className":2945},[],[2947],{"type":45,"value":2948},"parse_as_json: true",{"type":45,"value":2950}," when the result must stay\na JSON object rather than a stringified scalar",{"type":39,"tag":166,"props":2952,"children":2953},{},[],{"type":39,"tag":40,"props":2955,"children":2957},{"id":2956},"cannot",[2958],{"type":45,"value":2959},"CANNOT",{"type":39,"tag":298,"props":2961,"children":2962},{},[2963,2980,2990,3013,3030,3040],{"type":39,"tag":302,"props":2964,"children":2965},{},[2966,2971,2973,2978],{"type":39,"tag":54,"props":2967,"children":2968},{},[2969],{"type":45,"value":2970},"Cannot partially update a flow",{"type":45,"value":2972}," — ",{"type":39,"tag":69,"props":2974,"children":2976},{"className":2975},[],[2977],{"type":45,"value":2137},{"type":45,"value":2979}," replaces the entire definition.\nFetch, modify the whole JSON, and send it all back. There is no patch.",{"type":39,"tag":302,"props":2981,"children":2982},{},[2983,2988],{"type":39,"tag":54,"props":2984,"children":2985},{},[2986],{"type":45,"value":2987},"Cannot create Pay Connectors via API",{"type":45,"value":2989}," — the Capture Payments widget needs a\nPay Connector configured in Console first (Console > Voice > Pay Connectors).",{"type":39,"tag":302,"props":2991,"children":2992},{},[2993,2998,3000,3005,3006,3011],{"type":39,"tag":54,"props":2994,"children":2995},{},[2996],{"type":45,"value":2997},"Cannot loop natively",{"type":45,"value":2999}," — Studio has no loop widget. Build an explicit cycle\n(counter recipe) or use ",{"type":39,"tag":69,"props":3001,"children":3003},{"className":3002},[],[3004],{"type":45,"value":272},{"type":45,"value":2592},{"type":39,"tag":69,"props":3007,"children":3009},{"className":3008},[],[3010],{"type":45,"value":278},{"type":45,"value":3012},"; high iteration counts hit\nper-execution step limits.",{"type":39,"tag":302,"props":3014,"children":3015},{},[3016,3021,3023,3028],{"type":39,"tag":54,"props":3017,"children":3018},{},[3019],{"type":45,"value":3020},"Cannot affect live traffic with a draft",{"type":45,"value":3022}," — only a ",{"type":39,"tag":69,"props":3024,"children":3026},{"className":3025},[],[3027],{"type":45,"value":1963},{"type":45,"value":3029}," revision runs\nfor real calls\u002Fmessages. Publishing is what goes live.",{"type":39,"tag":302,"props":3031,"children":3032},{},[3033,3038],{"type":39,"tag":54,"props":3034,"children":3035},{},[3036],{"type":45,"value":3037},"Cannot place test calls or trigger executions from this skill",{"type":45,"value":3039}," — authoring\nand deploying only. Test in the Console or wire the flow to a number\u002FMessaging\nService and exercise it from your own application.",{"type":39,"tag":302,"props":3041,"children":3042},{},[3043,3048],{"type":39,"tag":54,"props":3044,"children":3045},{},[3046],{"type":45,"value":3047},"Cannot trust inbound flow data",{"type":45,"value":3049}," — caller speech, message bodies, and REST\nparameters are untrusted external input; validate before using in Functions,\nHTTP requests, or LLM prompts.",{"type":39,"tag":166,"props":3051,"children":3052},{},[],{"type":39,"tag":40,"props":3054,"children":3056},{"id":3055},"next-steps",[3057],{"type":45,"value":3058},"Next Steps",{"type":39,"tag":298,"props":3060,"children":3061},{},[3062,3076,3090,3105],{"type":39,"tag":302,"props":3063,"children":3064},{},[3065,3070,3071],{"type":39,"tag":54,"props":3066,"children":3067},{},[3068],{"type":45,"value":3069},"Pure TwiML call logic (no visual flow):",{"type":45,"value":2592},{"type":39,"tag":69,"props":3072,"children":3074},{"className":3073},[],[3075],{"type":45,"value":286},{"type":39,"tag":302,"props":3077,"children":3078},{},[3079,3084,3085],{"type":39,"tag":54,"props":3080,"children":3081},{},[3082],{"type":45,"value":3083},"Securing the webhooks Studio calls \u002F signature validation:",{"type":45,"value":2592},{"type":39,"tag":69,"props":3086,"children":3088},{"className":3087},[],[3089],{"type":45,"value":162},{"type":39,"tag":302,"props":3091,"children":3092},{},[3093,3098,3099],{"type":39,"tag":54,"props":3094,"children":3095},{},[3096],{"type":45,"value":3097},"Routing calls to agents\u002Fqueues:",{"type":45,"value":2592},{"type":39,"tag":69,"props":3100,"children":3102},{"className":3101},[],[3103],{"type":45,"value":3104},"twilio-taskrouter-routing",{"type":39,"tag":302,"props":3106,"children":3107},{},[3108,3113,3114],{"type":39,"tag":54,"props":3109,"children":3110},{},[3111],{"type":45,"value":3112},"Production credentials (API Keys):",{"type":45,"value":2592},{"type":39,"tag":69,"props":3115,"children":3117},{"className":3116},[],[3118],{"type":45,"value":339},{"type":39,"tag":3120,"props":3121,"children":3122},"style",{},[3123],{"type":45,"value":3124},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":3126,"total":3229},[3127,3140,3160,3171,3183,3198,3215],{"slug":312,"name":312,"fn":3128,"description":3129,"org":3130,"tags":3131,"stars":23,"repoUrl":24,"updatedAt":3139},"configure Twilio accounts and credentials","Create and configure a Twilio account from scratch. Covers free trial signup, trial limitations, getting credentials (Account SID and Auth Token), buying a phone number, verifying recipient numbers for trial use, SDK installation, first API call, subaccount management (creation, inheritance, credential isolation, limits), and enabling specific products (AI Assistants, Conversations, Verify, ConversationRelay, WhatsApp). Use this skill before any other Twilio skill if you do not yet have a Twilio account or need to enable a product. For Organization-level governance (SSO, SCIM, multi-team), see `twilio-organizations-setup`.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3132,3133,3136],{"name":20,"slug":21,"type":15},{"name":3134,"slug":3135,"type":15},"Communications","communications",{"name":3137,"slug":3138,"type":15},"SMS","sms","2026-08-01T05:43:28.968968",{"slug":3141,"name":3141,"fn":3142,"description":3143,"org":3144,"tags":3145,"stars":23,"repoUrl":24,"updatedAt":3159},"twilio-agent-augmentation-architect","augment human agents with AI intelligence","Planning skill for augmenting human agents with real-time AI intelligence. Qualifies the developer's use case across coaching, compliance, QA, and routing to recommend the right Conversation Intelligence + Conversation Memory + TaskRouter architecture. Handles both \"I want to add AI coaching to my call center\" and \"configure Conversation Intelligence operators for script adherence.\"\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3146,3149,3152,3155,3158],{"name":3147,"slug":3148,"type":15},"Agents","agents",{"name":3150,"slug":3151,"type":15},"AI","ai",{"name":3153,"slug":3154,"type":15},"Coaching","coaching",{"name":3156,"slug":3157,"type":15},"QA","qa",{"name":9,"slug":8,"type":15},"2026-07-17T06:07:58.250609",{"slug":3161,"name":3161,"fn":3162,"description":3163,"org":3164,"tags":3165,"stars":23,"repoUrl":24,"updatedAt":3170},"twilio-agent-connect","connect AI agents to Twilio channels","Connect third-party AI agents (OpenAI, Bedrock, LangChain, Microsoft Foundry) to Twilio's communication channels using the Twilio Agent Connect SDK. Covers identity resolution, memory and context management via Conversation Memory, conversation orchestration via Conversation Orchestrator, multi-channel handling (Voice, SMS, RCS, WhatsApp, Chat), and AI-to-human escalation. Use this skill when integrating an existing LLM agent with Twilio services.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3166,3167,3168,3169],{"name":3147,"slug":3148,"type":15},{"name":20,"slug":21,"type":15},{"name":3134,"slug":3135,"type":15},{"name":9,"slug":8,"type":15},"2026-07-17T06:06:05.217098",{"slug":3172,"name":3172,"fn":3173,"description":3174,"org":3175,"tags":3176,"stars":23,"repoUrl":24,"updatedAt":3182},"twilio-ai-agent-architect","plan Twilio conversational AI agents","Planning skill for AI-powered conversational agents. Qualifies the developer's use case across outcome sophistication, entry point, and customer profile to recommend the right Twilio Conversations architecture and implementation skills. Handles both high-level requests (\"build me a voice AI assistant\") and specific ones (\"integrate ConversationRelay with my OpenAI backend\").\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3177,3178,3181],{"name":3147,"slug":3148,"type":15},{"name":3179,"slug":3180,"type":15},"Architecture","architecture",{"name":9,"slug":8,"type":15},"2026-07-17T06:07:48.883723",{"slug":3184,"name":3184,"fn":3185,"description":3186,"org":3187,"tags":3188,"stars":23,"repoUrl":24,"updatedAt":3197},"twilio-call-recordings","record and manage Twilio voice calls","Record Twilio voice calls correctly. Covers the critical distinction between Record verb (voicemail) and Dial record (call recording), dual-channel for QA, mid-call pause for PCI, Conference recording, and the ConversationRelay workaround. Use this skill whenever you need to capture call audio for compliance, QA, or analytics.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3189,3192,3195,3196],{"name":3190,"slug":3191,"type":15},"Audio","audio",{"name":3193,"slug":3194,"type":15},"Compliance","compliance",{"name":3156,"slug":3157,"type":15},{"name":9,"slug":8,"type":15},"2026-07-17T06:07:55.268412",{"slug":3199,"name":3199,"fn":3200,"description":3201,"org":3202,"tags":3203,"stars":23,"repoUrl":24,"updatedAt":3214},"twilio-cli-reference","manage Twilio resources via CLI","Twilio CLI reference for managing Twilio resources from the terminal. Covers installation, credential profiles, phone number provisioning, sending SMS and email, webhook configuration, local development with a tunneling service, debugging with watch and logs, serverless deployment, and plugin ecosystem. Use when the developer asks to \"just do it\", \"set this up\", \"run a command\", mentions \"CLI\", \"command line\", or \"terminal\", or when an AI agent can execute a task directly instead of writing application code.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3204,3207,3210,3213],{"name":3205,"slug":3206,"type":15},"CLI","cli",{"name":3208,"slug":3209,"type":15},"Local Development","local-development",{"name":3211,"slug":3212,"type":15},"Operations","operations",{"name":9,"slug":8,"type":15},"2026-07-17T06:07:54.925664",{"slug":3216,"name":3216,"fn":3217,"description":3218,"org":3219,"tags":3220,"stars":23,"repoUrl":24,"updatedAt":3228},"twilio-compliance-onboarding","manage Twilio messaging and voice compliance","Registrations required BEFORE Twilio traffic works. Covers messaging programs (A2P 10DLC, toll-free verification, WhatsApp WABA, RCS, short code, alphanumeric sender) and voice trust programs (STIR\u002FSHAKEN, Voice Integrity, Branded Calling, CNAM). Each number\u002Fsender type has its own program — registration blocks traffic until complete.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3221,3222,3223,3224,3225],{"name":3193,"slug":3194,"type":15},{"name":17,"slug":18,"type":15},{"name":3137,"slug":3138,"type":15},{"name":9,"slug":8,"type":15},{"name":3226,"slug":3227,"type":15},"WhatsApp","whatsapp","2026-07-17T06:05:47.897229",57,{"items":3231,"total":3229},[3232,3238,3246,3253,3259,3266,3273,3281,3297,3310,3326,3344],{"slug":312,"name":312,"fn":3128,"description":3129,"org":3233,"tags":3234,"stars":23,"repoUrl":24,"updatedAt":3139},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3235,3236,3237],{"name":20,"slug":21,"type":15},{"name":3134,"slug":3135,"type":15},{"name":3137,"slug":3138,"type":15},{"slug":3141,"name":3141,"fn":3142,"description":3143,"org":3239,"tags":3240,"stars":23,"repoUrl":24,"updatedAt":3159},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3241,3242,3243,3244,3245],{"name":3147,"slug":3148,"type":15},{"name":3150,"slug":3151,"type":15},{"name":3153,"slug":3154,"type":15},{"name":3156,"slug":3157,"type":15},{"name":9,"slug":8,"type":15},{"slug":3161,"name":3161,"fn":3162,"description":3163,"org":3247,"tags":3248,"stars":23,"repoUrl":24,"updatedAt":3170},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3249,3250,3251,3252],{"name":3147,"slug":3148,"type":15},{"name":20,"slug":21,"type":15},{"name":3134,"slug":3135,"type":15},{"name":9,"slug":8,"type":15},{"slug":3172,"name":3172,"fn":3173,"description":3174,"org":3254,"tags":3255,"stars":23,"repoUrl":24,"updatedAt":3182},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3256,3257,3258],{"name":3147,"slug":3148,"type":15},{"name":3179,"slug":3180,"type":15},{"name":9,"slug":8,"type":15},{"slug":3184,"name":3184,"fn":3185,"description":3186,"org":3260,"tags":3261,"stars":23,"repoUrl":24,"updatedAt":3197},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3262,3263,3264,3265],{"name":3190,"slug":3191,"type":15},{"name":3193,"slug":3194,"type":15},{"name":3156,"slug":3157,"type":15},{"name":9,"slug":8,"type":15},{"slug":3199,"name":3199,"fn":3200,"description":3201,"org":3267,"tags":3268,"stars":23,"repoUrl":24,"updatedAt":3214},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3269,3270,3271,3272],{"name":3205,"slug":3206,"type":15},{"name":3208,"slug":3209,"type":15},{"name":3211,"slug":3212,"type":15},{"name":9,"slug":8,"type":15},{"slug":3216,"name":3216,"fn":3217,"description":3218,"org":3274,"tags":3275,"stars":23,"repoUrl":24,"updatedAt":3228},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3276,3277,3278,3279,3280],{"name":3193,"slug":3194,"type":15},{"name":17,"slug":18,"type":15},{"name":3137,"slug":3138,"type":15},{"name":9,"slug":8,"type":15},{"name":3226,"slug":3227,"type":15},{"slug":3282,"name":3282,"fn":3283,"description":3284,"org":3285,"tags":3286,"stars":23,"repoUrl":24,"updatedAt":3296},"twilio-compliance-traffic","ensure compliance for Twilio messaging traffic","Rules you must follow for Twilio messaging and voice traffic. Covers TCPA (consent tiers, quiet hours, DNC), GDPR (EU consent, right to deletion), PCI DSS (payment recording, Pay verb), HIPAA (BAA, PHI), FDCPA (debt collection limits), CAN-SPAM, WhatsApp policies, SHAKEN\u002FSTIR, and consent management patterns. Use this skill proactively when developers have working traffic to ensure they follow the rules.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3287,3288,3289,3292,3295],{"name":3193,"slug":3194,"type":15},{"name":17,"slug":18,"type":15},{"name":3290,"slug":3291,"type":15},"Regulatory Compliance","regulatory-compliance",{"name":3293,"slug":3294,"type":15},"Security","security",{"name":9,"slug":8,"type":15},"2026-07-17T06:07:55.952779",{"slug":3298,"name":3298,"fn":3299,"description":3300,"org":3301,"tags":3302,"stars":23,"repoUrl":24,"updatedAt":3309},"twilio-conference-calls","build multi-party calls with Twilio Conference","Build multi-party calls using Twilio Conference. Covers warm transfer, cold transfer, coaching (whisper), hold vs mute, participant modes, and supervisor barge. Use this skill for any contact center, support line, or scenario requiring transfers, holds, or multi-party calls.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3303,3304,3305,3308],{"name":3190,"slug":3191,"type":15},{"name":3134,"slug":3135,"type":15},{"name":3306,"slug":3307,"type":15},"Meetings","meetings",{"name":9,"slug":8,"type":15},"2026-07-17T06:07:55.603708",{"slug":3311,"name":3311,"fn":3312,"description":3313,"org":3314,"tags":3315,"stars":23,"repoUrl":24,"updatedAt":3325},"twilio-content-template-builder","create and send message templates with Twilio","Create, manage, and send message templates using Twilio's Content API. Covers template creation for WhatsApp, SMS, RCS, and MMS; variable usage; WhatsApp Meta approval; and sending templates via ContentSid. Use this skill when building structured messages that require pre-approval or consistent formatting across channels.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3316,3319,3320,3321,3324],{"name":3317,"slug":3318,"type":15},"Email","email",{"name":17,"slug":18,"type":15},{"name":3137,"slug":3138,"type":15},{"name":3322,"slug":3323,"type":15},"Templates","templates",{"name":9,"slug":8,"type":15},"2026-07-17T06:04:26.637309",{"slug":3327,"name":3327,"fn":3328,"description":3329,"org":3330,"tags":3331,"stars":23,"repoUrl":24,"updatedAt":3343},"twilio-conversation-intelligence","build conversation intelligence pipelines","Twilio Conversation Intelligence development guide. Use when building real-time or post-call conversation analysis, language operator pipelines, sentiment analysis, agent assist, cross-channel analytics, or querying aggregated conversation insights (sentiment trends, escalation rates, dashboards).",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3332,3333,3336,3339,3342],{"name":3147,"slug":3148,"type":15},{"name":3334,"slug":3335,"type":15},"Analytics","analytics",{"name":3337,"slug":3338,"type":15},"Monitoring","monitoring",{"name":3340,"slug":3341,"type":15},"NLP","nlp",{"name":9,"slug":8,"type":15},"2026-07-17T06:07:52.545387",{"slug":3345,"name":3345,"fn":3346,"description":3347,"org":3348,"tags":3349,"stars":23,"repoUrl":24,"updatedAt":3355},"twilio-conversation-memory","manage conversation memory with Twilio","Store and retrieve conversation context using Twilio Conversation Memory. Covers Memory Store provisioning, profile management, traits, observations, conversation summaries, and semantic Recall. Use this skill to give AI agents or human agents persistent memory of conversations across sessions and channels.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3350,3351,3354],{"name":3147,"slug":3148,"type":15},{"name":3352,"slug":3353,"type":15},"Memory","memory",{"name":9,"slug":8,"type":15},"2026-07-17T06:04:19.526724"]