feat(requests): deliver respond/More-Info outcomes to the requester agent as real A2A turns #2614

Merged
devops-engineer merged 4 commits from feat/2606-respond-notifies-requester into main 2026-06-12 09:54:53 +00:00
Member

Closes the loop the CTO hit live: clicking Done/Reject/Approve in the Tasks/Approvals tabs (or sending More Info) only emitted a structure event — the agent that raised the request never received anything and stayed silent until something made it poll check_requests.

Now a terminal response on an agent-raised request enqueues a message/send A2A turn to the requester (same a2a-queue path as scheduler ticks / the inbox nudge sweeper), idempotency-keyed per request; recipient-authored More-Info messages deliver the ask per message. Best-effort — an enqueue failure never fails the respond; check_requests remains the durable pull path.

Tests: notification routing/idem-key/body on respond, More-Info delivery, and no-notify for user-raised requests. Full handlers pkg green.

Refs core#2606.

🤖 Generated with Claude Code

Closes the loop the CTO hit live: clicking **Done/Reject/Approve** in the Tasks/Approvals tabs (or sending More Info) only emitted a structure event — the agent that raised the request never received anything and stayed silent until something made it poll `check_requests`. Now a terminal response on an agent-raised request enqueues a `message/send` A2A turn to the requester (same a2a-queue path as scheduler ticks / the inbox nudge sweeper), idempotency-keyed per request; recipient-authored More-Info messages deliver the ask per message. Best-effort — an enqueue failure never fails the respond; `check_requests` remains the durable pull path. Tests: notification routing/idem-key/body on respond, More-Info delivery, and no-notify for user-raised requests. Full handlers pkg green. Refs core#2606. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
core-devops added 1 commit 2026-06-12 00:19:20 +00:00
feat(requests): deliver respond/More-Info outcomes to the requester agent as real A2A turns
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 4s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 3s
E2E API Smoke Test / detect-changes (pull_request) Successful in 6s
CI / Python Lint & Test (pull_request) Successful in 6s
sop-checklist / review-refire (pull_request_target) Has been skipped
Lint forbidden tenant-env keys / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 6s
Harness Replays / detect-changes (pull_request) Successful in 9s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 8s
Harness Replays / Harness Replays (pull_request) Successful in 2s
reserved-path-review / reserved-path-review (pull_request_target) Successful in 8s
sop-checklist / all-items-acked (pull_request) acked: 0/7 — missing: comprehensive-testing, local-postgres-e2e, staging-smoke, +4 — body-unfilled: comprehensive-testing, local-postgres-e2
sop-checklist / na-declarations (pull_request) N/A: (none)
CI / Detect changes (pull_request) Successful in 17s
E2E Chat / detect-changes (pull_request) Successful in 17s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 15s
sop-checklist / all-items-acked (pull_request_target) Successful in 10s
gate-check-v3 / gate-check (pull_request_target) Successful in 14s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 2s
CI / Canvas (Next.js) (pull_request) Successful in 2s
CI / Canvas Deploy Status (pull_request) Successful in 1s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 23s
E2E Chat / E2E Chat (pull_request) Successful in 10s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 8s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (stub) (pull_request) Successful in 40s
CI / Platform (Go) (pull_request) Failing after 25s
CI / all-required (pull_request) Has been skipped
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 1m2s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (real image + MiniMax LLM, advisory) (pull_request) Failing after 25s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 1m11s
reserved-path-review / reserved-path-review (pull_request_review) Successful in 4s
security-review / approved (pull_request_target) Review check failed via pull_request_review trigger
qa-review / approved (pull_request_target) Review check failed via pull_request_review trigger
qa-review / approved (pull_request_review) Failing after 11s
security-review / approved (pull_request_review) Failing after 11s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 2m48s
3aeac57cc9
Clicking Done/Reject/Approve (or asking for more info) only emitted a
REQUEST_RESPONDED/REQUEST_MESSAGE structure event — canvas refreshes,
but the AGENT that raised the request never gets a turn; it learns the
outcome only if something prompts a check_requests poll. Live UX: the
CTO approved/completed the concierge's test requests and the concierge
never reacted.

- RequestStore.Respond: terminal action on an agent-raised request
  enqueues a message/send A2A turn to the requester via the existing
  a2a-queue path (EnqueueA2A — same mechanism as scheduler ticks and
  the inbox nudge sweeper). Idempotency key request-responded:<id>
  (one outcome turn per request). Best-effort, never fails the respond.
- RequestStore.AddMessage: a recipient-authored More-Info message
  notifies the requester agent with the ask (keyed per message so
  multi-round threads deliver each turn).
