Summary
Add real Agent Client Protocol (ACP) support so one Junior runtime can delegate work to another Junior runtime. The upstream Junior acts as an ACP client; the downstream Junior exposes an ACP agent surface backed by Junior's durable session log and worker model.
This should support timeout-bound compute by using ACP session/load for replay/gap recovery, session/resume for fast reconnects, and ACP _meta fields for Junior-specific prompt dedupe/correlation.
Goal
Enable:
Slack user -> Junior A -> ACP delegation -> Junior B -> durable agent work
Junior A should be able to yield before platform timeout, resume later, reconnect to Junior B, recover missed events, and deliver a final Slack answer without duplicating delegated work.
Protocol Baseline
Implement ACP v1 semantics:
initialize
session/new
session/load
session/resume
session/list
session/prompt
session/cancel
session/close
Use ACP _meta for Junior-specific correlation:
{
"sentry.dev/junior": {
"sourceConversationId": "...",
"sourceTurnId": "...",
"sourceToolCallId": "...",
"delegationId": "..."
}
}
Transport
Start with a Junior HTTP transport that preserves ACP JSON-RPC semantics.
Suggested shape:
POST /acp client-to-agent JSON-RPC
GET /acp/events optional event stream/replay endpoint
Do not depend on the ACP Streamable HTTP/WebSocket RFD being finalized. Keep the implementation close enough to that shape that we can migrate later.
Durability Model
Junior A records outbound ACP delegation in its local session log:
acp.session.created
acp.prompt.submitting
acp.session.update.received
acp.prompt.completed
acp.prompt.failed
Junior B records the authoritative ACP session in its own durable log:
acp.session.created
acp.prompt.accepted
acp.session.update.emitted
acp.prompt.completed
acp.prompt.cancelled
On timeout recovery, Junior A calls session/load, dedupes replayed updates against its mirrored log, and continues.
Prompt Dedupe
ACP does not standardize prompt idempotency. Use Junior _meta identity as a receiver-side dedupe key:
sessionId + sourceConversationId + sourceTurnId + sourceToolCallId
If Junior B has already accepted the prompt, it should not enqueue duplicate work. It should replay/return the existing session state.
Implementation Phases
- Add ACP protocol types and JSON-RPC validation under
packages/junior/src/chat/acp/protocol/.
- Add ACP server adapter that maps ACP sessions to Junior durable conversations/session logs.
- Implement
initialize, session/new, session/load, and session/prompt.
- Add prompt dedupe using
_meta source ids.
- Add ACP client adapter/tool for Junior A delegation.
- Add timeout recovery path: local mirror log +
session/load replay + dedupe.
- Add
session/resume, session/cancel, session/close, and session/list.
- Add optional event streaming/replay endpoint for efficiency after correctness works.
Acceptance Criteria
- Junior A can delegate a prompt to Junior B and receive streamed ACP
session/update output.
- If Junior A times out after prompt submission, it can recover via
session/load.
- Replaying a remote session does not duplicate Slack progress or final replies.
- Retrying a submitted prompt does not enqueue duplicate work in Junior B.
- Junior B can cancel and close delegated sessions.
- The implementation remains ACP-compatible, with Junior-only behavior isolated to
_meta or custom _sentry.dev/* methods.
Tests
- Protocol unit tests for JSON-RPC parsing, method routing, and capability negotiation.
- Integration test: Junior A delegates to Junior B and receives final output.
- Integration test: A times out after B accepts prompt; A reconnects with
session/load.
- Integration test: duplicate
session/prompt with same _meta key is deduped.
- Integration test: cancel/close stops downstream work and records terminal state.
References
Summary
Add real Agent Client Protocol (ACP) support so one Junior runtime can delegate work to another Junior runtime. The upstream Junior acts as an ACP client; the downstream Junior exposes an ACP agent surface backed by Junior's durable session log and worker model.
This should support timeout-bound compute by using ACP
session/loadfor replay/gap recovery,session/resumefor fast reconnects, and ACP_metafields for Junior-specific prompt dedupe/correlation.Goal
Enable:
Junior A should be able to yield before platform timeout, resume later, reconnect to Junior B, recover missed events, and deliver a final Slack answer without duplicating delegated work.
Protocol Baseline
Implement ACP v1 semantics:
initializesession/newsession/loadsession/resumesession/listsession/promptsession/cancelsession/closeUse ACP
_metafor Junior-specific correlation:{ "sentry.dev/junior": { "sourceConversationId": "...", "sourceTurnId": "...", "sourceToolCallId": "...", "delegationId": "..." } }Transport
Start with a Junior HTTP transport that preserves ACP JSON-RPC semantics.
Suggested shape:
Do not depend on the ACP Streamable HTTP/WebSocket RFD being finalized. Keep the implementation close enough to that shape that we can migrate later.
Durability Model
Junior A records outbound ACP delegation in its local session log:
Junior B records the authoritative ACP session in its own durable log:
On timeout recovery, Junior A calls
session/load, dedupes replayed updates against its mirrored log, and continues.Prompt Dedupe
ACP does not standardize prompt idempotency. Use Junior
_metaidentity as a receiver-side dedupe key:If Junior B has already accepted the prompt, it should not enqueue duplicate work. It should replay/return the existing session state.
Implementation Phases
packages/junior/src/chat/acp/protocol/.initialize,session/new,session/load, andsession/prompt._metasource ids.session/loadreplay + dedupe.session/resume,session/cancel,session/close, andsession/list.Acceptance Criteria
session/updateoutput.session/load._metaor custom_sentry.dev/*methods.Tests
session/load.session/promptwith same_metakey is deduped.References
_meta: https://agentclientprotocol.com/protocol/extensibility