feat: allow to emit end exchange event from client for stopping response#510
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds a client-facing “end exchange” capability to the Conversational Agent SDK so callers can explicitly stop an in-progress response by ending an exchange via a dedicated REST endpoint, while keeping the returned exchange shape consistent with existing exchange retrieval APIs.
Changes:
- Added a new
EXCHANGE_ENDPOINTS.END(...)endpoint constant and anExchangeService.end(conversationId, exchangeId)method (telemetry-tracked) that POSTs to it and returns a transformed exchange. - Extended exchange models/types to include an optional
endedAttimestamp and introducedExchangeEndResponseas an alias ofExchangeGetResponse. - Added unit coverage for both the service method (
exchanges.end) and the conversation-scoped delegate (conversation.exchanges.end), plus documented OAuth scope requirements.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| tests/unit/services/conversational-agent/exchanges.test.ts | Adds unit tests validating the new ExchangeService.end behavior, transformation, and error handling. |
| tests/unit/models/conversational-agent/conversations.test.ts | Adds tests ensuring conversation.exchanges.end() delegates correctly and validates required prerequisites. |
| src/utils/constants/endpoints/conversational-agent.ts | Introduces the /end exchange endpoint builder. |
| src/services/conversational-agent/conversations/exchanges.ts | Implements ExchangeService.end() with telemetry and transformation. |
| src/models/conversational-agent/conversations/types/core.types.ts | Adds endedAt?: string to the Exchange model. |
| src/models/conversational-agent/conversations/exchanges.types.ts | Adds ExchangeEndResponse type alias. |
| src/models/conversational-agent/conversations/exchanges.models.ts | Extends service model interfaces to include end(...). |
| src/models/conversational-agent/conversations/conversations.models.ts | Adds conversation-scoped exchanges.end(exchangeId) delegate method. |
| docs/oauth-scopes.md | Documents OAuth scopes required for end(). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Review findingsNew inline comment posted:
Missing integration test (no file exists): Per CLAUDE.md ( |
Review findingsNew inline comment posted:
Still outstanding from previous review: Per |
|
✅ No issues found. Checked for bugs and CLAUDE.md compliance. |
Review findingsNew inline comments posted this run:
Still outstanding from previous review: Per |
| /** | ||
| * Ends an exchange, setting the endedAt timestamp and stopping any running agent job | ||
| * | ||
| * @internal |
There was a problem hiding this comment.
Since we are adding the scopes on OAuth lets change this to @experimental
|
✅ No issues found. Checked for bugs and CLAUDE.md compliance. |
|
✅ No issues found. Checked for bugs and CLAUDE.md compliance. |
Review findingsNew inline comment posted this run:
|
Review findingsNew inline comment posted this run:
|
|
✅ No issues found. Checked for bugs and CLAUDE.md compliance. |
|
Hm, I thought we were going with the event-through-websocket approach? It seems like this is using the API rather than the end-event? |
@maxduu Edit: Actually it seems like endExchange was already set up through the websocket - it was just ignored by CAS, so we shouldnt need to add anything here (it's just handled in CAS now instead of a no-op) |
Review findingsNew inline comment posted this run:
|
|
✅ No issues found. Checked for bugs and CLAUDE.md compliance. |
|
✅ No issues found. Checked for bugs and CLAUDE.md compliance. |
1 similar comment
|
✅ No issues found. Checked for bugs and CLAUDE.md compliance. |
|



Adds tests demonstrating client-side exchange termination via
sendExchangeEnd()onExchangeStream. This validates that the existing WebSocket event path correctly supports the stop-response flow added in UiPath/AgentInterfaces#1018, where CAS now handles clientendExchangeevents by ending the exchange in DB and killing the running Orchestrator job.What changed:
onExchangeEndhandler firing on client-initiated stop (echo mode)Why no REST API
end()method:The WebSocket
sendExchangeEnd()is the consistent pattern — all other exchange lifecycle operations (start, message, tool calls) use the WebSocketConversationEventprotocol, not REST. The CAS PR wired up the server-side handler for clientendExchangeevents, making the existing SDK method fully functional for stop-response without needing a new HTTP endpoint.