Hook Events
| Event | When | Can Block | Can Modify |
|---|
on_session_start | Before agent runs | Yes | No |
pre_tool_use | Before each tool call | Yes | Yes |
post_tool_failure | After a tool errors | No | No |
pre_query | Before LLM call | Yes | No |
post_response | After LLM responds | No | No |
file_changed | After file write | No | No |
on_error | On agent error | No | No |
hooks.yaml Config
# hooks/hooks.yaml
hooks:
on_session_start:
- script:check-auth.sh
description: "Verify user authorization"
pre_tool_use:
- script:validate-command.sh
description: "Block dangerous CLI commands"
post_tool_failure:
- script:notify-error.sh
post_response:
- script:log-response.sh
pre_query:
- script:rate-limit.sh
file_changed:
- script:track-changes.sh
on_error:
- script:incident-report.sh
stdin (JSON input):
{
"event": "pre_tool_use",
"session_id": "uuid",
"tool": "cli",
"args": {"command": "rm -rf /"}
}
stdout (output options):
{"action": "allow"}
{"action": "block", "reason": "Destructive command blocked"}
{"action": "modify", "args": {"command": "echo safe"}}
Programmatic Hooks (SDK)
// sdk-hooks.ts
for await (const msg of query({
prompt: "Deploy the service",
hooks: {
preToolUse: async (ctx) => {
if (ctx.toolName === "cli" && ctx.args.command?.includes("rm -rf"))
return { action: "block", reason: "Destructive command blocked" };
if (ctx.toolName === "write" && !ctx.args.path.startsWith("/safe/"))
return { action: "modify", args: { ...ctx.args, path: `/safe/${ctx.args.path}` } };
return { action: "allow" };
},
onError: async (ctx) => {
console.error(`Agent error: ${ctx.error}`);
},
},
})) { /* ... */ }
SDK hooks run before script hooks — if an SDK hook blocks, the script hook is never called. Both can run independently when the SDK hook allows.
Tools
Built-in and declarative tools the agent uses to act
Skills
Reusable task modules the agent learns and crystallizes over time
Workflows
Chain skills into deterministic, repeatable pipelines
SDK Reference
Embed GitAgent programmatically, including hook callbacks