[{"data":1,"prerenderedAt":606},["ShallowReactive",2],{"docs-\u002Fdocs\u002Fv2\u002Fmodules\u002Fserver":3},{"id":4,"title":5,"body":6,"description":16,"extension":600,"meta":601,"navigation":179,"path":602,"seo":603,"stem":604,"__hash__":605},"docs\u002Fdocs\u002Fv2\u002Fmodules\u002Fserver.md","server\u002F",{"type":7,"value":8,"toc":595},"minimark",[9,13,17,22,33,64,67,440,443,447,450,453,581,585,588,591],[10,11,5],"h1",{"id":12},"server",[14,15,16],"p",{},"Route and plugin contributions. Modules that integrate external services ship their\nHTTP surface here — the agent author gets a working webhook receiver without writing\nverification or normalization code.",[18,19,21],"h2",{"id":20},"serverapi","server\u002Fapi\u002F",[14,23,24,25,28,29,32],{},"Files in ",[26,27,21],"code",{}," are mounted on the parent agent's HTTP server at ",[26,30,31],{},"\u002Fapi\u002F*",".\nThe naming convention follows the same pattern as agent routes:",[34,35,40],"pre",{"className":36,"code":37,"language":38,"meta":39,"style":39},"language-bash shiki shiki-themes dark-plus","server\u002Fapi\u002Fgithub.post.ts    # → POST \u002Fapi\u002Fgithub\nserver\u002Fapi\u002Fstripe.post.ts    # → POST \u002Fapi\u002Fstripe\n","bash","",[26,41,42,55],{"__ignoreMap":39},[43,44,47,51],"span",{"class":45,"line":46},"line",1,[43,48,50],{"class":49},"sCudf","server\u002Fapi\u002Fgithub.post.ts",[43,52,54],{"class":53},"sOLPB","    # → POST \u002Fapi\u002Fgithub\n",[43,56,58,61],{"class":45,"line":57},2,[43,59,60],{"class":49},"server\u002Fapi\u002Fstripe.post.ts",[43,62,63],{"class":53},"    # → POST \u002Fapi\u002Fstripe\n",[14,65,66],{},"The canonical pattern for a connector route: verify the inbound payload, normalize\nit, emit a hook. Nothing else.",[34,68,72],{"className":69,"code":70,"language":71,"meta":39,"style":39},"language-ts shiki shiki-themes dark-plus","\u002F\u002F server\u002Fapi\u002Fgithub.post.ts\nexport default defineEventHandler(async (event) => {\n    const rawBody = (await readRawBody(event)) ?? \"\"\n    const sig = getRequestHeader(event, \"x-hub-signature-256\") ?? \"\"\n\n    if (!verifySignature(rawBody, sig, process.env.GITHUB_WEBHOOK_SECRET!)) {\n        throw createError({ statusCode: 403, message: \"invalid signature\" })\n    }\n\n    const payload = JSON.parse(rawBody)\n\n    await axon.callHook(\"github:issue.opened\", {\n        number: payload.issue.number,\n        title: payload.issue.title,\n        labels: payload.issue.labels.map((l: any) => l.name),\n    })\n\n    return { ok: true }\n})\n","ts",[26,73,74,79,115,145,174,181,222,252,258,263,288,293,315,336,355,405,411,416,434],{"__ignoreMap":39},[43,75,76],{"class":45,"line":46},[43,77,78],{"class":53},"\u002F\u002F server\u002Fapi\u002Fgithub.post.ts\n",[43,80,81,85,88,91,95,99,102,106,109,112],{"class":45,"line":57},[43,82,84],{"class":83},"sYbnZ","export",[43,86,87],{"class":83}," default",[43,89,90],{"class":49}," defineEventHandler",[43,92,94],{"class":93},"sTNBD","(",[43,96,98],{"class":97},"scz_3","async",[43,100,101],{"class":93}," (",[43,103,105],{"class":104},"s3F5K","event",[43,107,108],{"class":93},") ",[43,110,111],{"class":97},"=>",[43,113,114],{"class":93}," {\n",[43,116,118,121,125,128,131,134,136,138,141],{"class":45,"line":117},3,[43,119,120],{"class":97},"    const",[43,122,124],{"class":123},"s9McN"," rawBody",[43,126,127],{"class":93}," = (",[43,129,130],{"class":83},"await",[43,132,133],{"class":49}," readRawBody",[43,135,94],{"class":93},[43,137,105],{"class":104},[43,139,140],{"class":93},")) ?? ",[43,142,144],{"class":143},"sKc5r","\"\"\n",[43,146,148,150,153,156,159,161,163,166,169,172],{"class":45,"line":147},4,[43,149,120],{"class":97},[43,151,152],{"class":123}," sig",[43,154,155],{"class":93}," = ",[43,157,158],{"class":49},"getRequestHeader",[43,160,94],{"class":93},[43,162,105],{"class":104},[43,164,165],{"class":93},", ",[43,167,168],{"class":143},"\"x-hub-signature-256\"",[43,170,171],{"class":93},") ?? ",[43,173,144],{"class":143},[43,175,177],{"class":45,"line":176},5,[43,178,180],{"emptyLinePlaceholder":179},true,"\n",[43,182,184,187,190,193,195,198,200,203,205,208,211,214,216,219],{"class":45,"line":183},6,[43,185,186],{"class":83},"    if",[43,188,189],{"class":93}," (!",[43,191,192],{"class":49},"verifySignature",[43,194,94],{"class":93},[43,196,197],{"class":104},"rawBody",[43,199,165],{"class":93},[43,201,202],{"class":104},"sig",[43,204,165],{"class":93},[43,206,207],{"class":104},"process",[43,209,210],{"class":93},".",[43,212,213],{"class":104},"env",[43,215,210],{"class":93},[43,217,218],{"class":123},"GITHUB_WEBHOOK_SECRET",[43,220,221],{"class":93},"!)) {\n",[43,223,225,228,231,234,237,241,243,246,249],{"class":45,"line":224},7,[43,226,227],{"class":83},"        throw",[43,229,230],{"class":49}," createError",[43,232,233],{"class":93},"({ ",[43,235,236],{"class":104},"statusCode:",[43,238,240],{"class":239},"sDGX8"," 403",[43,242,165],{"class":93},[43,244,245],{"class":104},"message:",[43,247,248],{"class":143}," \"invalid signature\"",[43,250,251],{"class":93}," })\n",[43,253,255],{"class":45,"line":254},8,[43,256,257],{"class":93},"    }\n",[43,259,261],{"class":45,"line":260},9,[43,262,180],{"emptyLinePlaceholder":179},[43,264,266,268,271,273,276,278,281,283,285],{"class":45,"line":265},10,[43,267,120],{"class":97},[43,269,270],{"class":123}," payload",[43,272,155],{"class":93},[43,274,275],{"class":123},"JSON",[43,277,210],{"class":93},[43,279,280],{"class":49},"parse",[43,282,94],{"class":93},[43,284,197],{"class":104},[43,286,287],{"class":93},")\n",[43,289,291],{"class":45,"line":290},11,[43,292,180],{"emptyLinePlaceholder":179},[43,294,296,299,302,304,307,309,312],{"class":45,"line":295},12,[43,297,298],{"class":83},"    await",[43,300,301],{"class":104}," axon",[43,303,210],{"class":93},[43,305,306],{"class":49},"callHook",[43,308,94],{"class":93},[43,310,311],{"class":143},"\"github:issue.opened\"",[43,313,314],{"class":93},", {\n",[43,316,318,321,323,325,328,330,333],{"class":45,"line":317},13,[43,319,320],{"class":104},"        number:",[43,322,270],{"class":104},[43,324,210],{"class":93},[43,326,327],{"class":104},"issue",[43,329,210],{"class":93},[43,331,332],{"class":104},"number",[43,334,335],{"class":93},",\n",[43,337,339,342,344,346,348,350,353],{"class":45,"line":338},14,[43,340,341],{"class":104},"        title:",[43,343,270],{"class":104},[43,345,210],{"class":93},[43,347,327],{"class":104},[43,349,210],{"class":93},[43,351,352],{"class":104},"title",[43,354,335],{"class":93},[43,356,358,361,363,365,367,369,372,374,377,380,383,386,390,392,394,397,399,402],{"class":45,"line":357},15,[43,359,360],{"class":104},"        labels:",[43,362,270],{"class":104},[43,364,210],{"class":93},[43,366,327],{"class":104},[43,368,210],{"class":93},[43,370,371],{"class":104},"labels",[43,373,210],{"class":93},[43,375,376],{"class":49},"map",[43,378,379],{"class":93},"((",[43,381,382],{"class":104},"l",[43,384,385],{"class":93},": ",[43,387,389],{"class":388},"sNl3T","any",[43,391,108],{"class":93},[43,393,111],{"class":97},[43,395,396],{"class":104}," l",[43,398,210],{"class":93},[43,400,401],{"class":104},"name",[43,403,404],{"class":93},"),\n",[43,406,408],{"class":45,"line":407},16,[43,409,410],{"class":93},"    })\n",[43,412,414],{"class":45,"line":413},17,[43,415,180],{"emptyLinePlaceholder":179},[43,417,419,422,425,428,431],{"class":45,"line":418},18,[43,420,421],{"class":83},"    return",[43,423,424],{"class":93}," { ",[43,426,427],{"class":104},"ok:",[43,429,430],{"class":97}," true",[43,432,433],{"class":93}," }\n",[43,435,437],{"class":45,"line":436},19,[43,438,439],{"class":93},"})\n",[14,441,442],{},"The module handles verification. The agent author handles what happens when the hook\nfires — they subscribe in their own plugin.",[18,444,446],{"id":445},"serverplugins","server\u002Fplugins\u002F",[14,448,449],{},"Plugin files run at agent boot, before routes are mounted. Use for setup that routes\nor hooks depend on — database connections, SDK initialization, anything that needs to\nbe ready before requests arrive.",[14,451,452],{},"Module plugins run before user plugins. That ordering guarantee means a module can\nestablish a connection in its plugin and the agent author can use it in theirs.",[34,454,456],{"className":69,"code":455,"language":71,"meta":39,"style":39},"\u002F\u002F server\u002Fplugins\u002Fdb.ts\nexport default defineAxonPlugin(async (axon) => {\n    const db = await connectDatabase(process.env.DATABASE_URL!)\n    axon.provide(\"db\", db)\n\n    axon.hooks.hook(\"axon:agent:shutdown\", () => db.close())\n})\n",[26,457,458,463,487,517,539,543,577],{"__ignoreMap":39},[43,459,460],{"class":45,"line":46},[43,461,462],{"class":53},"\u002F\u002F server\u002Fplugins\u002Fdb.ts\n",[43,464,465,467,469,472,474,476,478,481,483,485],{"class":45,"line":57},[43,466,84],{"class":83},[43,468,87],{"class":83},[43,470,471],{"class":49}," defineAxonPlugin",[43,473,94],{"class":93},[43,475,98],{"class":97},[43,477,101],{"class":93},[43,479,480],{"class":104},"axon",[43,482,108],{"class":93},[43,484,111],{"class":97},[43,486,114],{"class":93},[43,488,489,491,494,496,498,501,503,505,507,509,511,514],{"class":45,"line":117},[43,490,120],{"class":97},[43,492,493],{"class":123}," db",[43,495,155],{"class":93},[43,497,130],{"class":83},[43,499,500],{"class":49}," connectDatabase",[43,502,94],{"class":93},[43,504,207],{"class":104},[43,506,210],{"class":93},[43,508,213],{"class":104},[43,510,210],{"class":93},[43,512,513],{"class":123},"DATABASE_URL",[43,515,516],{"class":93},"!)\n",[43,518,519,522,524,527,529,532,534,537],{"class":45,"line":147},[43,520,521],{"class":104},"    axon",[43,523,210],{"class":93},[43,525,526],{"class":49},"provide",[43,528,94],{"class":93},[43,530,531],{"class":143},"\"db\"",[43,533,165],{"class":93},[43,535,536],{"class":104},"db",[43,538,287],{"class":93},[43,540,541],{"class":45,"line":176},[43,542,180],{"emptyLinePlaceholder":179},[43,544,545,547,549,552,554,557,559,562,565,567,569,571,574],{"class":45,"line":183},[43,546,521],{"class":104},[43,548,210],{"class":93},[43,550,551],{"class":104},"hooks",[43,553,210],{"class":93},[43,555,556],{"class":49},"hook",[43,558,94],{"class":93},[43,560,561],{"class":143},"\"axon:agent:shutdown\"",[43,563,564],{"class":93},", () ",[43,566,111],{"class":97},[43,568,493],{"class":104},[43,570,210],{"class":93},[43,572,573],{"class":49},"close",[43,575,576],{"class":93},"())\n",[43,578,579],{"class":45,"line":224},[43,580,439],{"class":93},[18,582,584],{"id":583},"what-the-boundary-is","What the boundary is",[14,586,587],{},"Module routes are registered through the module system and mounted by Axon — not\ninjected by arbitrary file mutation. The parent agent still owns top-level policy,\nauth middleware, and behavior routing.",[14,589,590],{},"A module contributes the route. Axon decides how it is mounted. The agent author\ndecides what the hook does.",[592,593,594],"style",{},"html pre.shiki code .sCudf, html code.shiki .sCudf{--shiki-default:#DCDCAA}html pre.shiki code .sOLPB, html code.shiki .sOLPB{--shiki-default:#6A9955}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 pre.shiki code .sYbnZ, html code.shiki .sYbnZ{--shiki-default:#C586C0}html pre.shiki code .sTNBD, html code.shiki .sTNBD{--shiki-default:#D4D4D4}html pre.shiki code .scz_3, html code.shiki .scz_3{--shiki-default:#569CD6}html pre.shiki code .s3F5K, html code.shiki .s3F5K{--shiki-default:#9CDCFE}html pre.shiki code .s9McN, html code.shiki .s9McN{--shiki-default:#4FC1FF}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 pre.shiki code .sNl3T, html code.shiki .sNl3T{--shiki-default:#4EC9B0}",{"title":39,"searchDepth":57,"depth":57,"links":596},[597,598,599],{"id":20,"depth":57,"text":21},{"id":445,"depth":57,"text":446},{"id":583,"depth":57,"text":584},"md",{},"\u002Fdocs\u002Fv2\u002Fmodules\u002Fserver",{"title":5,"description":16},"docs\u002Fv2\u002Fmodules\u002Fserver","3QNwkOZ0rNVnajlXuhcIUyTl-ITbUrepv943i1TEPRw",1785671806687]