~/.deepagents/hooks.json and it pipes a JSON payload to each matching command’s stdin whenever an event fires.
Hooks run fire-and-forget in a background thread. They never block Deep Agents Code and failures are logged without interrupting your session.
Setup
Create~/.deepagents/hooks.json:
~/deepagents-events.log.
Hook configuration
The config file contains a singlehooks array. Each entry has:
Command and arguments to run. No shell expansion: use
["bash", "-c", "..."] if needed.Event names to subscribe to. Omit or leave empty to receive all events.
events filter, so it receives every event Deep Agents Code emits.
Payload format
Each hook command receives a JSON object on stdin with an"event" key plus event-specific fields:
Events reference
session.start
Fired when an agent session begins (both interactive and non-interactive modes).
The session thread identifier.
session.end
Fired when a session exits.
The session thread identifier.
user.prompt
Fired in interactive mode when the user submits a chat message.
No additional fields.
input.required
Fired when the agent requires human input (human-in-the-loop interrupt).
No additional fields.
permission.request
Fired before the approval dialog when one or more tool calls need user permission.
Names of the tools requesting approval.
tool.error
Fired when a tool call returns an error.
Names of the tool(s) that errored.
task.complete
Fired when the agent finishes its current task (the streaming loop ends without further interrupts).
The session thread identifier.
context.compact
Fired before Deep Agents Code compacts (summarizes) the conversation context.
No additional fields.
Execution model
- Background thread: Hook subprocesses run in a thread via
asyncio.to_threadso the main event loop is never blocked. - Concurrent dispatch: When multiple hooks match an event, they run concurrently in a thread pool.
- 5-second timeout: Each command has a 5-second timeout. Commands that exceed this are killed.
- Fire-and-forget: Errors are caught per-hook and logged at debug/warning level. A failing hook never crashes or stalls Deep Agents Code.
- Lazy loading: The config file is read once on the first event dispatch and cached for the rest of the session.
- No shell expansion: Commands are executed directly (not through a shell). Wrap in
["bash", "-c", "..."]if you need shell features like pipes or variable expansion.
Hook examples
Log all events to a file
Log all events to a file
Desktop notification on task completion (macOS)
Desktop notification on task completion (macOS)
Python handler
Python handler
Write a handler script that reads the JSON payload from stdin:
my_handler.py
~/.deepagents/hooks.json
Security considerations
Hooks follow the same trust model as Git hooks or shell aliases — any user who can write to~/.deepagents/hooks.json can execute arbitrary commands. This is by design:
- No command injection: Payload data flows only to stdin as JSON, never to command-line arguments.
json.dumpshandles escaping. - No shell by default: Commands run with
shell=False, preventing shell injection. - Malformed config: Invalid JSON or unexpected types produce logged warnings, not security issues.
See also
Connect these docs to Claude, VSCode, and more via MCP for real-time answers.

