Skip to content

No way to reduce Linear agent-activity posting volume — every thought/ack is an agentActivityCreate (incl. empty body:""), exhausting the per-token rate limit #1325

Description

@burnashevrr

Summary

Cyrus posts an agentActivityCreate mutation to Linear for every thought, tool action, and acknowledgment — including empty body:"" thoughts and ephemeral status updates ("Compacting conversation history…"). There is no configuration to turn this down. In multi-repo deployments that share one Linear workspace token, this chatter is the primary driver of exhausting Linear's 5,000 requests/hour per-token limit, which then breaks in-flight sessions (see #1324).

Notably, Slack thread-following already has a toggle (CYRUS_SLACK_THREAD_FOLLOWING_DISABLED) — but Linear activity streaming has no equivalent.

Environment

cyrus-ai 0.2.65, self-hosted edge worker, 5 repos sharing one Linear workspace token.

Evidence

  • The dominant rate-limited operation is agentActivityCreate with content.type:"thought", frequently body:"" (a literal no-op post) and ephemeral:true.
  • ~12 unconditional post*Activity call-sites in EdgeWorker (cyrus-edge-worker): postThoughtActivity (several), postInstantAcknowledgment, postInstantPromptedAcknowledgment, postParentResumeAcknowledgment, postRoutingActivity, postSystemPromptSelectionThought, postModelNotificationThought, postAnalyzingThought.
  • No concurrency / max-session knob exists either (checked cyrus-core + cyrus-edge-worker config schemas), so request volume can't be bounded that way — it has to be reduced at the posting layer.

Proposed fix

  1. Add a config field for Linear activity-streaming verbosity — per-repo (RepositoryConfig) and/or global (EdgeConfig) in cyrus-core, with a default that preserves current behavior:
    • linearActivityStreaming: "full" | "minimal" | "off", or granular booleans (streamThoughts, streamAcks, streamRouting).
    • "minimal" = keep meaningful action results + the final response + session lifecycle; skip thoughts and ephemeral acks.
  2. Gate the post*Activity call-sites in EdgeWorker on the flag.
  3. Unconditionally skip empty-body:"" thought posts (pure waste) in ActivityPoster.postThoughtActivity, regardless of the flag.
  4. Optional: debounce/coalesce rapid ephemeral thought updates (each is replaced by the next anyway).

Acceptance criteria

  • With minimal / thoughts-off, a typical session issues materially fewer agentActivityCreate calls (target ≳60% reduction) with no loss of the final response or session-lifecycle visibility in Linear.
  • Empty-body thoughts are never posted.
  • Default behavior is unchanged when the flag is unset.

Related

Graceful handling when the limit is still hit: #1324. Together they address both sides — fewer requests (this) + resilience under throttle (#1324).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions