[{"data":1,"prerenderedAt":364},["ShallowReactive",2],{"docs-\u002Fdocs\u002Fv2\u002Frecipes\u002Fcoding-partner":3},{"id":4,"title":5,"body":6,"description":16,"extension":356,"meta":357,"navigation":359,"path":360,"seo":361,"stem":362,"__hash__":363},"docs\u002Fdocs\u002Fv2\u002Frecipes\u002Fcoding-partner\u002Findex.md","Coding Partner",{"type":7,"value":8,"toc":351},"minimark",[9,13,17,37,40,45,304,308,319,329,332,336,347],[10,11,5],"h1",{"id":12},"coding-partner",[14,15,16],"p",{},"This recipe builds a small custom coding assistant.",[14,18,19,20,24,25,28,29,32,33,36],{},"The point is not to expose an agent loop. The point is to show how a normal Axon agent is authored: ",[21,22,23],"code",{},"src\u002F"," defines who the agent is and how tasks are framed, ",[21,26,27],{},"server\u002F"," defines how the world reaches the agent, ",[21,30,31],{},"data\u002F"," holds durable reference material, ",[21,34,35],{},"modules\u002F"," adds packaged capabilities, and policy constrains what the agent may do.",[14,38,39],{},"The agent handles interactive chat and headless API review.",[41,42,44],"h2",{"id":43},"folder-structure","Folder structure",[46,47,52],"pre",{"className":48,"code":49,"language":50,"meta":51,"style":51},"language-bash shiki shiki-themes dark-plus","coding-partner\u002F\n├── data\u002F\n│   └── knowledge\u002F\n│       └── repo-guidelines.md\n├── modules\u002F\n│   └── typescript\u002F\n├── server\u002F\n│   └── api\u002F\n│       ├── chat.post.ts\n│       └── repo-review.post.ts\n├── src\u002F\n│   ├── prompts\u002F\n│   │   ├── components\u002F\n│   │   │   ├── coding-standards.vue\n│   │   │   ├── identity.vue\n│   │   │   └── personality.vue\n│   │   ├── chat-context.vue\n│   │   ├── command-approval.vue\n│   │   └── repo-review.vue\n│   ├── tools\u002F\n│   │   └── github.ts\n│   └── boot.vue\n└── axon.config.ts\n","bash","",[21,53,54,63,73,85,96,104,114,122,132,143,153,161,172,185,199,213,227,239,251,263,273,285,295],{"__ignoreMap":51},[55,56,59],"span",{"class":57,"line":58},"line",1,[55,60,62],{"class":61},"sCudf","coding-partner\u002F\n",[55,64,66,69],{"class":57,"line":65},2,[55,67,68],{"class":61},"├──",[55,70,72],{"class":71},"sKc5r"," data\u002F\n",[55,74,76,79,82],{"class":57,"line":75},3,[55,77,78],{"class":61},"│",[55,80,81],{"class":71},"   └──",[55,83,84],{"class":71}," knowledge\u002F\n",[55,86,88,90,93],{"class":57,"line":87},4,[55,89,78],{"class":61},[55,91,92],{"class":71},"       └──",[55,94,95],{"class":71}," repo-guidelines.md\n",[55,97,99,101],{"class":57,"line":98},5,[55,100,68],{"class":61},[55,102,103],{"class":71}," modules\u002F\n",[55,105,107,109,111],{"class":57,"line":106},6,[55,108,78],{"class":61},[55,110,81],{"class":71},[55,112,113],{"class":71}," typescript\u002F\n",[55,115,117,119],{"class":57,"line":116},7,[55,118,68],{"class":61},[55,120,121],{"class":71}," server\u002F\n",[55,123,125,127,129],{"class":57,"line":124},8,[55,126,78],{"class":61},[55,128,81],{"class":71},[55,130,131],{"class":71}," api\u002F\n",[55,133,135,137,140],{"class":57,"line":134},9,[55,136,78],{"class":61},[55,138,139],{"class":71},"       ├──",[55,141,142],{"class":71}," chat.post.ts\n",[55,144,146,148,150],{"class":57,"line":145},10,[55,147,78],{"class":61},[55,149,92],{"class":71},[55,151,152],{"class":71}," repo-review.post.ts\n",[55,154,156,158],{"class":57,"line":155},11,[55,157,68],{"class":61},[55,159,160],{"class":71}," src\u002F\n",[55,162,164,166,169],{"class":57,"line":163},12,[55,165,78],{"class":61},[55,167,168],{"class":71},"   ├──",[55,170,171],{"class":71}," prompts\u002F\n",[55,173,175,177,180,182],{"class":57,"line":174},13,[55,176,78],{"class":61},[55,178,179],{"class":71},"   │",[55,181,168],{"class":71},[55,183,184],{"class":71}," components\u002F\n",[55,186,188,190,192,194,196],{"class":57,"line":187},14,[55,189,78],{"class":61},[55,191,179],{"class":71},[55,193,179],{"class":71},[55,195,168],{"class":71},[55,197,198],{"class":71}," coding-standards.vue\n",[55,200,202,204,206,208,210],{"class":57,"line":201},15,[55,203,78],{"class":61},[55,205,179],{"class":71},[55,207,179],{"class":71},[55,209,168],{"class":71},[55,211,212],{"class":71}," identity.vue\n",[55,214,216,218,220,222,224],{"class":57,"line":215},16,[55,217,78],{"class":61},[55,219,179],{"class":71},[55,221,179],{"class":71},[55,223,81],{"class":71},[55,225,226],{"class":71}," personality.vue\n",[55,228,230,232,234,236],{"class":57,"line":229},17,[55,231,78],{"class":61},[55,233,179],{"class":71},[55,235,168],{"class":71},[55,237,238],{"class":71}," chat-context.vue\n",[55,240,242,244,246,248],{"class":57,"line":241},18,[55,243,78],{"class":61},[55,245,179],{"class":71},[55,247,168],{"class":71},[55,249,250],{"class":71}," command-approval.vue\n",[55,252,254,256,258,260],{"class":57,"line":253},19,[55,255,78],{"class":61},[55,257,179],{"class":71},[55,259,81],{"class":71},[55,261,262],{"class":71}," repo-review.vue\n",[55,264,266,268,270],{"class":57,"line":265},20,[55,267,78],{"class":61},[55,269,168],{"class":71},[55,271,272],{"class":71}," tools\u002F\n",[55,274,276,278,280,282],{"class":57,"line":275},21,[55,277,78],{"class":61},[55,279,179],{"class":71},[55,281,81],{"class":71},[55,283,284],{"class":71}," github.ts\n",[55,286,288,290,292],{"class":57,"line":287},22,[55,289,78],{"class":61},[55,291,81],{"class":71},[55,293,294],{"class":71}," boot.vue\n",[55,296,298,301],{"class":57,"line":297},23,[55,299,300],{"class":61},"└──",[55,302,303],{"class":71}," axon.config.ts\n",[41,305,307],{"id":306},"how-it-works","How it works",[14,309,310,311,314,315,318],{},"The chat route handles interactive conversation. It renders ",[21,312,313],{},"chat-context.vue"," with the current request and calls ",[21,316,317],{},"axon.stream()"," on a named thread — the thread name keeps context across messages in the same conversation.",[14,320,321,322,325,326,328],{},"The review route runs a stateless task. It renders ",[21,323,324],{},"repo-review.vue"," with the target repo and branch, then calls ",[21,327,317],{}," with no thread — each review is independent.",[14,330,331],{},"Both routes use the same agent identity and tools. The route context (task scope, policy constraints) changes the agent's behavior for that invocation.",[41,333,335],{"id":334},"what-to-read-first","What to read first",[14,337,338,339,342,343,346],{},"Start with ",[21,340,341],{},"src\u002Fboot.vue"," to see how identity and operating rules are composed, then\nread ",[21,344,345],{},"server\u002Fapi\u002Fchat.post.ts"," to see how the TUI path prepares a task. Per-file\nwalkthroughs are coming to this recipe.",[348,349,350],"style",{},"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 .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":51,"searchDepth":65,"depth":65,"links":352},[353,354,355],{"id":43,"depth":65,"text":44},{"id":306,"depth":65,"text":307},{"id":334,"depth":65,"text":335},"md",{"icon":358},"vscode-icons:file-type-markdown",true,"\u002Fdocs\u002Fv2\u002Frecipes\u002Fcoding-partner",{"title":5,"description":16},"docs\u002Fv2\u002Frecipes\u002Fcoding-partner\u002Findex","SIIp0ioqKgrXOgJjAhPbT18U2mY7zbWf8gG4bCmPuCI",1785671807148]