[{"data":1,"prerenderedAt":1101},["ShallowReactive",2],{"blog-ko-multi-agent-queue":3,"blog-navigation-ko":464},{"id":4,"title":5,"author":6,"body":7,"category":449,"date":450,"description":451,"extension":452,"featured":453,"icon":298,"image":454,"meta":455,"navigation":453,"path":456,"readTime":457,"seo":458,"stem":459,"tags":460,"__hash__":463},"blog\u002Fko\u002Fblog\u002Fmulti-agent-queue.md","테스트","fxpoet",{"type":8,"value":9,"toc":442},"minimark",[10,19,27,32,35,45,48,54,61,65,68,182,193,196,201,208,212,219,225,228,250,254,261,273,280,414,421,425,432,435,438],[11,12,13,14,18],"p",{},"Prompt Combo의 출발점은 ",[15,16,17],"strong",{},"\"프롬프트를 큐에 넣고 알아서 돌아가게 하자\""," 는 생각이었습니다. 말로 하면 간단하지만, 실제로 구현해보면 전혀 다른 문제였습니다.",[11,20,21,22,26],{},"처음에는 정말 단순하게 시작했습니다. 프롬프트 배열을 만들고 ",[23,24,25],"code",{},"for...of"," 로 순차 실행한 뒤, 응답을 로그에 쌓으면 끝이라고 생각했습니다. 문제는 그 다음부터였습니다.",[28,29,31],"h2",{"id":30},"_1차-구조-순차-실행의-한계","1차 구조: 순차 실행의 한계",[11,33,34],{},"첫 번째 구조는 아래와 같았습니다.",[36,37,43],"pre",{"className":38,"code":40,"language":41,"meta":42},[39],"language-text","[Queue]\nPrompt A -> Claude -> Response A\nPrompt B -> Claude -> Response B\nPrompt C -> Claude -> Response C\n","text","",[23,44,40],{"__ignoreMap":42},[11,46,47],{},"작동은 했습니다. 그런데 바로 첫 번째 피드백이 들어왔습니다.",[49,50,51],"blockquote",{},[11,52,53],{},"\"이 프롬프트는 GPT-4o로 돌리고, 저건 Claude로 돌리면 안 되나요?\"",[11,55,56,57,60],{},"단일 모델만 가정한 큐 구조에서는 답이 나오지 않았습니다. 하지만 이 요구 하나가 아키텍처 전체를 흔들었습니다. 이제 아이템마다 ",[15,58,59],{},"어떤 모델을 어떤 API 키로, 어떤 파라미터로"," 실행할지 개별 설정이 가능해야 했습니다.",[28,62,64],{"id":63},"_2차-구조-모델별-라우팅","2차 구조: 모델별 라우팅",[11,66,67],{},"큐 아이템에 모델 정보를 붙였습니다.",[36,69,73],{"className":70,"code":71,"language":72,"meta":42,"style":42},"language-ts shiki shiki-themes github-dark","interface QueueItem {\n  id: string\n  prompt: string\n  model: 'claude' | 'gpt' | 'gemini'\n  params: ModelParams\n  status: 'pending' | 'running' | 'done' | 'error'\n}\n","ts",[23,74,75,92,106,116,139,150,176],{"__ignoreMap":42},[76,77,80,84,88],"span",{"class":78,"line":79},"line",1,[76,81,83],{"class":82},"snl16","interface",[76,85,87],{"class":86},"svObZ"," QueueItem",[76,89,91],{"class":90},"s95oV"," {\n",[76,93,95,99,102],{"class":78,"line":94},2,[76,96,98],{"class":97},"s9osk","  id",[76,100,101],{"class":82},":",[76,103,105],{"class":104},"sDLfK"," string\n",[76,107,109,112,114],{"class":78,"line":108},3,[76,110,111],{"class":97},"  prompt",[76,113,101],{"class":82},[76,115,105],{"class":104},[76,117,119,122,124,128,131,134,136],{"class":78,"line":118},4,[76,120,121],{"class":97},"  model",[76,123,101],{"class":82},[76,125,127],{"class":126},"sU2Wk"," 'claude'",[76,129,130],{"class":82}," |",[76,132,133],{"class":126}," 'gpt'",[76,135,130],{"class":82},[76,137,138],{"class":126}," 'gemini'\n",[76,140,142,145,147],{"class":78,"line":141},5,[76,143,144],{"class":97},"  params",[76,146,101],{"class":82},[76,148,149],{"class":86}," ModelParams\n",[76,151,153,156,158,161,163,166,168,171,173],{"class":78,"line":152},6,[76,154,155],{"class":97},"  status",[76,157,101],{"class":82},[76,159,160],{"class":126}," 'pending'",[76,162,130],{"class":82},[76,164,165],{"class":126}," 'running'",[76,167,130],{"class":82},[76,169,170],{"class":126}," 'done'",[76,172,130],{"class":82},[76,174,175],{"class":126}," 'error'\n",[76,177,179],{"class":78,"line":178},7,[76,180,181],{"class":90},"}\n",[11,183,184,185,188,189,192],{},"각 모델별 API 클라이언트를 만들고, 러너가 아이템의 ",[23,186,187],{},"model"," 필드를 보고 적절한 클라이언트로 라우팅하는 구조였습니다. 여기서 ",[15,190,191],{},"동시 실행"," 이라는 두 번째 문제가 등장했습니다.",[11,194,195],{},"순차 실행이면 단순합니다. 하나 끝나면 다음 하나. 하지만 사용자는 곧 이렇게 묻습니다.",[49,197,198],{},[11,199,200],{},"\"Claude 응답 기다리는 동안 GPT도 같이 돌리면 안 되나요?\"",[11,202,203,204,207],{},"가능합니다. 대신 그러려면 ",[15,205,206],{},"동시성 제어"," 가 필요합니다. 모델별 rate limit은 다르고, 에러 처리도 독립적이어야 하며, 터미널 뷰어는 여러 스트림을 동시에 보여줘야 했습니다.",[28,209,211],{"id":210},"_3차-구조-워커-풀","3차 구조: 워커 풀",[11,213,214,215,218],{},"결국 ",[15,216,217],{},"워커 풀(Worker Pool)"," 구조로 돌아왔습니다.",[36,220,223],{"className":221,"code":222,"language":41,"meta":42},[39],"------------------------------------------------------------\n|                     Queue Manager                        |\n|        priority sorting + dependency resolve            |\n|-----------|-----------|-----------|-----------|\n            |           |           |\n         Worker 1    Worker 2    Worker 3\n         (Claude)      (GPT)      (Gemini)\n            |           |           |\n            |------ merged streams -----------|\n                          |\n                   Log Aggregator\n",[23,224,222],{"__ignoreMap":42},[11,226,227],{},"이 구조의 핵심은 세 가지였습니다.",[229,230,231,238,244],"ol",{},[232,233,234,237],"li",{},[15,235,236],{},"워커는 모델에 종속되지 않습니다."," 워커는 실행 단위일 뿐이고, 어떤 모델이든 어떤 프롬프트든 받아서 처리합니다.",[232,239,240,243],{},[15,241,242],{},"큐 매니저가 라우팅을 결정합니다."," 우선순위, 의존 관계, 모델별 rate limit을 종합해서 다음 실행 대상을 고릅니다.",[232,245,246,249],{},[15,247,248],{},"로그 애그리게이터가 스트림을 합칩니다."," 각 워커에서 오는 SSE 스트림을 하나의 타임라인으로 병합합니다.",[28,251,253],{"id":252},"의존-관계가-있는-경우","의존 관계가 있는 경우",[11,255,256,257,260],{},"이 구조에서 가장 가치 있었던 건 ",[15,258,259],{},"프롬프트 간 의존 관계"," 였습니다. 예를 들면:",[262,263,264,267,270],"ul",{},[232,265,266],{},"Prompt A: \"이 코드를 분석해줘\" -> Claude",[232,268,269],{},"Prompt B: \"A의 결과를 바탕으로 테스트 코드를 작성해줘\" -> GPT",[232,271,272],{},"Prompt C: \"A와 B의 결과를 종합해서 문서화해줘\" -> Claude",[11,274,275,276,279],{},"B는 A가 끝나야 실행할 수 있고, C는 A와 B가 모두 끝나야 합니다. 이런 순서를 처리하려면 ",[15,277,278],{},"DAG(Directed Acyclic Graph)"," 기반의 의존성 해석이 필요했습니다.",[36,281,283],{"className":70,"code":282,"language":72,"meta":42,"style":42},"function getNextExecutable(queue, completed) {\n  return queue\n    .filter(item => item.status === 'pending')\n    .filter(item => item.dependsOn.every(depId => completed.has(depId)))\n    .sort((a, b) => a.priority - b.priority)\n}\n",[23,284,285,308,316,343,377,410],{"__ignoreMap":42},[76,286,287,290,293,296,299,302,305],{"class":78,"line":79},[76,288,289],{"class":82},"function",[76,291,292],{"class":86}," getNextExecutable",[76,294,295],{"class":90},"(",[76,297,298],{"class":97},"queue",[76,300,301],{"class":90},", ",[76,303,304],{"class":97},"completed",[76,306,307],{"class":90},") {\n",[76,309,310,313],{"class":78,"line":94},[76,311,312],{"class":82},"  return",[76,314,315],{"class":90}," queue\n",[76,317,318,321,324,326,329,332,335,338,340],{"class":78,"line":108},[76,319,320],{"class":90},"    .",[76,322,323],{"class":86},"filter",[76,325,295],{"class":90},[76,327,328],{"class":97},"item",[76,330,331],{"class":82}," =>",[76,333,334],{"class":90}," item.status ",[76,336,337],{"class":82},"===",[76,339,160],{"class":126},[76,341,342],{"class":90},")\n",[76,344,345,347,349,351,353,355,358,361,363,366,368,371,374],{"class":78,"line":118},[76,346,320],{"class":90},[76,348,323],{"class":86},[76,350,295],{"class":90},[76,352,328],{"class":97},[76,354,331],{"class":82},[76,356,357],{"class":90}," item.dependsOn.",[76,359,360],{"class":86},"every",[76,362,295],{"class":90},[76,364,365],{"class":97},"depId",[76,367,331],{"class":82},[76,369,370],{"class":90}," completed.",[76,372,373],{"class":86},"has",[76,375,376],{"class":90},"(depId)))\n",[76,378,379,381,384,387,390,392,395,398,401,404,407],{"class":78,"line":141},[76,380,320],{"class":90},[76,382,383],{"class":86},"sort",[76,385,386],{"class":90},"((",[76,388,389],{"class":97},"a",[76,391,301],{"class":90},[76,393,394],{"class":97},"b",[76,396,397],{"class":90},") ",[76,399,400],{"class":82},"=>",[76,402,403],{"class":90}," a.priority ",[76,405,406],{"class":82},"-",[76,408,409],{"class":90}," b.priority)\n",[76,411,412],{"class":78,"line":152},[76,413,181],{"class":90},[11,415,416,417,420],{},"순환 의존성 감지, 실패한 의존성의 후속 처리, 재시도 규칙까지 들어가면 단순한 큐가 아니라 사실상 ",[15,418,419],{},"작업 스케줄러"," 에 가까워집니다.",[28,422,424],{"id":423},"결국-배운-점","결국 배운 점",[11,426,427,428,431],{},"세 번 구조를 바꾸면서 배운 건 ",[15,429,430],{},"\"사용자의 멘탈 모델이 맞아야 한다\""," 는 점이었습니다. 사용자는 이를 그냥 \"프롬프트 목록\"처럼 생각합니다. 내부적으로는 워커 풀과 DAG가 돌아가더라도, UI에서는 드래그로 순서를 바꾸고 선으로 의존 관계를 연결하는 정도로 보여야 했습니다.",[11,433,434],{},"결국 중요한 건 내부 구조를 과시하는 게 아니라, 사용자가 복잡함을 느끼지 않게 만드는 일이었습니다. 그게 좋은 도구라고 생각합니다.",[11,436,437],{},"다음 글에서는 Cross Validation, 즉 여러 LLM에게 같은 질문을 보내고 응답을 비교하는 기능을 구현하면서 겪은 이야기를 정리합니다.",[439,440,441],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}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":42,"searchDepth":94,"depth":94,"links":443},[444,445,446,447,448],{"id":30,"depth":94,"text":31},{"id":63,"depth":94,"text":64},{"id":210,"depth":94,"text":211},{"id":252,"depth":94,"text":253},{"id":423,"depth":94,"text":424},"Architecture","2026-04-07","순차 실행에서 워커 풀 구조로 넘어오기까지, Prompt Combo의 큐 아키텍처를 세 번 뜯어고친 기록입니다.","md",true,"\u002Fmain-screenshot.png",{},"\u002Fko\u002Fblog\u002Fmulti-agent-queue","12 min read",{"title":5,"description":451},"ko\u002Fblog\u002Fmulti-agent-queue",[298,461,462],"architecture","multi-agent","qAKODt_Lu9tJq45NN9pzGMutl4yd-jPQb9Q_8BYW9ak",[465,764],{"id":4,"title":5,"author":6,"body":466,"category":449,"date":450,"description":451,"extension":452,"featured":453,"icon":298,"image":454,"meta":761,"navigation":453,"path":456,"readTime":457,"seo":762,"stem":459,"tags":763,"__hash__":463},{"type":8,"value":467,"toc":754},[468,472,476,478,480,485,487,491,495,497,499,575,581,583,587,591,593,597,602,604,618,620,624,632,636,738,742,744,748,750,752],[11,469,13,470,18],{},[15,471,17],{},[11,473,21,474,26],{},[23,475,25],{},[28,477,31],{"id":30},[11,479,34],{},[36,481,483],{"className":482,"code":40,"language":41,"meta":42},[39],[23,484,40],{"__ignoreMap":42},[11,486,47],{},[49,488,489],{},[11,490,53],{},[11,492,56,493,60],{},[15,494,59],{},[28,496,64],{"id":63},[11,498,67],{},[36,500,501],{"className":70,"code":71,"language":72,"meta":42,"style":42},[23,502,503,511,519,527,543,551,571],{"__ignoreMap":42},[76,504,505,507,509],{"class":78,"line":79},[76,506,83],{"class":82},[76,508,87],{"class":86},[76,510,91],{"class":90},[76,512,513,515,517],{"class":78,"line":94},[76,514,98],{"class":97},[76,516,101],{"class":82},[76,518,105],{"class":104},[76,520,521,523,525],{"class":78,"line":108},[76,522,111],{"class":97},[76,524,101],{"class":82},[76,526,105],{"class":104},[76,528,529,531,533,535,537,539,541],{"class":78,"line":118},[76,530,121],{"class":97},[76,532,101],{"class":82},[76,534,127],{"class":126},[76,536,130],{"class":82},[76,538,133],{"class":126},[76,540,130],{"class":82},[76,542,138],{"class":126},[76,544,545,547,549],{"class":78,"line":141},[76,546,144],{"class":97},[76,548,101],{"class":82},[76,550,149],{"class":86},[76,552,553,555,557,559,561,563,565,567,569],{"class":78,"line":152},[76,554,155],{"class":97},[76,556,101],{"class":82},[76,558,160],{"class":126},[76,560,130],{"class":82},[76,562,165],{"class":126},[76,564,130],{"class":82},[76,566,170],{"class":126},[76,568,130],{"class":82},[76,570,175],{"class":126},[76,572,573],{"class":78,"line":178},[76,574,181],{"class":90},[11,576,184,577,188,579,192],{},[23,578,187],{},[15,580,191],{},[11,582,195],{},[49,584,585],{},[11,586,200],{},[11,588,203,589,207],{},[15,590,206],{},[28,592,211],{"id":210},[11,594,214,595,218],{},[15,596,217],{},[36,598,600],{"className":599,"code":222,"language":41,"meta":42},[39],[23,601,222],{"__ignoreMap":42},[11,603,227],{},[229,605,606,610,614],{},[232,607,608,237],{},[15,609,236],{},[232,611,612,243],{},[15,613,242],{},[232,615,616,249],{},[15,617,248],{},[28,619,253],{"id":252},[11,621,256,622,260],{},[15,623,259],{},[262,625,626,628,630],{},[232,627,266],{},[232,629,269],{},[232,631,272],{},[11,633,275,634,279],{},[15,635,278],{},[36,637,638],{"className":70,"code":282,"language":72,"meta":42,"style":42},[23,639,640,656,662,682,710,734],{"__ignoreMap":42},[76,641,642,644,646,648,650,652,654],{"class":78,"line":79},[76,643,289],{"class":82},[76,645,292],{"class":86},[76,647,295],{"class":90},[76,649,298],{"class":97},[76,651,301],{"class":90},[76,653,304],{"class":97},[76,655,307],{"class":90},[76,657,658,660],{"class":78,"line":94},[76,659,312],{"class":82},[76,661,315],{"class":90},[76,663,664,666,668,670,672,674,676,678,680],{"class":78,"line":108},[76,665,320],{"class":90},[76,667,323],{"class":86},[76,669,295],{"class":90},[76,671,328],{"class":97},[76,673,331],{"class":82},[76,675,334],{"class":90},[76,677,337],{"class":82},[76,679,160],{"class":126},[76,681,342],{"class":90},[76,683,684,686,688,690,692,694,696,698,700,702,704,706,708],{"class":78,"line":118},[76,685,320],{"class":90},[76,687,323],{"class":86},[76,689,295],{"class":90},[76,691,328],{"class":97},[76,693,331],{"class":82},[76,695,357],{"class":90},[76,697,360],{"class":86},[76,699,295],{"class":90},[76,701,365],{"class":97},[76,703,331],{"class":82},[76,705,370],{"class":90},[76,707,373],{"class":86},[76,709,376],{"class":90},[76,711,712,714,716,718,720,722,724,726,728,730,732],{"class":78,"line":141},[76,713,320],{"class":90},[76,715,383],{"class":86},[76,717,386],{"class":90},[76,719,389],{"class":97},[76,721,301],{"class":90},[76,723,394],{"class":97},[76,725,397],{"class":90},[76,727,400],{"class":82},[76,729,403],{"class":90},[76,731,406],{"class":82},[76,733,409],{"class":90},[76,735,736],{"class":78,"line":152},[76,737,181],{"class":90},[11,739,416,740,420],{},[15,741,419],{},[28,743,424],{"id":423},[11,745,427,746,431],{},[15,747,430],{},[11,749,434],{},[11,751,437],{},[439,753,441],{},{"title":42,"searchDepth":94,"depth":94,"links":755},[756,757,758,759,760],{"id":30,"depth":94,"text":31},{"id":63,"depth":94,"text":64},{"id":210,"depth":94,"text":211},{"id":252,"depth":94,"text":253},{"id":423,"depth":94,"text":424},{},{"title":5,"description":451},[298,461,462],{"id":765,"title":5,"author":6,"body":766,"category":449,"date":450,"description":1094,"extension":452,"featured":453,"icon":298,"image":454,"meta":1095,"navigation":453,"path":1096,"readTime":457,"seo":1097,"stem":1098,"tags":1099,"__hash__":1100},"blog\u002Fen\u002Fblog\u002Fmulti-agent-queue.md",{"type":8,"value":767,"toc":1087},[768,775,781,785,788,793,796,801,804,808,811,887,894,897,902,905,909,912,917,920,940,944,947,950,961,964,1066,1069,1073,1076,1079,1082,1085],[11,769,770,771,774],{},"Prompt Combo started with one simple idea: ",[15,772,773],{},"\"put prompts into a queue and let them finish on their own.\""," It sounded trivial on paper. In practice, it forced three separate architecture rewrites.",[11,776,777,778,780],{},"At the start, the queue was nothing more than an array plus a ",[23,779,25],{}," loop. Each prompt ran, returned a response, and appended output to a log. That was enough for a first prototype. It stopped being enough as soon as real usage showed up.",[28,782,784],{"id":783},"first-version-sequential-execution","First version: sequential execution",[11,786,787],{},"The earliest shape looked like this:",[36,789,791],{"className":790,"code":40,"language":41,"meta":42},[39],[23,792,40],{"__ignoreMap":42},[11,794,795],{},"It worked, but the first real user request broke the assumption immediately:",[49,797,798],{},[11,799,800],{},"\"Can this prompt run on GPT-4o while the next one runs on Claude?\"",[11,802,803],{},"A queue that assumes one model is not really a workflow engine. From that moment on, every queue item needed to carry its own model, parameters, and execution context.",[28,805,807],{"id":806},"second-version-model-aware-routing","Second version: model-aware routing",[11,809,810],{},"The next step was to enrich each queue item:",[36,812,813],{"className":70,"code":71,"language":72,"meta":42,"style":42},[23,814,815,823,831,839,855,863,883],{"__ignoreMap":42},[76,816,817,819,821],{"class":78,"line":79},[76,818,83],{"class":82},[76,820,87],{"class":86},[76,822,91],{"class":90},[76,824,825,827,829],{"class":78,"line":94},[76,826,98],{"class":97},[76,828,101],{"class":82},[76,830,105],{"class":104},[76,832,833,835,837],{"class":78,"line":108},[76,834,111],{"class":97},[76,836,101],{"class":82},[76,838,105],{"class":104},[76,840,841,843,845,847,849,851,853],{"class":78,"line":118},[76,842,121],{"class":97},[76,844,101],{"class":82},[76,846,127],{"class":126},[76,848,130],{"class":82},[76,850,133],{"class":126},[76,852,130],{"class":82},[76,854,138],{"class":126},[76,856,857,859,861],{"class":78,"line":141},[76,858,144],{"class":97},[76,860,101],{"class":82},[76,862,149],{"class":86},[76,864,865,867,869,871,873,875,877,879,881],{"class":78,"line":152},[76,866,155],{"class":97},[76,868,101],{"class":82},[76,870,160],{"class":126},[76,872,130],{"class":82},[76,874,165],{"class":126},[76,876,130],{"class":82},[76,878,170],{"class":126},[76,880,130],{"class":82},[76,882,175],{"class":126},[76,884,885],{"class":78,"line":178},[76,886,181],{"class":90},[11,888,889,890,893],{},"Now the runner could inspect ",[23,891,892],{},"item.model"," and send work to the correct client. That solved model choice, but it surfaced the next constraint almost immediately: concurrency.",[11,895,896],{},"The question turned into:",[49,898,899],{},[11,900,901],{},"\"While Claude is thinking, can GPT work on something else at the same time?\"",[11,903,904],{},"Technically, yes. Operationally, that means rate-limit awareness, independent failure handling, and a viewer that can make multiple active streams readable at once.",[28,906,908],{"id":907},"third-version-worker-pool-plus-queue-manager","Third version: worker pool plus queue manager",[11,910,911],{},"That is where the current design came from. The queue stopped being a single runner and became a scheduler with workers.",[36,913,915],{"className":914,"code":222,"language":41,"meta":42},[39],[23,916,222],{"__ignoreMap":42},[11,918,919],{},"Three ideas made this version hold:",[229,921,922,928,934],{},[232,923,924,927],{},[15,925,926],{},"Workers are generic execution units."," They are not tied to a single model.",[232,929,930,933],{},[15,931,932],{},"The queue manager decides routing."," It combines priority, dependencies, and rate limits before dispatching.",[232,935,936,939],{},[15,937,938],{},"The log aggregator merges streams into one timeline."," Without that layer, the terminal viewer becomes noise.",[28,941,943],{"id":942},"dependencies-change-the-problem-completely","Dependencies change the problem completely",[11,945,946],{},"The most valuable addition in this design was explicit dependencies between prompts.",[11,948,949],{},"For example:",[262,951,952,955,958],{},[232,953,954],{},"Prompt A: \"Analyze this codebase\" -> Claude",[232,956,957],{},"Prompt B: \"Write tests based on A\" -> GPT",[232,959,960],{},"Prompt C: \"Summarize A and B into docs\" -> Claude",[11,962,963],{},"B cannot start until A finishes. C cannot start until both A and B finish. At that point, the queue is no longer just a queue. It behaves more like a job scheduler over a DAG.",[36,965,966],{"className":70,"code":282,"language":72,"meta":42,"style":42},[23,967,968,984,990,1010,1038,1062],{"__ignoreMap":42},[76,969,970,972,974,976,978,980,982],{"class":78,"line":79},[76,971,289],{"class":82},[76,973,292],{"class":86},[76,975,295],{"class":90},[76,977,298],{"class":97},[76,979,301],{"class":90},[76,981,304],{"class":97},[76,983,307],{"class":90},[76,985,986,988],{"class":78,"line":94},[76,987,312],{"class":82},[76,989,315],{"class":90},[76,991,992,994,996,998,1000,1002,1004,1006,1008],{"class":78,"line":108},[76,993,320],{"class":90},[76,995,323],{"class":86},[76,997,295],{"class":90},[76,999,328],{"class":97},[76,1001,331],{"class":82},[76,1003,334],{"class":90},[76,1005,337],{"class":82},[76,1007,160],{"class":126},[76,1009,342],{"class":90},[76,1011,1012,1014,1016,1018,1020,1022,1024,1026,1028,1030,1032,1034,1036],{"class":78,"line":118},[76,1013,320],{"class":90},[76,1015,323],{"class":86},[76,1017,295],{"class":90},[76,1019,328],{"class":97},[76,1021,331],{"class":82},[76,1023,357],{"class":90},[76,1025,360],{"class":86},[76,1027,295],{"class":90},[76,1029,365],{"class":97},[76,1031,331],{"class":82},[76,1033,370],{"class":90},[76,1035,373],{"class":86},[76,1037,376],{"class":90},[76,1039,1040,1042,1044,1046,1048,1050,1052,1054,1056,1058,1060],{"class":78,"line":141},[76,1041,320],{"class":90},[76,1043,383],{"class":86},[76,1045,386],{"class":90},[76,1047,389],{"class":97},[76,1049,301],{"class":90},[76,1051,394],{"class":97},[76,1053,397],{"class":90},[76,1055,400],{"class":82},[76,1057,403],{"class":90},[76,1059,406],{"class":82},[76,1061,409],{"class":90},[76,1063,1064],{"class":78,"line":152},[76,1065,181],{"class":90},[11,1067,1068],{},"Once you add circular dependency detection, retry rules, and failure propagation, the problem is operational design, not just iteration order.",[28,1070,1072],{"id":1071},"what-this-taught-us","What this taught us",[11,1074,1075],{},"The most important lesson was not about workers or graphs. It was about the user mental model.",[11,1077,1078],{},"Users think in terms of \"a list of prompts.\" Internally, Prompt Combo may be running a worker pool, dependency resolver, and merged log pipeline. None of that should leak into the surface unless it helps.",[11,1080,1081],{},"The UI should let people drag items, connect dependencies, and understand what is blocked or done. The internal complexity is justified only if the product still feels simpler than doing the work manually.",[11,1083,1084],{},"That is the bar we ended up optimizing for.",[439,1086,441],{},{"title":42,"searchDepth":94,"depth":94,"links":1088},[1089,1090,1091,1092,1093],{"id":783,"depth":94,"text":784},{"id":806,"depth":94,"text":807},{"id":907,"depth":94,"text":908},{"id":942,"depth":94,"text":943},{"id":1071,"depth":94,"text":1072},"A build note on how Prompt Combo moved from sequential execution to a worker-pool queue with dependencies.",{},"\u002Fen\u002Fblog\u002Fmulti-agent-queue",{"title":5,"description":1094},"en\u002Fblog\u002Fmulti-agent-queue",[298,461,462],"4zuOHfUTI0VH9YztmZ76HWvNqsctH0xCcg_5hgfEV2o",1775722676874]