Skip to content
This repository was archived by the owner on Aug 6, 2026. It is now read-only.

feat(agent): echo initiating message_id on relay_message - #3434

Merged
VojtechBartos merged 1 commit into
mainfrom
vojtab/relay-echo-message-id
Jul 20, 2026
Merged

feat(agent): echo initiating message_id on relay_message#3434
VojtechBartos merged 1 commit into
mainfrom
vojtab/relay-echo-message-id

Conversation

@VojtechBartos

@VojtechBartos VojtechBartos commented Jul 14, 2026

Copy link
Copy Markdown
Member

Problem

When a turn ends, the agent-server relays the answer to relay_message with only text/text_parts — no link to the user message it answers, so the backend has to guess who to @-mention and mis-tags replies in multiplayer threads.

Changes

  • Echo the initiating user_message's messageId (the id already used for duplicate-delivery suppression) as an optional message_id on the relay_message body. Captured in the handler closure, so overlapping turns each relay their own id.
  • Omitted when no id is known (e.g. the boot prompt), so older backends see the exact same payload as before.

Paired with PostHog/posthog#70762

The backend consumes message_id to attribute each Slack reply to the right sender (that PR, part of the follow-up queue work #70806 → #70762). Neither side hard-depends on the other; verified end-to-end locally with both together.

How did you test this?

  • Tests: relay echoes each turn's own id through the /command endpoint (overlapping turns, the no-id case, no leak from a failed turn into the next), relayAgentResponse pass-through, and the request body shape.
  • pnpm --filter @posthog/agent test — 1295 tests pass; typecheck + biome clean.

Automatic notifications

  • Publish to changelog?
  • Alert Sales and Marketing teams?

@VojtechBartos VojtechBartos self-assigned this Jul 14, 2026
@trunk-io

trunk-io Bot commented Jul 14, 2026

Copy link
Copy Markdown

Merging to main in this repository is managed by Trunk.

  • To merge this pull request, check the box to the left or comment /trunk merge below.

After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here

@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown

React Doctor found no issues in the changed files. 🎉

Reviewed by React Doctor for commit f11ab9f.

Pass the id of the user_message command that initiated a turn from the
handler closure to relayAgentResponse and include it as an optional
message_id field in the relay_message POST body. Each turn's relay
carries its own initiating message's id; the field is omitted when no
id is known (e.g. the boot prompt), so older backends are unaffected.
@VojtechBartos
VojtechBartos force-pushed the vojtab/relay-echo-message-id branch from 4c745d2 to f11ab9f Compare July 15, 2026 08:01
@VojtechBartos VojtechBartos changed the title feat(agent): echo initiating message_id on relay_message and turn_complete feat(agent): echo initiating message_id on relay_message Jul 15, 2026
@VojtechBartos
VojtechBartos marked this pull request as ready for review July 16, 2026 12:40
@VojtechBartos
VojtechBartos requested a review from a team July 16, 2026 12:40
@greptile-apps

greptile-apps Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Security Review

The new correlation ID comes from the command body and is not checked against the authenticated user. In a shared run, this can misattribute a reply unless ownership is enforced before forwarding or by the relay endpoint.

Reviews (1): Last reviewed commit: "feat(agent): echo initiating message_id ..." | Re-trigger Greptile

this.logger.debug("Failed to relay follow-up response", err),
// delivery path — the HTTP caller only handles reactions. Echo the
// initiating message's id so the backend can attribute the answer.
this.relayAgentResponse(this.session.payload, messageId).catch(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Captured ID Gets Later Response

When another command starts before this unawaited relay finishes flushing, that turn resets and repopulates the session-wide response buffer. The first relay can then read the later turn's text while retaining the first turn's messageId, causing the backend to attribute the wrong answer to a participant. Capture the completed response with the ID before another turn can mutate the buffer, or serialize relay completion with turn processing.

this.logger.debug("Failed to relay follow-up response", err),
// delivery path — the HTTP caller only handles reactions. Echo the
// initiating message's id so the backend can attribute the answer.
this.relayAgentResponse(this.session.payload, messageId).catch(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 security Message Ownership Is Unchecked

A caller with a valid token for a multiplayer run can submit another participant's message ID because the request body value is forwarded without checking its owner. If the relay endpoint uses that ID directly for attribution, the answer is attached to the wrong sender; validate that the ID belongs to the authenticated user and current task/run before forwarding it.

Rule Used: When implementing new features, ensure that owners... (source)

Learned From
PostHog/posthog#31236

@VojtechBartos
VojtechBartos merged commit c14064e into main Jul 20, 2026
33 checks passed
@VojtechBartos
VojtechBartos deleted the vojtab/relay-echo-message-id branch July 20, 2026 10:10
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants