letsautom8
← Lab notes

Who decides, who works: the three slots that run my lab

Part 1 set up the record and the protocol: every task is an issue, and a handful of labels say what happens next. That's the trusted place GTD asks for. But a list doesn't do anything. Someone still has to decide what's next, do it, and remember the things that are due on a date.

If that someone is me, the system is only as fast as my attention. This part is about the three slots that take that job off me: a chief of staff that decides the routine things, a session per project that does the work, and a script that starts work on the day it's due.

3. A chief of staff

Slot 3: why it exists

Once agents do the work, they start asking questions. Should I start this one? Is this merge request fine? I found something else, what now? Each question is small. Together they make you the queue.

More agents don't mean less work for you unless something other than you answers them.

The job: make the calls I'd make, so I'm only asked about the ones that need me.

Ours: one long-running Claude Code session, the one for the lab's own repo. It doesn't write the projects' code. It judges.

Three inputs reach the chief of staff: an idle session (the next ready issue, proposed by a script), a merge request with a green pipeline, and a session's question or discovered work. It judges against decision-style.md, my rules in my words, and answers one of three ways: yes, routine (adds go, or passes the review), not now (parked with a comment), or needs me (needs-decision with options, a recommendation and a default). Every morning: at 07:15 its calls since yesterday are collected, at 07:30 a push on my phone says the review is ready, I agree or change each one by voice, and afterwards reversed calls are undone and agreed rules are added to decision-style.md.
It decides the routine calls. I review its calls, not the work.

Three kinds of question reach it, and none of them needs me to ask:

Here is one real exchange from the script's log, a minute apart:

19:04:49 feed   asked the chief of staff to approve 1: <project>#43
19:05:51 nudge  <project>#43 -> folder=<project> (routine)

The chief of staff read the issue, judged it worth doing next, and added go. A minute later the script woke the session. Nobody asked me, and nobody needed to.

The part that makes this safe is the morning review. At 07:15 a script collects every call the chief of staff made since yesterday. Every call it makes goes through its own account. At 07:30 my phone says the review is ready, and I go through it by voice: agree, or change it and say how. A call I reverse is undone on its issue. A rule I agree with goes into a file of my rules, in my words, with the date.

There are more than a dozen rules in that file so far. One came from a minor UI fix it brought me: "why does this need my explicit approval - this is minor UI change." Display-only fixes are its call now.

Lesson: don't try to write the delegation rules up front. Let the agent make calls, review them daily, and keep only the rules you agree with.

4. A session per project

Slot 4: why it exists

Something has to actually do the work. A chat window forgets where it was, and one agent juggling every project mixes them up. So each project gets its own worker with its own memory, and it takes one issue at a time.

The worker is the part you'll swap most. The rules it follows are the part you keep.

The job: do the work, one project at a time, without losing the thread.

Ours: one Claude Code session per project, kept alive in tmux and pinned to its own conversation. That post covers the launcher. What matters here is how a session handles one issue.

A real request file, shortened: folder, source=go, and a prompt saying work on the issue, confirm the go label on GitLab first, swap it for Doing, report on the issue. The session wakes on its own conversation, checks go on GitLab itself, swaps go for Doing, works from main and comments as each step lands, sends small fixes to main and features to a branch and MR for the chief of staff, then closes the issue with a note. Work found on the way is filed as discovered and not started.
The request carries only the issue number. The issue carries everything else.

The request file says nothing about the work. It names the issue and tells the session to check the label itself. That's deliberate: a request is just text in a folder, and text can be written by anything. The label on GitLab has an author.

From there the rules are short. One issue at a time. Start from main, never on another issue's branch. Small fixes go straight to main; a feature goes to a branch and an MR for the chief of staff. Anything else found along the way becomes a new issue labelled discovered, and waits.

Any agent that can read an issue, check a label and open an MR can take this slot.

The worker can also be a whole team. A project manager agent, a senior dev, a QA agent and a UI/UX reviewer, all on one issue. From the outside it's still one slot: an issue goes in with go, progress lands on the issue, and one MR comes out. That's the point of a slot. It names a job, not a headcount, so the same setup scales from one session to a team without changing anything around it.

Mileage varies, and it costs more. Two rules keep a team inside the slot:

If you're starting out, use one session. Add roles where it actually fails. A separate reviewer that didn't write the code is usually the first one worth adding.

5. The on-the-date nudger

Slot 5: why it exists

Some work can't start today but has to start on a given day. Reminders are built for people: an email, a calendar alert. An agent can read those once you give it access, but a reminder only says something is due. It doesn't start anything.

If nothing wakes the work up on the day, it waits until someone remembers.

The job: start something on a given day without anyone remembering to.

Ours: a due date plus a when-due label, and a plain script that runs every minute.

An issue with a due date and when-due: if it's due today or earlier and clear to start, the script swaps when-due for go, the session starts it and a phone push says Started. If it's gated, already Doing, blocked or has no session, the label is kept, the chief of staff is told and a push says due, not started. Below, three real log lines from one run: due, nudge, ntfy, all in the same second.
Its only write is one label swap. Removing when-due is what makes it fire once.

The board and the calendar work from the same date. A sync puts the issues' due dates on my calendar, so I see what's coming, and the nudger starts the agent's side on the day. The date lives only on the issue, so the two can't disagree.

Two details do most of the work. "Due today or earlier" means a laptop that slept through the date still catches up when it wakes. And the script adds go as an automation account, so it can't start gated work even by mistake: the check from part 1 refuses it.

Keeping it a dumb script means it can't decide to do anything clever.

Tip: each slot can run a different brain

Part 1 said the model is replaceable. It's also replaceable per slot, because the slots only talk to each other through issues and labels. Nothing needs to share a vendor. What each slot asks of a model is different:

Local models fit too. Open-weight models can take the chief of staff's seat on your own hardware. The big ones need serious hardware, so check before you plan around it.

Two things keep a mixed setup honest. Give each slot its own account on the tracker, so the morning review can tell who made which call. And keep the rules in one plain file that any model can read, not inside one vendor's settings.

What this changed

I used to be the scheduler, the reviewer and the reminder. Now I'm asked about money, production, security and anything the issue didn't decide, and each morning I check the calls that were made without me.

Take any one of these three away and the work lands back on you. Without the chief of staff, every agent's question is yours to answer. Without a session per project, you re-explain where things were every morning. Without the nudger, anything with a date waits until you remember it. Part 1 gave the system a memory. These three give it a judge, hands and a clock.

Next: part 3

The lab now runs without me watching. Part 3 is about reaching it when I'm away from the desk, and making sure it survives a bad day:

← All lab notesQuestions? Say hi →
Say hi hello@
letsautom8.dev

Write to me about a post, an experiment, or something you'd like me to try in the lab. If you'd like me on your project, testing or automation, that goes through my company, so you get proper terms and a proper invoice.

Work with me through Shiloah →