
Mastering Agent Hooks in Kiro: Event-Driven Automation for Professional Workflows
Agent Hooks are Kiro's mechanism for event-driven developer automation, they intercept the IDE events, file saves, tool invocations, spec task transitions and execute agent prompts or shell commands in response behavior. This web post will cover the hook lifecycle, advanced patterns with Pre/Post Tool Use, composition strategies, and production-hardened configurations for teams building on AWS.
Introduction
If you’ve been playing around with Kiro, you probably already realized it’s not just another tool for spitting out lines of code. That spec-driven flow, moving from requirements to design and then into tasks, actually gives some much-needed sanity to agentic coding.
But let’s be real: once you’re knee-deep in implementation, you hit a wall. How do you actually keep the quality high and stop yourself from doing the same boring, repetitive tasks without having to "babysit" the agent with manual prompts every five minutes?
That’s exactly why Agent Hooks exist!
If you’re coming from the AWS world, the easiest way to wrap your head around Hooks is to think of them as CloudWatch Events rules, but living right inside your IDE.
They follow that same event-driven pattern we’re all used to in production: you’ve got an event source (something happening in your editor), a filter to catch the right moment, and a target action to get things done. Instead of constant manual input, you use declarative JSON to automate the boring stuff and keep your workflow on track.
Indice
- Important Notes!
- How Hooks Work
- What the Hook Schema looks like, being small by design.
- Scenarios for Using Event Hooks
- Best Practices Summary (Golden Tips here, don't miss them)
- Hook Lifecycle: Understanding Execution Order
- Conclusion
1) Important Notes!
Kiro Agent Hooks are a local mechanism inside the IDE that reacts to editor events (saving a file, invoking a tool, completing a task);
They are designed to eliminate manual and repetitive tasks. Instead of you asking the AI to review your code every time, the editor itself intelligently triggers the action in the background.
2) How Hooks Work
The lifecycle of a Kiro Hook is based on three main components:
- Trigger:
The event monitored by the IDE (e.g., saving, creating, or deleting files; before or after running a tool, or the completion of a task).
Example :fileEdited,promptSubmit,preToolUse, etc. - Filtered Pattern:
The scope of affected files, it's usually defined by rules (glob)
Example :src/**/*.ts - Action:
The executed behavior, which can be a prompt interpreted by the AI agent (askAgent) or a direct command in the system terminal (runCommand).
So, what is the difference between runCommand and askAgent?
This is a critical architectural decision that impacts cost, latency, and determinism. Right?
runCommand (Shell Command)
Use runCommand for anything that can be codified into a script;
- Deterministic execution, no LLM credits consumed;
- Ideal for: linters, formatters, test runners, curl calls, scripts;
- Exit code 0 → stdout added to agent context;
- Non-zero exit → stderr sent to agent + blocks tool (for Pre Tool Use);
- Default timeout: 60 seconds, but configurable, and 0 to disable;
askAgent (Agent Prompt)
Reserve askAgent for tasks that genuinely need reasoning over context;
- Sends a prompt to the LLM for contextual reasoning;
- Ideal for: code review, refactoring suggestions, policy enforcement that requires judgment;
- Consumes credits per invocation;
- More flexible but slower and non-deterministic;
3) What the Hook Schema looks like, being small by design.
Being small by design, the Kiro Hook schema typically takes the form of a minimalist and declarative configuration file, using JSON or YAML.
Below is an example of what this structure looks like in a clean and straightforward way:
JSON Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"name": "The hook name",
"version": "1.0.0",
"description": "The description of what this event hook does",
"when": {
"type": "<event_type>", //example:fileEdited
"patterns": ["<glob_patterns>"], //example: *.txt or *.ts and etc.
"toolTypes": ["<tool_categories_or_regex>"] //example:write, read, *
},
"then": {
"type": "askAgent | runCommand", //only both options
"prompt": "Instructions for the agent",
"command": "shell command to execute" //example: npm run dev
}
}YAML Example
1
2
3
4
5
6
7
8
9
10
11
12
13
name: "The hook name"
version: "1.0.0"
description: "The description of what this event hook does"
when:
type: "<event_type>" # example: fileEdited
patterns:
- "<glob_patterns>" # example: *.txt or *.ts and etc.
toolTypes:
- "<tool_categories_or_regex>" # example: write, read, *
then:
type: "askAgent | runCommand" # only both options
prompt: "Instructions for the agent"
command: "shell command to execute" # example: npm run devTo maintain clarity and keep this post to an acceptable length, I will continue using examples exclusively in JSON format, it's just my preference! :)
Ok, let's start to detail some fields that need to be filled.
EVENT TYPE
| Event Type | Fires When | Key Use Case |
|---|---|---|
| fileEdited | User saves a file | Lint, format, sync i18n |
| fileCreated | New file appears in workspace | Generate boilerplate, add headers |
| fileDeleted | File is removed | Clean up imports, orphan detection |
| promptSubmit | User sends a message to agent | Context injection, policy enforcement |
| agentStop | Agent completes a turn | Post-execution validation, security scan |
| preToolUse | Before a tool executes | Access control, write guardrails |
| postToolUse | After a tool executes | Audit logging, output validation |
| preTaskExecution | Spec task starts | Environment prep, prerequisite checks |
| postTaskExecution | Spec task completes | Run tests, generate docs |
| userTriggered | Manual click by user | On-demand reviews, one-off tasks |
TOOL TYPES
| Built-in categories | Prefix filters |
|---|---|
| read : file read tools | @mcp : all MCP tools |
| write : file write/create tools | @powers : all Powers tools |
| shell : terminal command tools | @builtin : all built-in tools |
| web : web search and fetch tools | - |
| spec : spec manipulation tools | - |
| * : everything | - |
4) Scenarios for Using Event Hooks
We will move forward with some practical examples that can be used in the daily workflows of Architects, Developers, Testers, and other Kiro users.
- Example: Automated Test Generation on Save
This hook will trigger on every save, which can consume a lot of credits if the developer saves frequently (compulsive Ctrl+S). A more cost-effective alternative would be to usepostTaskExecutionto generate tests only when a spec task is completed, oruserTriggeredto run on demand.
1
2
3
4
5
6
7
8
9
10
11
12
13
{
"name": "Auto Generate Tests",
"version": "1.0.0",
"description": "Automatically write missing unit tests when a new service file is edited",
"when": {
"type": "fileEdited",
"patterns": ["src/services/**/*.ts"]
},
"then": {
"type": "askAgent",
"prompt": "Review the edited service file. If a corresponding .test.ts file does not exist or lacks coverage for the new logic, generate or update the tests using Jest with the new unit test."
}
}
- Example: Database Migration Safety Check
1
2
3
4
5
6
7
8
9
10
11
12
13
{
"name": "Guardrail for DB Migrations",
"version": "1.0.0",
"description": "Intercept write operations to prevent destructive SQL actions in migration files",
"when": {
"type": "preToolUse",
"toolTypes": ["write"]
},
"then": {
"type": "askAgent",
"prompt": "Check if this write targets a file in db/migrations/ or migrations/. If it does, analyze the content for destructive actions like DROP COLUMN, DROP TABLE, TRUNCATE, or DELETE without WHERE. If any are found, alert the user with the specific risk and do NOT proceed. If the file is not a migration, proceed normally."
}
}- Auto-Installing Dependencies on Config Change
Here is an example that I love to use in Kiro, this is so helpful.
1
2
3
4
5
6
7
8
9
10
11
12
13
{
"name": "Sync Project Dependencies",
"version": "1.0.0",
"description": "Run package manager install automatically when dependency files change",
"when": {
"type": "fileEdited",
"patterns": ["package.json", "package-lock.json"]
},
"then": {
"type": "runCommand",
"command": "npm install"
}
}
- Test After Spec Task Completion
1
2
3
4
5
6
7
8
9
10
11
{
"name": "Run Tests After Task",
"version": "1.0.0",
"when": {
"type": "postTaskExecution"
},
"then": {
"type": "runCommand",
"command": "npm run test -- --run"
}
}
- Security Scanner on Agent Completion
1
2
3
4
5
6
7
8
9
10
11
12
{
"name": "Security Scan",
"version": "1.0.0",
"description": "Scan for secrets and vulnerabilities after agent makes changes",
"when": {
"type": "agentStop"
},
"then": {
"type": "askAgent",
"prompt": "Review all changed files for: 1) API keys, tokens, or credentials in source code, 2) Private keys or sensitive data, 3) Hardcoded internal URLs, 4) Database connection strings. Flag any findings with severity and remediation steps."
}
}
- Validate IaC before the agent writes to CDK/Terraform files
I also really like this event hook because it helps maintain the quality of your IaC, and the same concept can be applied to other types of documents.
1
2
3
4
5
6
7
8
9
10
11
12
13
{
"name": "IaC Safety Check",
"version": "1.0.0",
"description": "Validate infrastructure code against AWS best practices before writing",
"when": {
"type": "preToolUse",
"toolTypes": ["write"]
},
"then": {
"type": "askAgent",
"prompt": "If this write targets a file in infra/, cdk/, or terraform/, validate: 1) No resources are created with public access unless explicitly required, 2) All S3 buckets have encryption enabled, 3) No IAM policies use wildcard (*) on both Action and Resource, 4) Security groups do not allow 0.0.0.0/0 on sensitive ports. If violations are found, block the write and explain the risk. If the file is not infrastructure code, proceed normally."
}
}
5) Best Practices Summary (Golden Tips here, don't miss them)
Let's talk about best practices. Here you can find a group of actions that need attention.
Design Principles:
- Single Responsibility:
Imagine an Event Hook is like a specialized employee on your team. If you hire an electrician, you don't ask them to fix the plumbing and paint the wall at the same time. In Kiro, the rule is the same. (Do not mix linting + testing + formatting into a single Hook) - Prefer runCommand over askAgent
I like to say "Use brawn, not brains", It's funny, right? let me explain, If you can write a script or a terminal command to do the task, use always "runCommand". Never waste AI tokens on what the shell can handle. - Be specific with patterns
In Kiro, thepatternfield (or GLOB filter) tells the Hook which files it should watch. The golden rule here is "Be as specific as possible with the path (hit the bullseye)".
- Set appropriate timeouts
In Kiro, every Event Hook has an execution timeout. If the task does not finish within this timeframe, the IDE aborts the process. The golden rule is "Customize the timer based on the task's effort. Do not leave everything at the default setting". - Test incrementally
Creating an Event Hook and deploying it straight to the entire project is like building a brand-new rocket engine and testing it directly on the launchpad with a crew on board. The golden rule in Kiro is: Start by testing on a single, isolated file, validate the behavior, and only then expand the scope. - Security Considerations
The promptSubmit event allows you to intercept the exact text a user typed into the AI chat before it is processed. This text is stored in an environment variable called $USER_PROMPT.
If you are going to take $USER_PROMPT and pass it to a terminal command (runCommand), you must sanitize the content of this prompt before anything else. Treat all human input as dangerous, and you will always succeed!" - Limit Pre Tool Use hooks
It means that when the AI decides to use a tool, such as reading or saving a file, the Kiro IDE pauses the AI agent and waits for your Hook to give the 'green light'.
Pro Tip: Set a strict limit on these types of Hooks and ensure they run ultra-fast. A poorly configured pre-tool Hook can completely freeze your workflow." - Review hook configurations in version control
All Kiro Event Hooks are saved in the ".kiro/hooks/" folder, right at the root of your project.
The absolute golden rule here is: 'Add this folder to your Git repository and commit all Hooks'. - Team Collaboration
Sharing Kiro Hooks in the repository means creating a unified path for the team. If everyone plays the same game, everyone needs to follow the same rules. The golden rule here is "Hooks in the repository ensure that the quality standard of a senior developer is automatically applied to a junior developer". - Document hook purpose and expected behavior
The Hook JSON configuration files have a native field called "description", It doesn't change how the code runs, but it completely changes how you manage the project. The golden rule here is "Please, never create a Hook with a blank description field, your future self a few months from now will thank you deeply"; - Version your hooks
Event Hooks natively include a field calledversion. It is used to track the evolution of that automation over time. The absolute golden rule here is: Whenever you change the behavior, a command flag, or the scope of a Hook, bump the version number. Never leave it blank or stagnant at1.0.0. - Disable, don't delete
In the Kiro control panel, there is an eye toggle icon next to each listed Event Hook. The golden rule when an automation gets in your way is: Disable the Hook via the IDE panel. Never delete the JSON file from the.kiro/hooks/folder just because you don't need it at this exact second.

6) Hook Lifecycle: Understanding Execution Order
When multiple hooks could fire on the same event, you will need to understand the execution order.

For spec-driven workflows, the workflow is executed between PreTaskExecutionHooks and PostTaskExecutionHooks, after the Spec Driven workflow initiation.

This ordering means you can build layered policies: inject context at prompt time, guard tool access, validate results, and verify task completion, each at the appropriate stage.
7) Conclusion
When I first started exploring Agent Hooks, I'll admit I thought: "just another nice feature in the docs that I'll never actually use day to day." I was wrong.
The first time a preToolUse hook intercepted a write with hardcoded credentials that I myself had missed, before it ever became a commit, I understood the real potential. It's like having a teammate who never sleeps, never forgets, and is never too shy to call you out.
What truly excites me is the composition. You start with a simple hook, a lint on save, a post-task test run, then you realize you can chain them, inject context at prompt time, guard writes to infrastructure files, sync translations automatically. Each hook is small and focused, but together they form a quality pipeline that runs silently while you focus on what matters.
The best part is that you can share your Agent Hooks, because it all lives in your project repository, so when a new developer joins the team, they inherit the same guardrails. No manual onboarding, and no "remember to run lint before committing." The process becomes code.
Nowadays, agent hooks are part of my daily workflow, both in personal side projects and professional production codebases.
See you in the next post! :)
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article