[{"data":1,"prerenderedAt":875},["ShallowReactive",2],{"navigation":3,"\u002Fblog\u002Fmulti-agent-loan-approval-human-in-the-loop":204,"\u002Fblog\u002Fmulti-agent-loan-approval-human-in-the-loop-surround":870},[4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172,176,180,184,188,192,196,200],{"title":5,"path":6,"stem":7},"You do not have time to not have tests","\u002Fblog\u002Fyou-do-not-have-time-to-not-have-tests","2.blog\u002F20211217.you-do-not-have-time-to-not-have-tests",{"title":9,"path":10,"stem":11},"Migrate Vue 2 with Vuetify and Jest to Vite and Vitest","\u002Fblog\u002Fmigrate-vue-2-with-vuetify-and-jest-to-vite-and-vitest","2.blog\u002F20220109.migrate-vue-2-with-vuetify-and-jest-to-vite-and-vitest",{"title":13,"path":14,"stem":15},"I am a Dark Matter Developer","\u002Fblog\u002Fi-am-a-dark-matter-developer","2.blog\u002F20220626.i-am-a-dark-matter-developer",{"title":17,"path":18,"stem":19},"Why using Conventional commits is useful","\u002Fblog\u002Fusing-conventional-commits","2.blog\u002F20240623.using-conventional-commits",{"title":21,"path":22,"stem":23},"Why you should make a toolbox repository","\u002Fblog\u002Fwhy-you-should-make-a-toolbox-repository","2.blog\u002F20240630.Why-you-should-make-a-toolbox-repository",{"title":25,"path":26,"stem":27},"Apache Airflow Part 1 - Why and Goals for a near Serverless ELT","\u002Fblog\u002Fapache-airflow-part-1-why-and-goals","2.blog\u002F20240710.apache-airflow-part-1-why-and-goals",{"title":29,"path":30,"stem":31},"Oh My Zsh on your server","\u002Fblog\u002Foh-my-zsh-on-your-server","2.blog\u002F20240711.oh-my-zsh-on-your-server",{"title":33,"path":34,"stem":35},"Fire tablet and YouTube Kids","\u002Fblog\u002Ffire-tablet-and-youtube-kids","2.blog\u002F20240714.fire-tablet-and-youtube-kids",{"title":37,"path":38,"stem":39},"Using Ollama and Continue as a GitHub Copilot Alternative","\u002Fblog\u002Fusing-ollama-and-continue-as-github-copilot-alternative","2.blog\u002F20240723.using-ollama-and-continue-as-github-copilot-alternative",{"title":41,"path":42,"stem":43},"Debugging Local Packages Made Easy with pnpm","\u002Fblog\u002Fdebugging-local-packages-with-pnpm-link","2.blog\u002F20250422.debugging local-packages-with-pnpm-link",{"title":45,"path":46,"stem":47},"Two Weeks with Cloudflare AI and Tools","\u002Fblog\u002Ftwo-weeks-with-cloudflare-ai-and-tools","2.blog\u002F20250509.two-weeks-with-cloudflare-aI-and-tools",{"title":49,"path":50,"stem":51},"Adding Prompts to VS Code - How I Learned to Stop Worrying and Love AI Context","\u002Fblog\u002Fadding-prompts-to-vscode","2.blog\u002F20250528.adding-prompts-to-vscode",{"title":53,"path":54,"stem":55},"My Best Practices","\u002Fblog\u002Fmy-best-practicies","2.blog\u002F20250607.my-best-practicies",{"title":57,"path":58,"stem":59},"Creating my own CLI Tool - Towles Tool","\u002Fblog\u002Ftowles-tool","2.blog\u002F20250607.towles-tool",{"title":61,"path":62,"stem":63},"Software Development Best Practices & ITIL","\u002Fblog\u002Fsoftware-engineering-and-itil-best-practices","2.blog\u002F20250612.software-engineering-and-itil-best-practices",{"title":65,"path":66,"stem":67},"Voice to Text","\u002Fblog\u002Fvoice-to-text","2.blog\u002F20250622.voice-to-text",{"title":69,"path":70,"stem":71},"Setting Up ComfyUI - A Better Alternative to Fooocus","\u002Fblog\u002Fcomfy-ui-setup","2.blog\u002F20250628.comfy-ui-setup",{"title":73,"path":74,"stem":75},"Voice to System","\u002Fblog\u002Fvoice-to-system","2.blog\u002F20250705.voice-to-system",{"title":77,"path":78,"stem":79},"Tips for Claude Code","\u002Fblog\u002Ftips-for-claude-code","2.blog\u002F20250713.tips-for-claude-code",{"title":81,"path":82,"stem":83},"Review That AI Code: Why I Read Every Line Generated Code","\u002Fblog\u002Freview-that-ai-code","2.blog\u002F20250720.review-that-ai-code",{"title":85,"path":86,"stem":87},"My Context Engineering Journey: From Dev Scripts to AI Collaboration","\u002Fblog\u002F20250803-1.my-context-engineering-journey","2.blog\u002F20250803-1.my-context-engineering-journey",{"title":89,"path":90,"stem":91},"Context Engineering at Scale: Enterprise Lessons and the Future of Development","\u002Fblog\u002F20250803-2.context-engineering-at-scale","2.blog\u002F20250803-2.context-engineering-at-scale",{"title":93,"path":94,"stem":95},"Check That Your Tools and Linters Do Not Burn Tokens","\u002Fblog\u002Fcheck-that-your-tools-and-linters-do-not-burn-tokens","2.blog\u002F20250806.check-that-your-tools-and-linters-do-not-burn-tokens",{"title":97,"path":98,"stem":99},"Markdown + AI: The Communication Protocol That Changes Everything","\u002Fblog\u002Fmarkdown-plus-ai-the-communication-protocol-that-changes-everything","2.blog\u002F20250814.markdown-plus-ai-the-communication-protocol-that-changes-everything",{"title":101,"path":102,"stem":103},"Finally: Type-Safe AI in Production (And Why I'm Here For It)","\u002Fblog\u002Ffinally-type-safe-ai-in-production-and-why-im-here-for-it","2.blog\u002F20250819.finally-type-safe-ai-in-production-and-why-im-here-for-it",{"title":105,"path":106,"stem":107},"Dotfiles: Masterpiece or Late Stage Picasso?","\u002Fblog\u002Fdotfiles-masterpiece-or-late-stage-picasso","2.blog\u002F20250822.dotfiles-masterpiece-or-late-stage-picasso",{"title":109,"path":110,"stem":111},"Beyond API Wrappers: Building State-Driven MCP Servers for Long-Horizon Agent Orchestration","\u002Fblog\u002Fbeyond-api-wrappers-mcp-servers","2.blog\u002F20250907.beyond-api-wrappers-mcp-servers",{"title":113,"path":114,"stem":115},"Why Vertical Integration Wins: A Software Engineer's Case for Owning Your Stack","\u002Fblog\u002Fwhy-i-bought-tesla-model-3-vertical-integration","2.blog\u002F20250928.why-i-bought-tesla-model-3-vertical-integration",{"title":117,"path":118,"stem":119},"The Min-Maxer's Trifecta: Building Tools for the Game You Actually Play","\u002Fblog\u002Fmin-maxer-trifecta","2.blog\u002F20251004.min-maxer-trifecta",{"title":121,"path":122,"stem":123},"Read The Source: Learning by Cutting Out The Middleman and RTFM","\u002Fblog\u002Fread-the-source","2.blog\u002F20251010.read-the-source",{"title":125,"path":126,"stem":127},"The Exponential Shift: Why AI Progress Feels Different Now","\u002Fblog\u002Fthe-exponential-shift","2.blog\u002F20251015.the-exponential-shift",{"title":129,"path":130,"stem":131},"Plan Mode for Your Problems, Edit Mode for Claude's","\u002Fblog\u002Fplan-mode-problems-edit-mode-solutions","2.blog\u002F20251019.plan-mode-problems-edit-mode-solutions",{"title":133,"path":134,"stem":135},"AWS Aurora DSQL Looked Perfect Until I Needed the Connection String","\u002Fblog\u002Faws-aurora-dsql-postgres-serverless-authentication","2.blog\u002F20251028.aws-aurora-dsql-postgres-serverless-authentication",{"title":137,"path":138,"stem":139},"Switchback: Browser History for Your Thoughts","\u002Fblog\u002Fswitchback-second-order-reasoning","2.blog\u002F20251205.switchback-second-order-reasoning",{"title":141,"path":142,"stem":143},"AI Pairing: Notes to Self","\u002Fblog\u002Fai-pairing-notes-to-self","2.blog\u002F20251216.ai-pairing-notes-to-self",{"title":145,"path":146,"stem":147},"I've Been Sleeping on Zellij","\u002Fblog\u002Fsleeping-on-zellij","2.blog\u002F20251229.sleeping-on-zellij",{"title":149,"path":150,"stem":151},"Implementing a Ralph Wiggum Loop: The Secret is Session Markers","\u002Fblog\u002Fimplementing-ralph-wiggum-loop-for-autonomous-ai-coding","2.blog\u002F20260114.implementing-ralph-wiggum-loop-for-autonomous-ai-coding",{"title":153,"path":154,"stem":155},"Goodhart's Law Ate My Context Window","\u002Fblog\u002Fgoodharts-law-ate-my-context-window","2.blog\u002F20260119.goodharts-law-ate-my-context-window",{"title":157,"path":158,"stem":159},"Claude Code's Hidden Multi-Agent System Is Real","\u002Fblog\u002Fclaude-code-hidden-multi-agent-system","2.blog\u002F20260124.claude-code-hidden-multi-agent-system",{"title":161,"path":162,"stem":163},"Free Printable Math Sheets for Kids — Number Chart, Skip Counting, Multiplication, and More","\u002Fblog\u002Ffree-printable-number-chart-and-coin-sheets","2.blog\u002F20260214.free-printable-number-chart-and-coin-sheets",{"title":165,"path":166,"stem":167},"We Are Near the End of the Exponential","\u002Fblog\u002Fnear-the-end-of-the-exponential","2.blog\u002F20260214.near-the-end-of-the-exponential",{"title":169,"path":170,"stem":171},"Free Printable Language Arts Sheets for Kids — Sight Words, Parts of Speech, Homophones, and More","\u002Fblog\u002Ffree-printable-sight-words-and-grammar-sheets","2.blog\u002F20260215.free-printable-sight-words-and-grammar-sheets",{"title":173,"path":174,"stem":175},"Interactive Code Execution with Artifacts","\u002Fblog\u002Finteractive-code-execution-with-artifacts","2.blog\u002F20260215.interactive-code-execution-with-artifacts",{"title":177,"path":178,"stem":179},"Free Printable Telling Time Worksheet for Kids — Clock Reference & Practice Sheet","\u002Fblog\u002Ffree-printable-telling-time-worksheet","2.blog\u002F20260216.free-printable-telling-time-worksheet",{"title":181,"path":182,"stem":183},"Claude Code Skills: Teaching AI Your Playbook","\u002Fblog\u002Fclaude-code-skills-guide","2.blog\u002F20260221.claude-code-skills-guide",{"title":185,"path":186,"stem":187},"Building a Multi-Agent Loan Approval System with Human-in-the-Loop","\u002Fblog\u002Fmulti-agent-loan-approval-human-in-the-loop","2.blog\u002F20260225.multi-agent-loan-approval-human-in-the-loop",{"title":189,"path":190,"stem":191},"The Inception of AI Infrastructure: Bottlenecks All the Way Down","\u002Fblog\u002Fbiggest-bottleneck-scaling-ai-compute","2.blog\u002F20260313.biggest-bottleneck-scaling-ai-compute",{"title":193,"path":194,"stem":195},"What I Tell Teams About Claude Code","\u002Fblog\u002Fwhat-i-tell-teams-about-claude-code","2.blog\u002F20260314.what-i-tell-teams-about-claude-code",{"title":197,"path":198,"stem":199},"The Hardest Part of AI Isn't the AI","\u002Fblog\u002Fthe-hardest-part-of-ai-isnt-the-ai","2.blog\u002F20260327.the-hardest-part-of-ai-isnt-the-ai",{"title":201,"path":202,"stem":203},"Claude Code Hooks: The Capability I Left on the Table","\u002Fblog\u002Fclaude-code-hooks-capability-left-on-the-table","2.blog\u002F20260401.claude-code-hooks-capability-left-on-the-table",{"id":205,"title":185,"authors":206,"badge":212,"body":214,"date":860,"description":861,"extension":862,"image":863,"meta":866,"navigation":657,"path":186,"seo":867,"status":868,"stem":187,"__hash__":869},"posts\u002F2.blog\u002F20260225.multi-agent-loan-approval-human-in-the-loop.md",[207],{"name":208,"to":209,"avatar":210},"Chris Towles","https:\u002F\u002Ftwitter.com\u002FChris_Towles",{"src":211},"\u002Fimages\u002Fctowles-profile-512x512.png",{"label":213},"Architecture",{"type":215,"value":216,"toc":843},"minimark",[217,233,238,241,244,248,284,289,292,299,302,306,309,331,346,351,361,370,379,388,402,408,412,415,421,424,427,433,437,440,446,450,453,456,460,492,496,532,559,563,569,575,599,605,609,616,796,799,802,806,839],[218,219,221],"callout",{"icon":220},"i-lucide-play",[222,223,224,232],"p",{},[225,226,227],"strong",{},[228,229,231],"a",{"href":230},"\u002Floan","Try the demo"," — walk through the full workflow yourself. Requires GitHub login.",[234,235,237],"h2",{"id":236},"what-i-built","What I Built",[222,239,240],{},"A home loan application workflow where AI agents review applications but a human makes the final call. Three specialized AI reviewers analyze every application independently, then a human approves, denies, or flags it — the AI advises, it doesn't decide.",[222,242,243],{},"This is a demo\u002Fplayground, not production financial software. But it demonstrates a pattern that matters: multi-agent AI systems that keep humans in the decision loop.",[234,245,247],{"id":246},"the-flow","The Flow",[249,250,255],"pre",{"className":251,"code":252,"language":253,"meta":254,"style":254},"language-mermaid shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","flowchart LR\n    A[Intake Chat] -->|submit| B[AI Review]\n    B -->|3 agents stream| C[Human Decision]\n    C -->|re-review| A\n","mermaid","",[256,257,258,266,272,278],"code",{"__ignoreMap":254},[259,260,263],"span",{"class":261,"line":262},"line",1,[259,264,265],{},"flowchart LR\n",[259,267,269],{"class":261,"line":268},2,[259,270,271],{},"    A[Intake Chat] -->|submit| B[AI Review]\n",[259,273,275],{"class":261,"line":274},3,[259,276,277],{},"    B -->|3 agents stream| C[Human Decision]\n",[259,279,281],{"class":261,"line":280},4,[259,282,283],{},"    C -->|re-review| A\n",[285,286,288],"h3",{"id":287},"_1-intake-conversational-data-collection","1. Intake — Conversational Data Collection",[222,290,291],{},"The applicant chats with an AI assistant that collects loan details naturally. No forms — just conversation. The AI uses tool calls behind the scenes to extract structured data (name, income, employment, property details, credit score range) and updates a progress bar in real time.",[222,293,294],{},[295,296],"img",{"alt":297,"src":298},"Intake chat interface with progress bar showing fields to collect","\u002Fimages\u002Fblog\u002F20260225-loan-intake.png",[222,300,301],{},"Once all 12 fields are collected, a \"Submit for Review\" button appears.",[285,303,305],{"id":304},"_2-multi-agent-review-three-independent-ai-reviewers","2. Multi-Agent Review — Three Independent AI Reviewers",[222,307,308],{},"Submitting triggers three AI reviewers that run sequentially, each streaming their analysis in real-time via SSE:",[310,311,312,319,325],"ul",{},[313,314,315,318],"li",{},[225,316,317],{},"The Bank — Financial Risk",": Evaluates DTI ratio, LTV ratio, credit score, income stability. Conservative risk assessment focused on regulatory compliance.",[313,320,321,324],{},[225,322,323],{},"Loan Market — Deal Structure",": Analyzes the deal from a market perspective — is the property fairly valued? Is the loan amount reasonable for the area?",[313,326,327,330],{},[225,328,329],{},"Background Checks — Fraud Detection",": Looks for inconsistencies in the application data. Cross-references employment claims, income vs. debt ratios, and flags suspicious patterns.",[222,332,333,334,337,338,341,342,345],{},"Each reviewer uses a custom system prompt and independently decides: ",[225,335,336],{},"approve",", ",[225,339,340],{},"deny",", or ",[225,343,344],{},"flag",".",[347,348,350],"h4",{"id":349},"the-reviewer-prompts","The Reviewer Prompts",[222,352,353,354,360],{},"Each reviewer's personality and evaluation criteria live in a ",[228,355,359],{"href":356,"rel":357},"https:\u002F\u002Fdocs.anthropic.com\u002Fen\u002Fdocs\u002Fclaude-code\u002Fskills",[358],"nofollow","Claude Code Skills"," markdown file. The server loads these at review time as the system prompt for each agent call. Here's the key section from each:",[222,362,363,369],{},[225,364,365],{},[228,366,317],{"href":367,"rel":368},"https:\u002F\u002Fgithub.com\u002FChrisTowles\u002Fblog\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Floan-the-bank\u002FSKILL.md",[358]," evaluates DTI, LTV, credit score, and employment stability. It's told to be conservative: \"It is MORE IMPORTANT to flag issues than to approve.\" Red flags include DTI > 43%, LTV > 95%, subprime credit scores, and employment under 2 years.",[222,371,372,378],{},[225,373,374],{},[228,375,323],{"href":376,"rel":377},"https:\u002F\u002Fgithub.com\u002FChrisTowles\u002Fblog\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Floan-market\u002FSKILL.md",[358]," focuses on the deal economics, not the borrower. It checks property value reasonableness, jumbo loan thresholds, down payment signals, and property type risk profiles. \"Focus on the deal economics. Be specific.\"",[222,380,381,387],{},[225,382,383],{},[228,384,329],{"href":385,"rel":386},"https:\u002F\u002Fgithub.com\u002FChrisTowles\u002Fblog\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Floan-background\u002FSKILL.md",[358]," is the skeptic: \"Assume nothing. Question everything.\" It looks for income\u002Femployment mismatches, suspiciously round numbers, mathematically impossible combinations, and vague employer names.",[222,389,390,391,337,394,397,398,401],{},"All three share the same output format — a JSON object with ",[256,392,393],{},"decision",[256,395,396],{},"flags",", and ",[256,399,400],{},"analysis"," — but their evaluation criteria and tone are completely different. This is what makes the multi-agent approach interesting: same input, different lenses.",[222,403,404],{},[295,405],{"alt":406,"src":407},"Review page showing The Bank's financial risk analysis with Approved badge","\u002Fimages\u002Fblog\u002F20260225-loan-review-top.png",[285,409,411],{"id":410},"_3-human-decision-ai-recommends-human-decides","3. Human Decision — AI Recommends, Human Decides",[222,413,414],{},"After all three reviewers complete, the system shows the AI's aggregate recommendation but keeps the status as \"reviewing.\" The application doesn't move forward until a human clicks Approve, Deny, or Flag.",[222,416,417],{},[295,418],{"alt":419,"src":420},"AI Recommendation showing fraud flags and Approve\u002FDeny\u002FFlag buttons","\u002Fimages\u002Fblog\u002F20260225-loan-review-recommendation.png",[222,422,423],{},"This is the key design decision. Even if all three AI agents approve unanimously, a human must confirm. The AI recommendation is clearly labeled as advisory.",[222,425,426],{},"After deciding, the human can still change their decision or send the application back for a fresh re-review.",[222,428,429],{},[295,430],{"alt":431,"src":432},"Landing page for the Agentic Loan Workflow demo","\u002Fimages\u002Fblog\u002F20260225-loan-landing.png",[285,434,436],{"id":435},"_4-admin-dashboard","4. Admin Dashboard",[222,438,439],{},"An admin view shows all applications across all users with status counts and a table for quick navigation.",[222,441,442],{},[295,443],{"alt":444,"src":445},"Admin dashboard showing all loan applications with status counts","\u002Fimages\u002Fblog\u002F20260225-loan-admin.png",[285,447,449],{"id":448},"_5-re-review","5. Re-review",[222,451,452],{},"Hit \"Re-review\" and the system clears all AI reviews, resets to intake status, and sends the user back to the chat. The application data is preserved — they can modify answers or submit again for a fresh set of AI reviews.",[234,454,213],{"id":455},"architecture",[285,457,459],{"id":458},"tech-stack","Tech Stack",[310,461,462,468,474,480,486],{},[313,463,464,467],{},[225,465,466],{},"Frontend",": Nuxt 4, Vue 3, Nuxt UI",[313,469,470,473],{},[225,471,472],{},"Backend",": Nitro server routes, Drizzle ORM, PostgreSQL",[313,475,476,479],{},[225,477,478],{},"AI",": Anthropic Claude (via SDK), three independent agent calls",[313,481,482,485],{},[225,483,484],{},"Streaming",": Server-Sent Events (SSE) for real-time review streaming",[313,487,488,491],{},[225,489,490],{},"Hosting",": GCP Cloud Run",[285,493,495],{"id":494},"status-model","Status Model",[249,497,499],{"className":251,"code":498,"language":253,"meta":254,"style":254},"flowchart LR\n    intake -->|submit| reviewing\n    reviewing -->|approve| approved\n    reviewing -->|deny| denied\n    reviewing -->|flag| flagged\n    approved & denied & flagged -->|re-review| intake\n",[256,500,501,505,510,515,520,526],{"__ignoreMap":254},[259,502,503],{"class":261,"line":262},[259,504,265],{},[259,506,507],{"class":261,"line":268},[259,508,509],{},"    intake -->|submit| reviewing\n",[259,511,512],{"class":261,"line":274},[259,513,514],{},"    reviewing -->|approve| approved\n",[259,516,517],{"class":261,"line":280},[259,518,519],{},"    reviewing -->|deny| denied\n",[259,521,523],{"class":261,"line":522},5,[259,524,525],{},"    reviewing -->|flag| flagged\n",[259,527,529],{"class":261,"line":528},6,[259,530,531],{},"    approved & denied & flagged -->|re-review| intake\n",[310,533,534,540,546],{},[313,535,536,539],{},[256,537,538],{},"intake"," — collecting application data via chat",[313,541,542,545],{},[256,543,544],{},"reviewing"," — AI agents have run, waiting for human decision",[313,547,548,551,552,551,555,558],{},[256,549,550],{},"approved"," \u002F ",[256,553,554],{},"denied",[256,556,557],{},"flagged"," — human has decided",[285,560,562],{"id":561},"key-design-choices","Key Design Choices",[222,564,565,568],{},[225,566,567],{},"AI agents don't share context."," Each reviewer gets the same application data independently. They can't see each other's analysis. This prevents groupthink and ensures genuinely independent assessments.",[222,570,571,574],{},[225,572,573],{},"Streaming, not batch."," Reviews stream token-by-token via SSE so the user watches each analysis build in real time. This matters for trust — you see the reasoning unfold, not just a verdict.",[222,576,577,580,581,584,585,587,588,591,592,594,595,594,597,345],{},[225,578,579],{},"Human-in-the-loop is mandatory, not optional."," The server never sets a final status automatically. The ",[256,582,583],{},"submit"," endpoint leaves status as ",[256,586,544],{}," after AI completes. Only the ",[256,589,590],{},"status.patch"," endpoint (triggered by human click) sets ",[256,593,550],{},"\u002F",[256,596,554],{},[256,598,557],{},[222,600,601,604],{},[225,602,603],{},"Clean analysis, not raw JSON."," During streaming, the user sees plain text as the LLM generates it. Once complete, the server parses the structured JSON response and replaces the raw output with clean analysis text. A \"Show raw response\" toggle is available for debugging.",[285,606,608],{"id":607},"how-skills-become-system-prompts","How Skills Become System Prompts",[222,610,611,612,615],{},"The reviewer prompts are loaded at runtime from markdown files on disk — not hardcoded in the server code. A utility function strips the YAML frontmatter and passes the body as the ",[256,613,614],{},"system"," parameter to the Anthropic SDK:",[249,617,621],{"className":618,"code":619,"language":620,"meta":254,"style":254},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F server\u002Futils\u002Fai\u002Floan-review-utils.ts\nconst systemPrompt = loadApproverPrompt(reviewer);\n\nconst streamResponse = client.messages.stream({\n  model: config.public.model,\n  max_tokens: 4096,\n  system: systemPrompt,\n  messages: [{ role: 'user', content: formattedApplication }],\n});\n","typescript",[256,622,623,629,653,659,687,712,725,738,786],{"__ignoreMap":254},[259,624,625],{"class":261,"line":262},[259,626,628],{"class":627},"sHwdD","\u002F\u002F server\u002Futils\u002Fai\u002Floan-review-utils.ts\n",[259,630,631,635,639,643,647,650],{"class":261,"line":268},[259,632,634],{"class":633},"spNyl","const",[259,636,638],{"class":637},"sTEyZ"," systemPrompt ",[259,640,642],{"class":641},"sMK4o","=",[259,644,646],{"class":645},"s2Zo4"," loadApproverPrompt",[259,648,649],{"class":637},"(reviewer)",[259,651,652],{"class":641},";\n",[259,654,655],{"class":261,"line":274},[259,656,658],{"emptyLinePlaceholder":657},true,"\n",[259,660,661,663,666,668,671,673,676,678,681,684],{"class":261,"line":280},[259,662,634],{"class":633},[259,664,665],{"class":637}," streamResponse ",[259,667,642],{"class":641},[259,669,670],{"class":637}," client",[259,672,345],{"class":641},[259,674,675],{"class":637},"messages",[259,677,345],{"class":641},[259,679,680],{"class":645},"stream",[259,682,683],{"class":637},"(",[259,685,686],{"class":641},"{\n",[259,688,689,693,696,699,701,704,706,709],{"class":261,"line":522},[259,690,692],{"class":691},"swJcz","  model",[259,694,695],{"class":641},":",[259,697,698],{"class":637}," config",[259,700,345],{"class":641},[259,702,703],{"class":637},"public",[259,705,345],{"class":641},[259,707,708],{"class":637},"model",[259,710,711],{"class":641},",\n",[259,713,714,717,719,723],{"class":261,"line":528},[259,715,716],{"class":691},"  max_tokens",[259,718,695],{"class":641},[259,720,722],{"class":721},"sbssI"," 4096",[259,724,711],{"class":641},[259,726,728,731,733,736],{"class":261,"line":727},7,[259,729,730],{"class":691},"  system",[259,732,695],{"class":641},[259,734,735],{"class":637}," systemPrompt",[259,737,711],{"class":641},[259,739,741,744,746,749,752,755,757,760,764,767,770,773,775,778,781,784],{"class":261,"line":740},8,[259,742,743],{"class":691},"  messages",[259,745,695],{"class":641},[259,747,748],{"class":637}," [",[259,750,751],{"class":641},"{",[259,753,754],{"class":691}," role",[259,756,695],{"class":641},[259,758,759],{"class":641}," '",[259,761,763],{"class":762},"sfazB","user",[259,765,766],{"class":641},"'",[259,768,769],{"class":641},",",[259,771,772],{"class":691}," content",[259,774,695],{"class":641},[259,776,777],{"class":637}," formattedApplication ",[259,779,780],{"class":641},"}",[259,782,783],{"class":637},"]",[259,785,711],{"class":641},[259,787,789,791,794],{"class":261,"line":788},9,[259,790,780],{"class":641},[259,792,793],{"class":637},")",[259,795,652],{"class":641},[222,797,798],{},"Each reviewer gets the same formatted application data as the user message. The skill file controls their perspective — the bank is conservative, the market analyst cares about deal structure, the fraud investigator is deeply skeptical.",[222,800,801],{},"This means you can tweak a reviewer's personality or evaluation criteria by editing a markdown file. No code changes, no redeployment.",[234,803,805],{"id":804},"what-this-demonstrates","What This Demonstrates",[807,808,809,815,821,827,833],"ol",{},[313,810,811,814],{},[225,812,813],{},"Multi-agent orchestration"," — Multiple specialized AI agents working on the same input independently",[313,816,817,820],{},[225,818,819],{},"Human-in-the-loop"," — AI as advisor, not decision-maker",[313,822,823,826],{},[225,824,825],{},"Real-time streaming"," — SSE for progressive UI updates during AI processing",[313,828,829,832],{},[225,830,831],{},"Conversational data collection"," — Chat-based intake instead of traditional forms",[313,834,835,838],{},[225,836,837],{},"Tool use"," — AI extracts structured data from natural language via function calling",[840,841,842],"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 .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}",{"title":254,"searchDepth":268,"depth":268,"links":844},[845,846,853,859],{"id":236,"depth":268,"text":237},{"id":246,"depth":268,"text":247,"children":847},[848,849,850,851,852],{"id":287,"depth":274,"text":288},{"id":304,"depth":274,"text":305},{"id":410,"depth":274,"text":411},{"id":435,"depth":274,"text":436},{"id":448,"depth":274,"text":449},{"id":455,"depth":268,"text":213,"children":854},[855,856,857,858],{"id":458,"depth":274,"text":459},{"id":494,"depth":274,"text":495},{"id":561,"depth":274,"text":562},{"id":607,"depth":274,"text":608},{"id":804,"depth":268,"text":805},"2026-02-25","A demo of multi-agent AI orchestration where three specialized reviewers analyze loan applications independently, stream results in real-time via SSE, and a human makes the final call.","md",{"src":864,"alt":865},"\u002Fimages\u002Fblog\u002F20260225-1430-multi-agent-loan-approval-human-in-the-loop.jpeg","Multi-agent loan approval workflow with AI reviewers and human decision",{},{"title":185,"description":861},"published","umDB2-Cy7rQMMzRJaPtxuXZAq79byrLSIhtNQzl9gyQ",[871,873],{"title":181,"path":182,"stem":183,"description":872,"status":868,"children":-1},"Skills are how you give Claude your team's specific knowledge — processes, conventions, and expertise that no foundation model ships with. Here's how they work, how discovery happens, and how to build your own.",{"title":189,"path":190,"stem":191,"description":874,"status":868,"children":-1},"Dylan Patel's breakdown of the 3 big bottlenecks to scaling AI compute reveals a supply chain so deeply nested it feels like waking up from another level of Inception.",1776221196452]