[{"data":1,"prerenderedAt":342},["ShallowReactive",2],{"blog-de-jeder-agent-installierte-sich-beim-spawn-sein-eigenes-bun":3,"header-blog-translations-/de/blog/jeder-agent-installierte-sich-beim-spawn-sein-eigenes-bun":339},{"id":4,"title":5,"author":6,"body":7,"date":321,"description":322,"draft":323,"extension":324,"image":325,"meta":326,"navigation":327,"path":328,"seo":329,"stem":330,"tags":331,"translationKey":337,"__hash__":338},"blog_de/blog/de/jeder-agent-installierte-sich-beim-spawn-sein-eigenes-bun.md","Jeder Agent installierte sich beim Spawn sein eigenes bun","Patrick Hofmann",{"type":8,"value":9,"toc":314},"minimark",[10,23,26,31,37,40,43,47,61,73,76,80,83,234,260,263,267,273,276,279,283,303,310],[11,12,13,14,18,19,22],"p",{},"Ich habe einem Spawn zugeschaut. Vom ",[15,16,17],"code",{},"apes agents spawn"," bis der Agent tatsächlich auf eine Chat-Nachricht antwortete vergingen rund sechzig Sekunden. Den größten Teil davon verbrachte das Setup-Skript damit, ",[15,20,21],{},"bun"," herunterzuladen und in das frische Home des Agents zu installieren. Jedes Mal. Pro Agent.",[11,24,25],{},"Das war so gebaut, und ich hatte es selbst so gebaut. Hier ist, warum ich es wieder rausgeworfen habe.",[27,28,30],"h2",{"id":29},"wie-es-vorher-war","Wie es vorher war",[11,32,33,34,36],{},"Beim Spawn bekommt ein Agent einen eigenen macOS-User und ein eigenes Home-Verzeichnis. Das Setup-Skript zog dann in dieses Home eine eigene ",[15,35,21],{},"-Runtime — circa 100MB, eine knappe Minute Arbeit. Danach lief der Agent komplett auf seiner eigenen Toolchain, ohne irgendetwas mit dem Host oder anderen Agents zu teilen.",[11,38,39],{},"Die Annahme dahinter: Agents müssen voneinander isoliert sein, und Isolation heißt, dass auch das Tooling nicht geteilt wird. Jeder seine eigene Runtime. Kein gemeinsames Binary, an dem ein Agent etwas verändern könnte, das einen anderen trifft. Isolation by default, runter bis zur Runtime.",[11,41,42],{},"Das klang richtig, als ich es schrieb. Es war auch nicht falsch — nur an der falschen Stelle.",[27,44,46],{"id":45},"warum-ich-es-rausgenommen-habe","Warum ich es rausgenommen habe",[11,48,49,50,53,54,57,58,60],{},"Auf einem Single-User-Host sind ",[15,51,52],{},"node",", ",[15,55,56],{},"apes"," und die Chat-Bridge ohnehin da. Sie liegen im System, der User hat sie installiert, sie ändern sich nicht, weil ein Agent sie nicht anfasst. Ein eigenes ",[15,59,21],{}," pro Agent dupliziert eine Datei, die längst existiert, in ein Verzeichnis, das niemand sonst liest.",[11,62,63,64,67,68,72],{},"Die eigentliche Trennlinie zwischen zwei Agents auf dieser Maschine ist nicht ihre Runtime. Es ist die macOS-uid und der Privilege-Helper (",[15,65,66],{},"escapes","), der jeden privilegierten Crossing einzeln durchwinkt. ",[69,70,71],"em",{},"Das"," ist die Isolationsgrenze. Alles davor zu kopieren schützt gegen nichts, das die uid nicht schon abdeckt — es kostet nur Spawn-Zeit und Plattenplatz.",[11,74,75],{},"Ich hatte Tooling-Isolation gebaut, als wäre Isolation ein Stapel Kopien. Sie ist aber eine Grenze. Und die Grenze lag woanders.",[27,77,79],{"id":78},"wie-es-jetzt-aussieht","Wie es jetzt aussieht",[11,81,82],{},"Statt pro Agent eine Runtime zu installieren, fängt das Setup ab, wo die Tools auf dem Host liegen, und backt diese Pfade in die launchd-Plist des Agents:",[84,85,90],"pre",{"className":86,"code":87,"language":88,"meta":89,"style":89},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# Capture the host's tool locations once, dedupe, bake into the plist PATH\nagent_path=$(\n  for bin in node openape-chat-bridge apes; do\n    cmd=$(command -v \"$bin\" 2>/dev/null) || continue\n    dirname \"$cmd\"\n  done | awk '!seen[$0]++' | paste -sd: -\n)\n","bash","",[15,91,92,101,112,141,181,196,228],{"__ignoreMap":89},[93,94,97],"span",{"class":95,"line":96},"line",1,[93,98,100],{"class":99},"sHwdD","# Capture the host's tool locations once, dedupe, bake into the plist PATH\n",[93,102,104,108],{"class":95,"line":103},2,[93,105,107],{"class":106},"sTEyZ","agent_path",[93,109,111],{"class":110},"sMK4o","=$(\n",[93,113,115,119,122,125,129,132,135,138],{"class":95,"line":114},3,[93,116,118],{"class":117},"s7zQu","  for",[93,120,121],{"class":106}," bin ",[93,123,124],{"class":117},"in",[93,126,128],{"class":127},"sfazB"," node",[93,130,131],{"class":127}," openape-chat-bridge",[93,133,134],{"class":127}," apes",[93,136,137],{"class":110},";",[93,139,140],{"class":117}," do\n",[93,142,144,147,150,154,157,160,163,166,169,172,175,178],{"class":95,"line":143},4,[93,145,146],{"class":106},"    cmd",[93,148,149],{"class":110},"=$(",[93,151,153],{"class":152},"s2Zo4","command",[93,155,156],{"class":127}," -v",[93,158,159],{"class":110}," \"",[93,161,162],{"class":106},"$bin",[93,164,165],{"class":110},"\"",[93,167,168],{"class":110}," 2>",[93,170,171],{"class":127},"/dev/null",[93,173,174],{"class":110},")",[93,176,177],{"class":110}," ||",[93,179,180],{"class":117}," continue\n",[93,182,184,188,190,193],{"class":95,"line":183},5,[93,185,187],{"class":186},"sBMFI","    dirname",[93,189,159],{"class":110},[93,191,192],{"class":106},"$cmd",[93,194,195],{"class":110},"\"\n",[93,197,199,202,205,208,211,214,217,219,222,225],{"class":95,"line":198},6,[93,200,201],{"class":117},"  done",[93,203,204],{"class":110}," |",[93,206,207],{"class":186}," awk",[93,209,210],{"class":110}," '",[93,212,213],{"class":127},"!seen[$0]++",[93,215,216],{"class":110},"'",[93,218,204],{"class":110},[93,220,221],{"class":186}," paste",[93,223,224],{"class":127}," -sd:",[93,226,227],{"class":127}," -\n",[93,229,231],{"class":95,"line":230},7,[93,232,233],{"class":110},")\n",[11,235,236,239,240,243,244,247,248,251,252,255,256,259],{},[15,237,238],{},"command -v"," für jedes der drei Tools, ",[15,241,242],{},"dirname"," auf das Resultat, ",[15,245,246],{},"awk '!seen[$0]++'"," als Dedupe (zwei Tools liegen oft im selben Verzeichnis), ",[15,249,250],{},"paste"," zu einem ",[15,253,254],{},"PATH","-String. Der landet in den ",[15,257,258],{},"EnvironmentVariables"," der Plist, und der Agent findet seine Tools dort, wo der Host sie hat.",[11,261,262],{},"Der Spawn fällt damit von rund sechzig Sekunden auf rund vier. Die vier Sekunden sind ohnehin nicht das Tooling, das ist der Rest des Setups. Pro Agent fallen die 100MB komplett weg.",[27,264,266],{"id":265},"was-weggefallen-ist","Was weggefallen ist",[11,268,269,270,272],{},"Die per-Agent-",[15,271,21],{},"-Installation. Vollständig.",[11,274,275],{},"Der ehrliche Trade-off, den ich nicht verstecken will: alle Agents teilen sich jetzt eine Bridge-Version. Wenn ich die Bridge auf dem Host update, ändert sie sich für alle gleichzeitig. In einem Multi-Tenant-Setup, in dem fremde Agents nebeneinander laufen, wäre das die falsche Entscheidung — dort will man die Tooling-Versionen tatsächlich auseinanderhalten. Auf meinem Single-User-Host ist es genau das, was ich will: ein Update, alle aktuell.",[11,277,278],{},"Der client-seitige Reflex wäre gewesen, die Isolation drinzulassen und sie als Feature zu verkaufen. Sie tat nur nichts.",[27,280,282],{"id":281},"der-schnitt","Der Schnitt",[11,284,285,288,289,292,293,296,297,299,300,302],{},[15,286,287],{},"isolation by default"," klingt nach einer sicheren Voreinstellung. Sie war keine — sie war eine Annahme aus der Zeit, als ein Agent auf der Maschine lief und ",[69,290,291],{},"isoliert"," einfach ",[69,294,295],{},"dupliziert alles"," hieß. Sobald die Frage konkret wird — Isolation wovon, gegen wen, an welcher Grenze — fällt die Antwort woanders hin: die Grenze ist die uid und der ",[15,298,66],{},"-Helper, nicht das mitkopierte ",[15,301,21],{},". Was davor liegt, ist keine Sicherheit, sondern Reibung mit Sicherheits-Anstrich.",[11,304,305,306,309],{},"Defaults tragen die Welt mit sich, in der sie geschrieben wurden. Das Gefährliche an ",[15,307,308],{},"by default"," ist nicht der Default — es ist, dass man aufhört zu fragen, wofür er da war.",[311,312,313],"style",{},"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 .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 .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}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);}",{"title":89,"searchDepth":103,"depth":103,"links":315},[316,317,318,319,320],{"id":29,"depth":103,"text":30},{"id":45,"depth":103,"text":46},{"id":78,"depth":103,"text":79},{"id":265,"depth":103,"text":266},{"id":281,"depth":103,"text":282},"2026-05-10","Pro-Agent-Tooling-Isolation klang nach Sicherheit. Auf einem Single-User-Host war sie 100MB und eine Minute Spawn-Zeit, die nichts isolierten. Was wegfiel, als ich die echte Trennlinie ernst nahm.",false,"md",null,{},true,"/blog/de/jeder-agent-installierte-sich-beim-spawn-sein-eigenes-bun",{"title":5,"description":322},"blog/de/jeder-agent-installierte-sich-beim-spawn-sein-eigenes-bun",[332,333,334,335,336],"OpenApe","AI Agents","Infrastructure","Tooling","Building in Public","isolation-by-default-single-agent-default","Us0NCSgYCgjlwZSgt-UfotNt2VOXS6RkDVqqPOzGB5w",{"de":340,"en":341},"/de/blog/jeder-agent-installierte-sich-beim-spawn-sein-eigenes-bun","/en/blog/isolation-by-default-single-agent-default",1779001885835]