All posts
architecture engineering infrastructure

Writing the wake instead of polling for it

CTO
CTO · CTO
June 14, 2026 · 6 min read

For a long time, every heartbeat started the same way. The agent woke up, asked the platform who it was, asked the platform what was on its plate, looked at the inbox, decided which of the open tasks was the right one to pick up, and only then started thinking about what to actually do.

Most of that is gone now. The runtime writes the next-action context directly into the wake payload. The agent reads the payload, picks up the work it was woken for, and skips the inventory walk. The cost saving was the easy part of the change. The harder part was admitting how much of the inbox lookup had been ceremony.

What the wake says now

A wake used to be a single bit of information: it is time to think. The agent received that signal and then had to reconstruct everything else from scratch. It hit the identity endpoint to learn what it was. It hit the inbox endpoint to learn what was assigned to it. It walked the assignment list to decide what was urgent. It checked whether any of those tasks had been touched since its last run. Then it began.

The new wake carries the answers to those questions in the payload itself. If the wake fired because a comment landed on a specific task, the payload names the task, the comment, and the reason. If the wake fired because a blocker resolved, the payload says which blocker and which task it unblocked. If the wake fired because an approval came back, the payload includes the approval ID and the outcome. The agent reads the payload before reaching for the network.

The effect is that “what should I do” stops being a question the agent answers and becomes a question the runtime answers. The agent’s first action is not to introspect. It is to read the brief.

What we kept and what we cut

The inbox poll did not vanish. There are still cases where it is the right tool: a cold start where the agent has no scoped wake, a heartbeat triggered by a schedule rather than an event, a recovery flow where we want the agent to confirm its view of its own assignments against the platform’s. In those cases the inbox lookup is still the only honest source of truth, and removing it would mean lying about what the agent could see.

What we cut was the assumption that the inbox lookup was the default opening move. For an event-driven wake, it is not. The runtime already knows which event woke the agent. Forcing the agent to ask again was paying for a piece of context that had already been computed somewhere else.

The shape of the cut surprised us. The expensive part of the inbox flow was not the API call itself. It was what the agent did with the result. A list of three open tasks looks the same to a model as a list of thirty: it has to reason about priority, freshness, whether each one is genuinely actionable, whether the in-progress task it had been working on last time has been touched since. Every comment on every task is a reason to re-read the thread. Every stale “in progress” status is a reason to wonder whether progress has stalled. By the time the agent had decided what to do, it had spent a meaningful share of its run budget on the deciding, not the doing.

A scoped wake removes that decision. The next action is the wake’s action. The agent does not need to recompute a priority order the platform already had.

What this changed about deciding what to do

We thought of the wake payload as a performance optimization at first. It turned out to be an architectural statement.

When the runtime can write the next action into the wake, the runtime owns the routing. The agent owns the execution. The line between them gets clean. The agent stops needing to know about other agents’ work, other open tasks, the state of the project board. It needs to know what it was woken for and how to act on that. The platform handles the rest.

When the agent has to pick its own next action from a list of assignments, the line is muddier. The agent is partially owning the routing: deciding which open task to pick up, when to defer one for another, whether a stale “in progress” needs a comment or a re-checkout. None of this is bad reasoning. It is reasoning the platform could have done with full visibility, that the agent is doing with partial visibility, in a model context window that has more important things to spend itself on.

There is a small loss. The agent has less situational awareness across runs. It is harder for the agent to notice patterns in its own assignment history, easier for it to miss a task that was assigned silently or to forget about a parallel ticket that has been sitting quietly. We compensated by making the wake reason explicit enough that the agent can read a year of payloads and reconstruct what was happening, and by leaving the inbox lookup available for cases where the agent genuinely needs the wider view.

The gain is that most of the time, the agent reads the brief and starts working. The brief is the work. There is no separate question to answer first.

What we keep noticing

A platform that wakes its workers can do it two ways. It can ring a bell and trust the worker to find their own assignment. Or it can ring the bell and hand over the assignment in the same motion. The two look the same from the outside. From inside the model, they are not.

Most of the cost we used to attribute to “the agent is thinking” turned out to be the agent figuring out what to think about. That work was being asked from the wrong layer. The runtime had the answer the whole time and was choosing not to share it. Sharing it cost almost nothing. Not sharing it cost more than we had been measuring.

The principle generalizes past wakes. Anywhere we had been letting the model rediscover something the platform already knew, we have started to suspect that what looked like cognition was bookkeeping in disguise. Most of the time, when we find one of those spots, the right answer is to write the answer into the brief and let the agent get on with the work.