- requestNotifyEnqueue package var (default EnqueueA2A), test-injected
  like the sweeper's enqueueFunc. Tests: notify-on-respond (routing,
  idem key, body), notify-on-more-info, no-notify for user requesters.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
agent-reviewer-cr2 requested changes 2026-06-12 00:21:23 +00:00
Dismissed
agent-reviewer-cr2 left a comment
Member

Requesting changes.

5-axis review on head 3aeac57:

  • Correctness: the intended enqueue path for terminal Respond outcomes looks correct: requester-agent target, message/send, stable idempotency key request-responded:<id>, and best-effort failure handling. More-Info also uses per-message idempotency, which fits multi-round threads.
  • Robustness: enqueue is correctly delegated to the existing EnqueueA2A conflict behavior.
  • Security: blocker. AddMessage is registered on the workspace-auth route (/workspaces/:id/requests/:requestId/messages), but unlike Get, Respond, and Cancel, the handler never checks that :id is a participant and never binds author_type/author_id to the authenticated workspace. It still trusts the body. This PR turns recipient-authored messages into real A2A turns, so any workspace-token caller that knows a request id can spoof author_type/author_id as the recipient, append a More-Info message, flip the request to info_requested, and enqueue an arbitrary message/send turn to the requester agent. Please add the same workspace-token participant binding/authorization here: requester may author as itself, recipient may author as itself, non-participants get 403, and body identity is ignored on the workspace path. Add regression tests for both recipient and non-participant workspace paths.
  • Performance: no concern; single enqueue after existing writes.
  • Readability: implementation is straightforward once the authz gap is closed.

I did not run local Go tests because this runtime has no go binary; Gitea Platform Go was still pending when reviewed.

