Skip to content

feat(automations): Post declared thread replies under an automation message - #2215

Closed
antonis wants to merge 2 commits into
mainfrom
feat/automation-thread-replies
Closed

antonis wants to merge 2 commits into
mainfrom
feat/automation-thread-replies

Conversation

@antonis

@antonis antonis commented Oct 23, 2026

Copy link
Copy Markdown

An automation run can only post one declared message. When the message is long, Slack delivery cuts it by size (2,200 characters or 45 lines). A section of a digest can then start in the channel message and break in the middle with [Continued below].

finishAutomationRun now takes an optional threadReplies list (at most 10). Slack delivery posts the message, then posts each reply as its own post in the thread under it. Each part is split on its own, so a section always starts a new post. An oversized section still splits safely. Chat replies do not change.

Example: the Mobile SDK team's weekly hybrid dependency digest (team-mobile#219). It needs a short channel message and one thread reply per dependency. In a test run today, the size cut put the first section in the channel and broke later sections in the middle.

Related: #2051 (how automation runs deliver results).

Changes

  • automation-result.ts: send_message accepts threadReplies, with the same cleanup as message. finishedRunReply returns { text, threadReplies }.
  • finish-automation-run.ts: the tool exposes threadReplies.
  • slack/reply.ts: sendSlackReply splits the message and each reply separately. The existing post loop threads every post after the first one.
  • providers/slack/turn.ts, resume.ts: pass threadReplies to delivery. History records the message and replies together, so a reply in the thread continues with the full context.

Open questions

  • The tool description reaches every automation. It could make short automations split their output. The scheduler delivery evals were not run locally because they need recordings. Should the wording be narrower, for example "only for long, multi-section digests"?
  • resultMessageId is the last post, so with thread replies the result link opens the last reply, not the parent. Multi-chunk replies already work this way. Should it point at the first post?
  • A retryable failure partway through posting regenerates the delivery, so earlier posts can repeat. This is not new for multi-chunk replies, but a run can now have up to 11 posts per destination.

Tests

  • tests/integration/slack/reply-delivery.test.ts: each thread reply is its own post, threaded under the first message. This test fails without the reply.ts change.
  • tests/unit/chat/automation-result.test.ts: finishedRunReply returns the declared thread replies; existing cases are updated for the new return shape.
  • Local: full @sentry/junior suite, typecheck, lint, Prettier, file-length and test-architecture checks.

🤖 Generated with Claude Code

…essage

An automation run can only post one declared message. Long digests are cut
by size, so a section can start in the channel message and break with
"[Continued below]" in the middle.

finishAutomationRun now takes optional threadReplies. Slack delivery posts
the message, then each reply as its own post in the thread under it. Each
part is split on its own, so a section always starts a new post.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
junior-docs Ready Ready Preview Oct 23, 2026 12:43pm UTC

Request Review

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

Static review supports the delivery changes; the remaining validation-diagnostic improvement is non-blocking, and tests were not executed.

1 open issue
What changed in this PR

Adds declared thread replies to automation results so long digests can place each section in a separate Slack post, without changing ordinary chat replies.

Changes:

  • Accepts up to 10 thread replies through finishAutomationRun, with reply text cleanup.
  • Splits each message and reply independently, and passes replies through initial and resumed delivery.
  • Records the full output in conversation history and adds result and delivery coverage.
File Description
packages/​junior/​tests/​unit/​chat/​automation-result.test.ts Tests declared replies and the updated result shape.
packages/​junior/​tests/​integration/​slack/​reply-delivery.test.ts Tests separate posts under the parent message.
packages/​junior/​src/​chat/​tools/​runtime/​finish-automation-run.ts Exposes optional thread replies to automations.
packages/​junior/​src/​chat/​slack/​reply.ts Splits each declared part independently.
packages/​junior/​src/​chat/​README.md Documents the thread-reply contract.
packages/​junior/​src/​chat/​providers/​slack/​turn.ts Delivers and records replies for initial runs.
packages/​junior/​src/​chat/​providers/​slack/​resume.ts Delivers and records replies for resumed runs.
packages/​junior/​src/​chat/​automation-result.ts Defines reply validation, limits, and the delivery result shape.

Review effort: Balanced

Comment thread packages/junior/src/chat/tools/runtime/finish-automation-run.ts
…errors

A blank thread reply failed validation with "send_message requires a
non-empty message.", even when the message was valid. Name the thread
reply instead, so the agent fixes the right field.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@dcramer dcramer left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a leaky abstraction

  1. why would it expose the thread. That's slack specific and unrelated to automations

  2. why wouldn't it try to make something more slack consumable? Aka don't write essays

  3. why couldn't it use canvas if it is an essay?

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

Delivery and history handling are consistent across both execution paths; the remaining validation-message issue is a non-blocking nit.

1 open issue
1 resolved since last review

Review effort: Balanced

Comment on lines +68 to +72
input.result !== "send_message"
? `${input.result} requires a non-empty reason.`
: typeof input.message === "string" && input.message.trim()
? "Every threadReplies item must be non-empty."
: "send_message requires a non-empty message.",
@antonis

antonis commented Oct 23, 2026

Copy link
Copy Markdown
Author

This is a leaky abstraction

  1. why would it expose the thread. That's slack specific and unrelated to automations
  2. why wouldn't it try to make something more slack consumable? Aka don't write essays
  3. why couldn't it use canvas if it is an essay?

Thank you for looking at it and the feedback 🙇 All fair points! Closing this PR

@antonis antonis closed this Oct 23, 2026

This branch was successfully deployed

1 active deployment
Preview – junior-docs — 73df74ef Deployed Oct 23, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants