Skip to content

A Crew thread's provider approvals and questions reach the Inbox (server) #263

Description

@bryantderosier

When a thread is a Crew Captain or a live seat, every question or approval its provider raises for me (tool-approval requests, and user-input questions such as Claude's AskUserQuestion or Codex's request_user_input) renders inline in that thread's composer. Captains and seats run while I'm somewhere else, so those prompts sit unseen and the Crew stalls. My rule: anything a Captain or seat needs from me goes to my Inbox, the same way Crew seat requests and agent asks already do. The one exception is the initial roster approval card, which stays inline above the Captain's composer (crews.md, gate placement).

This issue is the server half. The web Inbox and hiding the inline cards is #264.

Where it breaks:

  • The Inbox (apps/server/src/j5/a2a/HumanInboxService.ts) holds only ledger Exchanges, and Crew seat additions are merged in on the client (apps/web/src/j5/crew/crewProposals.logic.ts:25-28). Nothing reads projection.runtimeRequests for Crew threads, so provider approvals and questions never reach the Inbox.
  • The only automatic Inbox producer for Crews is crewFailureAlert.ts, and it handles run failures only.

What should change:

  • A J5 read of pending provider requests (runtime-request.updated, status pending, kinds approval and user_input, skipping auth_refresh and dynamic_tool_call as derivePendingThreadRequests does) on every thread that AgentCrewInstanceService.listInvolving resolves to a live Captain or seat. Each item carries the thread, its Crew and seat (or Captain), the request kind, and the payload needed to answer (approval options, or the questions with their choices).
  • Serve it as its own Inbox source beside Crew requests, not as ledger Exchanges: HumanInboxService.answer writes an A2A reply, not a provider response. Read the live state from the projection instead of copying it into a new table, unless a measured need appears.
  • A J5 answer route under /api/j5/... that authenticates with operate scope and dispatches runtime-request.respond (packages/contracts/src/orchestrationV2.ts:2461-2469), copying the server-side precedent in apps/server/src/mcp/toolkits/thread/handlers.ts:201-213. Answering a request that is already resolved, or that was answered inline on another device, is refused with a clear message and changes nothing.
  • A request stops being listed once it is resolved or its Crew retires.
  • No upstream files. Wire the read into the J5 runtime layer and the J5 contract in packages/contracts/src/j5.ts.

Tests to ship:

  • a pending approval on a seat thread is listed with its Crew and seat; a pending question on the Captain's thread is listed as the Captain
  • a thread outside any Crew is never listed
  • answering through the route resolves the provider request exactly once; a second answer, or an answer after an inline answer, is refused
  • a retired Crew's requests leave the list
  • drive the flow with receipts, never sleeps or polling

Done when every pending provider approval or question on a live Captain or seat thread can be read and answered through the J5 Inbox API, and only those.

Related criteria: crews.md AC9 ("a Crew's contact with the person goes through the inbox or its Captain").

Activity

  1. added this to the Crews milestone on Sep 24, 2026
  2. added
    size:M30-99 effective changed lines (test files excluded in mixed PRs).
    on Sep 24, 2026
  3. added 2 commits that reference this issue on Sep 28, 2026
    1dab187
    ff73442
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

size:M30-99 effective changed lines (test files excluded in mixed PRs).

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions