[{"data":1,"prerenderedAt":4008},["ShallowReactive",2],{"navigation_docs":3,"-docs-reference-assistant":968,"-docs-reference-assistant-surround":4003},[4,27,63,129,287,311,893,902,950,964],{"title":5,"path":6,"stem":7,"children":8,"order":10,"icon":11},"Overview","\u002Fdocs\u002Foverview","docs\u002F1.overview\u002Findex",[9,12,18,24],{"title":5,"path":6,"stem":7,"order":10,"icon":11},1,"i-lucide-info",{"title":13,"path":14,"stem":15,"order":16,"icon":17},"Getting Started","\u002Fdocs\u002Foverview\u002Fgetting-started","docs\u002F1.overview\u002F2.getting-started",2,"i-lucide-rocket",{"title":19,"path":20,"stem":21,"order":22,"icon":23},"Contributing","\u002Fdocs\u002Foverview\u002Fcontributing","docs\u002F1.overview\u002F3.contributing",3,"i-lucide-heart",{"title":5,"path":25,"stem":26,"order":10},"\u002Fdocs\u002Foverview\u002F_dir","docs\u002F1.overview\u002F_dir",{"title":28,"path":29,"stem":30,"children":31,"page":62},"Concepts","\u002Fdocs\u002Fconcepts","docs\u002F2.concepts",[32,37,42,47,53,59],{"title":33,"path":34,"stem":35,"order":10,"icon":36},"Events","\u002Fdocs\u002Fconcepts\u002Fevents","docs\u002F2.concepts\u002F1.events","i-lucide-zap",{"title":38,"path":39,"stem":40,"order":16,"icon":41},"Transports","\u002Fdocs\u002Fconcepts\u002Ftransports","docs\u002F2.concepts\u002F2.transports","i-lucide-network",{"title":43,"path":44,"stem":45,"order":22,"icon":46},"Module System","\u002Fdocs\u002Fconcepts\u002Fmodules","docs\u002F2.concepts\u002F3.modules","i-lucide-puzzle",{"title":48,"path":49,"stem":50,"order":51,"icon":52},"Flows","\u002Fdocs\u002Fconcepts\u002Fflows","docs\u002F2.concepts\u002F4.flows",4,"i-lucide-workflow",{"title":54,"path":55,"stem":56,"order":57,"icon":58},"Scheduler","\u002Fdocs\u002Fconcepts\u002Fscheduler","docs\u002F2.concepts\u002F5.scheduler",5,"i-lucide-clock",{"title":28,"path":60,"stem":61,"order":16},"\u002Fdocs\u002Fconcepts\u002F_dir","docs\u002F2.concepts\u002F_dir",false,{"title":64,"path":65,"stem":66,"children":67,"page":62},"Guides","\u002Fdocs\u002Fguides","docs\u002F3.guides",[68,73,77,81,85,89,93,98,104,110,116,122,126],{"title":69,"path":70,"stem":71,"order":10,"icon":72},"Creating a Go App","\u002Fdocs\u002Fguides\u002Fcreating-go-app","docs\u002F3.guides\u002F1.creating-go-app","i-lucide-terminal",{"title":74,"path":75,"stem":76},"E2E tests & demo videos","\u002Fdocs\u002Fguides\u002Fe2e-and-demo-videos","docs\u002F3.guides\u002F10.e2e-and-demo-videos",{"title":78,"path":79,"stem":80,"icon":17},"Deploying to production","\u002Fdocs\u002Fguides\u002Fdeploying-to-production","docs\u002F3.guides\u002F11.deploying-to-production",{"title":82,"path":83,"stem":84,"order":16,"icon":46},"Creating a Go Module","\u002Fdocs\u002Fguides\u002Fcreating-go-module","docs\u002F3.guides\u002F2.creating-go-module",{"title":86,"path":87,"stem":88,"order":22,"icon":36},"Adding Events","\u002Fdocs\u002Fguides\u002Fadding-events-to-go-module","docs\u002F3.guides\u002F3.adding-events-to-go-module",{"title":90,"path":91,"stem":92,"order":51,"icon":52},"FlowDSL to Service","\u002Fdocs\u002Fguides\u002Fflowdsl-to-redelay","docs\u002F3.guides\u002F4.flowdsl-to-redelay",{"title":94,"path":95,"stem":96,"order":57,"icon":97},"Choosing a Transport","\u002Fdocs\u002Fguides\u002Fchoosing-a-transport","docs\u002F3.guides\u002F5.choosing-a-transport","i-lucide-git-branch",{"title":99,"path":100,"stem":101,"order":102,"icon":103},"Module Browser (\u002Fmodules)","\u002Fdocs\u002Fguides\u002Fmodules-browser","docs\u002F3.guides\u002F6.modules-browser",6,"i-lucide-layout-dashboard",{"title":105,"path":106,"stem":107,"order":108,"icon":109},"Running Flows","\u002Fdocs\u002Fguides\u002Frunning-flows","docs\u002F3.guides\u002F7.running-flows",7,"i-lucide-play-circle",{"title":111,"path":112,"stem":113,"order":114,"icon":115},"Trace + Live Observability","\u002Fdocs\u002Fguides\u002Fobservability","docs\u002F3.guides\u002F8.observability",8,"i-lucide-activity",{"title":117,"path":118,"stem":119,"order":120,"icon":121},"Project AI Assistant","\u002Fdocs\u002Fguides\u002Fai-assistant","docs\u002F3.guides\u002F9.ai-assistant",9,"i-lucide-sparkles",{"title":123,"path":124,"stem":125},"Debug taps — trace live data through any node","\u002Fdocs\u002Fguides\u002Fdebug-taps","docs\u002F3.guides\u002F9.debug-taps",{"title":64,"path":127,"stem":128,"order":22},"\u002Fdocs\u002Fguides\u002F_dir","docs\u002F3.guides\u002F_dir",{"title":130,"path":131,"stem":132,"children":133,"page":62},"Reference","\u002Fdocs\u002Freference","docs\u002F4.reference",[134,139,143,148,153,158,163,168,172,177,182,187,193,199,205,210,215,219,225,230,236,242,247,253,259,263,267,273,278,284],{"title":135,"path":136,"stem":137,"order":10,"icon":138},"Go Framework","\u002Fdocs\u002Freference\u002Fgo-framework","docs\u002F4.reference\u002F01.go-framework","i-simple-icons-go",{"title":140,"path":141,"stem":142,"order":16,"icon":46},"Built-in Modules","\u002Fdocs\u002Freference\u002Fgo-modules","docs\u002F4.reference\u002F02.go-modules",{"title":144,"path":145,"stem":146,"order":22,"icon":147},"Domain Addon Modules","\u002Fdocs\u002Freference\u002Fgo-modules-addons","docs\u002F4.reference\u002F03.go-modules-addons","i-lucide-blocks",{"title":149,"path":150,"stem":151,"order":51,"icon":152},"Go Events","\u002Fdocs\u002Freference\u002Fgo-events","docs\u002F4.reference\u002F04.go-events","i-lucide-radio",{"title":154,"path":155,"stem":156,"order":57,"icon":157},"Email Module","\u002Fdocs\u002Freference\u002Fgo-module-email","docs\u002F4.reference\u002F05.go-module-email","i-lucide-mail",{"title":159,"path":160,"stem":161,"order":102,"icon":162},"Go Core & IR","\u002Fdocs\u002Freference\u002Fgo-core","docs\u002F4.reference\u002F06.go-core","i-lucide-cpu",{"title":164,"path":165,"stem":166,"order":108,"icon":167},"Module Definition Files","\u002Fdocs\u002Freference\u002Fgo-module-files","docs\u002F4.reference\u002F07.go-module-files","i-lucide-file-code",{"title":169,"path":170,"stem":171,"order":114,"icon":72},"CLI Reference","\u002Fdocs\u002Freference\u002Fgo-cli","docs\u002F4.reference\u002F08.go-cli",{"title":173,"path":174,"stem":175,"order":120,"icon":176},"Go Formats","\u002Fdocs\u002Freference\u002Fgo-formats","docs\u002F4.reference\u002F09.go-formats","i-lucide-file-json",{"title":178,"path":179,"stem":180,"order":181,"icon":152},"AsyncAPI Module","\u002Fdocs\u002Freference\u002Fgo-asyncapi","docs\u002F4.reference\u002F10.go-asyncapi",10,{"title":183,"path":184,"stem":185,"order":186,"icon":52},"Go FlowDSL","\u002Fdocs\u002Freference\u002Fgo-flowdsl","docs\u002F4.reference\u002F11.go-flowdsl",11,{"title":188,"path":189,"stem":190,"order":191,"icon":192},"FlowDSL Examples","\u002Fdocs\u002Freference\u002Fflowdsl-examples","docs\u002F4.reference\u002F12.flowdsl-examples",12,"i-lucide-file-code-2",{"title":194,"path":195,"stem":196,"order":197,"icon":198},"FlowDSL Sync","\u002Fdocs\u002Freference\u002Fflowdsl-sync","docs\u002F4.reference\u002F13.flowdsl-sync",13,"i-lucide-refresh-cw",{"title":200,"path":201,"stem":202,"order":203,"icon":204},"Node.js Framework","\u002Fdocs\u002Freference\u002Fjs-framework","docs\u002F4.reference\u002F14.js-framework",14,"i-simple-icons-nodedotjs",{"title":206,"path":207,"stem":208,"order":203,"icon":209},"Python Framework","\u002Fdocs\u002Freference\u002Fpy-framework","docs\u002F4.reference\u002F14.py-framework","i-simple-icons-python",{"title":211,"path":212,"stem":213,"order":214,"icon":204},"Node.js Events","\u002Fdocs\u002Freference\u002Fjs-events","docs\u002F4.reference\u002F15.js-events",15,{"title":216,"path":217,"stem":218,"order":214,"icon":209},"Python Events","\u002Fdocs\u002Freference\u002Fpy-events","docs\u002F4.reference\u002F15.py-events",{"title":220,"path":221,"stem":222,"order":223,"icon":224},"go-ai — LLM Providers, Guard, Ledger","\u002Fdocs\u002Freference\u002Fgo-ai","docs\u002F4.reference\u002F16.go-ai",16,"i-lucide-brain-circuit",{"title":226,"path":227,"stem":228,"order":229,"icon":41},"Infrastructure Modules","\u002Fdocs\u002Freference\u002Fgeneric-infra-modules","docs\u002F4.reference\u002F17.generic-infra-modules",17,{"title":231,"path":232,"stem":233,"order":234,"icon":235},"Flow Templates","\u002Fdocs\u002Freference\u002Fflow-templates","docs\u002F4.reference\u002F18.flow-templates",18,"i-lucide-library-big",{"title":237,"path":238,"stem":239,"order":240,"icon":241},"Assistant (chat + handoff)","\u002Fdocs\u002Freference\u002Fassistant","docs\u002F4.reference\u002F19.assistant",19,"i-lucide-messages-square",{"title":243,"path":244,"stem":245,"order":246,"icon":41},"Coordination","\u002Fdocs\u002Freference\u002Fcoordination","docs\u002F4.reference\u002F20.coordination",20,{"title":248,"path":249,"stem":250,"order":251,"icon":252},"Search (vector)","\u002Fdocs\u002Freference\u002Fsearch","docs\u002F4.reference\u002F21.search",21,"i-lucide-search",{"title":254,"path":255,"stem":256,"order":257,"icon":258},"Profiles","\u002Fdocs\u002Freference\u002Fprofiles","docs\u002F4.reference\u002F22.profiles",22,"i-lucide-bookmark",{"title":260,"path":261,"stem":262},"Flow-driven HTTP endpoints","\u002Fdocs\u002Freference\u002Fflow-driven-endpoints","docs\u002F4.reference\u002F23.flow-driven-endpoints",{"title":264,"path":265,"stem":266},"Deployments","\u002Fdocs\u002Freference\u002Fdeployments","docs\u002F4.reference\u002F24.deployments",{"title":268,"path":269,"stem":270,"order":271,"icon":272},"i18n (translations)","\u002Fdocs\u002Freference\u002Fi18n","docs\u002F4.reference\u002F25.i18n",25,"i-lucide-languages",{"title":274,"path":275,"stem":276,"order":277,"icon":152},"WebSockets","\u002Fdocs\u002Freference\u002Fwebsockets","docs\u002F4.reference\u002F26.websockets",26,{"title":279,"path":280,"stem":281,"order":282,"icon":283},"Localized content","\u002Fdocs\u002Freference\u002Flocalized-content","docs\u002F4.reference\u002F27.localized-content",27,"i-lucide-file-text",{"title":130,"path":285,"stem":286,"order":51},"\u002Fdocs\u002Freference\u002F_dir","docs\u002F4.reference\u002F_dir",{"title":288,"path":289,"stem":290,"children":291,"page":62},"Integrations","\u002Fdocs\u002Fintegrations","docs\u002F5.integrations",[292,296,300,304,308],{"title":293,"path":294,"stem":295,"order":10,"icon":52},"FlowDSL","\u002Fdocs\u002Fintegrations\u002Fflowdsl","docs\u002F5.integrations\u002F1.flowdsl",{"title":297,"path":298,"stem":299,"order":16,"icon":283},"OpenAPI","\u002Fdocs\u002Fintegrations\u002Fopenapi","docs\u002F5.integrations\u002F2.openapi",{"title":301,"path":302,"stem":303,"order":22,"icon":152},"AsyncAPI","\u002Fdocs\u002Fintegrations\u002Fasyncapi","docs\u002F5.integrations\u002F3.asyncapi",{"title":305,"path":306,"stem":307},"MCP Integration","\u002Fdocs\u002Fintegrations\u002Fmcp","docs\u002F5.integrations\u002F4.mcp",{"title":288,"path":309,"stem":310,"order":57},"\u002Fdocs\u002Fintegrations\u002F_dir","docs\u002F5.integrations\u002F_dir",{"title":312,"path":313,"stem":314,"children":315},"FlowDSL Node Catalog","\u002Fdocs\u002Fnodes","docs\u002F5.nodes\u002Findex",[316,317,321,325,329,333,337,341,345,349,353,357,361,365,369,373,377,381,385,389,393,397,401,405,409,413,417,421,425,429,433,437,441,445,449,453,457,461,465,469,473,477,481,485,489,493,497,501,505,509,513,517,521,525,529,533,537,541,545,549,553,557,561,565,569,573,577,581,585,589,593,597,601,605,609,613,617,621,625,629,633,637,641,645,649,653,657,661,665,669,673,677,681,685,689,693,697,701,705,709,713,717,721,725,729,733,737,741,745,749,753,757,761,765,769,773,777,781,785,789,793,797,801,805,809,813,817,821,825,829,833,837,841,845,849,853,857,861,865,869,873,877,881,885,889],{"title":312,"path":313,"stem":314},{"title":318,"path":319,"stem":320,"order":57},"Node Catalog","\u002Fdocs\u002Fnodes\u002F_dir","docs\u002F5.nodes\u002F_dir",{"title":322,"path":323,"stem":324},"Record Alert","\u002Fdocs\u002Fnodes\u002Falerts_record","docs\u002F5.nodes\u002Falerts_record",{"title":326,"path":327,"stem":328},"Log to API Log","\u002Fdocs\u002Fnodes\u002Fapilog_record","docs\u002F5.nodes\u002Fapilog_record",{"title":330,"path":331,"stem":332},"ClickHouse Exec","\u002Fdocs\u002Fnodes\u002Fclickhouse_exec","docs\u002F5.nodes\u002Fclickhouse_exec",{"title":334,"path":335,"stem":336},"ClickHouse Insert","\u002Fdocs\u002Fnodes\u002Fclickhouse_insert","docs\u002F5.nodes\u002Fclickhouse_insert",{"title":338,"path":339,"stem":340},"ClickHouse Query","\u002Fdocs\u002Fnodes\u002Fclickhouse_query","docs\u002F5.nodes\u002Fclickhouse_query",{"title":342,"path":343,"stem":344},"Array Op","\u002Fdocs\u002Fnodes\u002Fcore_array-ops","docs\u002F5.nodes\u002Fcore_array-ops",{"title":346,"path":347,"stem":348},"Assert","\u002Fdocs\u002Fnodes\u002Fcore_assert","docs\u002F5.nodes\u002Fcore_assert",{"title":350,"path":351,"stem":352},"Audit Emit","\u002Fdocs\u002Fnodes\u002Fcore_audit-emit","docs\u002F5.nodes\u002Fcore_audit-emit",{"title":354,"path":355,"stem":356},"Catch","\u002Fdocs\u002Fnodes\u002Fcore_catch","docs\u002F5.nodes\u002Fcore_catch",{"title":358,"path":359,"stem":360},"DateTime","\u002Fdocs\u002Fnodes\u002Fcore_datetime","docs\u002F5.nodes\u002Fcore_datetime",{"title":362,"path":363,"stem":364},"Dead Letter","\u002Fdocs\u002Fnodes\u002Fcore_dead-letter","docs\u002F5.nodes\u002Fcore_dead-letter",{"title":366,"path":367,"stem":368},"Delay","\u002Fdocs\u002Fnodes\u002Fcore_delay","docs\u002F5.nodes\u002Fcore_delay",{"title":370,"path":371,"stem":372},"ForEach","\u002Fdocs\u002Fnodes\u002Fcore_foreach","docs\u002F5.nodes\u002Fcore_foreach",{"title":374,"path":375,"stem":376},"Idempotency Key","\u002Fdocs\u002Fnodes\u002Fcore_idempotency-key","docs\u002F5.nodes\u002Fcore_idempotency-key",{"title":378,"path":379,"stem":380},"If","\u002Fdocs\u002Fnodes\u002Fcore_if","docs\u002F5.nodes\u002Fcore_if",{"title":382,"path":383,"stem":384},"Inspect","\u002Fdocs\u002Fnodes\u002Fcore_inspect","docs\u002F5.nodes\u002Fcore_inspect",{"title":386,"path":387,"stem":388},"JSON Merge","\u002Fdocs\u002Fnodes\u002Fcore_json-merge","docs\u002F5.nodes\u002Fcore_json-merge",{"title":390,"path":391,"stem":392},"JSON Schema Validate","\u002Fdocs\u002Fnodes\u002Fcore_json-schema-validate","docs\u002F5.nodes\u002Fcore_json-schema-validate",{"title":394,"path":395,"stem":396},"JSONPath Extract","\u002Fdocs\u002Fnodes\u002Fcore_jsonpath-extract","docs\u002F5.nodes\u002Fcore_jsonpath-extract",{"title":398,"path":399,"stem":400},"Log","\u002Fdocs\u002Fnodes\u002Fcore_log","docs\u002F5.nodes\u002Fcore_log",{"title":402,"path":403,"stem":404},"Math","\u002Fdocs\u002Fnodes\u002Fcore_math","docs\u002F5.nodes\u002Fcore_math",{"title":406,"path":407,"stem":408},"Merge","\u002Fdocs\u002Fnodes\u002Fcore_merge","docs\u002F5.nodes\u002Fcore_merge",{"title":410,"path":411,"stem":412},"Metric Counter","\u002Fdocs\u002Fnodes\u002Fcore_metric-counter","docs\u002F5.nodes\u002Fcore_metric-counter",{"title":414,"path":415,"stem":416},"Metric Gauge","\u002Fdocs\u002Fnodes\u002Fcore_metric-gauge","docs\u002F5.nodes\u002Fcore_metric-gauge",{"title":418,"path":419,"stem":420},"Mock","\u002Fdocs\u002Fnodes\u002Fcore_mock","docs\u002F5.nodes\u002Fcore_mock",{"title":422,"path":423,"stem":424},"No-op","\u002Fdocs\u002Fnodes\u002Fcore_noop","docs\u002F5.nodes\u002Fcore_noop",{"title":426,"path":427,"stem":428},"Object Omit","\u002Fdocs\u002Fnodes\u002Fcore_object-omit","docs\u002F5.nodes\u002Fcore_object-omit",{"title":430,"path":431,"stem":432},"Object Pick","\u002Fdocs\u002Fnodes\u002Fcore_object-pick","docs\u002F5.nodes\u002Fcore_object-pick",{"title":434,"path":435,"stem":436},"Parallel Fan-Out","\u002Fdocs\u002Fnodes\u002Fcore_parallel","docs\u002F5.nodes\u002Fcore_parallel",{"title":438,"path":439,"stem":440},"Raise","\u002Fdocs\u002Fnodes\u002Fcore_raise","docs\u002F5.nodes\u002Fcore_raise",{"title":442,"path":443,"stem":444},"Rate Limit Check","\u002Fdocs\u002Fnodes\u002Fcore_rate-limit-check","docs\u002F5.nodes\u002Fcore_rate-limit-check",{"title":446,"path":447,"stem":448},"Regex Extract","\u002Fdocs\u002Fnodes\u002Fcore_regex-extract","docs\u002F5.nodes\u002Fcore_regex-extract",{"title":450,"path":451,"stem":452},"Require Fields","\u002Fdocs\u002Fnodes\u002Fcore_require-fields","docs\u002F5.nodes\u002Fcore_require-fields",{"title":454,"path":455,"stem":456},"Rethrow","\u002Fdocs\u002Fnodes\u002Fcore_rethrow","docs\u002F5.nodes\u002Fcore_rethrow",{"title":458,"path":459,"stem":460},"Return","\u002Fdocs\u002Fnodes\u002Fcore_return","docs\u002F5.nodes\u002Fcore_return",{"title":462,"path":463,"stem":464},"HMAC Signature Verify","\u002Fdocs\u002Fnodes\u002Fcore_signature-verify","docs\u002F5.nodes\u002Fcore_signature-verify",{"title":466,"path":467,"stem":468},"String Op","\u002Fdocs\u002Fnodes\u002Fcore_string-ops","docs\u002F5.nodes\u002Fcore_string-ops",{"title":470,"path":471,"stem":472},"Subflow Invoke","\u002Fdocs\u002Fnodes\u002Fcore_subflow-invoke","docs\u002F5.nodes\u002Fcore_subflow-invoke",{"title":474,"path":475,"stem":476},"Switch","\u002Fdocs\u002Fnodes\u002Fcore_switch","docs\u002F5.nodes\u002Fcore_switch",{"title":478,"path":479,"stem":480},"Template Render","\u002Fdocs\u002Fnodes\u002Fcore_template-render","docs\u002F5.nodes\u002Fcore_template-render",{"title":482,"path":483,"stem":484},"Throttle","\u002Fdocs\u002Fnodes\u002Fcore_throttle","docs\u002F5.nodes\u002Fcore_throttle",{"title":486,"path":487,"stem":488},"Timeout","\u002Fdocs\u002Fnodes\u002Fcore_timeout","docs\u002F5.nodes\u002Fcore_timeout",{"title":490,"path":491,"stem":492},"Type Cast","\u002Fdocs\u002Fnodes\u002Fcore_type-cast","docs\u002F5.nodes\u002Fcore_type-cast",{"title":494,"path":495,"stem":496},"Webhook Respond","\u002Fdocs\u002Fnodes\u002Fcore_webhook-respond","docs\u002F5.nodes\u002Fcore_webhook-respond",{"title":498,"path":499,"stem":500},"File Delete","\u002Fdocs\u002Fnodes\u002Ffilesys_delete","docs\u002F5.nodes\u002Ffilesys_delete",{"title":502,"path":503,"stem":504},"Directory List","\u002Fdocs\u002Fnodes\u002Ffilesys_list","docs\u002F5.nodes\u002Ffilesys_list",{"title":506,"path":507,"stem":508},"File Read","\u002Fdocs\u002Fnodes\u002Ffilesys_read","docs\u002F5.nodes\u002Ffilesys_read",{"title":510,"path":511,"stem":512},"File Stat","\u002Fdocs\u002Fnodes\u002Ffilesys_stat","docs\u002F5.nodes\u002Ffilesys_stat",{"title":514,"path":515,"stem":516},"File Write","\u002Fdocs\u002Fnodes\u002Ffilesys_write","docs\u002F5.nodes\u002Ffilesys_write",{"title":518,"path":519,"stem":520},"FTP Delete","\u002Fdocs\u002Fnodes\u002Fftp_delete","docs\u002F5.nodes\u002Fftp_delete",{"title":522,"path":523,"stem":524},"FTP Download","\u002Fdocs\u002Fnodes\u002Fftp_download","docs\u002F5.nodes\u002Fftp_download",{"title":526,"path":527,"stem":528},"FTP List","\u002Fdocs\u002Fnodes\u002Fftp_list","docs\u002F5.nodes\u002Fftp_list",{"title":530,"path":531,"stem":532},"FTP Upload","\u002Fdocs\u002Fnodes\u002Fftp_upload","docs\u002F5.nodes\u002Fftp_upload",{"title":534,"path":535,"stem":536},"HTTP DELETE","\u002Fdocs\u002Fnodes\u002Fhttp_delete","docs\u002F5.nodes\u002Fhttp_delete",{"title":538,"path":539,"stem":540},"HTTP GET","\u002Fdocs\u002Fnodes\u002Fhttp_get","docs\u002F5.nodes\u002Fhttp_get",{"title":542,"path":543,"stem":544},"HTTP POST","\u002Fdocs\u002Fnodes\u002Fhttp_post","docs\u002F5.nodes\u002Fhttp_post",{"title":546,"path":547,"stem":548},"HTTP PUT","\u002Fdocs\u002Fnodes\u002Fhttp_put","docs\u002F5.nodes\u002Fhttp_put",{"title":550,"path":551,"stem":552},"HTTP Request","\u002Fdocs\u002Fnodes\u002Fhttp_request","docs\u002F5.nodes\u002Fhttp_request",{"title":554,"path":555,"stem":556},"Fill Translations","\u002Fdocs\u002Fnodes\u002Fi18n_fill-translations","docs\u002F5.nodes\u002Fi18n_fill-translations",{"title":558,"path":559,"stem":560},"Resolve Locale","\u002Fdocs\u002Fnodes\u002Fi18n_resolve-locale","docs\u002F5.nodes\u002Fi18n_resolve-locale",{"title":562,"path":563,"stem":564},"Translate","\u002Fdocs\u002Fnodes\u002Fi18n_translate","docs\u002F5.nodes\u002Fi18n_translate",{"title":566,"path":567,"stem":568},"Mongo AGGREGATE","\u002Fdocs\u002Fnodes\u002Fmongoops_aggregate","docs\u002F5.nodes\u002Fmongoops_aggregate",{"title":570,"path":571,"stem":572},"Mongo DELETE","\u002Fdocs\u002Fnodes\u002Fmongoops_delete","docs\u002F5.nodes\u002Fmongoops_delete",{"title":574,"path":575,"stem":576},"Mongo FIND","\u002Fdocs\u002Fnodes\u002Fmongoops_find","docs\u002F5.nodes\u002Fmongoops_find",{"title":578,"path":579,"stem":580},"Mongo FIND ONE","\u002Fdocs\u002Fnodes\u002Fmongoops_find-one","docs\u002F5.nodes\u002Fmongoops_find-one",{"title":582,"path":583,"stem":584},"Mongo INSERT","\u002Fdocs\u002Fnodes\u002Fmongoops_insert","docs\u002F5.nodes\u002Fmongoops_insert",{"title":586,"path":587,"stem":588},"Mongo UPDATE","\u002Fdocs\u002Fnodes\u002Fmongoops_update","docs\u002F5.nodes\u002Fmongoops_update",{"title":590,"path":591,"stem":592},"Postgres COPY FROM","\u002Fdocs\u002Fnodes\u002Fpostgres_copy-from","docs\u002F5.nodes\u002Fpostgres_copy-from",{"title":594,"path":595,"stem":596},"Postgres Exec","\u002Fdocs\u002Fnodes\u002Fpostgres_exec","docs\u002F5.nodes\u002Fpostgres_exec",{"title":598,"path":599,"stem":600},"Postgres Query","\u002Fdocs\u002Fnodes\u002Fpostgres_query","docs\u002F5.nodes\u002Fpostgres_query",{"title":602,"path":603,"stem":604},"Postgres Transaction","\u002Fdocs\u002Fnodes\u002Fpostgres_transaction","docs\u002F5.nodes\u002Fpostgres_transaction",{"title":606,"path":607,"stem":608},"RabbitMQ Consume","\u002Fdocs\u002Fnodes\u002Frabbitmq_consume","docs\u002F5.nodes\u002Frabbitmq_consume",{"title":610,"path":611,"stem":612},"RabbitMQ Declare","\u002Fdocs\u002Fnodes\u002Frabbitmq_declare","docs\u002F5.nodes\u002Frabbitmq_declare",{"title":614,"path":615,"stem":616},"RabbitMQ Publish","\u002Fdocs\u002Fnodes\u002Frabbitmq_publish","docs\u002F5.nodes\u002Frabbitmq_publish",{"title":618,"path":619,"stem":620},"Auth Login","\u002Fdocs\u002Fnodes\u002Fredelay_auth-login","docs\u002F5.nodes\u002Fredelay_auth-login",{"title":622,"path":623,"stem":624},"Require Permission","\u002Fdocs\u002Fnodes\u002Fredelay_auth-require-permission","docs\u002F5.nodes\u002Fredelay_auth-require-permission",{"title":626,"path":627,"stem":628},"Validate Token","\u002Fdocs\u002Fnodes\u002Fredelay_auth-validate-token","docs\u002F5.nodes\u002Fredelay_auth-validate-token",{"title":630,"path":631,"stem":632},"Render Email Template","\u002Fdocs\u002Fnodes\u002Fredelay_email-render-template","docs\u002F5.nodes\u002Fredelay_email-render-template",{"title":634,"path":635,"stem":636},"Send Email","\u002Fdocs\u002Fnodes\u002Fredelay_email-send","docs\u002F5.nodes\u002Fredelay_email-send",{"title":638,"path":639,"stem":640},"Send Templated Email","\u002Fdocs\u002Fnodes\u002Fredelay_email-send-templated","docs\u002F5.nodes\u002Fredelay_email-send-templated",{"title":642,"path":643,"stem":644},"Event Source","\u002Fdocs\u002Fnodes\u002Fredelay_event-source","docs\u002F5.nodes\u002Fredelay_event-source",{"title":646,"path":647,"stem":648},"Create Group","\u002Fdocs\u002Fnodes\u002Fredelay_groups-create-group","docs\u002F5.nodes\u002Fredelay_groups-create-group",{"title":650,"path":651,"stem":652},"Delete Group","\u002Fdocs\u002Fnodes\u002Fredelay_groups-delete-group","docs\u002F5.nodes\u002Fredelay_groups-delete-group",{"title":654,"path":655,"stem":656},"Resolve Permissions","\u002Fdocs\u002Fnodes\u002Fredelay_groups-resolve-permissions","docs\u002F5.nodes\u002Fredelay_groups-resolve-permissions",{"title":658,"path":659,"stem":660},"Update Group","\u002Fdocs\u002Fnodes\u002Fredelay_groups-update-group","docs\u002F5.nodes\u002Fredelay_groups-update-group",{"title":662,"path":663,"stem":664},"HTTP Endpoint","\u002Fdocs\u002Fnodes\u002Fredelay_http-endpoint","docs\u002F5.nodes\u002Fredelay_http-endpoint",{"title":666,"path":667,"stem":668},"JSON Stream Source","\u002Fdocs\u002Fnodes\u002Fredelay_json-stream-source","docs\u002F5.nodes\u002Fredelay_json-stream-source",{"title":670,"path":671,"stem":672},"JSON → Event","\u002Fdocs\u002Fnodes\u002Fredelay_json-to-event","docs\u002F5.nodes\u002Fredelay_json-to-event",{"title":674,"path":675,"stem":676},"Kafka Produce","\u002Fdocs\u002Fnodes\u002Fredelay_kafka-produce","docs\u002F5.nodes\u002Fredelay_kafka-produce",{"title":678,"path":679,"stem":680},"Create Short Link","\u002Fdocs\u002Fnodes\u002Fredelay_links-create","docs\u002F5.nodes\u002Fredelay_links-create",{"title":682,"path":683,"stem":684},"Delete Short Link","\u002Fdocs\u002Fnodes\u002Fredelay_links-delete","docs\u002F5.nodes\u002Fredelay_links-delete",{"title":686,"path":687,"stem":688},"Resolve Short Link","\u002Fdocs\u002Fnodes\u002Fredelay_links-resolve","docs\u002F5.nodes\u002Fredelay_links-resolve",{"title":690,"path":691,"stem":692},"LLM Chat","\u002Fdocs\u002Fnodes\u002Fredelay_llm-chat","docs\u002F5.nodes\u002Fredelay_llm-chat",{"title":694,"path":695,"stem":696},"LLM Embed","\u002Fdocs\u002Fnodes\u002Fredelay_llm-embed","docs\u002F5.nodes\u002Fredelay_llm-embed",{"title":698,"path":699,"stem":700},"LLM Guard","\u002Fdocs\u002Fnodes\u002Fredelay_llm-guard","docs\u002F5.nodes\u002Fredelay_llm-guard",{"title":702,"path":703,"stem":704},"LLM Tool Router","\u002Fdocs\u002Fnodes\u002Fredelay_llm-tool-router","docs\u002F5.nodes\u002Fredelay_llm-tool-router",{"title":706,"path":707,"stem":708},"NATS Publish","\u002Fdocs\u002Fnodes\u002Fredelay_nats-publish","docs\u002F5.nodes\u002Fredelay_nats-publish",{"title":710,"path":711,"stem":712},"Mark Notification Read","\u002Fdocs\u002Fnodes\u002Fredelay_notifications-mark-read","docs\u002F5.nodes\u002Fredelay_notifications-mark-read",{"title":714,"path":715,"stem":716},"Send Notification","\u002Fdocs\u002Fnodes\u002Fredelay_notifications-send","docs\u002F5.nodes\u002Fredelay_notifications-send",{"title":718,"path":719,"stem":720},"Redis Stream XADD","\u002Fdocs\u002Fnodes\u002Fredelay_redis-stream-publish","docs\u002F5.nodes\u002Fredelay_redis-stream-publish",{"title":722,"path":723,"stem":724},"S3 Copy Object","\u002Fdocs\u002Fnodes\u002Fredelay_s3-copy-object","docs\u002F5.nodes\u002Fredelay_s3-copy-object",{"title":726,"path":727,"stem":728},"S3 Delete Many","\u002Fdocs\u002Fnodes\u002Fredelay_s3-delete-many","docs\u002F5.nodes\u002Fredelay_s3-delete-many",{"title":730,"path":731,"stem":732},"S3 Head Object","\u002Fdocs\u002Fnodes\u002Fredelay_s3-head-object","docs\u002F5.nodes\u002Fredelay_s3-head-object",{"title":734,"path":735,"stem":736},"S3 List Objects","\u002Fdocs\u002Fnodes\u002Fredelay_s3-list-objects","docs\u002F5.nodes\u002Fredelay_s3-list-objects",{"title":738,"path":739,"stem":740},"Create Schedule","\u002Fdocs\u002Fnodes\u002Fredelay_scheduler-create-schedule","docs\u002F5.nodes\u002Fredelay_scheduler-create-schedule",{"title":742,"path":743,"stem":744},"Cron Trigger","\u002Fdocs\u002Fnodes\u002Fredelay_scheduler-cron-trigger","docs\u002F5.nodes\u002Fredelay_scheduler-cron-trigger",{"title":746,"path":747,"stem":748},"Delete Schedule","\u002Fdocs\u002Fnodes\u002Fredelay_scheduler-delete-schedule","docs\u002F5.nodes\u002Fredelay_scheduler-delete-schedule",{"title":750,"path":751,"stem":752},"Interval Trigger","\u002Fdocs\u002Fnodes\u002Fredelay_scheduler-interval-trigger","docs\u002F5.nodes\u002Fredelay_scheduler-interval-trigger",{"title":754,"path":755,"stem":756},"Search Query","\u002Fdocs\u002Fnodes\u002Fredelay_search-query","docs\u002F5.nodes\u002Fredelay_search-query",{"title":758,"path":759,"stem":760},"Search Upsert","\u002Fdocs\u002Fnodes\u002Fredelay_search-upsert","docs\u002F5.nodes\u002Fredelay_search-upsert",{"title":762,"path":763,"stem":764},"Delete Setting","\u002Fdocs\u002Fnodes\u002Fredelay_settings-delete","docs\u002F5.nodes\u002Fredelay_settings-delete",{"title":766,"path":767,"stem":768},"Get Setting","\u002Fdocs\u002Fnodes\u002Fredelay_settings-get","docs\u002F5.nodes\u002Fredelay_settings-get",{"title":770,"path":771,"stem":772},"Set Setting","\u002Fdocs\u002Fnodes\u002Fredelay_settings-set","docs\u002F5.nodes\u002Fredelay_settings-set",{"title":774,"path":775,"stem":776},"Delete File","\u002Fdocs\u002Fnodes\u002Fredelay_storage-delete","docs\u002F5.nodes\u002Fredelay_storage-delete",{"title":778,"path":779,"stem":780},"Download File","\u002Fdocs\u002Fnodes\u002Fredelay_storage-download","docs\u002F5.nodes\u002Fredelay_storage-download",{"title":782,"path":783,"stem":784},"Generate Presigned URL","\u002Fdocs\u002Fnodes\u002Fredelay_storage-presign-url","docs\u002F5.nodes\u002Fredelay_storage-presign-url",{"title":786,"path":787,"stem":788},"Upload File","\u002Fdocs\u002Fnodes\u002Fredelay_storage-upload","docs\u002F5.nodes\u002Fredelay_storage-upload",{"title":790,"path":791,"stem":792},"Subworkflow","\u002Fdocs\u002Fnodes\u002Fredelay_subworkflow","docs\u002F5.nodes\u002Fredelay_subworkflow",{"title":794,"path":795,"stem":796},"Activate User","\u002Fdocs\u002Fnodes\u002Fredelay_users-activate","docs\u002F5.nodes\u002Fredelay_users-activate",{"title":798,"path":799,"stem":800},"Create Pending User","\u002Fdocs\u002Fnodes\u002Fredelay_users-create-pending","docs\u002F5.nodes\u002Fredelay_users-create-pending",{"title":802,"path":803,"stem":804},"Create User","\u002Fdocs\u002Fnodes\u002Fredelay_users-create-user","docs\u002F5.nodes\u002Fredelay_users-create-user",{"title":806,"path":807,"stem":808},"Delete User","\u002Fdocs\u002Fnodes\u002Fredelay_users-delete-user","docs\u002F5.nodes\u002Fredelay_users-delete-user",{"title":810,"path":811,"stem":812},"Find User By Email","\u002Fdocs\u002Fnodes\u002Fredelay_users-find-by-email","docs\u002F5.nodes\u002Fredelay_users-find-by-email",{"title":814,"path":815,"stem":816},"Get User","\u002Fdocs\u002Fnodes\u002Fredelay_users-get-user","docs\u002F5.nodes\u002Fredelay_users-get-user",{"title":818,"path":819,"stem":820},"List Users","\u002Fdocs\u002Fnodes\u002Fredelay_users-list-users","docs\u002F5.nodes\u002Fredelay_users-list-users",{"title":822,"path":823,"stem":824},"Update User","\u002Fdocs\u002Fnodes\u002Fredelay_users-update-user","docs\u002F5.nodes\u002Fredelay_users-update-user",{"title":826,"path":827,"stem":828},"Request Email Verification (legacy)","\u002Fdocs\u002Fnodes\u002Fredelay_verification-request","docs\u002F5.nodes\u002Fredelay_verification-request",{"title":830,"path":831,"stem":832},"Request Email Verification","\u002Fdocs\u002Fnodes\u002Fredelay_verification-request-email","docs\u002F5.nodes\u002Fredelay_verification-request-email",{"title":834,"path":835,"stem":836},"Request SMS Verification","\u002Fdocs\u002Fnodes\u002Fredelay_verification-request-sms","docs\u002F5.nodes\u002Fredelay_verification-request-sms",{"title":838,"path":839,"stem":840},"Verify Token","\u002Fdocs\u002Fnodes\u002Fredelay_verification-verify","docs\u002F5.nodes\u002Fredelay_verification-verify",{"title":842,"path":843,"stem":844},"Redis DEL","\u002Fdocs\u002Fnodes\u002Fredisops_del","docs\u002F5.nodes\u002Fredisops_del",{"title":846,"path":847,"stem":848},"Redis EXPIRE","\u002Fdocs\u002Fnodes\u002Fredisops_expire","docs\u002F5.nodes\u002Fredisops_expire",{"title":850,"path":851,"stem":852},"Redis GET","\u002Fdocs\u002Fnodes\u002Fredisops_get","docs\u002F5.nodes\u002Fredisops_get",{"title":854,"path":855,"stem":856},"Redis HGET","\u002Fdocs\u002Fnodes\u002Fredisops_hget","docs\u002F5.nodes\u002Fredisops_hget",{"title":858,"path":859,"stem":860},"Redis HSET","\u002Fdocs\u002Fnodes\u002Fredisops_hset","docs\u002F5.nodes\u002Fredisops_hset",{"title":862,"path":863,"stem":864},"Redis INCR","\u002Fdocs\u002Fnodes\u002Fredisops_incr","docs\u002F5.nodes\u002Fredisops_incr",{"title":866,"path":867,"stem":868},"Redis LPOP","\u002Fdocs\u002Fnodes\u002Fredisops_lpop","docs\u002F5.nodes\u002Fredisops_lpop",{"title":870,"path":871,"stem":872},"Redis LPUSH","\u002Fdocs\u002Fnodes\u002Fredisops_lpush","docs\u002F5.nodes\u002Fredisops_lpush",{"title":874,"path":875,"stem":876},"Redis PUBLISH","\u002Fdocs\u002Fnodes\u002Fredisops_publish","docs\u002F5.nodes\u002Fredisops_publish",{"title":878,"path":879,"stem":880},"Redis SET","\u002Fdocs\u002Fnodes\u002Fredisops_set","docs\u002F5.nodes\u002Fredisops_set",{"title":882,"path":883,"stem":884},"SFTP Download","\u002Fdocs\u002Fnodes\u002Fsftp_download","docs\u002F5.nodes\u002Fsftp_download",{"title":886,"path":887,"stem":888},"SFTP Upload","\u002Fdocs\u002Fnodes\u002Fsftp_upload","docs\u002F5.nodes\u002Fsftp_upload",{"title":890,"path":891,"stem":892},"Send SMS","\u002Fdocs\u002Fnodes\u002Fsms_send","docs\u002F5.nodes\u002Fsms_send",{"title":894,"path":895,"stem":896,"children":897,"page":62},"Rfcs","\u002Fdocs\u002Frfcs","docs\u002F6.rfcs",[898],{"title":899,"path":900,"stem":901},"RFC 0001 — Worker Assignment for Flow Deployments","\u002Fdocs\u002Frfcs\u002F0001-worker-assignment","docs\u002F6.rfcs\u002F0001-worker-assignment",{"title":903,"path":904,"stem":905,"children":906,"page":62},"Admin","\u002Fdocs\u002Fadmin","docs\u002F7.admin",[907,912,917,922,927,932,937,941,946],{"title":5,"path":908,"stem":909,"order":910,"icon":911},"\u002Fdocs\u002Fadmin\u002Foverview","docs\u002F7.admin\u002F00.overview",0,"i-lucide-compass",{"title":913,"path":914,"stem":915,"order":10,"icon":916},"Getting started","\u002Fdocs\u002Fadmin\u002Fgetting-started","docs\u002F7.admin\u002F01.getting-started","i-lucide-play",{"title":918,"path":919,"stem":920,"order":16,"icon":921},"Layered architecture","\u002Fdocs\u002Fadmin\u002Flayered-architecture","docs\u002F7.admin\u002F02.layered-architecture","i-lucide-layers",{"title":923,"path":924,"stem":925,"order":22,"icon":926},"Building a custom admin project","\u002Fdocs\u002Fadmin\u002Fbuilding-a-custom-admin-project","docs\u002F7.admin\u002F03.building-a-custom-admin-project","i-lucide-folder-plus",{"title":928,"path":929,"stem":930,"order":51,"icon":931},"Building admin modules","\u002Fdocs\u002Fadmin\u002Fbuilding-admin-modules","docs\u002F7.admin\u002F04.building-admin-modules","i-lucide-package-plus",{"title":933,"path":934,"stem":935,"order":57,"icon":936},"Base module reference","\u002Fdocs\u002Fadmin\u002Freference-base-modules","docs\u002F7.admin\u002F05.reference-base-modules","i-lucide-boxes",{"title":938,"path":939,"stem":940,"order":102,"icon":17},"Deployment","\u002Fdocs\u002Fadmin\u002Fdeployment","docs\u002F7.admin\u002F06.deployment",{"title":942,"path":943,"stem":944,"order":108,"icon":945},"Consuming the base layer (versioned)","\u002Fdocs\u002Fadmin\u002Fconsuming-the-base-layer","docs\u002F7.admin\u002F07.consuming-the-base-layer","i-lucide-package",{"title":947,"path":948,"stem":949,"order":108},"Admin UI","\u002Fdocs\u002Fadmin\u002F_dir","docs\u002F7.admin\u002F_dir",{"title":951,"path":952,"stem":953,"children":954,"page":62},"Services","\u002Fdocs\u002Fservices","docs\u002F8.services",[955,960],{"title":956,"path":957,"stem":958,"order":10,"icon":959},"Custom development & support services","\u002Fdocs\u002Fservices\u002Fcustom-development","docs\u002F8.services\u002F1.custom-development","i-lucide-briefcase",{"title":951,"path":961,"stem":962,"icon":959,"order":963},"\u002Fdocs\u002Fservices\u002F_dir","docs\u002F8.services\u002F_dir",80,{"title":965,"path":966,"stem":967,"order":910},"Dir","\u002Fdocs\u002F_dir","docs\u002F_dir",{"id":969,"title":237,"body":970,"description":3996,"extension":3997,"links":3998,"meta":3999,"navigation":4000,"path":238,"seo":4001,"stem":239,"__hash__":4002},"docs\u002Fdocs\u002F4.reference\u002F19.assistant.md",{"type":971,"value":972,"toc":3957},"minimark",[973,978,987,1056,1059,1064,1069,1161,1168,1272,1281,1285,1295,1378,1388,1444,1455,1459,1462,1470,1488,1491,1567,1571,1583,1589,1592,1664,1667,1714,1717,1726,1751,1757,1771,1782,1787,1848,1853,1930,1939,1943,1949,1974,1985,1989,2027,2031,2034,2342,2346,2362,2372,2388,2408,2424,2443,2476,2490,2511,2518,2539,2543,2617,2621,2663,2667,2683,2689,2713,2717,2731,2735,2739,2766,2774,2859,2866,2870,2960,2964,3038,3043,3051,3058,3224,3238,3242,3264,3268,3279,3310,3316,3320,3329,3356,3371,3374,3434,3436,3442,3471,3491,3498,3502,3657,3666,3670,3881,3895,3899,3905,3909,3912,3946,3953],[974,975,977],"h1",{"id":976},"assistant","Assistant",[979,980,981,982,986],"p",{},"The assistant module (",[983,984,985],"code",{},"backend\u002Fmodules\u002Fassistant",") is the project-facing chat surface. It sits in front of a FlowDSL flow — picking the published variant, launching a run, pumping flow events as SSE frames — and owns three durable collections:",[988,989,990,1006],"table",{},[991,992,993],"thead",{},[994,995,996,1000,1003],"tr",{},[997,998,999],"th",{},"Collection",[997,1001,1002],{},"Purpose",[997,1004,1005],{},"Retention",[1007,1008,1009,1023,1036],"tbody",{},[994,1010,1011,1017,1020],{},[1012,1013,1014],"td",{},[983,1015,1016],{},"assistant_chats",[1012,1018,1019],{},"Per-session conversation history",[1012,1021,1022],{},"TTL (default 30 days)",[994,1024,1025,1030,1033],{},[1012,1026,1027],{},[983,1028,1029],{},"assistant_handoffs",[1012,1031,1032],{},"Customer escalation records",[1012,1034,1035],{},"Permanent (business audit)",[994,1037,1038,1043,1053],{},[1012,1039,1040],{},[983,1041,1042],{},"llm_usage",[1012,1044,1045,1046,1052],{},"Per-call LLM cost ledger (owned by ",[1047,1048,1049],"a",{"href":221},[983,1050,1051],{},"go-ai\u002Fledger",")",[1012,1054,1055],{},"Time-series, default 30 days",[979,1057,1058],{},"Chat + handoff are new in this release; LLM usage is cross-cutting and tracks every LLM call the app makes (not just assistant ones).",[1060,1061,1063],"h2",{"id":1062},"http-surface","HTTP surface",[1065,1066,1068],"h3",{"id":1067},"public-api-admin-api","Public (api + admin-api)",[988,1070,1071,1083],{},[991,1072,1073],{},[994,1074,1075,1078,1081],{},[997,1076,1077],{},"Method",[997,1079,1080],{},"Path",[997,1082,1002],{},[1007,1084,1085,1102,1115,1130,1146],{},[994,1086,1087,1090,1095],{},[1012,1088,1089],{},"POST",[1012,1091,1092],{},[983,1093,1094],{},"\u002Fassistant\u002Fmessages",[1012,1096,1097,1098,1101],{},"Chat SSE stream. Server echoes ",[983,1099,1100],{},"X-Assistant-Session-Id",".",[994,1103,1104,1107,1112],{},[1012,1105,1106],{},"GET",[1012,1108,1109],{},[983,1110,1111],{},"\u002Fassistant\u002Fchats\u002Fme\u002F{sessionID}",[1012,1113,1114],{},"Read-own transcript. Session id is the capability.",[994,1116,1117,1119,1124],{},[1012,1118,1089],{},[1012,1120,1121],{},[983,1122,1123],{},"\u002Fassistant\u002Fhandoff",[1012,1125,1126,1127,1101],{},"Request a human callback. Persists + emits ",[983,1128,1129],{},"assistant.handoff_requested",[994,1131,1132,1134,1139],{},[1012,1133,1106],{},[1012,1135,1136],{},[983,1137,1138],{},"\u002Fassistant\u002Fconfig",[1012,1140,1141,1142,1145],{},"Public runtime config — flow id, TTL days, anonymous allowed, and a ",[983,1143,1144],{},"capabilities"," object derived from the published flow topology (handoff\u002Fescalation\u002Fstreaming).",[994,1147,1148,1150,1155],{},[1012,1149,1089],{},[1012,1151,1152],{},[983,1153,1154],{},"\u002Fassistant\u002Freset",[1012,1156,1157,1158,1101],{},"Reseed + publish the live flow from an embedded template (superuser). ",[983,1159,1160],{},"?template=default|production",[1065,1162,1164,1165,1052],{"id":1163},"admin-only-admin-api-blank-import-backendmodulesassistantadmin","Admin-only (admin-api — blank-import ",[983,1166,1167],{},"backend\u002Fmodules\u002Fassistant\u002Fadmin",[988,1169,1170,1180],{},[991,1171,1172],{},[994,1173,1174,1176,1178],{},[997,1175,1077],{},[997,1177,1080],{},[997,1179,1002],{},[1007,1181,1182,1210,1222,1237,1249],{},[994,1183,1184,1186,1191],{},[1012,1185,1106],{},[1012,1187,1188],{},[983,1189,1190],{},"\u002Fassistant\u002Fchats",[1012,1192,1193,1194,1197,1198,1197,1201,1197,1204,1197,1207,1101],{},"List chats. Filters: ",[983,1195,1196],{},"userId",", ",[983,1199,1200],{},"flowId",[983,1202,1203],{},"variantLabel",[983,1205,1206],{},"cursor",[983,1208,1209],{},"limit",[994,1211,1212,1214,1219],{},[1012,1213,1106],{},[1012,1215,1216],{},[983,1217,1218],{},"\u002Fassistant\u002Fchats\u002F{id}",[1012,1220,1221],{},"Fetch one chat.",[994,1223,1224,1226,1231],{},[1012,1225,1106],{},[1012,1227,1228],{},[983,1229,1230],{},"\u002Fassistant\u002Fhandoffs",[1012,1232,1233,1234,1101],{},"List handoffs. Default ",[983,1235,1236],{},"status=pending",[994,1238,1239,1241,1246],{},[1012,1240,1106],{},[1012,1242,1243],{},[983,1244,1245],{},"\u002Fassistant\u002Fhandoffs\u002F{id}",[1012,1247,1248],{},"Fetch one handoff.",[994,1250,1251,1254,1258],{},[1012,1252,1253],{},"PATCH",[1012,1255,1256],{},[983,1257,1245],{},[1012,1259,1260,1261,1264,1265,1268,1269,1101],{},"Update status + notes. ",[983,1262,1263],{},"ContactedAt"," + ",[983,1266,1267],{},"ContactedBy"," stamped on transition to ",[983,1270,1271],{},"contacted",[979,1273,1274,1275,1264,1278,1101],{},"All admin routes are gated on ",[983,1276,1277],{},"admin:access",[983,1279,1280],{},"auth:active-user",[1060,1282,1284],{"id":1283},"flow-driven-capabilities","Flow-driven capabilities",[979,1286,1287,1290,1291,1101],{},[983,1288,1289],{},"GET \u002Fassistant\u002Fconfig"," walks the currently-published flow document and reports which\nfeatures the widget should expose. The widget renders buttons only for capabilities the\nflow actually implements, so ",[1292,1293,1294],"strong",{},"adding a node in Studio flips the matching UI affordance on\nwithout a frontend change",[1296,1297,1302],"pre",{"className":1298,"code":1299,"language":1300,"meta":1301,"style":1301},"language-jsonc shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"flowId\": \"assistant\",\n  \"flowName\": \"Project Assistant\",\n  \"handoffEnabled\": true,                 \u002F\u002F back-compat mirror of capabilities.handoff\n  \"anonymousAllowed\": true,\n  \"chatTtlDays\": 30,\n  \"capabilities\": {\n    \"handoff\":    true,    \u002F\u002F flow has a redelay\u002Fassistant-handoff-request node\n    \"escalation\": true,    \u002F\u002F flow has a redelay\u002Femail-send fan-out\n    \"streaming\":  false    \u002F\u002F llm-chat node has stream=true\n  }\n}\n","jsonc","",[983,1303,1304,1311,1316,1321,1329,1334,1339,1344,1352,1360,1368,1373],{"__ignoreMap":1301},[1305,1306,1308],"span",{"class":1307,"line":10},"line",[1305,1309,1310],{},"{\n",[1305,1312,1313],{"class":1307,"line":16},[1305,1314,1315],{},"  \"flowId\": \"assistant\",\n",[1305,1317,1318],{"class":1307,"line":22},[1305,1319,1320],{},"  \"flowName\": \"Project Assistant\",\n",[1305,1322,1323,1326],{"class":1307,"line":51},[1305,1324,1325],{},"  \"handoffEnabled\": true,",[1305,1327,1328],{},"                 \u002F\u002F back-compat mirror of capabilities.handoff\n",[1305,1330,1331],{"class":1307,"line":57},[1305,1332,1333],{},"  \"anonymousAllowed\": true,\n",[1305,1335,1336],{"class":1307,"line":102},[1305,1337,1338],{},"  \"chatTtlDays\": 30,\n",[1305,1340,1341],{"class":1307,"line":108},[1305,1342,1343],{},"  \"capabilities\": {\n",[1305,1345,1346,1349],{"class":1307,"line":114},[1305,1347,1348],{},"    \"handoff\":    true,",[1305,1350,1351],{},"    \u002F\u002F flow has a redelay\u002Fassistant-handoff-request node\n",[1305,1353,1354,1357],{"class":1307,"line":120},[1305,1355,1356],{},"    \"escalation\": true,",[1305,1358,1359],{},"    \u002F\u002F flow has a redelay\u002Femail-send fan-out\n",[1305,1361,1362,1365],{"class":1307,"line":181},[1305,1363,1364],{},"    \"streaming\":  false",[1305,1366,1367],{},"    \u002F\u002F llm-chat node has stream=true\n",[1305,1369,1370],{"class":1307,"line":186},[1305,1371,1372],{},"  }\n",[1305,1374,1375],{"class":1307,"line":191},[1305,1376,1377],{},"}\n",[979,1379,1380,1381,1387],{},"Detection rules (in ",[1047,1382,1386],{"href":1383,"rel":1384},"https:\u002F\u002Fgithub.com\u002Fredelay\u002Fredelay\u002Fblob\u002Fmain\u002Fbackend\u002Fmodules\u002Fassistant\u002Fcapabilities.go",[1385],"nofollow","capabilities.go","):",[988,1389,1390,1400],{},[991,1391,1392],{},[994,1393,1394,1397],{},[997,1395,1396],{},"Capability",[997,1398,1399],{},"Trigger",[1007,1401,1402,1415,1427],{},[994,1403,1404,1409],{},[1012,1405,1406],{},[983,1407,1408],{},"handoff",[1012,1410,1411,1412],{},"Any node with ",[983,1413,1414],{},"action_ref=redelay\u002Fassistant-handoff-request",[994,1416,1417,1422],{},[1012,1418,1419],{},[983,1420,1421],{},"escalation",[1012,1423,1411,1424],{},[983,1425,1426],{},"action_ref=redelay\u002Femail-send",[994,1428,1429,1434],{},[1012,1430,1431],{},[983,1432,1433],{},"streaming",[1012,1435,1436,1437,1440,1441],{},"Any ",[983,1438,1439],{},"redelay\u002Fllm-chat"," node with ",[983,1442,1443],{},"config.stream=true",[979,1445,1446,1447,1450,1451,1454],{},"Adding a new capability is a two-line change: add a field to ",[983,1448,1449],{},"AssistantCapabilities"," and\nteach ",[983,1452,1453],{},"capabilitiesFromWorkflow"," which node provides it.",[1060,1456,1458],{"id":1457},"flow-shape","Flow shape",[979,1460,1461],{},"The default assistant flow ships with a router edge so the \"Talk to a human\" button in the\nwidget surfaces as a real branch in Studio, not a hidden side channel:",[1296,1463,1468],{"className":1464,"code":1466,"language":1467},[1465],"language-text","start ──► (condition: meta.intent == \"handoff\") ──► handoff ─┐\n      \\                                                       │\n       └────────────────────────────────────────────► chat ──►├──► end\n","text",[983,1469,1466],{"__ignoreMap":1301},[979,1471,1472,1473,1476,1477,1480,1481,1483,1484,1487],{},"The widget POSTs ",[983,1474,1475],{},"meta.intent = \"handoff\""," when the user clicks the button; the edge\ncondition routes to the ",[983,1478,1479],{},"redelay\u002Fassistant-handoff-request"," node which persists the record\nand publishes ",[983,1482,1129],{},". The ",[983,1485,1486],{},"handoff-notification"," template flow\nlistens for that event and fans out via email.",[979,1489,1490],{},"Two variants are shipped:",[988,1492,1493,1506],{},[991,1494,1495],{},[994,1496,1497,1500,1503],{},[997,1498,1499],{},"Template ID",[997,1501,1502],{},"File",[997,1504,1505],{},"Shape",[1007,1507,1508,1526,1545],{},[994,1509,1510,1515,1520],{},[1012,1511,1512],{},[983,1513,1514],{},"assistant\u002Fdefault",[1012,1516,1517],{},[983,1518,1519],{},"backend\u002Fmodules\u002Fassistant\u002Fflows\u002Fdefault.flowdsl.json",[1012,1521,1522,1525],{},[983,1523,1524],{},"start → {chat | handoff} → end"," — the minimal router + two branches. Seeded on first startup.",[994,1527,1528,1533,1538],{},[1012,1529,1530],{},[983,1531,1532],{},"assistant\u002Fproduction",[1012,1534,1535],{},[983,1536,1537],{},"backend\u002Fmodules\u002Fassistant\u002Fflows\u002Fproduction.flowdsl.json",[1012,1539,1540,1541,1544],{},"Adds an ",[983,1542,1543],{},"[[ESCALATE]]","-token detector that fans out to an email-send node on the chat branch.",[994,1546,1547,1552,1557],{},[1012,1548,1549],{},[983,1550,1551],{},"assistant\u002Fhandoff-notification",[1012,1553,1554],{},[983,1555,1556],{},"backend\u002Fmodules\u002Fassistant\u002Fflows\u002Fhandoff-notification.flowdsl.json",[1012,1558,1559,1560,1562,1563,1566],{},"Event-driven: listens for ",[983,1561,1129],{}," and emits ",[983,1564,1565],{},"email.send",". Install separately from the main flow.",[1060,1568,1570],{"id":1569},"pattern-domain-grounded-chat-deterministic-search-llm","Pattern: domain-grounded chat (deterministic search → LLM)",[979,1572,1573,1574,1578,1579,1582],{},"RAG templates embed the ",[1575,1576,1577],"em",{},"question"," and retrieve prose chunks. When the answer\nshould instead point at ",[1292,1580,1581],{},"rows you own"," — products, programs, tickets — a\ndeterministic node in front of the LLM is usually a better fit than tool-calling:\ncheaper, predictable, and the model can't invent an item that isn't in the catalog.",[1296,1584,1587],{"className":1585,"code":1586,"language":1467},[1465],"start ─► guard-in ─► domain-search ─► llm-chat ─► guard-out ─► end\n             │Block                       │Block\n             └─► refusal-in ─► rejected   └─► refusal-out ─► rejected\n",[983,1588,1586],{"__ignoreMap":1301},[979,1590,1591],{},"The custom node does three things and writes them onto the packet:",[1296,1593,1597],{"className":1594,"code":1595,"language":1596,"meta":1301,"style":1301},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","func (m *Module) searchHandler(ctx context.Context, step *runtime.Step) error {\n    msg := latestUserMessage(step.Input)     \u002F\u002F 1. read the turn\n    rows := m.search(ctx, msg)               \u002F\u002F 2. query YOUR data (vector and\u002For facets)\n\n    \u002F\u002F 3. hand the LLM a grounded prompt, plus UI affordances\n    step.Output[\"messages\"] = []any{\n        map[string]any{\"role\": \"system\", \"content\": promptListing(rows)},\n        map[string]any{\"role\": \"user\", \"content\": msg},\n    }\n    step.Output[\"sources\"] = rowLinks(rows)   \u002F\u002F clickable cards under the reply\n    step.Output[\"actions\"] = rowActions(rows) \u002F\u002F buttons: adopt, add to cart, book…\n    return nil\n}\n","go",[983,1598,1599,1604,1609,1614,1620,1625,1630,1635,1640,1645,1650,1655,1660],{"__ignoreMap":1301},[1305,1600,1601],{"class":1307,"line":10},[1305,1602,1603],{},"func (m *Module) searchHandler(ctx context.Context, step *runtime.Step) error {\n",[1305,1605,1606],{"class":1307,"line":16},[1305,1607,1608],{},"    msg := latestUserMessage(step.Input)     \u002F\u002F 1. read the turn\n",[1305,1610,1611],{"class":1307,"line":22},[1305,1612,1613],{},"    rows := m.search(ctx, msg)               \u002F\u002F 2. query YOUR data (vector and\u002For facets)\n",[1305,1615,1616],{"class":1307,"line":51},[1305,1617,1619],{"emptyLinePlaceholder":1618},true,"\n",[1305,1621,1622],{"class":1307,"line":57},[1305,1623,1624],{},"    \u002F\u002F 3. hand the LLM a grounded prompt, plus UI affordances\n",[1305,1626,1627],{"class":1307,"line":102},[1305,1628,1629],{},"    step.Output[\"messages\"] = []any{\n",[1305,1631,1632],{"class":1307,"line":108},[1305,1633,1634],{},"        map[string]any{\"role\": \"system\", \"content\": promptListing(rows)},\n",[1305,1636,1637],{"class":1307,"line":114},[1305,1638,1639],{},"        map[string]any{\"role\": \"user\", \"content\": msg},\n",[1305,1641,1642],{"class":1307,"line":120},[1305,1643,1644],{},"    }\n",[1305,1646,1647],{"class":1307,"line":181},[1305,1648,1649],{},"    step.Output[\"sources\"] = rowLinks(rows)   \u002F\u002F clickable cards under the reply\n",[1305,1651,1652],{"class":1307,"line":186},[1305,1653,1654],{},"    step.Output[\"actions\"] = rowActions(rows) \u002F\u002F buttons: adopt, add to cart, book…\n",[1305,1656,1657],{"class":1307,"line":191},[1305,1658,1659],{},"    return nil\n",[1305,1661,1662],{"class":1307,"line":197},[1305,1663,1377],{},[979,1665,1666],{},"Why this composes cleanly:",[1668,1669,1670,1688,1698,1707],"ul",{},[1671,1672,1673,1687],"li",{},[1292,1674,1675,1678,1679,1682,1683,1686],{},[983,1676,1677],{},"llm-chat"," forwards ",[983,1680,1681],{},"sources"," and ",[983,1684,1685],{},"actions"," verbatim",", so whatever the search\nnode attaches reaches the terminal node untouched.",[1671,1689,1690,1693,1694,1697],{},[1292,1691,1692],{},"The SSE pump emits them alongside the content frame",", and the widget's action\nregistry dispatches clicks by ",[983,1695,1696],{},"type"," — no frontend change per new action.",[1671,1699,1700,1706],{},[1292,1701,1702,1705],{},[983,1703,1704],{},"llm-guard"," is a pass-through router on Allow\u002FFlag",", copying the whole packet,\nso guards can wrap the chain without the search node knowing.",[1671,1708,1709,1710,1713],{},"The prompt instructs the model to recommend ",[1292,1711,1712],{},"only"," from the supplied list and\nto reply in the user's language; retrieval stays deterministic and auditable.",[979,1715,1716],{},"Register the node on the shared engine at Startup, exactly like the assistant's\nown nodes:",[1296,1718,1720],{"className":1594,"code":1719,"language":1596,"meta":1301,"style":1301},"flowexecmod.Current().Engine().RegisterHandler(\"myapp\u002Fdomain-search\", m.searchHandler)\n",[983,1721,1722],{"__ignoreMap":1301},[1305,1723,1724],{"class":1307,"line":10},[1305,1725,1719],{},[979,1727,1728,1729,1732,1733,1735,1736,1739,1740,1743,1744,1682,1747,1750],{},"Point the deployment at your flow with ",[983,1730,1731],{},"ASSISTANT_DEPLOYMENT_ID",". Reach for the\ntool-calling loop (",[983,1734,1677],{}," with ",[983,1737,1738],{},"tools"," → ",[983,1741,1742],{},"llm-tool-router",") only when the model\ngenuinely needs to decide ",[1575,1745,1746],{},"whether",[1575,1748,1749],{},"how many times"," to search.",[1060,1752,1754,1755],{"id":1753},"flowdsl-node-redelayassistant-handoff-request","FlowDSL node: ",[983,1756,1479],{},[979,1758,1759,1760,1763,1764,1767,1768,1770],{},"Package: ",[983,1761,1762],{},"backend\u002Fmodules\u002Fassistant\u002Fflowdsl"," (factory id ",[983,1765,1766],{},"assistant-flowdsl",",\ndepends on ",[983,1769,976],{},").",[979,1772,1773,1774,1777,1778,1781],{},"One node — an ",[983,1775,1776],{},"action"," kind — wraps ",[983,1779,1780],{},"handoff.Service.Request",". It is the\nprimitive behind the \"Talk to a human\" branch of the default flow shape. Drop\nit into any flow that should turn a packet into a handoff record.",[979,1783,1784],{},[1292,1785,1786],{},"Settings:",[988,1788,1789,1804],{},[991,1790,1791],{},[994,1792,1793,1796,1799,1802],{},[997,1794,1795],{},"Setting",[997,1797,1798],{},"Type",[997,1800,1801],{},"Default",[997,1803,1002],{},[1007,1805,1806,1827],{},[994,1807,1808,1813,1819,1824],{},[1012,1809,1810],{},[983,1811,1812],{},"defaultPriority",[1012,1814,1815,1816],{},"enum ",[983,1817,1818],{},"low | normal | high | urgent",[1012,1820,1821],{},[983,1822,1823],{},"normal",[1012,1825,1826],{},"Priority to apply when the incoming packet does not carry one.",[994,1828,1829,1834,1837,1842],{},[1012,1830,1831],{},[983,1832,1833],{},"defaultReason",[1012,1835,1836],{},"string",[1012,1838,1839],{},[983,1840,1841],{},"\"User requested human assistance\"",[1012,1843,1844,1845,1101],{},"Fallback reason written to the admin inbox when the packet has no explicit ",[983,1846,1847],{},"reason",[979,1849,1850],{},[1292,1851,1852],{},"Ports:",[988,1854,1855,1867],{},[991,1856,1857],{},[994,1858,1859,1862,1865],{},[997,1860,1861],{},"Direction",[997,1863,1864],{},"Name",[997,1866,1505],{},[1007,1868,1869,1895,1915],{},[994,1870,1871,1874,1879],{},[1012,1872,1873],{},"input",[1012,1875,1876],{},[983,1877,1878],{},"Request",[1012,1880,1881,1884,1885,1197,1888,1197,1890,1197,1893,1101],{},[983,1882,1883],{},"{sessionId, email}"," required; optional ",[983,1886,1887],{},"phone",[983,1889,1847],{},[983,1891,1892],{},"priority",[983,1894,1196],{},[994,1896,1897,1900,1905],{},[1012,1898,1899],{},"output",[1012,1901,1902],{},[983,1903,1904],{},"Handoff",[1012,1906,1907,1910,1911,1914],{},[983,1908,1909],{},"{handoffId, status, duplicate}",". ",[983,1912,1913],{},"duplicate=true"," when the service deduped against an existing pending handoff for the same session (no new row written).",[994,1916,1917,1919,1924],{},[1012,1918,1899],{},[1012,1920,1921],{},[983,1922,1923],{},"Error",[1012,1925,1926,1929],{},[983,1927,1928],{},"{error}",". Use this branch to notify the user that their handoff could not be filed.",[979,1931,1932,1933,1935,1936,1938],{},"Settings-level ",[983,1934,1812],{}," \u002F ",[983,1937,1833],{}," are only applied when the\npacket leaves the corresponding field blank — explicit packet values always win.",[1060,1940,1942],{"id":1941},"llm-tuning-from-studio","LLM tuning from Studio",[979,1944,1945,1946,1948],{},"The ",[983,1947,1439],{}," node on the assistant flow exposes three Studio-editable settings\nthat replace hand-written prompt prose:",[1668,1950,1951,1960,1968],{},[1671,1952,1953,1956,1957],{},[983,1954,1955],{},"replyStyle"," — ",[983,1958,1959],{},"short | normal | detailed",[1671,1961,1962,1956,1965],{},[983,1963,1964],{},"examplesPolicy",[983,1966,1967],{},"avoid | when_asked | always",[1671,1969,1970,1973],{},[983,1971,1972],{},"systemPrompt"," — free-form textarea",[979,1975,1976,1977,1981,1982,1984],{},"See ",[1047,1978,1980],{"href":1979},"\u002Fdocs\u002Freference\u002Fgo-ai#handler-behaviour","go-ai — system prompt composition"," for the exact\nordering rules. The short version: ",[983,1983,1972],{}," is the base, the two enums append plain-\nEnglish directives when they're anything other than the neutral default.",[1060,1986,1988],{"id":1987},"embedded-template-catalog","Embedded template catalog",[979,1990,1991,1992,1995,1996,1999,2000,2003,2004,2007,2008,1197,2011,2014,2015,1197,2018,1197,2021,1197,2024,1770],{},"The module ships with ",[1292,1993,1994],{},"11 flow templates"," covering dev → production, cost-free →\nquality-maxed, stateless Q&A → chat with memory. Each is a fully-realised\n",[983,1997,1998],{},".flowdsl.json"," embedded into the binary; all are selectable via\n",[983,2001,2002],{},"POST \u002Fadmin\u002Fassistant\u002Freset?template=\u003Cname>",". Operators can also discover them at\nruntime via ",[983,2005,2006],{},"GET \u002Fadmin\u002Fassistant\u002Ftemplates"," (returned fields: ",[983,2009,2010],{},"name",[983,2012,2013],{},"title",",\n",[983,2016,2017],{},"description",[983,2019,2020],{},"tier",[983,2022,2023],{},"recommended",[983,2025,2026],{},"requires",[1065,2028,2030],{"id":2029},"tiers","Tiers",[979,2032,2033],{},"Templates are tiered by quality \u002F sophistication. Higher tier ≈ more infrastructure\nand cost per turn, usually better answers.",[988,2035,2036,2064],{},[991,2037,2038],{},[994,2039,2040,2043,2046,2050,2053,2055,2058,2061],{},[997,2041,2042],{},"Tier",[997,2044,2045],{},"Template",[997,2047,2049],{"align":2048},"center","Guards",[997,2051,2052],{"align":2048},"RAG",[997,2054,1904],{"align":2048},[997,2056,2057],{"align":2048},"Streaming",[997,2059,2060],{"align":2048},"LLM calls \u002F turn",[997,2062,2063],{},"Extra infra",[1007,2065,2066,2094,2119,2145,2169,2194,2220,2246,2270,2294,2317],{},[994,2067,2068,2073,2078,2081,2083,2085,2087,2092],{},[1012,2069,2070],{},[1292,2071,2072],{},"T0",[1012,2074,2075],{},[983,2076,2077],{},"echo",[1012,2079,2080],{"align":2048},"—",[1012,2082,2080],{"align":2048},[1012,2084,2080],{"align":2048},[1012,2086,2080],{"align":2048},[1012,2088,2089],{"align":2048},[1292,2090,2091],{},"0",[1012,2093,2080],{},[994,2095,2096,2101,2106,2108,2110,2112,2114,2117],{},[1012,2097,2098],{},[1292,2099,2100],{},"T1",[1012,2102,2103],{},[983,2104,2105],{},"minimal",[1012,2107,2080],{"align":2048},[1012,2109,2080],{"align":2048},[1012,2111,2080],{"align":2048},[1012,2113,2080],{"align":2048},[1012,2115,2116],{"align":2048},"1",[1012,2118,2080],{},[994,2120,2121,2126,2131,2134,2136,2138,2140,2143],{},[1012,2122,2123],{},[1292,2124,2125],{},"T2",[1012,2127,2128],{},[983,2129,2130],{},"default",[1012,2132,2133],{"align":2048},"✓",[1012,2135,2080],{"align":2048},[1012,2137,2133],{"align":2048},[1012,2139,2080],{"align":2048},[1012,2141,2142],{"align":2048},"1 + 2 guards",[1012,2144,2080],{},[994,2146,2147,2152,2157,2159,2161,2163,2165,2167],{},[1012,2148,2149],{},[1292,2150,2151],{},"T2s",[1012,2153,2154],{},[983,2155,2156],{},"default-stream",[1012,2158,2133],{"align":2048},[1012,2160,2080],{"align":2048},[1012,2162,2133],{"align":2048},[1012,2164,2133],{"align":2048},[1012,2166,2142],{"align":2048},[1012,2168,2080],{},[994,2170,2171,2176,2181,2183,2185,2187,2189,2191],{},[1012,2172,2173],{},[1292,2174,2175],{},"T3",[1012,2177,2178],{},[983,2179,2180],{},"production",[1012,2182,2133],{"align":2048},[1012,2184,2080],{"align":2048},[1012,2186,2133],{"align":2048},[1012,2188,2080],{"align":2048},[1012,2190,2142],{"align":2048},[1012,2192,2193],{},"SMTP",[994,2195,2196,2201,2206,2209,2211,2213,2215,2218],{},[1012,2197,2198],{},[1292,2199,2200],{},"T3+",[1012,2202,2203],{},[983,2204,2205],{},"multi-guard",[1012,2207,2208],{"align":2048},"✓✓",[1012,2210,2080],{"align":2048},[1012,2212,2080],{"align":2048},[1012,2214,2080],{"align":2048},[1012,2216,2217],{"align":2048},"1 + 4 guards",[1012,2219,2080],{},[994,2221,2222,2227,2232,2234,2236,2238,2240,2243],{},[1012,2223,2224],{},[1292,2225,2226],{},"T4",[1012,2228,2229],{},[983,2230,2231],{},"rag",[1012,2233,2133],{"align":2048},[1012,2235,2133],{"align":2048},[1012,2237,2133],{"align":2048},[1012,2239,2080],{"align":2048},[1012,2241,2242],{"align":2048},"1 + 2 guards + 1 embed",[1012,2244,2245],{},"Qdrant + embedder",[994,2247,2248,2253,2258,2260,2262,2264,2266,2268],{},[1012,2249,2250],{},[1292,2251,2252],{},"T4b",[1012,2254,2255],{},[983,2256,2257],{},"rag-clean",[1012,2259,2133],{"align":2048},[1012,2261,2133],{"align":2048},[1012,2263,2133],{"align":2048},[1012,2265,2080],{"align":2048},[1012,2267,2242],{"align":2048},[1012,2269,2245],{},[994,2271,2272,2277,2282,2284,2286,2288,2290,2292],{},[1012,2273,2274],{},[1292,2275,2276],{},"T4s",[1012,2278,2279],{},[983,2280,2281],{},"rag-stream",[1012,2283,2133],{"align":2048},[1012,2285,2133],{"align":2048},[1012,2287,2133],{"align":2048},[1012,2289,2133],{"align":2048},[1012,2291,2242],{"align":2048},[1012,2293,2245],{},[994,2295,2296,2300,2305,2307,2309,2311,2313,2315],{},[1012,2297,2298],{},[1292,2299,2226],{},[1012,2301,2302],{},[983,2303,2304],{},"qa-only",[1012,2306,2133],{"align":2048},[1012,2308,2133],{"align":2048},[1012,2310,2080],{"align":2048},[1012,2312,2080],{"align":2048},[1012,2314,2242],{"align":2048},[1012,2316,2245],{},[994,2318,2319,2324,2329,2331,2333,2335,2337,2340],{},[1012,2320,2321],{},[1292,2322,2323],{},"T5",[1012,2325,2326],{},[983,2327,2328],{},"rag-rewrite",[1012,2330,2133],{"align":2048},[1012,2332,2133],{"align":2048},[1012,2334,2133],{"align":2048},[1012,2336,2080],{"align":2048},[1012,2338,2339],{"align":2048},"2 + 2 guards + 1 embed",[1012,2341,2245],{},[1065,2343,2345],{"id":2344},"per-template-guide","Per-template guide",[979,2347,2348,2353,2354,2357,2358,2361],{},[1292,2349,2350,2352],{},[983,2351,2077],{}," (T0)"," — start → ",[983,2355,2356],{},"core\u002Ftemplate-render"," → end. ",[1292,2359,2360],{},"Zero LLM tokens",". Echoes\nthe user's latest message back in a banner. Purpose: CI smoke tests, UI development\nwithout provider costs, wiring sanity checks when external providers are rate-limited\nor down, cost-free customer demos.",[979,2363,2364,2353,2369,2371],{},[1292,2365,2366,2368],{},[983,2367,2105],{}," (T1)",[983,2370,1439],{}," → end. No safety, no grounding, no\nhandoff. Rawest possible LLM integration. Purpose: local development, model-\ncomparison bench, fast feedback loops when guard latency hurts iteration.",[979,2373,2374,2379,2380,2383,2384,2387],{},[1292,2375,2376,2378],{},[983,2377,2130],{}," (T2)"," — minimal + ",[983,2381,2382],{},"redelay\u002Fllm-guard"," on both sides + configurable\nrefusals + human-handoff branch. Baseline for any production deployment. Unsafe\nuser input → ",[983,2385,2386],{},"rejected"," with a configurable refusal; unsafe model draft → same.",[979,2389,2390,1956,2395,1735,2397,2400,2401,2404,2405,2407],{},[1292,2391,2392,2394],{},[983,2393,2156],{}," (T2s)",[983,2396,2130],{},[983,2398,2399],{},"stream: true"," on llm-chat. Tokens\narrive as the model writes; lower time-to-first-token. Caveat: ",[983,2402,2403],{},"guard-out"," can't\nsuppress output mid-stream — it runs once the full draft is complete. Use for\ninternal tools and authenticated user bases; prefer ",[983,2406,2130],{}," for public anonymous\nchat where pre-send moderation matters.",[979,2409,2410,1956,2415,2417,2418,2420,2421,2423],{},[1292,2411,2412,2414],{},[983,2413,2180],{}," (T3)",[983,2416,2130],{}," + trust-and-safety email fan-out on ",[983,2419,2403],{},"\nblocks + ",[983,2422,1543],{}," token detection that short-circuits the chat path to\nhandoff. Public-facing deployments. Ephemeral email delivery so SMTP failures\nnever affect the user-facing stream.",[979,2425,2426,2431,2432,2434,2435,2438,2439,2442],{},[1292,2427,2428,2430],{},[983,2429,2205],{}," (T3+)"," — chains two ",[983,2433,2382],{}," classifiers on each side\nof the LLM (",[983,2436,2437],{},"guard-in-1"," fails open, ",[983,2440,2441],{},"guard-in-2"," fails closed; same on the output\nside). Use when single-classifier recall isn't adequate for your risk tolerance:\nregulated industries, child-facing products, high-liability verticals. ~2x guard\nlatency per turn.",[979,2444,2445,1956,2450,1264,2452,2455,2456,2459,2460,2463,2464,2467,2468,2471,2472,2475],{},[1292,2446,2447,2449],{},[983,2448,2231],{}," (T4)",[983,2451,2130],{},[983,2453,2454],{},"redelay\u002Fassistant-rag-context"," between ",[983,2457,2458],{},"guard-in"," and\n",[983,2461,2462],{},"chat",". Retrieves top-K chunks from the configured Qdrant index (default\n",[983,2465,2466],{},"redelay_docs",") and prepends them as a system-prompt excerpt. LLM is instructed\nto quote excerpts and cite by their ",[983,2469,2470],{},"[N]"," index. Eliminates hallucinated facts.\nRequires ",[983,2473,2474],{},"assistant-ingest-docs"," CLI to have populated the index first.",[979,2477,2478,2483,2484,2486,2487,2489],{},[1292,2479,2480,2482],{},[983,2481,2257],{}," (T4b)"," — same retrieval as ",[983,2485,2231],{},", but the LLM system prompts are\ntuned to suppress inline ",[983,2488,2470],{}," markers and write polished conversational prose.\nSources still ride the SSE stream; the UI renders a \"Sources\" footer below each\nassistant turn. Use when chat tone matters more than inline traceability.",[979,2491,2492,1956,2497,1735,2499,2501,2502,2504,2505,2507,2508,1101],{},[1292,2493,2494,2496],{},[983,2495,2281],{}," (T4s)",[983,2498,2231],{},[983,2500,2399],{},". Same latency tradeoffs as\n",[983,2503,2156],{},"; citation pills materialise as the model writes ",[983,2506,2470],{},", and the\nSources footer appears on ",[983,2509,2510],{},"run.completed",[979,2512,2513,2517],{},[1292,2514,2515,2449],{},[983,2516,2304],{}," — stateless single-turn RAG. Guards + retrieval + guard-out,\nbut the LLM is instructed to treat each user turn independently and NOT reference\nprior messages. Useful for FAQ bots, help-centre deployments, and privacy-sensitive\nverticals where retaining chat context is a liability.",[979,2519,2520,1956,2525,2527,2528,2530,2531,2534,2535,2538],{},[1292,2521,2522,2524],{},[983,2523,2328],{}," (T5)",[983,2526,2231],{}," + a small preprocessor ",[983,2529,1677],{}," call that rewrites\nthe user's question into a search-friendly query before retrieval. Terse follow-ups\n(\"is it PHP?\") and pronoun-heavy messages (\"how do I configure it?\") recall much\nbetter after rewrite. The main chat still sees the ORIGINAL messages so the\nconversation reads naturally. Uses the ",[983,2532,2533],{},"queryKey"," setting on ",[983,2536,2537],{},"rag-context"," to read\nthe rewrite from a dedicated packet field. Cost: ~50–100 extra tokens per turn.",[1065,2540,2542],{"id":2541},"how-to-pick","How to pick",[1668,2544,2545,2557,2565,2573,2584,2592,2600,2608],{},[1671,2546,2547,2550,2551,2553,2554,2556],{},[1292,2548,2549],{},"Building \u002F debugging",": ",[983,2552,2077],{}," (wiring) → ",[983,2555,2105],{}," (model comparison)",[1671,2558,2559,2550,2562,2564],{},[1292,2560,2561],{},"MVP",[983,2563,2130],{}," (baseline prod safety + handoff)",[1671,2566,2567,2550,2570,2572],{},[1292,2568,2569],{},"Ship to users",[983,2571,2180],{}," (+ SMTP monitoring)",[1671,2574,2575,2550,2578,2580,2581,2583],{},[1292,2576,2577],{},"Docs bot",[983,2579,2231],{}," (show sources) or ",[983,2582,2257],{}," (polished prose)",[1671,2585,2586,2550,2589,2591],{},[1292,2587,2588],{},"Help centre",[983,2590,2304],{}," (stateless, no memory liability)",[1671,2593,2594,2550,2597,2599],{},[1292,2595,2596],{},"Long chat sessions with follow-ups",[983,2598,2328],{}," (best recall on short queries)",[1671,2601,2602,2550,2605,2607],{},[1292,2603,2604],{},"Regulated \u002F high-liability",[983,2606,2205],{}," + your own audit log",[1671,2609,2610,2550,2613,1935,2615],{},[1292,2611,2612],{},"Real-time feel",[983,2614,2156],{},[983,2616,2281],{},[1065,2618,2620],{"id":2619},"roadmap-future-templates-not-yet-shipped","Roadmap — future templates not yet shipped",[1668,2622,2623,2637,2657],{},[1671,2624,2625,2628,2629,2632,2633,2636],{},[983,2626,2627],{},"rag-rerank"," — cross-encoder rerank after vector retrieval (OVH's free\n",[983,2630,2631],{},"bge-reranker-v2-m3","). Measurably higher precision. Requires a new\n",[983,2634,2635],{},"redelay\u002Frerank"," node.",[1671,2638,2639,2642,2643,1197,2646,1197,2649,2652,2653,2656],{},[983,2640,2641],{},"agentic"," — tool-calling LLM with ",[983,2644,2645],{},"search_docs",[983,2647,2648],{},"read_file",[983,2650,2651],{},"list_modules","\ntools. Uses existing ",[983,2654,2655],{},"redelay\u002Fllm-tool-router","; requires tool-action wiring.",[1671,2658,2659,2662],{},[983,2660,2661],{},"rag-memory"," — chat-history summarization before retrieval. Reduces token bloat\non long sessions.",[1060,2664,2666],{"id":2665},"picking-which-flows-the-widget-uses","Picking which flow(s) the widget uses",[979,2668,2669,2670,2675,2676,2679,2680,2682],{},"The assistant module references a ",[1292,2671,2672],{},[983,2673,2674],{},"FlowDeployment"," — a framework-level routing entity\nthat lives in ",[983,2677,2678],{},"go-flowdsl\u002Fflowexec\u002Fstore"," and is shared by every module that binds flows\nat run time. The deployment has one or more variants; each variant points at a ",[983,2681,1200],{},"\n(optionally pinned to a versionId) with a routing weight.",[1296,2684,2687],{"className":2685,"code":2686,"language":1467},[1465],"ASSISTANT_DEPLOYMENT_ID = \"assistant\"    ← module config\n                          │\n                          ▼\n              ┌─── FlowDeployment ───┐\n              │ stable: flow.v1 90%  │\n              │ canary: flow.v2 10%  │\n              └──────────────────────┘\n",[983,2688,2686],{"__ignoreMap":1301},[979,2690,2691,2692,2695,2696,2700,2701,1197,2704,1197,2706,2709,2710,1770],{},"Sticky bucketing by ",[983,2693,2694],{},"session_id"," keeps the same user on the same variant across reloads\nand container restarts. See the full framework reference at\n",[1047,2697,2699],{"href":2698},"\u002Fdocs\u002Freference\u002Fgo-flowdsl#flowexec","go-flowdsl → FlowDeployment"," for the data model, store API,\nand admin HTTP surface (",[983,2702,2703],{},"POST \u002Fdeployments\u002F…",[983,2705,1253],{},[983,2707,2708],{},"DELETE",", the one-shot\n",[983,2711,2712],{},"\u002Fdeployments\u002F{id}\u002Fvariants\u002Ffrom-template",[1065,2714,2716],{"id":2715},"back-compat","Back-compat",[979,2718,2719,2720,2723,2724,2727,2728,2730],{},"Existing installs set ",[983,2721,2722],{},"ASSISTANT_FLOW_ID","; the module auto-synthesises a deployment with a\nsingle ",[983,2725,2726],{},"stable 100%"," variant pointing at that flow on first Startup. No manual migration.\nOnce you start managing variants through the deployment CRUD, ",[983,2729,2722],{}," is\nignored.",[1065,2732,2734],{"id":2733},"five-paths-to-switch-flows-in-increasing-order-of-flexibility","Five paths to switch flows, in increasing order of flexibility:",[1065,2736,2738],{"id":2737},"_1-studio-ui","1. Studio UI",[979,2740,2741,2744,2745,1739,2747,2750,2751,2754,2755,2758,2759,2761,2762,2765],{},[983,2742,2743],{},"\u002Fflowdsl"," → select ",[983,2746,976],{},[1292,2748,2749],{},"Versions"," tab → click ",[1292,2752,2753],{},"Publish"," on the row you want.\nNew chat runs go through it immediately; existing SSE connections stay on the old version\nuntil reconnect. To swap shape entirely, use ",[1292,2756,2757],{},"Templates"," → pick ",[983,2760,1532],{}," →\n",[1292,2763,2764],{},"Save as new version"," → Publish.",[1065,2767,2769,2770,2773],{"id":2768},"_2-post-assistantresettemplate-one-liner-template-switcher","2. ",[983,2771,2772],{},"POST \u002Fassistant\u002Freset?template="," — one-liner template switcher",[1296,2775,2779],{"className":2776,"code":2777,"language":2778,"meta":1301,"style":1301},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# Swap to the production variant (adds [[ESCALATE]] email fan-out)\ncurl -X POST -H \"Authorization: Bearer $TOKEN\" \\\n  http:\u002F\u002Flocalhost:8001\u002Fapi\u002Fv1\u002Fassistant\u002Freset?template=production\n\n# Back to default (minimal router)\ncurl -X POST -H \"Authorization: Bearer $TOKEN\" \\\n  http:\u002F\u002Flocalhost:8001\u002Fapi\u002Fv1\u002Fassistant\u002Freset?template=default\n","bash",[983,2780,2781,2787,2820,2825,2829,2834,2854],{"__ignoreMap":1301},[1305,2782,2783],{"class":1307,"line":10},[1305,2784,2786],{"class":2785},"sHwdD","# Swap to the production variant (adds [[ESCALATE]] email fan-out)\n",[1305,2788,2789,2793,2797,2800,2803,2807,2810,2814,2817],{"class":1307,"line":16},[1305,2790,2792],{"class":2791},"sBMFI","curl",[1305,2794,2796],{"class":2795},"sfazB"," -X",[1305,2798,2799],{"class":2795}," POST",[1305,2801,2802],{"class":2795}," -H",[1305,2804,2806],{"class":2805},"sMK4o"," \"",[1305,2808,2809],{"class":2795},"Authorization: Bearer ",[1305,2811,2813],{"class":2812},"sTEyZ","$TOKEN",[1305,2815,2816],{"class":2805},"\"",[1305,2818,2819],{"class":2812}," \\\n",[1305,2821,2822],{"class":1307,"line":22},[1305,2823,2824],{"class":2795},"  http:\u002F\u002Flocalhost:8001\u002Fapi\u002Fv1\u002Fassistant\u002Freset?template=production\n",[1305,2826,2827],{"class":1307,"line":51},[1305,2828,1619],{"emptyLinePlaceholder":1618},[1305,2830,2831],{"class":1307,"line":57},[1305,2832,2833],{"class":2785},"# Back to default (minimal router)\n",[1305,2835,2836,2838,2840,2842,2844,2846,2848,2850,2852],{"class":1307,"line":102},[1305,2837,2792],{"class":2791},[1305,2839,2796],{"class":2795},[1305,2841,2799],{"class":2795},[1305,2843,2802],{"class":2795},[1305,2845,2806],{"class":2805},[1305,2847,2809],{"class":2795},[1305,2849,2813],{"class":2812},[1305,2851,2816],{"class":2805},[1305,2853,2819],{"class":2812},[1305,2855,2856],{"class":1307,"line":108},[1305,2857,2858],{"class":2795},"  http:\u002F\u002Flocalhost:8001\u002Fapi\u002Fv1\u002Fassistant\u002Freset?template=default\n",[979,2860,2861,2862,2865],{},"Superuser only. Saves a new version from the embedded JSON and publishes it atomically.\nHistory is preserved — rollback via ",[983,2863,2864],{},"\u002Fflows\u002F{id}\u002Frollback"," still works.",[1065,2867,2869],{"id":2868},"_3-flowexec-api-publish-any-existing-version","3. flowexec API — publish any existing version",[1296,2871,2873],{"className":2776,"code":2872,"language":2778,"meta":1301,"style":1301},"# List versions\ncurl -H \"Authorization: Bearer $TOKEN\" \\\n  http:\u002F\u002Flocalhost:8001\u002Fapi\u002Fv1\u002Fflows\u002Fassistant\u002Fversions\n\n# Publish one of them\ncurl -X POST -H \"Authorization: Bearer $TOKEN\" -H \"Content-Type: application\u002Fjson\" \\\n  http:\u002F\u002Flocalhost:8001\u002Fapi\u002Fv1\u002Fflows\u002Fassistant\u002Fpublish \\\n  -d '{\"versionID\":\"ver.XXXX\"}'\n",[983,2874,2875,2880,2896,2901,2905,2910,2939,2946],{"__ignoreMap":1301},[1305,2876,2877],{"class":1307,"line":10},[1305,2878,2879],{"class":2785},"# List versions\n",[1305,2881,2882,2884,2886,2888,2890,2892,2894],{"class":1307,"line":16},[1305,2883,2792],{"class":2791},[1305,2885,2802],{"class":2795},[1305,2887,2806],{"class":2805},[1305,2889,2809],{"class":2795},[1305,2891,2813],{"class":2812},[1305,2893,2816],{"class":2805},[1305,2895,2819],{"class":2812},[1305,2897,2898],{"class":1307,"line":22},[1305,2899,2900],{"class":2795},"  http:\u002F\u002Flocalhost:8001\u002Fapi\u002Fv1\u002Fflows\u002Fassistant\u002Fversions\n",[1305,2902,2903],{"class":1307,"line":51},[1305,2904,1619],{"emptyLinePlaceholder":1618},[1305,2906,2907],{"class":1307,"line":57},[1305,2908,2909],{"class":2785},"# Publish one of them\n",[1305,2911,2912,2914,2916,2918,2920,2922,2924,2926,2928,2930,2932,2935,2937],{"class":1307,"line":102},[1305,2913,2792],{"class":2791},[1305,2915,2796],{"class":2795},[1305,2917,2799],{"class":2795},[1305,2919,2802],{"class":2795},[1305,2921,2806],{"class":2805},[1305,2923,2809],{"class":2795},[1305,2925,2813],{"class":2812},[1305,2927,2816],{"class":2805},[1305,2929,2802],{"class":2795},[1305,2931,2806],{"class":2805},[1305,2933,2934],{"class":2795},"Content-Type: application\u002Fjson",[1305,2936,2816],{"class":2805},[1305,2938,2819],{"class":2812},[1305,2940,2941,2944],{"class":1307,"line":108},[1305,2942,2943],{"class":2795},"  http:\u002F\u002Flocalhost:8001\u002Fapi\u002Fv1\u002Fflows\u002Fassistant\u002Fpublish",[1305,2945,2819],{"class":2812},[1305,2947,2948,2951,2954,2957],{"class":1307,"line":114},[1305,2949,2950],{"class":2795},"  -d",[1305,2952,2953],{"class":2805}," '",[1305,2955,2956],{"class":2795},"{\"versionID\":\"ver.XXXX\"}",[1305,2958,2959],{"class":2805},"'\n",[1065,2961,2963],{"id":2962},"_4-weighted-variants-within-one-flow-ab-between-versions","4. Weighted variants within one flow — A\u002FB between versions",[1296,2965,2967],{"className":2776,"code":2966,"language":2778,"meta":1301,"style":1301},"curl -X POST -H \"Authorization: Bearer $TOKEN\" -H \"Content-Type: application\u002Fjson\" \\\n  http:\u002F\u002Flocalhost:8001\u002Fapi\u002Fv1\u002Fflows\u002Fassistant\u002Fpublish \\\n  -d '{\n    \"variants\": [\n      {\"label\": \"stable\", \"versionID\": \"ver.minimal\",    \"weight\": 80},\n      {\"label\": \"canary\", \"versionID\": \"ver.production\", \"weight\": 20}\n    ]\n  }'\n",[983,2968,2969,2997,3003,3011,3016,3021,3026,3031],{"__ignoreMap":1301},[1305,2970,2971,2973,2975,2977,2979,2981,2983,2985,2987,2989,2991,2993,2995],{"class":1307,"line":10},[1305,2972,2792],{"class":2791},[1305,2974,2796],{"class":2795},[1305,2976,2799],{"class":2795},[1305,2978,2802],{"class":2795},[1305,2980,2806],{"class":2805},[1305,2982,2809],{"class":2795},[1305,2984,2813],{"class":2812},[1305,2986,2816],{"class":2805},[1305,2988,2802],{"class":2795},[1305,2990,2806],{"class":2805},[1305,2992,2934],{"class":2795},[1305,2994,2816],{"class":2805},[1305,2996,2819],{"class":2812},[1305,2998,2999,3001],{"class":1307,"line":16},[1305,3000,2943],{"class":2795},[1305,3002,2819],{"class":2812},[1305,3004,3005,3007,3009],{"class":1307,"line":22},[1305,3006,2950],{"class":2795},[1305,3008,2953],{"class":2805},[1305,3010,1310],{"class":2795},[1305,3012,3013],{"class":1307,"line":51},[1305,3014,3015],{"class":2795},"    \"variants\": [\n",[1305,3017,3018],{"class":1307,"line":57},[1305,3019,3020],{"class":2795},"      {\"label\": \"stable\", \"versionID\": \"ver.minimal\",    \"weight\": 80},\n",[1305,3022,3023],{"class":1307,"line":102},[1305,3024,3025],{"class":2795},"      {\"label\": \"canary\", \"versionID\": \"ver.production\", \"weight\": 20}\n",[1305,3027,3028],{"class":1307,"line":108},[1305,3029,3030],{"class":2795},"    ]\n",[1305,3032,3033,3036],{"class":1307,"line":114},[1305,3034,3035],{"class":2795},"  }",[1305,3037,2959],{"class":2805},[979,3039,3040,3041,1101],{},"80\u002F20 split across versions of the same flow, sticky per ",[983,3042,2694],{},[1065,3044,3046,3047,3050],{"id":3045},"_5-weighted-variants-across-different-flows-deployment-level-ab","5. Weighted variants across ",[1292,3048,3049],{},"different flows"," — deployment-level A\u002FB",[979,3052,3053,3054,3057],{},"Use this when variants differ in ",[1575,3055,3056],{},"shape",", not just parameters — e.g. a plain chat flow vs\na RAG-enabled flow. Build or promote the flows separately, then bind them in a deployment:",[1296,3059,3061],{"className":2776,"code":3060,"language":2778,"meta":1301,"style":1301},"# One call: create a new flow from the production template, publish v1, and append it\n# as a 10% canary on the \"assistant\" deployment. Sticky per session_id so every user\n# stays on one variant across reloads.\ncurl -X POST -H \"Authorization: Bearer $TOKEN\" -H \"Content-Type: application\u002Fjson\" \\\n  http:\u002F\u002Flocalhost:8001\u002Fapi\u002Fv1\u002Fdeployments\u002Fassistant\u002Fvariants\u002Ffrom-template \\\n  -d '{\n    \"templateId\": \"assistant\u002Fproduction\",\n    \"label\":      \"canary\",\n    \"weight\":     10,\n    \"pinVersion\": false\n  }'\n\n# Adjust weights later without provisioning new flows:\ncurl -X PATCH -H \"Authorization: Bearer $TOKEN\" -H \"Content-Type: application\u002Fjson\" \\\n  http:\u002F\u002Flocalhost:8001\u002Fapi\u002Fv1\u002Fdeployments\u002Fassistant \\\n  -d '{\n    \"variants\": [\n      {\"label\": \"stable\", \"flowId\": \"assistant\",                         \"weight\": 50},\n      {\"label\": \"canary\", \"flowId\": \"flow.assistant-production-XXXXXX\",  \"weight\": 50}\n    ]\n  }'\n",[983,3062,3063,3068,3073,3078,3106,3113,3121,3126,3131,3136,3141,3147,3151,3156,3185,3192,3200,3204,3209,3214,3218],{"__ignoreMap":1301},[1305,3064,3065],{"class":1307,"line":10},[1305,3066,3067],{"class":2785},"# One call: create a new flow from the production template, publish v1, and append it\n",[1305,3069,3070],{"class":1307,"line":16},[1305,3071,3072],{"class":2785},"# as a 10% canary on the \"assistant\" deployment. Sticky per session_id so every user\n",[1305,3074,3075],{"class":1307,"line":22},[1305,3076,3077],{"class":2785},"# stays on one variant across reloads.\n",[1305,3079,3080,3082,3084,3086,3088,3090,3092,3094,3096,3098,3100,3102,3104],{"class":1307,"line":51},[1305,3081,2792],{"class":2791},[1305,3083,2796],{"class":2795},[1305,3085,2799],{"class":2795},[1305,3087,2802],{"class":2795},[1305,3089,2806],{"class":2805},[1305,3091,2809],{"class":2795},[1305,3093,2813],{"class":2812},[1305,3095,2816],{"class":2805},[1305,3097,2802],{"class":2795},[1305,3099,2806],{"class":2805},[1305,3101,2934],{"class":2795},[1305,3103,2816],{"class":2805},[1305,3105,2819],{"class":2812},[1305,3107,3108,3111],{"class":1307,"line":57},[1305,3109,3110],{"class":2795},"  http:\u002F\u002Flocalhost:8001\u002Fapi\u002Fv1\u002Fdeployments\u002Fassistant\u002Fvariants\u002Ffrom-template",[1305,3112,2819],{"class":2812},[1305,3114,3115,3117,3119],{"class":1307,"line":102},[1305,3116,2950],{"class":2795},[1305,3118,2953],{"class":2805},[1305,3120,1310],{"class":2795},[1305,3122,3123],{"class":1307,"line":108},[1305,3124,3125],{"class":2795},"    \"templateId\": \"assistant\u002Fproduction\",\n",[1305,3127,3128],{"class":1307,"line":114},[1305,3129,3130],{"class":2795},"    \"label\":      \"canary\",\n",[1305,3132,3133],{"class":1307,"line":120},[1305,3134,3135],{"class":2795},"    \"weight\":     10,\n",[1305,3137,3138],{"class":1307,"line":181},[1305,3139,3140],{"class":2795},"    \"pinVersion\": false\n",[1305,3142,3143,3145],{"class":1307,"line":186},[1305,3144,3035],{"class":2795},[1305,3146,2959],{"class":2805},[1305,3148,3149],{"class":1307,"line":191},[1305,3150,1619],{"emptyLinePlaceholder":1618},[1305,3152,3153],{"class":1307,"line":197},[1305,3154,3155],{"class":2785},"# Adjust weights later without provisioning new flows:\n",[1305,3157,3158,3160,3162,3165,3167,3169,3171,3173,3175,3177,3179,3181,3183],{"class":1307,"line":203},[1305,3159,2792],{"class":2791},[1305,3161,2796],{"class":2795},[1305,3163,3164],{"class":2795}," PATCH",[1305,3166,2802],{"class":2795},[1305,3168,2806],{"class":2805},[1305,3170,2809],{"class":2795},[1305,3172,2813],{"class":2812},[1305,3174,2816],{"class":2805},[1305,3176,2802],{"class":2795},[1305,3178,2806],{"class":2805},[1305,3180,2934],{"class":2795},[1305,3182,2816],{"class":2805},[1305,3184,2819],{"class":2812},[1305,3186,3187,3190],{"class":1307,"line":214},[1305,3188,3189],{"class":2795},"  http:\u002F\u002Flocalhost:8001\u002Fapi\u002Fv1\u002Fdeployments\u002Fassistant",[1305,3191,2819],{"class":2812},[1305,3193,3194,3196,3198],{"class":1307,"line":223},[1305,3195,2950],{"class":2795},[1305,3197,2953],{"class":2805},[1305,3199,1310],{"class":2795},[1305,3201,3202],{"class":1307,"line":229},[1305,3203,3015],{"class":2795},[1305,3205,3206],{"class":1307,"line":234},[1305,3207,3208],{"class":2795},"      {\"label\": \"stable\", \"flowId\": \"assistant\",                         \"weight\": 50},\n",[1305,3210,3211],{"class":1307,"line":240},[1305,3212,3213],{"class":2795},"      {\"label\": \"canary\", \"flowId\": \"flow.assistant-production-XXXXXX\",  \"weight\": 50}\n",[1305,3215,3216],{"class":1307,"line":246},[1305,3217,3030],{"class":2795},[1305,3219,3220,3222],{"class":1307,"line":251},[1305,3221,3035],{"class":2795},[1305,3223,2959],{"class":2805},[979,3225,3226,3227,3229,3230,3233,3234,3237],{},"The widget picks up the new split on the next ",[983,3228,1138],{}," call. ",[983,3231,3232],{},"GET \u002Fassistant\u002Fconfig?sessionId=X","\nnow returns ",[983,3235,3236],{},"activeVariant: \"canary\""," for sessions that bucket into the canary, so telemetry\ncan join on the label without a second round-trip.",[1060,3239,3241],{"id":3240},"flow-version-upgrades","Flow version upgrades",[979,3243,3244,3247,3248,3251,3252,3255,3256,3259,3260,3263],{},[983,3245,3246],{},"ensureFlow"," auto-upgrades a module-owned published version when the embedded\n",[983,3249,3250],{},"meta.schemaVersion"," advances past the stored one. User-owned versions (anything with a\n",[983,3253,3254],{},"CreatedBy"," other than ",[983,3257,3258],{},"assistant-module",") are left alone — never overwritten. Disable the\nauto-upgrade entirely with ",[983,3261,3262],{},"ASSISTANT_FLOW_SKIP_AUTO_UPGRADE=true"," for fully managed\ndeployments.",[1060,3265,3267],{"id":3266},"session-management","Session management",[979,3269,3270,3271,3274,3275,3278],{},"The client holds a UUID session id in ",[983,3272,3273],{},"localStorage[\"redelay.assistant.session\"]",". On each ",[983,3276,3277],{},"POST \u002Fassistant\u002Fmessages",":",[3280,3281,3282,3289,3292,3298],"ol",{},[1671,3283,3284,3285,3288],{},"Client sends ",[983,3286,3287],{},"sessionId"," in the body (omit on first ever message).",[1671,3290,3291],{},"Server generates one if missing.",[1671,3293,3294,3295,3297],{},"Server echoes it via ",[983,3296,1100],{}," so the client can persist.",[1671,3299,3300,3301,3304,3305,3309],{},"Every subsequent request uses the same id — the ",[983,3302,3303],{},"Chat"," document gets appended in place, TTL rolls forward on each turn, and sticky-by-session variant routing (",[1047,3306,3308],{"href":3307},"\u002Fdocs\u002Freference\u002Fdeployments#variants-and-routing","see Flow Templates",") routes the caller to the same variant for the life of the chat.",[979,3311,3312,3315],{},[983,3313,3314],{},"clear()"," rotates the id so a \"new chat\" UI button gets a fresh document rather than appending to the old one.",[1060,3317,3319],{"id":3318},"chat-persistence","Chat persistence",[979,3321,3322,3325,3326,3328],{},[983,3323,3324],{},"chats.Service"," owns ",[983,3327,1016],{},". Indexes:",[1668,3330,3331,3337,3342,3347],{},[1671,3332,3333,3336],{},[983,3334,3335],{},"{session_id: 1}"," unique",[1671,3338,3339],{},[983,3340,3341],{},"{user_id: 1, last_at: -1}",[1671,3343,3344],{},[983,3345,3346],{},"{flow_id: 1, variant_label: 1}",[1671,3348,3349,3352,3353,1052],{},[983,3350,3351],{},"{expires_at: 1}"," TTL (",[983,3354,3355],{},"expireAfterSeconds=0",[979,3357,3358,3359,3362,3363,3366,3367,3370],{},"Every append bumps ",[983,3360,3361],{},"expires_at = now + TTL",". Dormant chats are reaped automatically by Mongo's TTL monitor. The associated ",[983,3364,3365],{},"HandoffRequest"," (if any) is ",[1292,3368,3369],{},"not"," tied to the TTL — handoff rows survive TTL expiry because they're business audit.",[979,3372,3373],{},"Env config:",[988,3375,3376,3387],{},[991,3377,3378],{},[994,3379,3380,3383,3385],{},[997,3381,3382],{},"Env",[997,3384,1801],{},[997,3386,1002],{},[1007,3388,3389,3402,3422],{},[994,3390,3391,3396,3399],{},[1012,3392,3393],{},[983,3394,3395],{},"ASSISTANT_CHAT_TTL_DAYS",[1012,3397,3398],{},"30",[1012,3400,3401],{},"Chat retention",[994,3403,3404,3409,3412],{},[1012,3405,3406],{},[983,3407,3408],{},"ASSISTANT_ANONYMOUS_ALLOWED",[1012,3410,3411],{},"true",[1012,3413,3414,3415,1264,3418,3421],{},"Gate ",[983,3416,3417],{},"\u002Fmessages",[983,3419,3420],{},"\u002Fhandoff"," on auth",[994,3423,3424,3429,3431],{},[1012,3425,3426],{},[983,3427,3428],{},"ASSISTANT_HANDOFF_ENABLED",[1012,3430,3411],{},[1012,3432,3433],{},"Master switch for the handoff path",[1060,3435,1904],{"id":1408},[979,3437,3438,3439,3441],{},"When a user clicks \"Talk to a human\" in the widget (or a flow node explicitly publishes the event), ",[983,3440,1780],{}," does three things:",[3280,3443,3444,3453,3459],{},[1671,3445,3446,3449,3450,3452],{},[1292,3447,3448],{},"Persists"," a ",[983,3451,3365],{}," row with the transcript snapshot. Permanent — no TTL.",[1671,3454,3455,3458],{},[1292,3456,3457],{},"Attaches"," the handoff id back to the chat so admin UIs can navigate either way.",[1671,3460,3461,3464,3465,3467,3468,1101],{},[1292,3462,3463],{},"Publishes"," ",[983,3466,1129],{}," via the framework ",[983,3469,3470],{},"EventBus",[979,3472,3473,3474,3476,3477,1739,3480,3483,3484,3486,3487,3490],{},"Notification is entirely decoupled — the service never sends email. A downstream flow subscribes to the event and does whatever the project needs (email, Slack, PagerDuty, CRM push). The ",[983,3475,1551],{}," flow template ships pre-wired for email: ",[983,3478,3479],{},"event-source",[983,3481,3482],{},"redelay\u002Femit-event"," (",[983,3485,1565],{}," with a rendered template) → ",[983,3488,3489],{},"end",". Customise in Studio, or replace entirely.",[979,3492,3493,3494,3497],{},"Dedup: a second pending handoff for the same session returns ",[983,3495,3496],{},"409 Conflict",". Users hitting the button repeatedly don't flood the admin inbox.",[1065,3499,3501],{"id":3500},"event-contract","Event contract",[1296,3503,3507],{"className":3504,"code":3505,"language":3506,"meta":1301,"style":1301},"language-yaml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","name: assistant.handoff_requested\nentityType: assistant_handoff\naction: requested\ntopic: assistant.handoff_requested\npayload:\n  handoffId:   string (ObjectID hex)\n  chatId:      string (ObjectID hex, \"\" when no chat)\n  sessionId:   string\n  userId:      string (optional — authed callers only)\n  email:       string (always set)\n  phone:       string (optional)\n  reason:      string (optional, free-form)\n  priority:    \"low\" | \"normal\" | \"high\"\n  transcript:  string (plain-text dump at request time)\n  requestedAt: string (RFC3339)\n","yaml",[983,3508,3509,3519,3529,3538,3547,3555,3565,3575,3585,3595,3605,3615,3625,3647,3652],{"__ignoreMap":1301},[1305,3510,3511,3514,3516],{"class":1307,"line":10},[1305,3512,2010],{"class":3513},"swJcz",[1305,3515,3278],{"class":2805},[1305,3517,3518],{"class":2795}," assistant.handoff_requested\n",[1305,3520,3521,3524,3526],{"class":1307,"line":16},[1305,3522,3523],{"class":3513},"entityType",[1305,3525,3278],{"class":2805},[1305,3527,3528],{"class":2795}," assistant_handoff\n",[1305,3530,3531,3533,3535],{"class":1307,"line":22},[1305,3532,1776],{"class":3513},[1305,3534,3278],{"class":2805},[1305,3536,3537],{"class":2795}," requested\n",[1305,3539,3540,3543,3545],{"class":1307,"line":51},[1305,3541,3542],{"class":3513},"topic",[1305,3544,3278],{"class":2805},[1305,3546,3518],{"class":2795},[1305,3548,3549,3552],{"class":1307,"line":57},[1305,3550,3551],{"class":3513},"payload",[1305,3553,3554],{"class":2805},":\n",[1305,3556,3557,3560,3562],{"class":1307,"line":102},[1305,3558,3559],{"class":3513},"  handoffId",[1305,3561,3278],{"class":2805},[1305,3563,3564],{"class":2795},"   string (ObjectID hex)\n",[1305,3566,3567,3570,3572],{"class":1307,"line":108},[1305,3568,3569],{"class":3513},"  chatId",[1305,3571,3278],{"class":2805},[1305,3573,3574],{"class":2795},"      string (ObjectID hex, \"\" when no chat)\n",[1305,3576,3577,3580,3582],{"class":1307,"line":114},[1305,3578,3579],{"class":3513},"  sessionId",[1305,3581,3278],{"class":2805},[1305,3583,3584],{"class":2795},"   string\n",[1305,3586,3587,3590,3592],{"class":1307,"line":120},[1305,3588,3589],{"class":3513},"  userId",[1305,3591,3278],{"class":2805},[1305,3593,3594],{"class":2795},"      string (optional — authed callers only)\n",[1305,3596,3597,3600,3602],{"class":1307,"line":181},[1305,3598,3599],{"class":3513},"  email",[1305,3601,3278],{"class":2805},[1305,3603,3604],{"class":2795},"       string (always set)\n",[1305,3606,3607,3610,3612],{"class":1307,"line":186},[1305,3608,3609],{"class":3513},"  phone",[1305,3611,3278],{"class":2805},[1305,3613,3614],{"class":2795},"       string (optional)\n",[1305,3616,3617,3620,3622],{"class":1307,"line":191},[1305,3618,3619],{"class":3513},"  reason",[1305,3621,3278],{"class":2805},[1305,3623,3624],{"class":2795},"      string (optional, free-form)\n",[1305,3626,3627,3630,3632,3635,3638,3640,3644],{"class":1307,"line":197},[1305,3628,3629],{"class":3513},"  priority",[1305,3631,3278],{"class":2805},[1305,3633,3634],{"class":2805},"    \"",[1305,3636,3637],{"class":2795},"low",[1305,3639,2816],{"class":2805},[1305,3641,3643],{"class":3642},"s7zQu"," |",[1305,3645,3646],{"class":2812}," \"normal\" | \"high\"\n",[1305,3648,3649],{"class":1307,"line":203},[1305,3650,3651],{"class":2795},"  transcript:  string (plain-text dump at request time)\n",[1305,3653,3654],{"class":1307,"line":214},[1305,3655,3656],{"class":2795},"  requestedAt: string (RFC3339)\n",[979,3658,3659,3660,3662,3663,1101],{},"Handoff schemas + the full ",[983,3661,3365],{}," type are defined in ",[983,3664,3665],{},"backend\u002Fmodules\u002Fassistant\u002Fhandoff\u002Fmodel.go",[1060,3667,3669],{"id":3668},"vue-integration","Vue integration",[1296,3671,3675],{"className":3672,"code":3673,"language":3674,"meta":1301,"style":1301},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","const {\n  messages, isOpen, isLoading,\n  sessionID, handoffRequested,\n  send, clear, requestHandoff,\n} = useChat()\n\n\u002F\u002F Chat normally.\nawait send(\"How do flows work?\")\n\n\u002F\u002F User asks for a human.\nconst res = await requestHandoff({\n  email: 'me@example.com',\n  reason: 'billing question',\n  priority: 'normal',\n})\nif (res.ok) {\n  \u002F\u002F show res.message\n}\n","ts",[983,3676,3677,3686,3704,3716,3733,3748,3752,3757,3778,3782,3787,3806,3822,3837,3851,3857,3872,3877],{"__ignoreMap":1301},[1305,3678,3679,3683],{"class":1307,"line":10},[1305,3680,3682],{"class":3681},"spNyl","const",[1305,3684,3685],{"class":2805}," {\n",[1305,3687,3688,3691,3694,3697,3699,3702],{"class":1307,"line":16},[1305,3689,3690],{"class":2812},"  messages",[1305,3692,3693],{"class":2805},",",[1305,3695,3696],{"class":2812}," isOpen",[1305,3698,3693],{"class":2805},[1305,3700,3701],{"class":2812}," isLoading",[1305,3703,2014],{"class":2805},[1305,3705,3706,3709,3711,3714],{"class":1307,"line":22},[1305,3707,3708],{"class":2812},"  sessionID",[1305,3710,3693],{"class":2805},[1305,3712,3713],{"class":2812}," handoffRequested",[1305,3715,2014],{"class":2805},[1305,3717,3718,3721,3723,3726,3728,3731],{"class":1307,"line":51},[1305,3719,3720],{"class":2812},"  send",[1305,3722,3693],{"class":2805},[1305,3724,3725],{"class":2812}," clear",[1305,3727,3693],{"class":2805},[1305,3729,3730],{"class":2812}," requestHandoff",[1305,3732,2014],{"class":2805},[1305,3734,3735,3738,3741,3745],{"class":1307,"line":57},[1305,3736,3737],{"class":2805},"}",[1305,3739,3740],{"class":2805}," =",[1305,3742,3744],{"class":3743},"s2Zo4"," useChat",[1305,3746,3747],{"class":2812},"()\n",[1305,3749,3750],{"class":1307,"line":102},[1305,3751,1619],{"emptyLinePlaceholder":1618},[1305,3753,3754],{"class":1307,"line":108},[1305,3755,3756],{"class":2785},"\u002F\u002F Chat normally.\n",[1305,3758,3759,3762,3765,3768,3770,3773,3775],{"class":1307,"line":114},[1305,3760,3761],{"class":3642},"await",[1305,3763,3764],{"class":3743}," send",[1305,3766,3767],{"class":2812},"(",[1305,3769,2816],{"class":2805},[1305,3771,3772],{"class":2795},"How do flows work?",[1305,3774,2816],{"class":2805},[1305,3776,3777],{"class":2812},")\n",[1305,3779,3780],{"class":1307,"line":120},[1305,3781,1619],{"emptyLinePlaceholder":1618},[1305,3783,3784],{"class":1307,"line":181},[1305,3785,3786],{"class":2785},"\u002F\u002F User asks for a human.\n",[1305,3788,3789,3791,3794,3797,3800,3802,3804],{"class":1307,"line":186},[1305,3790,3682],{"class":3681},[1305,3792,3793],{"class":2812}," res ",[1305,3795,3796],{"class":2805},"=",[1305,3798,3799],{"class":3642}," await",[1305,3801,3730],{"class":3743},[1305,3803,3767],{"class":2812},[1305,3805,1310],{"class":2805},[1305,3807,3808,3810,3812,3814,3817,3820],{"class":1307,"line":191},[1305,3809,3599],{"class":3513},[1305,3811,3278],{"class":2805},[1305,3813,2953],{"class":2805},[1305,3815,3816],{"class":2795},"me@example.com",[1305,3818,3819],{"class":2805},"'",[1305,3821,2014],{"class":2805},[1305,3823,3824,3826,3828,3830,3833,3835],{"class":1307,"line":197},[1305,3825,3619],{"class":3513},[1305,3827,3278],{"class":2805},[1305,3829,2953],{"class":2805},[1305,3831,3832],{"class":2795},"billing question",[1305,3834,3819],{"class":2805},[1305,3836,2014],{"class":2805},[1305,3838,3839,3841,3843,3845,3847,3849],{"class":1307,"line":203},[1305,3840,3629],{"class":3513},[1305,3842,3278],{"class":2805},[1305,3844,2953],{"class":2805},[1305,3846,1823],{"class":2795},[1305,3848,3819],{"class":2805},[1305,3850,2014],{"class":2805},[1305,3852,3853,3855],{"class":1307,"line":214},[1305,3854,3737],{"class":2805},[1305,3856,3777],{"class":2812},[1305,3858,3859,3862,3865,3867,3870],{"class":1307,"line":223},[1305,3860,3861],{"class":3642},"if",[1305,3863,3864],{"class":2812}," (res",[1305,3866,1101],{"class":2805},[1305,3868,3869],{"class":2812},"ok) ",[1305,3871,1310],{"class":2805},[1305,3873,3874],{"class":1307,"line":229},[1305,3875,3876],{"class":2785},"  \u002F\u002F show res.message\n",[1305,3878,3879],{"class":1307,"line":234},[1305,3880,1377],{"class":2805},[979,3882,3883,3886,3887,3890,3891,3894],{},[983,3884,3885],{},"requestHandoff"," returns ",[983,3888,3889],{},"{ok, message}"," so the UI can render inline feedback without try\u002Fcatch. The handoff button gates itself on ",[983,3892,3893],{},"handoffRequested"," so users can't double-submit.",[1060,3896,3898],{"id":3897},"data-model-summary","Data model summary",[1296,3900,3903],{"className":3901,"code":3902,"language":1467,"meta":1301},[1465],"Chat            (assistant_chats, TTL)\n├─ SessionID         unique index\n├─ FlowID + VersionHash + VariantLabel    stamped at first create\n├─ Messages[]        append-only (user + assistant turns)\n├─ RunIDs[]          set of flow-run ids that served this chat\n├─ ExpiresAt         bumped on every append\n└─ HandoffID         set when user escalated\n\nHandoffRequest  (assistant_handoffs, permanent)\n├─ ChatID + SessionID\n├─ Email + Phone + Reason\n├─ Transcript        snapshot — readable after chat TTL\n├─ Priority          low | normal | high\n├─ Status            pending | contacted | resolved | dismissed\n└─ ContactedAt + ContactedBy + Notes   stamped by admin PATCH\n",[983,3904,3902],{"__ignoreMap":1301},[1060,3906,3908],{"id":3907},"testing","Testing",[979,3910,3911],{},"Three test packages cover the full surface:",[1668,3913,3914,3920,3926,3940],{},[1671,3915,3916,3919],{},[983,3917,3918],{},"backend\u002Fmodules\u002Fassistant\u002Fchats\u002Fservice_test.go"," — idempotent create, TTL bump, message persistence, run-id set tracking, list pagination, handoff attach.",[1671,3921,3922,3925],{},[983,3923,3924],{},"backend\u002Fmodules\u002Fassistant\u002Fhandoff\u002Fservice_test.go"," — persist-and-publish happy path, dedup, validation, no-chat fallback, status filter, state transitions, authed user-context propagation, RFC3339 format.",[1671,3927,3928,1956,3931,1197,3934,1197,3937,3939],{},[983,3929,3930],{},"backend\u002Fmodules\u002Fassistant\u002Fpublic_handlers_test.go",[983,3932,3933],{},"\u002Fconfig",[983,3935,3936],{},"\u002Fchats\u002Fme\u002F{id}",[983,3938,3420],{}," end-to-end including dedup and anonymous gating.",[1671,3941,3942,3945],{},[983,3943,3944],{},"backend\u002Fmodules\u002Fassistant\u002Fadmin\u002Fmodule_test.go"," — admin listings + status transitions through the real admin handlers.",[979,3947,3948,3949,3952],{},"Plus the existing ",[983,3950,3951],{},"module_test.go"," covers the SSE pump, flow seeding, and content extraction.",[3954,3955,3956],"style",{},"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);}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}",{"title":1301,"searchDepth":16,"depth":16,"links":3958},[3959,3964,3965,3966,3967,3969,3970,3976,3987,3988,3989,3990,3993,3994,3995],{"id":1062,"depth":16,"text":1063,"children":3960},[3961,3962],{"id":1067,"depth":22,"text":1068},{"id":1163,"depth":22,"text":3963},"Admin-only (admin-api — blank-import backend\u002Fmodules\u002Fassistant\u002Fadmin)",{"id":1283,"depth":16,"text":1284},{"id":1457,"depth":16,"text":1458},{"id":1569,"depth":16,"text":1570},{"id":1753,"depth":16,"text":3968},"FlowDSL node: redelay\u002Fassistant-handoff-request",{"id":1941,"depth":16,"text":1942},{"id":1987,"depth":16,"text":1988,"children":3971},[3972,3973,3974,3975],{"id":2029,"depth":22,"text":2030},{"id":2344,"depth":22,"text":2345},{"id":2541,"depth":22,"text":2542},{"id":2619,"depth":22,"text":2620},{"id":2665,"depth":16,"text":2666,"children":3977},[3978,3979,3980,3981,3983,3984,3985],{"id":2715,"depth":22,"text":2716},{"id":2733,"depth":22,"text":2734},{"id":2737,"depth":22,"text":2738},{"id":2768,"depth":22,"text":3982},"2. POST \u002Fassistant\u002Freset?template= — one-liner template switcher",{"id":2868,"depth":22,"text":2869},{"id":2962,"depth":22,"text":2963},{"id":3045,"depth":22,"text":3986},"5. Weighted variants across different flows — deployment-level A\u002FB",{"id":3240,"depth":16,"text":3241},{"id":3266,"depth":16,"text":3267},{"id":3318,"depth":16,"text":3319},{"id":1408,"depth":16,"text":1904,"children":3991},[3992],{"id":3500,"depth":22,"text":3501},{"id":3668,"depth":16,"text":3669},{"id":3897,"depth":16,"text":3898},{"id":3907,"depth":16,"text":3908},"Project-local AI assistant module — FlowDSL-backed chat, persisted conversations with TTL, LLM cost tracking, and a human-handoff path that fans out via the event bus.","md",null,{},{"order":240,"icon":241},{"title":237,"description":3996},"yLW_5tdwnn2tdTpNy6kswWtpaFJ3VYTwazu4FJJ73EM",[4004,4006],{"title":231,"path":232,"stem":233,"description":4005,"order":234,"icon":235,"children":-1},"Contributing starter flows from a Go module — the TemplateProvider interface, JSON document shape, and lifecycle.",{"title":243,"path":244,"stem":245,"description":4007,"order":246,"icon":41,"children":-1},"Cross-container coordination layer — pub\u002Fsub invalidation, fan-out streams, and watchable KV for multi-container Redelay deployments.",1790332226537]