Repository navigation
Description
Product or interface
CLI - ACP
Use case and problem
A delegated sub-agent of a session is a full runtime session with its own session id, and the
runtime can address it on its own. The ACP surface does not expose that: every extension
accepts only the id of a session that is attached to the connection, and the delegation
methods work on the whole tree.
So a client that speaks ACP can watch the tree of delegated tasks, but it cannot do what the
app itself does: talk to one delegated task, open it, or stop it without stopping its parent.
Measured against mcode 0.7.3 over raw JSON-RPC on stdio, with a child session that was
running (the parent had delegated a background task):
mcode/session/delegation/get {sessionId: <child>} -> -32002 Resource not found: <child>
mcode/session/delegation/stop {sessionId: <child>} -> -32002 Resource not found: <child>
mcode/session/steer {sessionId: <child>} -> -32002 Resource not found: <child>
mcode/session/queue/list {sessionId: <child>} -> -32002 Resource not found: <child>
mcode/session/goal/get {sessionId: <child>} -> -32002 Resource not found: <child>
mcode/session/activate {sessionId: <child>} -> -32002 Resource not found: <child>
session/prompt {sessionId: <child>} -> -32002 Resource not found: <child>
session/resume {sessionId: <child>} -> -32602 Sub-agent Sessions are internal and cannot be opened.
session/load {sessionId: <child>} -> -32602 Sub-agent Sessions are internal and cannot be opened.
session/fork {sessionId: <child>} -> -32602 Sub-agent Sessions are internal and cannot be opened.
session/cancel {sessionId: <child>} -> ignored without a reply; the child was still running after 6 s
The tree is visible from the parent (mcode/session/delegation/get returns the members with
their own session ids and statuses), and a delegated task also announces its session id in the
tool call output (sub_session_id). What is missing is any way to act on one of them.
One detail worth flagging: mcode/session/delegation/stop accepts unknown fields and ignores
them. A call that names a target is answered with a receipt for the whole tree:
mcode/session/delegation/stop {sessionId: <root>, targetSessionId: <child>, childSessionId: <child>}
-> {"rootSessionId":"<root>","rootStopped":true,"stoppedSessionIds":["<child>"],
"activeSessionIds":[],"failedSessionIds":[]}
A client that reads that receipt as "the named task was stopped" will be wrong: the whole
tree was stopped instead, and the receipt does not say which member it stopped.
Desired behavior
Four contract points, in order of how much they unlock.
- Address a delegated task. A way to send a message to one delegated task and to receive
its answer, addressed by its session id (the id is already known to the client — the tree
and the tool call output carry it). The same shape asmcode/session/steer, but with a
child as the target. - Stop one delegated task. Stopping a delegated task must not stop its parent: the
parent may still be waiting for the answer, and the point of the delegated task is that it
can end on its own. The runtime already distinguishes the two. - Read the transcript of a delegated task. Read-only access to what the delegated task
did and said. Without it there is nothing to show in a panel opened for that task. - Do not silently ignore what a call says. If a method receives a target it does not
support, it should say so rather than answer for a different target.
Acceptance criteria
- A client can send a message to a running delegated task and gets its answer, without the
parent's turn being affected. - A client can stop one delegated task; the parent session stays usable and its own turn is
not cancelled by that call. - A client can read the transcript of a delegated task in a read-only manner.
mcode/session/delegation/stopeither stops what the caller named, or rejects a target it
cannot honour with an explicit error. Silently stopping the whole tree and reporting a
receipt is not acceptable.- The existing behaviour of the tree methods is unchanged:
delegation/getstill answers for
the root,delegation/stopstill stops the tree.
Platform
Multiple platforms
Alternatives and additional context
- A separate method per action (
delegation/message,delegation/stop_child,delegation/attach)
is fine as long as the target is explicit and the answer says which task it acted on. - The desktop app already shows delegated tasks as an agent team and can stop one of them; the
client side of this problem is tracked in the Paseo repository:
bug: the subagent finish notification cancels the busy parent's turn and then fails with -32603 (ACP provider) getpaseo/paseo#8300 — it tracks the client side, but a client cannot
stop one delegated task over ACP while the methods above do not exist. - This request is about the ACP surface for delegated tasks. The queue of messages for a
session is a separate concern and is tracked separately.
Activity