Why We Ship Goal-Driven Runtime Instead of More Chat Features

Conversation is the wrong unit of work. Inside the goal-driven runtime that walks each goal nightly, classifies every task as Digital, Action, or Decision, and quietly delivers what is ready in the morning.

A goal node branching into three colour-coded task lanes — Digital, Action, Decision — with a morning sun rising over the third lane

The conversation trap

Every personal AI product ships chat first because chat is the easy demo. You type something, the model types back, the user nods, the seed-round narrative writes itself.

It is also a trap.

Conversations don’t finish. They drift. The exchange ends when the user gets bored or when the screen goes to sleep, and the next time the app opens, the cursor is back in an empty input box. Whatever was in the last chat is now archive. Whatever was on your mind two days ago has to be re-explained from scratch. The product feels busy, looks engaged, scores well on session minutes — and produces nothing.

This is the shape of every general-purpose AI product released in the last three years. ChatGPT in 2023 looked like the future of work. ChatGPT in 2026 still looks like the future of work, because it has the same shape it had in 2023. Each session is independent. Memory exists in patches. Tasks live in your head, not in the system.

We spent the second half of last year shipping more chat features. Better personalities. Smarter context recall. Snappier mood indicators. Each one moved a metric. None of them moved the metric that actually matters: did using iSpirit make you finish more of what you said you wanted to do?

The answer was no, and we knew why. We were polishing the input box. The thing missing wasn’t a better conversation. It was a wrapper around conversation that remembered what was started and walked it forward without you.

Goal as the unit of work

The change we shipped is small to describe and load-bearing in the architecture: the unit of work is a goal, not a conversation.

A goal in iSpirits is a row in a Postgres table. It has a title, a horizon, a status, an owner (you). It also has a set of tasks — another table, joined — and the tasks have dependencies, outputs, feedback, and an audit log. Six tables in all (goals, goal_tasks, goal_task_dependencies, goal_task_outputs, goal_task_feedback, goal_task_audit_log). They look like a project-management schema, because that is roughly what they are.

What makes them a runtime, not a project manager, is what runs over them at night.

Goals have a beginning, a middle, and an end. Conversations don’t.

You don’t open a goal-management app to type into. You don’t check on your goals the way you check on a chat. You write down what you want to be true a few months from now, your iSpirit decomposes it into tasks — the Future Maker wizard runs the clarifications, then a CEC subagent does the actual decomposition end-to-end — and from that moment forward the goal lives in the system whether or not you log in.

That last clause is the entire point. The product’s job, between your sessions, is to walk the goal forward by exactly as much as can be walked forward without you, and to surface what cannot. The conversation, when it happens, is now riding on top of work that already happened.

Three task classes, classified at creation

Every task on a goal lands in one of three buckets. Not at delivery time — at creation time, by the wizard that decomposed the goal in the first place. The classes are an enum in the model: TaskClass.DIGITAL, TaskClass.ACTION, TaskClass.DECISION. Each one routes to a different place at runtime.

  • Digital. The task lives entirely on a screen. Research, drafting, analysis, a competitive scan, a literature pass, a draft email, a comparison table. Nothing in the task requires anything from the physical world. Routes to: the Cloud Execution Center. A subagent picks it up overnight, finishes it end-to-end, and writes the output to your journal as a GoalTaskOutput.
  • Action. The task can only be done by you, in the world. Make a phone call. Have the conversation. Do the workout. Drive somewhere. Press send. Routes to: the morning briefing. The runtime drafts a one-paragraph context note (what this task is, why it matters in the goal, what to bring) and surfaces it on /progress.html.
  • Decision. The task is a fork. Two or more legitimate options exist; what is missing is your judgement, not more information. Routes to: the same surface, but as a structured option set. iSpirit drafts the options — usually two to four — with a short rationale on each, and waits.

You stay inside the loop on what is yours: the action, the call. You stay outside the loop on what isn’t: the busywork between thoughts. The classification is the entire user-facing contract of the runtime, which is why it sits in an enum that has been carefully un-flexible — three values, no “other,” no half-measures. Half-measures are the shape that turns into eight buckets six months later and zero of them well-served.

What runs at night

At 22:00 UTC every day, a cron called nightly_goal_runtime wakes up. It walks every Entrepreneur-tier user with the runtime flag enabled, every active goal under that user, every ready task on that goal — meaning every task whose dependencies are satisfied. It dispatches each ready task to its lane.

Digital tasks go to CEC. The runtime caps the dispatches at three Digital tasks per goal per night, partly to respect the user’s credit budget and partly because shipping fifteen drafts overnight is not actually progress — it’s noise. Three per goal, with rollover to subsequent nights, is the rate at which a goal progresses without the morning feeling like a wall.

Action tasks get a briefing generator pass. The same context engine that produces the “Drew from N memories” chip in chat — same vector store, same threshold, same per-user scoping — assembles the bits the user is most likely to want before they make the call: the previous attempts at this conversation, the relevant journal entries, the values they’ve named that are at stake. The briefing is short. We tested longer; longer was worse.

