Module 34: Extension Methods
Add your own_-prefixed requests and notifications to ACP, in both directions, typed and raw: builder handlers, annotations, and the senders on all four facades.
What You’ll Learn
- Why a custom method name must start with
_, and what happens if it doesn’t @ExtRequestand@ExtNotificationon an annotated agent, the recommended way in- The builder-API equivalent, typed (
TypeRef) or raw (the plain JSON value) - Sending with
sendExtRequest/sendExtNotificationfrom a client or an agent - What happens when nothing serves a method:
-32601for a request, silence for a notification
The Code
Naming the extension
A shared contract both sides agree on. ACP reserves every name without a leading_ for the protocol itself, so a custom method must start with it:
IllegalArgumentException before anything leaves the process, so an extension can never collide with or shadow a protocol method. Namespacing the rest of the name with a domain you control (_acptutorial/...) keeps it from colliding with someone else’s extension.
Serving, with annotations
_. A handler takes at most one params parameter (a record for typed params, Map<String, Object> for raw), plus, like any other annotated handler, the connection’s AcpSyncAgent/AcpAsyncAgent and NegotiatedCapabilities. An @ExtRequest’s return value is the result; returning null answers -32603. An @ExtNotification gets no answer at all, so it must return void, as log above does: building the agent rejects one that returns a value, naming the method.
The same handlers, with the builder API
null: a null result answers -32603; return an empty map when there’s nothing to say.
Calling the other side, from a prompt handler
ctx.client().sendExtRequest(Extensions.SELECTION, new SelectionQuery("src/Main.java"), new TypeRef<Selection>() {}) calls the same way agent.sendExtRequest(...) does above. Useful in a
builder prompt handler, which gets a PromptContext/SyncPromptContext either way, whether or not it
also takes the agent as a parameter.
Client: serving the agent’s calls, and calling back
What happens without a handler
A request nobody serves fails with
-32601 (method not found), the same as any unhandled protocol method. A notification nobody handles is silently ignored, since a notification has no response to fail. Both behaviors match the spec’s extensibility rules, not just this SDK’s convenience.