Summary
There is no framework-level way for a handler to complete a run without posting a visible message. Every persona reimplements "should I actually say something?" by hand, and the workarounds are inconsistent and occasionally wrong.
The problem
Proactive personas wake on events that frequently warrant no reply — a green check, a queued job, a bot echo, an event the handler inspects and decides isn't relevant. Without a suppression primitive, authors hand-roll it:
cloud-small-issue-codex/agent.ts:281 drops Slack messages with a broad bot_id / subtype === "bot_message" check to avoid self-answer loops. It works, but it also swallows legitimate messages from other bots — a real bug hiding inside a necessary guard.
- Other personas early-
return before ctx.harness.run, which suppresses the post but also throws away the model's judgment about whether the event mattered.
The gap is structural: once a handler has called ctx.harness.run(...), its only options are post the output or discard it in handler code. The model itself has no supported way to say "I looked, nothing to add."
The cost is noise. An agent that comments on every intermediate CI state is worse than no agent, so authors over-filter at the dispatch/handler layer to compensate — which is the opposite trade from the one we want (wake cheaply, decide well).
Proposal
A reserved marker the model can emit as its final message to complete successfully and silently:
Handled at the ctx.harness.run boundary in packages/runtime (with the runner in harness-kit), so it works identically across harnesses and personas:
- Inject the contract into the system prompt — one line, appended alongside the existing persona
systemPrompt: "When no visible reply is useful, make the final message exactly [[NO_REPLY]]."
- Exact match → suppress the post entirely; the run completes successfully (silent success is not failure).
- Mixed (model leaked the marker into otherwise real prose) → strip it and post the remainder. Users must never see the marker.
- Leak detection → a
containsMarker check so a leak is observable rather than silent.
Roughly sixteen lines of logic; the value is that it's in one place instead of re-derived per persona.
Why in runtime rather than cloud
The suppression decision belongs to the model and the harness boundary, which is ctx.harness.run — an authoring/runtime concern. Cloud's dispatch-level gates (where / match / conditions) solve the adjacent problem of not waking at all, and both are worth having:
- dispatch gates — cheap, but coarse, and they can't reason about content.
- suppression marker — costs a wake, but the model decides with full context.
Today only the first exists, which is why authors push filtering ever earlier and end up with blunt instruments like a bare bot_id check.
Acceptance
- A handler whose model returns exactly the marker completes successfully with no post.
- A model that embeds the marker in real prose posts the prose with the marker stripped.
- The marker never appears in any user-visible output.
- A persona can delete its hand-rolled "is this worth replying to" guard and rely on the framework.
Summary
There is no framework-level way for a handler to complete a run without posting a visible message. Every persona reimplements "should I actually say something?" by hand, and the workarounds are inconsistent and occasionally wrong.
The problem
Proactive personas wake on events that frequently warrant no reply — a green check, a queued job, a bot echo, an event the handler inspects and decides isn't relevant. Without a suppression primitive, authors hand-roll it:
cloud-small-issue-codex/agent.ts:281drops Slack messages with a broadbot_id/subtype === "bot_message"check to avoid self-answer loops. It works, but it also swallows legitimate messages from other bots — a real bug hiding inside a necessary guard.returnbeforectx.harness.run, which suppresses the post but also throws away the model's judgment about whether the event mattered.The gap is structural: once a handler has called
ctx.harness.run(...), its only options are post the output or discard it in handler code. The model itself has no supported way to say "I looked, nothing to add."The cost is noise. An agent that comments on every intermediate CI state is worse than no agent, so authors over-filter at the dispatch/handler layer to compensate — which is the opposite trade from the one we want (wake cheaply, decide well).
Proposal
A reserved marker the model can emit as its final message to complete successfully and silently:
Handled at the
ctx.harness.runboundary inpackages/runtime(with the runner inharness-kit), so it works identically across harnesses and personas:systemPrompt: "When no visible reply is useful, make the final message exactly[[NO_REPLY]]."containsMarkercheck so a leak is observable rather than silent.Roughly sixteen lines of logic; the value is that it's in one place instead of re-derived per persona.
Why in
runtimerather than cloudThe suppression decision belongs to the model and the harness boundary, which is
ctx.harness.run— an authoring/runtime concern. Cloud's dispatch-level gates (where/match/conditions) solve the adjacent problem of not waking at all, and both are worth having:Today only the first exists, which is why authors push filtering ever earlier and end up with blunt instruments like a bare
bot_idcheck.Acceptance