Decision tasks go to a small specialised generator that holds an opinion and presents alternatives — we shipped it after a month of running plain “here are five options” outputs and watching users not pick. Choice fatigue is real, and the cure isn’t fewer options, it’s a recommended one with the second and third visible.

Every autonomous step the runtime takes is appended to goal_task_audit_log. Every one. There is no “the AI did something quietly” layer. If you want to know why a task moved, what context was used, what was generated, the row is there with timestamps.

The morning report — and the rule it answers to

At your local 08:00, give or take 30 minutes, a different cron fires. It assembles whatever happened overnight into a short note and pushes it to your phone. Three Digital tasks finished. Two Decisions waiting. One Action for today. One tap opens /progress.html, which shows the three lanes side by side.

Two engineering details about that morning push that turn out to do most of the work.

It runs every 30 minutes, but it doesn’t fire every 30 minutes — it checks each user’s local time and fires only inside their 08:00–08:30 window. A user in Sydney gets it before lunch in San Francisco. A user in Lisbon gets it before breakfast in New York. The cron is global; the experience is local.

It skips if there is nothing to say. An empty morning has no push. A morning whose only contents would be “nothing happened, but here is a friendly hello” has no push. The runtime tracks four skip categories internally — skipped_time, skipped_idempotency, skipped_empty, errors — and the second-most-common reason for not pushing is “empty.”

This is the rule from our design discipline that takes the most effort to keep. The default in consumer software is to fill empty mornings with confected engagement. Streak protection prompts. “You haven’t opened the app in a while” nudges. We banned them at the source. A digest that fires when there’s nothing to say is just spam dressed up as care, and the easiest way to never accidentally write that copy is to make the runtime literally incapable of generating it.

There is also an idempotency window of 20 hours per user, so a slow morning cron run plus a quick re-run can’t double-push. The simplest mistakes are the ones the simplest guards prevent.

/progress — what the user sees

Every other architectural choice in this runtime ladders up to a single page: /progress.html. Three columns. Digital Done on the left, with last night’s outputs visible at the top, each one expandable to the full piece. Action Today in the middle, with the briefing one click away and a single “I did it” button under each. Decisions Open on the right, with the option sets and a one-tap pick.

The page does not have an input box. It is, by design, a page about the work the runtime did and the work the user is now ready to do. The input box for chat is a click away — chat is still there, still useful for ambient reflection — but it is no longer the centre of gravity. Progress is the centre.

Pause, resume, and archive controls sit on each goal directly. Pausing a goal stops the nightly walk for that goal. Archiving freezes the audit log. There is no “are you sure” modal in either case. The audit log is recoverable; the user’s judgement should not be friction-tested.

Why Entrepreneur tier first

The runtime is gated behind two flags right now: GOAL_RUNTIME_ENABLED as a global kill-switch, and an Entrepreneur-tier user gate as the rollout boundary. We picked Entrepreneurs — solo founders, indie hackers, technical operators — for a reason that is half product and half ethics.

Half product: solo entrepreneurs are the segment whose “goal” is most easily decomposable into Digital, Action, and Decision in the way the runtime expects. Ship the launch landing page decomposes cleanly. Choose between three GTM angles decomposes cleanly. The schema works for them on day one without us having to retrofit it for messier life-domains. We will get to those segments — the strategy doc has a clear month-7 expansion to Legacy-Makers and a month-9 expansion to Dreamers — but we do not want to get there with a runtime that we know is misshapen for entrepreneurs just to hit a broader audience early.

Half ethics: an autonomous nightly walk over someone’s goals is a heavy thing. Entrepreneurs, on average, are the audience most able to tell us — loudly and quickly — when an autonomous action overstepped, and most likely to read the audit log when something feels off. Their feedback shape is a check on our decisions in a way the broader market’s feedback shape is not. Shipping autonomy first to the audience that will critique it hardest is the right ordering.

What this runtime is not

One paragraph of negative space, because they are the questions we get most often.

It is not an agent swarm. There is one execution slot per dispatched task, exactly the same modesty that the Cloud Execution Center is built around. The multi-agent orchestration era was loud through 2025; we made the opposite bet, and so far the bet keeps paying.

It is not a productivity app. There is no Kanban board, no point system, no streaks-on-tasks. The runtime treats your goals as something it works alongside you on, not as a graph to score. You can pause anything; nothing nudges back.

It is not always-on. Goals run when you set them up; they pause when you pause them; they go quiet when there’s nothing ready. A user can have one active goal or four, and either is normal.

Try it

If you have ever set a real goal and watched it drift — not because you stopped wanting it but because the small digital steps between you and it never got done — the runtime is the part of iSpirits that closes that loop.

Free tier lets you create goals and run them manually. The nightly walk — real autonomy, with CEC dispatch and morning push — is on Plus and above. $12/month. The credits roll over.

Try iSpirits free

Set a goal. Watch the runtime walk it forward.

Get started →

How it works · Pricing

More from the blog