stablyai / stablyai/orca

Feature: sender-set delivery class on messages, plus a cheap presence check, so a harness can drain the mailbox for the agent

Open
#13,645 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
71.3k
Forks
4.7k
Avg merge
17h 8m
Merged PRs (30d)
475

Description

## Summary

Two small, additive gaps make Orca's mailbox hard to use as a push channel:

1. A sender cannot say **how urgent** a message is. "Stop what you are doing" and "read this when you finish" are the same message today.
2. There is no **cheap way to ask whether mail exists**. Every answer costs a full check.

This issue argues for a `delivery_class` on a message (`interrupt` | `tool` | `turn`), set by the sender, and a count-only mode on `orchestration check`. Both are additive and neither asks Orca to change how it delivers anything.

## Why

Orca's mail is a pull. The recipient must remember to run `orchestration check`. An LLM agent that must remember to poll is an agent that misses mail, and every miss looks exactly like silence: no error, no retry, no trace. The coordinator waits, the worker never read the message, and nothing in the system says so.

The fix is not to abandon the mailbox. It is to move the polling out of the agent and into the harness that runs it. Claude Code, for example, exposes hooks at two natural boundaries: after each tool call, and at the end of a turn. A hook can inject text into the agent's context or keep a finished turn alive. A hook that drains the mailbox at those boundaries means the agent never polls and never misses mail. Other harnesses have equivalent seams.

Two things are missing before that works well.

**The sender cannot state urgency.** A harness that drains the mailbox has to decide whether a message interrupts the agent now or waits for a boundary. Today it has to guess, from the message `type` or from nothing. But `type` answers a different question — `worker_done`, `escalation`, `question`, `heartbeat` say what a message *is*, not when it should land. An `escalation` may well be able to wait for the end of the turn; a plain `status` from a coordinator may be the one thing that should stop the worker right now. Urgency is an orthogonal axis, and only the sender knows it.

**A per-tool-call check is a tax on every turn.** A hook that runs on every tool call needs to ask "is there mail" thousands of times a session. Today the cheapest available answer is a full `orchestration check`, which resolves the mailbox, builds or replays a Delivery, and returns every queued message body. That work happens whether or not mail exists — and the empty case is the overwhelmingly common one.

Prior art worth citing: [firstmate](https://github.com/kunchenguid/firstmate) drives a whole agent fleet this way. A zero-token shell watcher classifies events and wakes the agent only when something is actionable, with a durable wake queue written before any detector state advances, so a missed event can still be recovered.

## Proposal

**A delivery class on a message.** A new optional field beside `type` and `priority`, not inside either:

- `interrupt` — surface as soon as possible, even mid-task;
- `tool` — surface at the recipient's next action boundary;
- `turn` — surface when the recipient finishes its current turn.

It defaults to `turn`, which is exactly the boundary a message already lands at when the recipient polls on its own, so every existing caller and every stored message keeps its current behavior. Orca stores the class and returns it wherever messages are read. Orca does **not** act on it.

**A count-only mode on `orchestration check`.** `--count` returns how many unread messages wait, broken down by delivery class, and nothing else: no Delivery is created, no bodies are read, nothing is marked read. A supervisor can therefore run it far more often than a real check, and a probe can never consume the batch a real check would replay. A count-only mode on an existing verb seems more in keeping with the CLI than a new command, but the shape is up for discussion.

## Out of scope

The harness side. This asks Orca for a word the sender can set and a question a supervisor can afford to ask often. Who acts on them — the hook, the interruption policy, the injection format — belongs outside Orca, and I am not asking Orca to implement it. If maintainers would rather Orca eventually act on the class itself, that is a good discussion to have here, but it does not have to happen first for the field to earn its place.

I have a small additive PR ready for both halves and will link it here.

Contributor guide

Open the contributing guide

Research direction

Start with the existing message handling and the `orchestration check` entry point. Verify that delivery classes are stored and returned with messages, and that `--count` reports unread totals by class without creating a Delivery, reading bodies, or marking messages read.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend, cli
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.