[{"data":1,"prerenderedAt":582},["ShallowReactive",2],{"docs-\u002Fdocs\u002Fv2\u002Fagent\u002Fui-handle":3},{"id":4,"title":5,"body":6,"description":575,"extension":576,"meta":577,"navigation":143,"path":578,"seo":579,"stem":580,"__hash__":581},"docs\u002Fdocs\u002Fv2\u002Fagent\u002Fui-handle.md","axon.ui",{"type":7,"value":8,"toc":570},"minimark",[9,13,20,23,30,37,258,261,286,289,313,317,326,534,537,541,546,563,566],[10,11,5],"h1",{"id":12},"axonui",[14,15,16,19],"p",{},[17,18,5],"code",{}," is the narrow host interaction surface. It lets route code, scripts, and policy escalation handlers ask the connected TUI for a decision.",[14,21,22],{},"It is not the agent loop. It does not call the engine. It must never block forever.",[24,25,27],"h2",{"id":26},"axonuiask",[17,28,29],{},"axon.ui.ask",[14,31,32,33,36],{},"Use ",[17,34,35],{},"axon.ui.ask(...)"," when code needs an explicit user decision before continuing.",[38,39,44],"pre",{"className":40,"code":41,"language":42,"meta":43,"style":43},"language-ts shiki shiki-themes dark-plus","const decision = await axon.ui.ask({\n    message: \"Deploy to production?\",\n    options: [\"deploy\", \"cancel\"],\n    timeoutMs: 60_000,\n})\n\nif (\"unavailable\" in decision || \"timeout\" in decision) {\n    return { status: \"cancelled\", message: \"No changes were made.\" }\n}\n\nif (decision.selected !== \"deploy\") {\n    return { status: \"cancelled\", message: \"No changes were made.\" }\n}\n","ts","",[17,45,46,86,99,120,132,138,145,175,201,207,212,234,253],{"__ignoreMap":43},[47,48,51,55,59,63,67,71,74,77,79,83],"span",{"class":49,"line":50},"line",1,[47,52,54],{"class":53},"scz_3","const",[47,56,58],{"class":57},"s9McN"," decision",[47,60,62],{"class":61},"sTNBD"," = ",[47,64,66],{"class":65},"sYbnZ","await",[47,68,70],{"class":69},"s3F5K"," axon",[47,72,73],{"class":61},".",[47,75,76],{"class":69},"ui",[47,78,73],{"class":61},[47,80,82],{"class":81},"sCudf","ask",[47,84,85],{"class":61},"({\n",[47,87,89,92,96],{"class":49,"line":88},2,[47,90,91],{"class":69},"    message:",[47,93,95],{"class":94},"sKc5r"," \"Deploy to production?\"",[47,97,98],{"class":61},",\n",[47,100,102,105,108,111,114,117],{"class":49,"line":101},3,[47,103,104],{"class":69},"    options:",[47,106,107],{"class":61}," [",[47,109,110],{"class":94},"\"deploy\"",[47,112,113],{"class":61},", ",[47,115,116],{"class":94},"\"cancel\"",[47,118,119],{"class":61},"],\n",[47,121,123,126,130],{"class":49,"line":122},4,[47,124,125],{"class":69},"    timeoutMs:",[47,127,129],{"class":128},"sDGX8"," 60_000",[47,131,98],{"class":61},[47,133,135],{"class":49,"line":134},5,[47,136,137],{"class":61},"})\n",[47,139,141],{"class":49,"line":140},6,[47,142,144],{"emptyLinePlaceholder":143},true,"\n",[47,146,148,151,154,157,160,162,165,168,170,172],{"class":49,"line":147},7,[47,149,150],{"class":65},"if",[47,152,153],{"class":61}," (",[47,155,156],{"class":94},"\"unavailable\"",[47,158,159],{"class":53}," in",[47,161,58],{"class":69},[47,163,164],{"class":61}," || ",[47,166,167],{"class":94},"\"timeout\"",[47,169,159],{"class":53},[47,171,58],{"class":69},[47,173,174],{"class":61},") {\n",[47,176,178,181,184,187,190,192,195,198],{"class":49,"line":177},8,[47,179,180],{"class":65},"    return",[47,182,183],{"class":61}," { ",[47,185,186],{"class":69},"status:",[47,188,189],{"class":94}," \"cancelled\"",[47,191,113],{"class":61},[47,193,194],{"class":69},"message:",[47,196,197],{"class":94}," \"No changes were made.\"",[47,199,200],{"class":61}," }\n",[47,202,204],{"class":49,"line":203},9,[47,205,206],{"class":61},"}\n",[47,208,210],{"class":49,"line":209},10,[47,211,144],{"emptyLinePlaceholder":143},[47,213,215,217,219,222,224,227,230,232],{"class":49,"line":214},11,[47,216,150],{"class":65},[47,218,153],{"class":61},[47,220,221],{"class":69},"decision",[47,223,73],{"class":61},[47,225,226],{"class":69},"selected",[47,228,229],{"class":61}," !== ",[47,231,110],{"class":94},[47,233,174],{"class":61},[47,235,237,239,241,243,245,247,249,251],{"class":49,"line":236},12,[47,238,180],{"class":65},[47,240,183],{"class":61},[47,242,186],{"class":69},[47,244,189],{"class":94},[47,246,113],{"class":61},[47,248,194],{"class":69},[47,250,197],{"class":94},[47,252,200],{"class":61},[47,254,256],{"class":49,"line":255},13,[47,257,206],{"class":61},[14,259,260],{},"Return shape — discriminated by key presence:",[262,263,264,271,280],"ul",{},[265,266,267,270],"li",{},[17,268,269],{},"{ selected: string }"," — user picked an option",[265,272,273,276,277],{},[17,274,275],{},"{ timeout: true }"," — no answer before ",[17,278,279],{},"timeoutMs",[265,281,282,285],{},[17,283,284],{},"{ unavailable: true }"," — no connected TUI host",[14,287,288],{},"Rules:",[262,290,291,299,307,310],{},[265,292,293,294,296,297,73],{},"If no host can answer, ",[17,295,29],{}," returns ",[17,298,284],{},[265,300,301,302,304,305,73],{},"If no answer arrives before ",[17,303,279],{},", it returns ",[17,306,275],{},[265,308,309],{},"Headless and background agents must not assume a connected UI.",[265,311,312],{},"Always return an HTTP response from routes.",[24,314,316],{"id":315},"policy-escalation","Policy escalation",[14,318,319,320,322,323,325],{},"Policy escalation is separate from ",[17,321,35],{},". Escalation is raised by the runtime or capsule when policy requires approval for a mediated action. A hook may use ",[17,324,35],{}," to ask the connected user.",[38,327,329],{"className":40,"code":328,"language":42,"meta":43,"style":43},"axon.hooks.hook(\"policy:escalation\", async request => {\n    const decision = await axon.ui.ask({\n        message: request.title ?? \"Approve action?\",\n        options: [\"allow\", \"deny\"],\n        timeoutMs: request.timeoutMs,\n    })\n\n    return {\n        allow: \"selected\" in decision && decision.selected === \"allow\",\n        reason: \"selected\" in decision ? decision.selected : Object.keys(decision)[0],\n    }\n})\n",[17,330,331,366,389,409,426,439,444,448,454,482,525,530],{"__ignoreMap":43},[47,332,333,336,338,341,343,346,349,352,354,357,360,363],{"class":49,"line":50},[47,334,335],{"class":69},"axon",[47,337,73],{"class":61},[47,339,340],{"class":69},"hooks",[47,342,73],{"class":61},[47,344,345],{"class":81},"hook",[47,347,348],{"class":61},"(",[47,350,351],{"class":94},"\"policy:escalation\"",[47,353,113],{"class":61},[47,355,356],{"class":53},"async",[47,358,359],{"class":69}," request",[47,361,362],{"class":53}," =>",[47,364,365],{"class":61}," {\n",[47,367,368,371,373,375,377,379,381,383,385,387],{"class":49,"line":88},[47,369,370],{"class":53},"    const",[47,372,58],{"class":57},[47,374,62],{"class":61},[47,376,66],{"class":65},[47,378,70],{"class":69},[47,380,73],{"class":61},[47,382,76],{"class":69},[47,384,73],{"class":61},[47,386,82],{"class":81},[47,388,85],{"class":61},[47,390,391,394,396,398,401,404,407],{"class":49,"line":101},[47,392,393],{"class":69},"        message:",[47,395,359],{"class":69},[47,397,73],{"class":61},[47,399,400],{"class":69},"title",[47,402,403],{"class":61}," ?? ",[47,405,406],{"class":94},"\"Approve action?\"",[47,408,98],{"class":61},[47,410,411,414,416,419,421,424],{"class":49,"line":122},[47,412,413],{"class":69},"        options:",[47,415,107],{"class":61},[47,417,418],{"class":94},"\"allow\"",[47,420,113],{"class":61},[47,422,423],{"class":94},"\"deny\"",[47,425,119],{"class":61},[47,427,428,431,433,435,437],{"class":49,"line":134},[47,429,430],{"class":69},"        timeoutMs:",[47,432,359],{"class":69},[47,434,73],{"class":61},[47,436,279],{"class":69},[47,438,98],{"class":61},[47,440,441],{"class":49,"line":140},[47,442,443],{"class":61},"    })\n",[47,445,446],{"class":49,"line":147},[47,447,144],{"emptyLinePlaceholder":143},[47,449,450,452],{"class":49,"line":177},[47,451,180],{"class":65},[47,453,365],{"class":61},[47,455,456,459,462,464,466,469,471,473,475,478,480],{"class":49,"line":203},[47,457,458],{"class":69},"        allow:",[47,460,461],{"class":94}," \"selected\"",[47,463,159],{"class":53},[47,465,58],{"class":69},[47,467,468],{"class":61}," && ",[47,470,221],{"class":69},[47,472,73],{"class":61},[47,474,226],{"class":69},[47,476,477],{"class":61}," === ",[47,479,418],{"class":94},[47,481,98],{"class":61},[47,483,484,487,489,491,493,496,498,500,502,505,508,510,513,515,517,520,523],{"class":49,"line":209},[47,485,486],{"class":69},"        reason:",[47,488,461],{"class":94},[47,490,159],{"class":53},[47,492,58],{"class":69},[47,494,495],{"class":61}," ? ",[47,497,221],{"class":69},[47,499,73],{"class":61},[47,501,226],{"class":69},[47,503,504],{"class":61}," : ",[47,506,507],{"class":69},"Object",[47,509,73],{"class":61},[47,511,512],{"class":81},"keys",[47,514,348],{"class":61},[47,516,221],{"class":69},[47,518,519],{"class":61},")[",[47,521,522],{"class":128},"0",[47,524,119],{"class":61},[47,526,527],{"class":49,"line":214},[47,528,529],{"class":61},"    }\n",[47,531,532],{"class":49,"line":236},[47,533,137],{"class":61},[14,535,536],{},"If no resolver or connected host can answer, escalation denies. V1 does not include external approval inboxes, durable approval queues, or background approval workflows.",[24,538,540],{"id":539},"what-is-excluded","What is excluded",[14,542,543,545],{},[17,544,5],{}," is deliberately small:",[262,547,548,551,554,557,560],{},[265,549,550],{},"no layout control",[265,552,553],{},"no custom panels",[265,555,556],{},"no arbitrary TUI mutation",[265,558,559],{},"no direct auth changes",[265,561,562],{},"no policy bypass",[14,564,565],{},"The UI can ask and display. Axon still owns runtime semantics.",[567,568,569],"style",{},"html pre.shiki code .scz_3, html code.shiki .scz_3{--shiki-default:#569CD6}html pre.shiki code .s9McN, html code.shiki .s9McN{--shiki-default:#4FC1FF}html pre.shiki code .sTNBD, html code.shiki .sTNBD{--shiki-default:#D4D4D4}html pre.shiki code .sYbnZ, html code.shiki .sYbnZ{--shiki-default:#C586C0}html pre.shiki code .s3F5K, html code.shiki .s3F5K{--shiki-default:#9CDCFE}html pre.shiki code .sCudf, html code.shiki .sCudf{--shiki-default:#DCDCAA}html pre.shiki code .sKc5r, html code.shiki .sKc5r{--shiki-default:#CE9178}html pre.shiki code .sDGX8, html code.shiki .sDGX8{--shiki-default:#B5CEA8}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);}",{"title":43,"searchDepth":88,"depth":88,"links":571},[572,573,574],{"id":26,"depth":88,"text":29},{"id":315,"depth":88,"text":316},{"id":539,"depth":88,"text":540},"axon.ui is the narrow host interaction surface. It lets route code, scripts, and policy escalation handlers ask the connected TUI for a decision.","md",{},"\u002Fdocs\u002Fv2\u002Fagent\u002Fui-handle",{"title":5,"description":575},"docs\u002Fv2\u002Fagent\u002Fui-handle","7S_zL4n_09ppDRn93VIjQhvPC4UVZe9Dv_zR0jnMUaI",1785671805784]