sdk: Expose AgentStop session hook across languages - #2054
Merged
Conversation
The runtime already fires the top-level agent's `agentStop` hook and
registers it for SDK callback sessions (REGISTERED_CALLBACK_EVENT_NAMES),
with a working block/continue re-prompt loop, but the Node SDK never
exposed it: SessionHooks had no `onAgentStop` and `_handleHooksInvoke`
had no dispatch entry, so `agentStop` callbacks were silently dropped.
Add the AgentStopHookInput/Output/Handler types, the `onAgentStop` field
on SessionHooks, and the `agentStop` entry in the hook dispatcher.
Returning `{ decision: "block", reason }` keeps the agent running with
`reason` enqueued as a follow-up message (e.g. to remediate findings a
handler surfaced); returning nothing lets the agent stop.
This unblocks the Copilot cloud agent restoring its post-completion
security-tool hooks (dependabot / secret scanning) on the proper platform
hook rather than ad-hoc per-commit hooks.
Note: parallel changes for the Python/Go/.NET SDKs are follow-ups.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 2031e02b-7fe5-4075-9d75-eb20eb29f407
Contributor
There was a problem hiding this comment.
Pull request overview
Exposes the Node.js SDK’s top-level agentStop lifecycle hook.
Changes:
- Adds typed agent-stop input, output, and handler APIs.
- Routes
agentStopcallbacks through the session dispatcher. - Adds dispatcher and JSON-RPC unit tests.
Show a summary per file
| File | Description |
|---|---|
nodejs/src/types.ts |
Defines the agent-stop hook API. |
nodejs/src/session.ts |
Dispatches agent-stop callbacks. |
nodejs/test/client.test.ts |
Tests direct and JSON-RPC dispatch. |
Review details
- Files reviewed: 3/3 changed files
- Comments generated: 3
- Review effort level: Medium
Add AgentStop types and dispatch support for Python, Go, .NET, Rust, and Java, and normalize the Node stop_hook_active wire field. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4f4d61ce-6d2f-4b72-a2da-52f60300df59
Export Node hook types, document the hook, cover wire-field normalization, add Go and .NET E2E block-continuation coverage, and format the Python README. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4f4d61ce-6d2f-4b72-a2da-52f60300df59
Document the public input member names for Node, Python, Go, .NET, Rust, and Java. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4f4d61ce-6d2f-4b72-a2da-52f60300df59
belaltaher8
marked this pull request as ready for review
July 28, 2026 02:50
The Python README formatting now exists on main independently, so merge the updated base to keep it out of this PR's effective diff. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add Node, Python, Rust, and Java replay tests for natural-stop callback delivery and block-driven continuation using the shared hooks_extended snapshot. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Apply Ruff formatting to the new replay test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Review details
Comments suppressed due to low confidence (1)
docs/hooks/hooks-overview.md:267
- The docs style requires a colon between a list-item label and its description (
.github/instructions/docs-style.instructions.md:79-82), rather than a spaced hyphen. Please use the prescribed separator here.
* **[Agent Stop Hook](./session-lifecycle.md#agent-stop)** - Validate completion before the agent stops
- Files reviewed: 32/32 changed files
- Comments generated: 0 new
- Review effort level: Medium
Contributor
There was a problem hiding this comment.
Review details
Comments suppressed due to low confidence (1)
docs/hooks/hooks-overview.md:267
- The docs style guide requires a colon, not a spaced hyphen, between a labeled list item and its description. Please keep this new guide entry compatible with the docs normalization conventions.
* **[Agent Stop Hook](./session-lifecycle.md#agent-stop)** - Validate completion before the agent stops
- Files reviewed: 32/32 changed files
- Comments generated: 0 new
- Review effort level: Medium
Match Spotless and nightly rustfmt output for the AgentStop replay tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Review details
Comments suppressed due to low confidence (1)
docs/hooks/hooks-overview.md:267
- The docs style guide requires a colon between a labeled list item and its description, rather than a spaced hyphen. Use a colon here so this new guide entry follows the
docs/formatting rules.
* **[Agent Stop Hook](./session-lifecycle.md#agent-stop)** - Validate completion before the agent stops
- Files reviewed: 32/32 changed files
- Comments generated: 0 new
- Review effort level: Medium
SteveSandersonMS
enabled auto-merge
July 28, 2026 12:58
SteveSandersonMS
approved these changes
Jul 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Exposes the top-level agent's
agentStoplifecycle hook across the Node.js, Python, Go, .NET, Rust, and Java SDKs.The Copilot CLI runtime already fires
agentStopwhen the top-level agent reaches a natural terminal stop and supports a block/continue loop: returning{ decision: "block", reason }enqueuesreasonas a follow-up message, while consecutive blocks are capped to prevent runaway loops. This PR adds the missing public SDK types and callback dispatch paths.Changes
agentStopthrough each language's existinghooks.invokecallback transport.stop_hook_activewire field to Node's publicstopHookActivefield.SessionHooksfrom the package root.Motivation
This enables SDK consumers, including Copilot cloud coding agent integrations, to run completion checks at the natural end of an agent turn and request remediation through the platform hook instead of relying on ad-hoc commit-boundary callbacks.
Behavior
Returning no decision allows the agent to stop normally. Returning:
{ "decision": "block", "reason": "Run final validation and fix any failures." }keeps the agent running with the reason as a follow-up prompt. Consumers can use the active-stop flag (
stopHookActive, with language-appropriate casing) to avoid repeatedly blocking a continuation turn.Related: github/copilot-agent-runtime#13230