@@ -14,6 +14,9 @@ agent or client implementation into a connection:
1414 notification params are available as ` ctx.params ` . Agent handlers use ` ctx.client `
1515 for outbound calls to the client. Client handlers use ` ctx.agent ` for outbound
1616 calls to the agent.
17+ - Long-lived connection handles also expose the peer context. ` agent.connect(...) `
18+ returns an ` AgentConnection ` with ` connection.client ` , and ` client.connect(...) `
19+ returns a ` ClientConnection ` with ` connection.agent ` .
1720
1821` AgentSideConnection ` and ` ClientSideConnection ` still exist as deprecated
1922compatibility wrappers, but new code should use the app API.
@@ -24,8 +27,8 @@ compatibility wrappers, but new code should use the app API.
2427| -------------------------------------------------------------- | --------------------------------------------------------------------------- |
2528| ` new AgentSideConnection((conn) => new MyAgent(conn), stream) ` | ` acp.agent({ name }).onRequest(...).onNotification(...).connect(stream) ` |
2629| ` new ClientSideConnection((_agent) => client, stream) ` | ` acp.client({ name }).onNotification(...).connectWith(stream, async ...) ` |
27- | Store ` AgentSideConnection ` on your agent class | Use ` ctx.client ` in agent handlers |
28- | Store/use ` ClientSideConnection ` for outgoing agent calls | Use the ` ctx ` passed to ` connectWith ` |
30+ | Store ` AgentSideConnection ` on your agent class | Use ` ctx.client ` , ` connection.client ` , or ` agent.onConnect(...) ` |
31+ | Store/use ` ClientSideConnection ` for outgoing agent calls | Use the ` ctx ` passed to ` connectWith ` , or ` connection.agent ` |
2932| Return a response from an ` Agent ` or ` Client ` method | Return a response from the app request handler |
3033| Throw from implementation methods for JSON-RPC errors | Throw from an app handler |
3134| Manually create session and prompt requests | Prefer ` ctx.buildSession(...).withSession(...) ` for common prompt workflows |
@@ -34,6 +37,11 @@ Both `connect(...)` and `connectWith(...)` accept either a `Stream` or the app
3437for the other side of the connection. Use streams for production transports and
3538direct app connections for tests or in-process examples.
3639
40+ Use ` connectWith(...) ` for a scoped workflow where the callback owns the
41+ connection lifetime. Use ` connect(...) ` when the connection should stay open
42+ independently of one operation; the returned connection can observe closure,
43+ close the transport, and call the peer.
44+
3745## Migrating an Agent
3846
3947Previously, an agent usually implemented ` acp.Agent ` , stored the
135143 .connect (stream );
136144```
137145
146+ If your agent keeps connection-scoped state or sends notifications from
147+ background work, use the connection handle returned by ` connect(...) ` :
148+
149+ ``` ts
150+ class MyAgent {
151+ private client? : acp .AgentContext ;
152+
153+ bindClient(client ? : acp .AgentContext ): void {
154+ this .client = client ;
155+ }
156+
157+ async sendBackgroundUpdate(sessionId : acp .SessionId ): Promise <void > {
158+ await this .client ?.notify (acp .methods .client .session .update , {
159+ sessionId ,
160+ update: {
161+ sessionUpdate: " agent_message_chunk" ,
162+ content: { type: " text" , text: " Still working..." },
163+ },
164+ });
165+ }
166+ }
167+
168+ const implementation = new MyAgent ();
169+ const app = acp .agent ({ name: " my-agent" });
170+
171+ const connection = app .connect (stream );
172+ implementation .bindClient (connection .client );
173+ ```
174+
175+ For server-owned connections, such as an app passed to ` AcpServer ` , register
176+ ` onConnect(...) ` instead. The hook receives the same connection-scoped client
177+ context. ` AcpServer ` runs the hook after the client has completed ` initialize ` ,
178+ so messages sent by the hook cannot replace the initialize response:
179+
180+ ``` ts
181+ const implementation = new MyAgent ();
182+
183+ const app = acp .agent ({ name: " my-agent" }).onConnect ((connection ) => {
184+ implementation .bindClient (connection .client );
185+ connection .signal .addEventListener (" abort" , () => {
186+ implementation .bindClient (undefined );
187+ });
188+ });
189+ ```
190+
138191For JSON-RPC errors, throw from the handler:
139192
140193``` ts
@@ -232,7 +285,26 @@ const prompt = await acp
232285` connectWith ` owns the connection lifetime for the callback. When the callback
233286finishes or throws, the connection is closed. If you need the connection to stay
234287open independently of one operation, call ` connect(stream) ` and keep the
235- returned ` AcpConnection ` .
288+ returned ` ClientConnection ` :
289+
290+ ``` ts
291+ const connection = acp
292+ .client ({ name: " my-client" })
293+ .onNotification (acp .methods .client .session .update , (ctx ) =>
294+ client .sessionUpdate (ctx .params ),
295+ )
296+ .connect (stream );
297+
298+ try {
299+ await connection .agent .request (acp .methods .agent .initialize , {
300+ protocolVersion: acp .PROTOCOL_VERSION ,
301+ clientCapabilities: {},
302+ });
303+ } finally {
304+ connection .close ();
305+ await connection .closed ;
306+ }
307+ ```
236308
237309All protocol paths should be absolute. That includes ` cwd ` ,
238310` additionalDirectories ` , file-system request paths, terminal/tool-call
@@ -298,6 +370,19 @@ acp.client().onRequest(acp.methods.client.session.requestPermission, (ctx) => {
298370Agent handler contexts include ` params ` and ` client ` . Client handler contexts
299371include ` params ` and ` agent ` .
300372
373+ Connection handles expose those same peer contexts for connection-scoped work:
374+
375+ ``` ts
376+ const agentConnection = acp .agent ({ name: " my-agent" }).connect (stream );
377+ await agentConnection .client .notify (acp .methods .client .session .update , update );
378+
379+ const clientConnection = acp .client ({ name: " my-client" }).connect (stream );
380+ await clientConnection .agent .request (acp .methods .agent .session .new , {
381+ cwd: " /workspace/project" ,
382+ mcpServers: [],
383+ });
384+ ```
385+
301386The ` connectWith ` callback receives a ` ClientContext ` , usually named ` ctx ` ,
302387with ` request(...) ` and ` notify(...) ` for talking to the agent:
303388
0 commit comments