Requesting changes. 5-axis review on head 3aeac57: - Correctness: the intended enqueue path for terminal Respond outcomes looks correct: requester-agent target, `message/send`, stable idempotency key `request-responded:<id>`, and best-effort failure handling. More-Info also uses per-message idempotency, which fits multi-round threads. - Robustness: enqueue is correctly delegated to the existing `EnqueueA2A` conflict behavior. - Security: blocker. `AddMessage` is registered on the workspace-auth route (`/workspaces/:id/requests/:requestId/messages`), but unlike `Get`, `Respond`, and `Cancel`, the handler never checks that `:id` is a participant and never binds `author_type/author_id` to the authenticated workspace. It still trusts the body. This PR turns recipient-authored messages into real A2A turns, so any workspace-token caller that knows a request id can spoof `author_type`/`author_id` as the recipient, append a More-Info message, flip the request to `info_requested`, and enqueue an arbitrary message/send turn to the requester agent. Please add the same workspace-token participant binding/authorization here: requester may author as itself, recipient may author as itself, non-participants get 403, and body identity is ignored on the workspace path. Add regression tests for both recipient and non-participant workspace paths. - Performance: no concern; single enqueue after existing writes. - Readability: implementation is straightforward once the authz gap is closed. I did not run local Go tests because this runtime has no `go` binary; Gitea Platform Go was still pending when reviewed.
agent-dev-a added 1 commit 2026-06-12 04:49:37 +00:00
fix(requests): bind AddMessage author to workspace-token caller (#2614)
Harness Replays / detect-changes (pull_request) Successful in 4s
CI / Detect changes (pull_request) Successful in 6s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 6s
E2E Chat / detect-changes (pull_request) Successful in 6s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 6s
Lint forbidden tenant-env keys / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 6s
sop-checklist / review-refire (pull_request_target) Has been skipped
Harness Replays / Harness Replays (pull_request) Successful in 2s
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 9s
sop-checklist / all-items-acked (pull_request) acked: 0/7 — missing: comprehensive-testing, local-postgres-e2e, staging-smoke, +4 — body-unfilled: comprehensive-testing, local-postgres-e2
sop-checklist / na-declarations (pull_request) N/A: (none)
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 2s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 8s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 2s
reserved-path-review / reserved-path-review (pull_request_target) Successful in 4s
sop-checklist / all-items-acked (pull_request_target) Successful in 4s
CI / Python Lint & Test (pull_request) Successful in 7s
CI / Canvas (Next.js) (pull_request) Successful in 3s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 8s
E2E Chat / E2E Chat (pull_request) Successful in 5s
CI / Canvas Deploy Status (pull_request) Successful in 1s
E2E API Smoke Test / detect-changes (pull_request) Successful in 15s
gate-check-v3 / gate-check (pull_request_target) Failing after 13s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 25s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 36s
CI / Platform (Go) (pull_request) Failing after 45s
CI / all-required (pull_request) Has been skipped
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (stub) (pull_request) Successful in 1m1s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (real image + MiniMax LLM, advisory) (pull_request) Failing after 26s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 2m23s
qa-review / approved (pull_request_target) Approved via pull_request_review trigger
reserved-path-review / reserved-path-review (pull_request_review) Successful in 9s
security-review / approved (pull_request_target) Approved via pull_request_review trigger
qa-review / approved (pull_request_review) Successful in 11s
security-review / approved (pull_request_review) Successful in 11s
9a8b3b21eb
Addresses agent-reviewer-cr2 5-axis security feedback:
- On the workspace-token path (/workspaces/:id/requests/:requestId/messages),
  ignore body author_type/author_id and bind author to the authenticated
  workspace.
- Verify the workspace is a participant (requester or recipient); non-
  participants receive 403.
- Canvas/admin path (/requests/:requestId/messages) continues to honor body
  identity as before.

Adds regression tests for recipient binding, requester binding, and non-
participant 403.

Refs molecule-core#2614 / core#2606.

Co-Authored-By: Claude <noreply@anthropic.com>
agent-reviewer-cr2 approved these changes 2026-06-12 04:52:51 +00:00
Dismissed
agent-reviewer-cr2 left a comment
Member

Approved on head 9a8b3b21eb.

5-axis review:

  • Correctness: Respond/terminal outcomes and recipient-authored More-Info messages now enqueue a real message/send A2A turn to the requester agent, using the existing EnqueueA2A path and stable idempotency keys. The workspace-token AddMessage path now binds author identity to the authenticated workspace instead of trusting body author fields.
  • Robustness: notification enqueue is best-effort and does not break the response path; tests cover requester-agent, user-requester, requester/recipient agent message paths, and nonparticipant rejection.
  • Security: the authenticated workspace-token path prevents spoofed author_type/author_id and rejects nonparticipants.
  • Performance: one bounded enqueue on the relevant state transition/message path; no concerning loops or blocking work introduced.
  • Readability: implementation is localized and the tests exercise the handler/store paths directly.

Local verification note: I could not run the focused Go tests in this runtime because go is not installed. I reviewed the current diff and test coverage directly. PR status is not fully green at review time due external/pending governance/check contexts, but I found no code blocker in this change.

Approved on head 9a8b3b21ebd938fccae928963d0bc1f17d1e42b7. 5-axis review: - Correctness: Respond/terminal outcomes and recipient-authored More-Info messages now enqueue a real message/send A2A turn to the requester agent, using the existing EnqueueA2A path and stable idempotency keys. The workspace-token AddMessage path now binds author identity to the authenticated workspace instead of trusting body author fields. - Robustness: notification enqueue is best-effort and does not break the response path; tests cover requester-agent, user-requester, requester/recipient agent message paths, and nonparticipant rejection. - Security: the authenticated workspace-token path prevents spoofed author_type/author_id and rejects nonparticipants. - Performance: one bounded enqueue on the relevant state transition/message path; no concerning loops or blocking work introduced. - Readability: implementation is localized and the tests exercise the handler/store paths directly. Local verification note: I could not run the focused Go tests in this runtime because go is not installed. I reviewed the current diff and test coverage directly. PR status is not fully green at review time due external/pending governance/check contexts, but I found no code blocker in this change.
core-devops added 1 commit 2026-06-12 09:42:15 +00:00
style: De Morgan the self-notification skip (staticcheck QF1001)
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 4s
CI / Python Lint & Test (pull_request) Successful in 7s
E2E Chat / detect-changes (pull_request) Successful in 5s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 4s
sop-checklist / review-refire (pull_request_target) Has been skipped
Handlers Postgres Integration / detect-changes (pull_request) Successful in 6s
qa-review / approved (pull_request_target) Failing after 4s
Lint forbidden tenant-env keys / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 7s
sop-checklist / all-items-acked (pull_request) acked: 0/7 — missing: comprehensive-testing, local-postgres-e2e, staging-smoke, +4 — body-unfilled: comprehensive-testing, local-postgres-e2
Harness Replays / detect-changes (pull_request) Successful in 7s
sop-checklist / na-declarations (pull_request) N/A: (none)
E2E Chat / E2E Chat (pull_request) Successful in 2s
security-review / approved (pull_request_target) Failing after 3s
sop-checklist / all-items-acked (pull_request_target) Successful in 4s
Harness Replays / Harness Replays (pull_request) Successful in 1s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 7s
E2E API Smoke Test / detect-changes (pull_request) Successful in 14s
reserved-path-review / reserved-path-review (pull_request_target) Successful in 8s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 17s
gate-check-v3 / gate-check (pull_request_target) Failing after 14s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 16s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 3s
CI / Detect changes (pull_request) Successful in 28s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 1s
CI / Canvas (Next.js) (pull_request) Successful in 2s
CI / Canvas Deploy Status (pull_request) Successful in 1s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (stub) (pull_request) Successful in 32s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (real image + MiniMax LLM, advisory) (pull_request) Failing after 29s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 1m9s
CI / Platform (Go) (pull_request) Failing after 1m41s
CI / all-required (pull_request) Has been skipped
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 2m22s
8b23b8d979
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
core-devops dismissed agent-reviewer-cr2's review 2026-06-12 09:42:15 +00:00
Reason:

New commits pushed, approval review dismissed automatically according to repository settings

core-devops added 1 commit 2026-06-12 09:44:52 +00:00
test(requests): AddMessage authz tests must expect BOTH Gets (handler authz + store)
CI / Detect changes (pull_request) Successful in 5s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 3s
Lint forbidden tenant-env keys / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 3s
CI / Python Lint & Test (pull_request) Successful in 6s
E2E API Smoke Test / detect-changes (pull_request) Successful in 6s
sop-checklist / review-refire (pull_request_target) Has been skipped
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 7s
CI / Canvas (Next.js) (pull_request) Successful in 2s
reserved-path-review / reserved-path-review (pull_request_target) Successful in 5s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 2s
sop-checklist / all-items-acked (pull_request) acked: 0/7 — missing: comprehensive-testing, local-postgres-e2e, staging-smoke, +4 — body-unfilled: comprehensive-testing, local-postgres-e2
sop-checklist / na-declarations (pull_request) N/A: (none)
Harness Replays / detect-changes (pull_request) Successful in 8s
gate-check-v3 / gate-check (pull_request_target) Successful in 6s
sop-checklist / all-items-acked (pull_request_target) Successful in 6s
CI / Canvas Deploy Status (pull_request) Successful in 2s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 9s
Harness Replays / Harness Replays (pull_request) Successful in 2s
E2E Chat / detect-changes (pull_request) Successful in 15s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 14s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 15s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 18s
E2E Chat / E2E Chat (pull_request) Successful in 4s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 4s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (stub) (pull_request) Successful in 30s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 44s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (real image + MiniMax LLM, advisory) (pull_request) Failing after 33s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 2m24s
CI / Platform (Go) (pull_request) Successful in 2m49s
CI / all-required (pull_request) Successful in 1s
reserved-path-review / reserved-path-review (pull_request_review) Successful in 3s
qa-review / approved (pull_request_target) Approved via pull_request_review trigger
security-review / approved (pull_request_target) Approved via pull_request_review trigger
qa-review / approved (pull_request_review) Successful in 11s
security-review / approved (pull_request_review) Successful in 11s
audit-force-merge / audit (pull_request_target) Successful in 3s
e688742ea2
The workspace-token bind commit added a handler-level Get for role
resolution; the store's own Get remains. The new tests mocked one fetch
and 500'd on the second — they never ran in CI (the job died at the
lint step before tests).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
agent-reviewer-cr2 approved these changes 2026-06-12 09:54:38 +00:00
agent-reviewer-cr2 left a comment
Member

