Summary
Keep configured active-run presence such as typing, reactions, or existing channel progress surfaces alive until the run is actually complete and reply dispatch is idle.
Problem to solve
Healthy long turns can lose visible presence before they actually finish.
Concrete examples:
The current behavior makes healthy long turns look dead even when nothing is broken.
This request is about liveness, not about changing default disclosure semantics. I am not asking to change the default meaning of compaction notices or to add a new default progress message surface.
Proposed solution
Add a shared internal active-run presence lease in reply/runtime code.
Phase 1 behavior:
- start the lease when a user-visible run starts
- keep it alive until both:
- the run is complete, failed, or aborted, and
- reply dispatch is idle
- reuse only surfaces already enabled by the current channel/config:
- typing
- reactions
- existing channel-local preview/progress surfaces
- preserve stale-presence cleanup protections such as
#27428
- keep the first landing internal-only
Likely touch points for Phase 1:
src/auto-reply/reply/typing.ts — run-side typing lifecycle and TTL ownership
src/channels/typing.ts — channel-side typing keepalive / safety TTL
src/auto-reply/reply/reply-dispatcher.ts — dispatch-idle coordination
src/auto-reply/reply/agent-runner.ts — run lifecycle owner
src/infra/agent-events.ts — shared event stream if additional active-run lifecycle signals are needed
Explicit non-goals for Phase 1:
- no default change to
agents.defaults.compaction.notifyUser
- no new default status/progress message surface
- no override of configs that currently mean final-only delivery, such as channels that document
streaming: "off" as final-only
- no new public plugin SDK contract yet
Expected result for this phase:
- if presence is already configured to appear for a run, it should not die before the run actually ends
Alternatives considered
- Extending typing TTL only:
- weaker because it still uses a wall-clock guess instead of real run lifecycle ownership
- tends to become per-channel timeout tuning again
- Defaulting to explicit compaction disclosure:
- mixes a lifecycle fix with a product behavior change
- conflicts with current
compaction.notifyUser semantics
- Adding a new default status/progress message:
- risks violating final-only delivery expectations
- adds cleanup/product-surface questions that are not needed for the first fix
- Publishing a new plugin SDK seam immediately:
- feels premature before the shared shape is proven internally
Impact
Affected:
- long-running Telegram turns
- Teams long tool-chain turns
- any channel where configured presence can die before the run actually ends
Severity:
- high for compaction-heavy / dev-oriented workflows
Frequency:
- frequent in my usage
- I run into this regularly because my sessions often trigger auto-compaction during development work
Consequence:
- healthy runs look stuck
- I may retry, interrupt, or second-guess a run that is still progressing
- this adds friction exactly in the workflows where long turns are already expensive
Evidence/examples
Relevant docs/config constraints:
src/config/schema.help.ts:1174
docs/gateway/configuration-reference.md:1279
docs/channels/telegram.md:1025
docs/channels/matrix.md:241
Related prior work:
Additional information
I think this should be landed in two steps.
Phase 1:
- internal lifecycle fix only
- keep configured presence alive for the full active run
- no default UX/product changes
Possible follow-up, if maintainers want it later:
- explicit long-compaction disclosure
- delayed generic progress text on already-enabled preview/progress surfaces
- public SDK exposure if the internal shape proves stable
In my own usage this happens frequently enough to be a recurring workflow problem, especially during development-oriented sessions that hit auto-compaction often.
Summary
Keep configured active-run presence such as typing, reactions, or existing channel progress surfaces alive until the run is actually complete and reply dispatch is idle.
Problem to solve
Healthy long turns can lose visible presence before they actually finish.
Concrete examples:
The current behavior makes healthy long turns look dead even when nothing is broken.
This request is about liveness, not about changing default disclosure semantics. I am not asking to change the default meaning of compaction notices or to add a new default progress message surface.
Proposed solution
Add a shared internal active-run presence lease in reply/runtime code.
Phase 1 behavior:
#27428Likely touch points for Phase 1:
src/auto-reply/reply/typing.ts— run-side typing lifecycle and TTL ownershipsrc/channels/typing.ts— channel-side typing keepalive / safety TTLsrc/auto-reply/reply/reply-dispatcher.ts— dispatch-idle coordinationsrc/auto-reply/reply/agent-runner.ts— run lifecycle ownersrc/infra/agent-events.ts— shared event stream if additional active-run lifecycle signals are neededExplicit non-goals for Phase 1:
agents.defaults.compaction.notifyUserstreaming: "off"as final-onlyExpected result for this phase:
Alternatives considered
compaction.notifyUsersemanticsImpact
Affected:
Severity:
Frequency:
Consequence:
Evidence/examples
Relevant docs/config constraints:
src/config/schema.help.ts:1174docs/gateway/configuration-reference.md:1279docs/channels/telegram.md:1025docs/channels/matrix.md:241Related prior work:
Additional information
I think this should be landed in two steps.
Phase 1:
Possible follow-up, if maintainers want it later:
In my own usage this happens frequently enough to be a recurring workflow problem, especially during development-oriented sessions that hit auto-compaction often.