feat: add hooks system for agent lifecycle events#1601
feat: add hooks system for agent lifecycle events#1601Raghavendiran-2002 wants to merge 1 commit intokagent-dev:mainfrom
Conversation
Signed-off-by: Raghavendiran-Github <raghavendiran46461@gmail.com>
There was a problem hiding this comment.
Pull request overview
This PR implements a hooks system for kagent agents, enabling agent developers to extend agent behavior through lifecycle hooks (PreToolUse, PostToolUse, SessionStart, SessionEnd) without modifying the kagent core. Hooks are loaded from OCI container images and communicate via the "claude-command" protocol (JSON stdin/stdout).
Changes:
- Added CRD types for hooks (HookSpec, HookEventType, HookProtocolType) with Go and Python serialization
- Implemented hooks init container builder that deduplicates OCI refs and mounts hook images into
/hooks - Created Python runtime hooks system with subprocess execution, regex matching, and callback composition with approval callbacks
- Integrated hooks into agent lifecycle (SessionStart/SessionEnd) via the agent executor
- Updated CRD and Helm chart definitions
- Added comprehensive test data for end-to-end validation
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| go/api/v1alpha2/agent_types.go | CRD types for hooks with validation |
| go/api/adk/types.go | Go serialization of HookConfig |
| go/core/internal/controller/translator/agent/adk_api_translator.go | Hooks init container builder and config translation |
| go/core/internal/controller/translator/agent/hooks-init.sh.tmpl | Shell script template for OCI image mounting |
| go/core/pkg/env/kagent.go | Added KAGENT_HOOKS_FOLDER env var |
| python/packages/kagent-adk/src/kagent/adk/types.py | Python HookConfig and hooks integration with Agent |
| python/packages/kagent-adk/src/kagent/adk/_hooks.py | New hook runtime with subprocess execution and callbacks |
| python/packages/kagent-adk/src/kagent/adk/_agent_executor.py | SessionStart/SessionEnd hook invocation |
| python/packages/kagent-adk/src/kagent/adk/cli.py | Setting hooks on agent instance |
| helm/kagent-crds/templates/kagent.dev_agents.yaml | Updated CRD schema |
| go/api/config/crd/bases/kagent.dev_agents.yaml | Updated CRD schema |
| go/core/internal/controller/translator/agent/testdata/ | Test data for hooks validation |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| """Return True if the hook's matcher regex matches tool_name, or no matcher is set.""" | ||
| if not hook.matcher: | ||
| return True | ||
| return bool(re.search(hook.matcher, tool_name)) |
There was a problem hiding this comment.
The _matches_tool function uses re.search() without error handling. If a user provides an invalid ECMAScript regex pattern in the hook's matcher field, this will raise a re.error exception and crash the tool callback, causing the agent to fail. Invalid regex patterns should be caught and logged, with the hook treated as non-matching or skipped to ensure the agent continues operating.
| return bool(re.search(hook.matcher, tool_name)) | |
| try: | |
| return bool(re.search(hook.matcher, tool_name)) | |
| except re.error as exc: | |
| logger.warning( | |
| "Invalid regex in hook.matcher %r for tool %r: %s", | |
| hook.matcher, | |
| tool_name, | |
| exc, | |
| ) | |
| # Treat invalid matcher as non-matching so the hook is effectively skipped. | |
| return False |
Summary
Closes #1564
Implements a hooks system for kagent agents, similar to Claude Code / opencode hooks. This allows agent developers to
extend agent behavior (memory, PII redaction, tool policy, notifications, etc.) without modifying kagent core.
What's added
New CRD fields — hooks field on AgentSpec with HookSpec type supporting PreToolUse, PostToolUse,
SessionStart, and SessionEnd events
OCI container mounting — hooks are loaded from OCI images via an hooks-init init container into /hooks/,
reusing the same pattern as Skills. Duplicate refs are deduplicated (same image mounted once)
claude-command protocol — hooks read JSON from stdin, write JSON to stdout (or exit code 2 for errors).
PreToolUse hooks can approve or block tool calls
Python runtime integration — hooks are wired into ADK callbacks (before_tool_callback, after_tool_callback)
and session lifecycle points
Example agent spec
spec:
hooks:
- ref: ghcr.io/org/security-hooks:v1.0
event: PreToolUse
type: claude-command
matcher: "bash|shell_exec"
command: check-tool-use.sh
- ref: ghcr.io/org/security-hooks:v1.0
event: SessionStart
type: claude-command
command: inject-session-metadata.py
Files changed
callbacks, session hooks)
Test plan
volume/env/config output