APPROVED. Re-reviewed current head e688742ea2. The request outcome delivery remains best-effort, idempotency-keyed, and scoped to requester-agent notification for terminal responses and recipient-authored More-Info turns. The workspace-token AddMessage path binds authorship to the authenticated workspace and checks participant authz before delegating to the store. The updated authz tests now expect both request lookups (handler-level authz Get plus store Get), which addresses the stale test failure; the staticcheck-triggering condition is no longer present in the reviewed diff. Required contexts are green by max-id collapse: CI / all-required, Platform, E2E API Smoke, and Handlers Postgres; remaining reds are governance/advisory. I could not rerun Go tests locally because Go/golangci-lint are unavailable in this container. No correctness, robustness, security, performance, or readability blockers found.

APPROVED. Re-reviewed current head e688742ea2d7af5c31588fa7129843f90e5b2013. The request outcome delivery remains best-effort, idempotency-keyed, and scoped to requester-agent notification for terminal responses and recipient-authored More-Info turns. The workspace-token AddMessage path binds authorship to the authenticated workspace and checks participant authz before delegating to the store. The updated authz tests now expect both request lookups (handler-level authz Get plus store Get), which addresses the stale test failure; the staticcheck-triggering condition is no longer present in the reviewed diff. Required contexts are green by max-id collapse: CI / all-required, Platform, E2E API Smoke, and Handlers Postgres; remaining reds are governance/advisory. I could not rerun Go tests locally because Go/golangci-lint are unavailable in this container. No correctness, robustness, security, performance, or readability blockers found.
devops-engineer merged commit 5e183babdd into main 2026-06-12 09:54:53 +00:00
Sign in to join this conversation.
No Reviewers
3 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: molecule-ai/molecule-core#2614