pages › AgentsOnboard · version 2 ·

Open the page

---
description: Run your agents in the background: the page after Start your agents (Create my agents); makes one link per ticked role, where they run (designer launcher, always-on Mac, my own setup, …), keep them going, talk to them, Open my dashboard. Razie chats 6acab6b2 (2026-10-10), 6acb85f4 and 6acb8f6d (2026-10-11), P-1318
tags: page, onboarding
---
<!doctype html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"><meta name="color-scheme" content="light dark"><title>Start your agents</title>
<style>
:root{--paper:#fbfaf7;--card:#fff;--ink:#1d1d1b;--soft:#6b6a66;--line:#e4e1da;--rose:#b23a48;--ok:#3c9a5f;--lv:#6c8cff;--display:'Manrope',system-ui,-apple-system,'Segoe UI',sans-serif;--body:system-ui,-apple-system,'Segoe UI',sans-serif}
@media (prefers-color-scheme:dark){:root{--paper:#141413;--card:#1d1d1b;--ink:#ecebe6;--soft:#9c9a93;--line:#33322f;--rose:#f08a92;--ok:#5cc282}}
*{box-sizing:border-box}html,body{background:var(--paper);color:var(--ink);margin:0}body{font:calc(15px*var(--fz,1))/1.5 var(--body)}
.sp-wrap{max-width:900px;margin:0 auto;padding:6px clamp(12px,3vw,28px) 56px}
h1{font:800 calc(clamp(26px,4vw,34px)*var(--fz,1))/1.1 var(--display);letter-spacing:-.02em;margin:12px 0}
h2{font:800 22px/1.2 var(--display);margin:28px 0 8px}a{color:var(--lv)}.small{font-size:13px;color:var(--soft)}
.sp-opts{display:grid;gap:10px;margin:12px 0 16px;max-width:620px}
.sp-opt{display:flex;gap:10px;align-items:flex-start;cursor:pointer;background:color-mix(in srgb,var(--lv) 9%,var(--card));border:1px solid color-mix(in srgb,var(--lv) 35%,var(--line));border-radius:12px;padding:12px 14px}
.sp-opt input{width:20px;height:20px;margin:2px 0 0;accent-color:var(--lv);flex:none}.sp-opt b{display:block}.sp-opt span{color:var(--soft);font-size:14px}
.sp-go{border:0;cursor:pointer;padding:14px 30px;border-radius:999px;background:var(--lv);color:#111;font:800 1.3em/1.2 var(--body);box-shadow:0 2px 8px rgba(0,0,0,.18)}.sp-go:disabled{opacity:.6;cursor:default}
.sp-say{display:block;margin-top:8px;color:var(--rose);font-size:13px;min-height:1em}
.cards{display:grid;gap:12px;max-width:720px}
.card{background:var(--card);border:1px solid var(--line);border-left:4px solid var(--lv);border-radius:12px;padding:12px 14px}
.card h3{margin:0 0 6px;font:800 17px/1.2 var(--display);display:flex;align-items:center;gap:8px}
.dot{width:10px;height:10px;border-radius:50%;background:var(--line);flex:none}.dot.on{background:var(--ok);box-shadow:0 0 0 3px color-mix(in srgb,var(--ok) 25%,transparent)}
.st{font:400 13px var(--body);color:var(--soft)}
pre{white-space:pre-wrap;word-break:break-all;background:color-mix(in srgb,var(--lv) 7%,var(--paper));border:1px solid var(--line);border-radius:8px;padding:8px 10px;margin:6px 0;font:12.5px/1.4 ui-monospace,Menlo,monospace}
.btn{border:1px solid var(--line);background:var(--card);color:var(--ink);border-radius:999px;padding:6px 14px;cursor:pointer;font:600 13px var(--body);margin-right:6px}
.sp-opt.off{opacity:.5;filter:grayscale(1);cursor:not-allowed;pointer-events:none;user-select:none}.sp-opt .soon{font-style:normal;font-size:12px;font-weight:700;padding:2px 8px;border-radius:999px;border:1px solid currentColor;margin-left:6px;vertical-align:1px}
</style>
</head><body><div class="sp-wrap">
<p class="small"><a href="/page/StartAgents" id="sp-back" data-go>← Start your agents</a></p>
<h1>Run your agents in the background</h1>
<p>Your agents work on their own, in the background, while you keep thinking. Three steps, a few minutes each.</p>
<style>.st3{display:grid;gap:14px;max-width:760px;counter-reset:s}.st3>div{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:16px 18px;position:relative;padding-left:58px}
.st3>div::before{counter-increment:s;content:counter(s);position:absolute;left:16px;top:14px;width:28px;height:28px;border-radius:50%;background:var(--lv);color:#111;font:800 15px/28px var(--display);text-align:center}
.st3 h3{margin:0 0 6px;font:800 18px/1.2 var(--display)}.st3 p{margin:6px 0}.st3 code{font-size:13px;background:color-mix(in srgb,var(--lv) 10%,var(--card));padding:1px 6px;border-radius:6px}
.todo{border:1px dashed #e0a43a;background:color-mix(in srgb,#e0a43a 8%,var(--card));border-radius:10px;padding:8px 12px;font-size:13px;margin-top:8px}
.dot{display:inline-block;width:10px;height:10px;border-radius:50%;background:#bbb;margin-right:8px}.dot.on{background:var(--ok)}</style>
<div class="st3">
<div><h3>Where they run</h3><p>Each agent is one session of an AI that can work on its own and reach the web. Pick where yours run:</p><style>.where{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px;margin-top:10px}.where>div{border:1px solid var(--line);border-top:4px solid var(--lv);border-radius:12px;padding:12px 14px;background:color-mix(in srgb,var(--lv) 6%,var(--card))}.where b{display:block;font:800 16px/1.2 var(--display);margin-bottom:4px}.where span{font-size:14px;color:var(--soft)}.where .tbd{border-top-color:var(--line);opacity:.55;filter:grayscale(1)}.where .tbd b::after{content:"coming soon";font:700 11px var(--body);margin-left:8px;padding:1px 7px;border-radius:999px;border:1px solid currentColor;vertical-align:2px}</style><p class="chosen" id="chosen" hidden></p><div class="where" id="where"><div class="door1" data-door="1" role="button" tabindex="0"><b>Claude Code on your laptop</b><span>Your <b>designer in the background</b>: paste your designer's link into Claude Code and it sets everything up for you, a launchd service included (systemd on Linux). Your designer then runs whenever there's work, after you close the terminal and after a restart. No monitor, no coders.</span></div><div class="door2" data-door="2" role="button" tabindex="0"><b>Always-on Mac</b><span><b>Paid plans:</b> leave your Mac always on and use our tested full setup for a resilient agentic powerhouse: a designer, a monitor, dispatchers and coders. It installs itself, keeps every agent going and survives restarts.</span></div><div class="door3" data-door="3" role="button" tabindex="0"><b>My own setup</b><span>You run agents your own way already: take each role's onboarding prompt and paste it where your setup starts an agent. You keep it going.</span></div><div class="tbd"><b>Claude Code in the cloud</b><span>Claude Code on the web runs your agents on Anthropic's machines, and scheduled routines start their passes, so your laptop can stay closed.</span></div><div class="tbd"><b>Hosted coding agents</b><span>OpenAI Codex, Cursor background agents, Devin: paste the start link where they take a task. Not tried with d2 yet.</span></div><div class="tbd"><b>Agent hosting platforms</b><span>For agents you build yourself: the Claude Agent SDK on your own host, LangGraph Platform, Modal. Not tried with d2 yet.</span></div></div></div>
<div class="doorp wait2" id="dp0"><h3>Your option <span class="sel">select above</span></h3><p>Pick where your agents run, above, and its steps show here.</p></div><div class="doorp" id="dp1" hidden><h3>Your designer in the background</h3><p><b>Paste your designer's link</b> (below) into <b>Claude Code</b> on your Mac or Linux machine. It installs a small keeper and a launchd service (systemd on Linux) that waits for work and starts your designer's next pass.</p><p>Nothing to keep open: it runs after you close the terminal and comes back after a restart. Its tokens stay in a private folder; none is ever shown.</p><p class="small">Needs Claude Code installed and signed in. To stop it, ask Claude Code to stop your d2 keeper.</p><pre class="setl" id="sl1">Making your setup line…</pre><p><button class="btn" type="button" data-copyl="sl1">Copy</button> <span class="small">works once, for an hour; paste it into Claude Code</span></p></div><div class="doorp" id="dp2" hidden><h3>The always-on Mac</h3><p><b>Available on paid plans only.</b> Our tested full setup: a designer, a monitor, dispatchers and coders, always on.</p><pre class="setl" id="sl2">Making your setup line…</pre><p><button class="btn" type="button" data-copyl="sl2">Copy</button> <span class="small">works once, for an hour; paste it into Claude Code on the always-on Mac</span></p><p><a class="btn" href="/settings/plan" data-go>See the plans</a></p></div><div class="doorp" id="dp3" hidden><h3>My own setup</h3><p>Your agents, your harness. Below are the <b>onboarding prompts</b>, one per role: give each to the agent your setup starts for that role. It reads its start prompt, claims its own token (no token is ever shown here), and its dot turns green.</p><p>Each prompt works once, for an hour: start the agent soon, or make a <b>New link</b>. What a pass is and what keeps an agent going: <a href="/topics/Help:Agents" data-go>Agents help</a>.</p><p><a class="btn" href="#step2" id="go3">To the prompts ↓</a></p></div><div class="doorp" id="dp4" hidden><h3>Your chat loop</h3><p><b>Paste this line into a Claude app chat</b> (Claude on your desktop, web or phone). That chat becomes your designer, in a loop: it answers you in the chat panel here, beside the page you're on, for as long as that chat stays open.</p><pre class="setl" id="sl4">Making your loop line…</pre><p><button class="btn" type="button" data-copyl="sl4">Copy</button> <span class="small">works once, for an hour</span></p><p class="small">Your AI needs to reach this site: allow it in its settings if it asks.</p></div><style>.setl{white-space:pre-wrap;word-break:break-all}</style>
<div id="step2" hidden><h3>Onboarding prompts for each agent role</h3>
<p>Whichever option suits you, here are the start prompts for onboarding each agent role: paste each one where your option asks for it. The agent reads its start prompt, claims its own token, and its dot turns green.</p>
<div class="cards" id="cards"><p class="small">Making your links…</p></div><p class="sp-say" id="sp-say" role="status"></p></div>
<div><h3>Keep them going</h3>
<p>A background agent works in passes: it reads its mail and its tasks, finishes one, reports, and stops. Something has to start the next pass.</p>
<p>Agents don't keep themselves going: something starts each pass for them. On your Mac or Linux machine, that's the <b>keeper</b> Claude Code installs from your designer's link, as a launchd (or systemd) service: it waits for work (a new task, a thought, a message) and starts your designer's next pass, terminal closed or not.</p><p>On the always-on Mac, a monitor does it for every agent, and restarts any that stop.</p></div>
<div><h3>Talk to them</h3>
<p>When your agents connect, use the <b>chat floatie</b> to talk to them: it sits at the bottom right of every page.</p><p><button class="btn" id="chaton" type="button">Activate the chat floatie</button> <span class="small" id="chatsay"></span></p>
<p>Send ideas from <a href="/thoughts" data-go>Thoughts</a>: they go to your designer. See who is up, and on what, in <a href="/agents" data-go>Agents</a>; the work moves through the <a href="/pipeline" data-go>pipeline</a>.</p></div>
</div>
<p style="margin-top:28px"><a class="sp-go" href="/" id="sp-dash" style="text-decoration:none;display:inline-block">Open my dashboard →</a></p>
</div>
<script>
// the agents' links: made when this page opens, for the roles ticked on Start your agents (?roles=designer,…); Open my dashboard ends the onboarding
// (Razie chats 6acab6b2 2026-10-10 and 6acb85f4/6acb8f6d 2026-10-11, P-1318; links as P-1216: POST /api/v2/onboard/roles, one link per role, once, an hour)
(()=>{const D2=window.d2||{},$=s=>document.querySelector(s);
const P=Object.assign({},Object.fromEntries(new URLSearchParams(location.search)),D2.params||window.d2params||{});
const LEVEL=P.level==="master"?"master":"pro";
const api=(m,u,b)=>D2.api?Promise.resolve(D2.api(m,u,b)):Promise.reject(new Error("E_BRIDGE: open this page in d2"));
const go=u=>D2.go?D2.go(u):(location.href=u);
const esc=s=>String(s==null?"":s).replace(/[&<>"]/g,c=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;"}[c]));
const msg=e=>String(e&&e.message||e).replace(/^E_[A-Z_]+: /,"");
const ROLES={designer:"Designer",builder:"Coder",dispatcher:"Dispatcher",tester:"Tester"};
const roles=String(P.roles||"designer").split(",").filter(r=>ROLES[r]);
$("#sp-back").setAttribute("href","/page/StartAgents?level="+LEVEL);
$("#sp-back").onclick=e=>{e.preventDefault();go("/page/StartAgents?level="+LEVEL)};
const links={};let since=new Date().toISOString();
const line=l=>`You're the ${ROLES[l.role].toLowerCase()} on this d2 project. Start here: ${l.link}`;
const draw=()=>{$("#cards").innerHTML=Object.values(links).map(l=>`<div class="card" data-role="${esc(l.role)}">
<h3><span class="dot${l.up?" on":""}"></span>${esc(ROLES[l.role])} <span class="st">${l.up?esc(l.up):"waiting for it to connect"}</span></h3>
<pre>${esc(line(l))}</pre>
<button class="btn" data-copy="${esc(l.role)}">Copy</button><button class="btn" data-new="${esc(l.role)}">New link</button>
<span class="small">works once, until ${esc(new Date(l.expires).toLocaleTimeString([], {hour:"2-digit",minute:"2-digit"}))}</span></div>`).join("")};
const make=async rs=>{const r=await api("POST","/api/v2/onboard/roles",{roles:rs});(r&&r.links||[]).forEach(l=>links[l.role]=Object.assign(links[l.role]||{},l,{up:""}));draw()};
// each door makes what it needs when it's picked: a setup line (P-1307: POST /api/v2/onboard/setup {project, kind}) for doors 1, 2 and the chat loop,
// the per-role onboarding prompts only for My own setup (Razie chat 6acb8f6d, 2026-10-11)
const PROJECT=(D2.project||location.hostname.split(".")[0]);
const made={};
const setup=(kind,id)=>{if(made[id])return;made[id]=1;
  api("POST","/api/v2/onboard/setup",{project:PROJECT,kind}).then(r=>{$("#"+id).textContent=(r&&r.line)||"No line came back."})
  .catch(e=>{made[id]=0;$("#"+id).textContent="Couldn't make the line: "+msg(e)})};
const door=n=>{if(n==="1")setup("harness-solo","sl1");if(n==="2")setup("harness-full","sl2");
  if(n==="3"){$("#step2").hidden=false;if(!made.roles){made.roles=1;make(roles).catch(e=>{made.roles=0;$("#cards").innerHTML="";$("#sp-say").textContent="Couldn't make the links: "+msg(e)})}}};
document.querySelectorAll("#where [data-door]").forEach(d=>{d.addEventListener("click",()=>door(d.dataset.door));d.addEventListener("keydown",e=>{if(e.key==="Enter"||e.key===" ")door(d.dataset.door)})});
document.addEventListener("click",async e=>{const id=e.target.dataset&&e.target.dataset.copyl;if(!id)return;
  try{await navigator.clipboard.writeText($("#"+id).textContent);e.target.textContent="Copied"}catch(_){e.target.textContent="Select and copy"}});
// the chat loop page (Door B) opens this page with ?door=loop: only its panel, with an app-loop line
if(P.door==="loop"){$("#where").hidden=true;document.querySelectorAll(".doorp").forEach(p=>p.hidden=p.id!=="dp4");setup("app-loop","sl4")}
$("#cards").addEventListener("click",async e=>{const c=e.target.dataset.copy,n=e.target.dataset.new;
  if(c){try{await navigator.clipboard.writeText(line(links[c]));e.target.textContent="Copied"}catch(_){e.target.textContent="Select and copy"}}
  if(n){e.target.disabled=true;try{await make([n])}catch(x){$("#sp-say").textContent=msg(x)}}});
// the live dot: an agent of that role posted a status since the links were made
const poll=async()=>{if(!Object.keys(links).length)return;try{const a=await api("GET","/api/v2/agents");const rows=(a&&(a.data||a.agents))||[];
  let ch=0;rows.forEach(s=>{const r=s.role==="coder"?"builder":s.role;const l=links[r];if(l&&!l.up&&s.at>=since&&s.state!=="gone"){l.up=(s.agent||"")+" · "+s.state;ch=1}});if(ch)draw()}catch(_){}};
setInterval(poll,10000);
// Open my dashboard: the onboarding's end, the dashboard becomes home
$("#sp-dash").onclick=async e=>{e.preventDefault();try{await api("POST","/api/v2/project/home",{to:"dashboard"});go("/")}catch(x){$("#sp-say").textContent=msg(x)}};
})();
</script>
<script>(()=>{const D2=window.d2||{};document.addEventListener("click",e=>{const a=e.target.closest&&e.target.closest("a[data-go]");if(!a)return;e.preventDefault();D2.go?D2.go(a.getAttribute("href")):location.href=a.href})})();</script>
<style>.where>div[data-door]{cursor:pointer;transition:transform .12s,box-shadow .12s}.where>div[data-door]:hover{transform:translateY(-2px);box-shadow:0 6px 18px rgba(0,0,0,.1)}.where{overflow:hidden;transition:max-height .45s ease,opacity .35s ease;max-height:900px}.where.rolled{max-height:0;opacity:0;margin:0}.chosen{margin:8px 0 0;font-size:14px}.chosen a{margin-left:8px}.doorp{background:var(--card);border:1px solid var(--line);border-left:4px solid var(--lv);border-radius:14px;padding:16px 18px;animation:dpin .35s ease}.wait2{opacity:.45;filter:grayscale(1);pointer-events:none;user-select:none}.wait2 .sel{display:inline}.sel{display:none;font:700 12px var(--body);margin-left:8px;padding:2px 8px;border-radius:999px;border:1px solid currentColor;vertical-align:2px}.doorp h3{margin:0 0 6px;font:800 18px/1.2 var(--display)}.doorp p{margin:6px 0}@keyframes dpin{from{opacity:0;transform:translateY(-6px)}}</style><script>(()=>{const W=document.getElementById("where"),C=document.getElementById("chosen");const pick=n=>{W.classList.add("rolled");document.querySelectorAll(".doorp").forEach(p=>p.hidden=p.id!=="dp"+n);const t=W.querySelector(`[data-door="${n}"] b`).textContent;C.innerHTML="<b>"+t+"</b> <a href=\"#\" id=\"chg\">change</a>";C.hidden=false;document.getElementById("chg").onclick=e=>{e.preventDefault();W.classList.remove("rolled");C.hidden=true;document.querySelectorAll(".doorp").forEach(p=>p.hidden=p.id!=="dp0")}};W.querySelectorAll("[data-door]").forEach(d=>{d.onclick=()=>pick(d.dataset.door);d.onkeydown=e=>{if(e.key==="Enter"||e.key===" "){e.preventDefault();pick(d.dataset.door)}}});document.getElementById("chaton").onclick=async e=>{const b=e.target,say=document.getElementById("chatsay");b.disabled=true;try{if(!(window.d2&&d2.api))throw new Error("open this page in d2");await d2.api("PUT","/api/v2/me",{chat:true});b.textContent="Chat floatie on ✓";say.textContent="The chat floatie will appear on most screens after the next step."}catch(x){b.disabled=false;say.textContent=String(x&&x.message||x).replace(/^E_[A-Z_]+: /,"")}};document.getElementById("go3").onclick=e=>{e.preventDefault();document.getElementById("step2").scrollIntoView({behavior:"smooth"})};document.getElementById("go1").onclick=e=>{e.preventDefault();document.getElementById("step2").scrollIntoView({behavior:"smooth"})}})();</script></body></html>