← ~/articles

The Agent Runs When I Don't

Lion Hummer/

Kit was useful but idle. Every time I closed my laptop, it stopped. Every time I opened it, I had to re-steer. The agent only existed when I was looking at it.

The first thing I added was scheduled tasks. A Heartbeat class that fires on clock-aligned intervals (5m, 15m, 30m, up to 24h) and runs any tasks that are due. These are predefined jobs: check something, summarize something, run a report. Useful, but limited. I'm still the one deciding what to schedule and when.

The thing that actually changed how Kit works was todos.

Todos

Kit can write todos for itself. Not just "remind me" stuff (though it does that too, including things like telling me to drink water). Actual deferred work: "research this topic later," "follow up on this after the API response comes back," "check if this deploy worked in an hour."

Each todo has a priority, an optional scheduledFor timestamp, and a prompt with the full instructions. They sit in ~/.assistant/todos.json. Every 30 seconds, a delivery loop checks if there are ready todos and the agent isn't busy. If there are, and I've been idle for at least 5 minutes, it delivers a batch (up to 5) and Kit starts working.

The idle grace period matters. Without it, Kit would start doing background work while I'm mid-thought, which is annoying. Five minutes of silence means I'm probably done for now.

Todos that create todos

The part I didn't plan but should have: a todo can result in another todo. Kit picks up a research task, does the first pass, realizes it needs to check a second source, writes a new todo for that, marks the current one complete. Next delivery cycle, it picks up the follow-on.

This means I can hand Kit something in the morning and come back to a chain of completed work in the afternoon. I didn't have to break the task down. Kit broke it down for itself, across time, in pieces that fit its own context window.

Getting Kit to be good at this took work. Early on it would create todos for things it should just do immediately, or misjudge its own capabilities and write a todo it would never be able to complete. The prompt engineering around urgency, priority, and self-assessment was probably the hardest part of the whole system.

The debrief

If Kit works while I'm away, I need to know what happened when I get back. The answer is a debrief: after each todo, Kit calls add_debrief with a short summary of what it did. These accumulate in ~/.assistant/debrief.json with timestamps.

When I send my next message, the system checks for debrief entries. If there are any, they get prepended to my message with a time context: "While you were idle (from 6 hours ago to 2 hours ago), you completed background work:" followed by the list. Kit reads that, acknowledges it naturally, and we pick up the conversation.

This is the part I'm happiest with. The debrief makes the handoff feel conversational. I say good morning, Kit says here's what I did overnight, and we move on. It's not a notification dump. It's context for the next conversation.

What changed

Before todos, Kit was a tool I used. After todos, Kit is a thing that runs. The difference is that I can put something down and genuinely stop thinking about it. Not because I trust Kit to handle everything perfectly, but because I know it'll either complete the work or flag itself as blocked. Either way I'll hear about it in the debrief.

The whole system is a JSON file, a 30-second poll loop, and a debrief prepend. It's not complicated. But it turned a chat interface into something that works on my behalf across time, which is a different kind of useful.