1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
/// Event fired **before** a tool is executed, enabling validation, modification, or blocking.
///
/// This event provides complete visibility into the tool that's about to be executed,
/// allowing you to implement security policies, modify inputs, or collect telemetry
/// before any potentially dangerous or expensive operations occur.
///
/// # Use Cases
///
/// - **Security gates**: Block dangerous operations (file deletion, network access)
/// - **Input validation**: Ensure tool inputs meet schema or business rules
/// - **Parameter injection**: Add authentication tokens, user context, or default values
/// - **Rate limiting**: Track and limit tool usage per user/session
/// - **Audit logging**: Record who is calling what tools with what parameters
///
/// # Fields
///
/// - `tool_name`: The name of the tool about to execute (e.g., "Bash", "Read", "WebFetch")
/// - `tool_input`: The parameters that will be passed to the tool (as JSON)
/// - `tool_use_id`: Unique identifier for this specific tool invocation
/// - `history`: Read-only snapshot of the conversation history up to this point
///
/// # Example: Security Gate
///
/// ```rust
/// use open_agent::{PreToolUseEvent, HookDecision};
/// use serde_json::json;
///
/// async fn security_gate(event: PreToolUseEvent) -> Option<HookDecision> {
/// // Block all Bash commands containing 'rm -rf'
/// if event.tool_name == "Bash" {
/// if let Some(command) = event.tool_input.get("command") {
/// if command.as_str()?.contains("rm -rf") {
/// return Some(HookDecision::block(
/// "Dangerous command blocked for safety"
/// ));
/// }
/// }
/// }
/// None // Allow other tools
/// }
/// ```
///
/// # Example: Parameter Injection
///
/// ```rust
/// use open_agent::{PreToolUseEvent, HookDecision};
/// use serde_json::json;
///
/// async fn inject_auth(event: PreToolUseEvent) -> Option<HookDecision> {
/// // Add authentication header to all API calls
/// if event.tool_name == "WebFetch" {
/// let mut modified = event.tool_input.clone();
/// modified["headers"] = json!({
/// "Authorization": "Bearer secret-token"
/// });
/// return Some(HookDecision::modify_input(
/// modified,
/// "Injected auth token"
/// ));
/// }
/// None
/// }
/// ```
/// Event fired **after** a tool completes execution, enabling audit, filtering, or validation.
///
/// This event provides complete visibility into what a tool did, including both the input
/// parameters and the output result. Use this for auditing, metrics collection, output
/// filtering, or post-execution validation.
///
/// # Use Cases
///
/// - **Audit logging**: Record all tool executions with inputs and outputs for compliance
/// - **Output filtering**: Redact sensitive information from tool results
/// - **Metrics collection**: Track tool performance, success rates, error patterns
/// - **Result validation**: Ensure tool outputs meet quality or safety standards
/// - **Error handling**: Implement custom error recovery or alerting
///
/// # Fields
///
/// - `tool_name`: The name of the tool that was executed
/// - `tool_input`: The parameters that were actually used (may have been modified by PreToolUse hooks)
/// - `tool_use_id`: Unique identifier for this invocation (matches PreToolUseEvent.tool_use_id)
/// - `tool_result`: The result returned by the tool (contains either success data or error info)
/// - `history`: Read-only snapshot of conversation history including this tool's execution
///
/// # Example: Audit Logging
///
/// ```rust
/// use open_agent::{PostToolUseEvent, HookDecision};
///
/// async fn audit_logger(event: PostToolUseEvent) -> Option<HookDecision> {
/// // Log all tool executions to your audit system
/// let is_error = event.tool_result.get("error").is_some();
///
/// println!(
/// "[AUDIT] Tool: {}, ID: {}, Status: {}",
/// event.tool_name,
/// event.tool_use_id,
/// if is_error { "ERROR" } else { "SUCCESS" }
/// );
///
/// // Send to external logging service
/// // log_to_service(&event).await;
///
/// None // Don't interfere with execution
/// }
/// ```
///
/// # Example: Sensitive Data Redaction
///
/// ```rust
/// use open_agent::{PostToolUseEvent, HookDecision};
/// use serde_json::json;
///
/// async fn redact_secrets(event: PostToolUseEvent) -> Option<HookDecision> {
/// // Redact API keys from Read tool output
/// if event.tool_name == "Read" {
/// if let Some(content) = event.tool_result.get("content") {
/// if let Some(text) = content.as_str() {
/// if text.contains("API_KEY=") {
/// let redacted = text.replace(
/// |c: char| c.is_alphanumeric(),
/// "*"
/// );
/// // Note: PostToolUse hooks typically don't modify results,
/// // but you could log this for security review
/// println!("Warning: Potential API key detected in output");
/// }
/// }
/// }
/// }
/// None
/// }
/// ```
///
/// # Note on Modification
///
/// While `HookDecision` theoretically allows modification in PostToolUse hooks, this is
/// rarely used in practice. The tool has already executed, and most agents don't support
/// modifying historical results. PostToolUse hooks are primarily for observation and auditing.
/// Event fired **before** processing user input, enabling content moderation and prompt enhancement.
///
/// This event is triggered whenever a user submits a prompt to the agent, before the agent
/// begins processing it. Use this to implement content moderation, add context, inject
/// instructions, or track user interactions.
///
/// # Use Cases
///
/// - **Content moderation**: Filter inappropriate or harmful user inputs
/// - **Prompt enhancement**: Add system context, timestamps, or user information
/// - **Input validation**: Ensure prompts meet format or length requirements
/// - **Usage tracking**: Log user interactions for analytics or billing
/// - **Context injection**: Add relevant background information to every prompt
///
/// # Fields
///
/// - `prompt`: The user's original input text
/// - `history`: Read-only snapshot of the conversation history before this prompt
///
/// # Example: Content Moderation
///
/// ```rust
/// use open_agent::{UserPromptSubmitEvent, HookDecision};
///
/// async fn content_moderator(event: UserPromptSubmitEvent) -> Option<HookDecision> {
/// // Block prompts containing banned words
/// let banned_words = ["spam", "malware", "hack"];
///
/// for word in banned_words {
/// if event.prompt.to_lowercase().contains(word) {
/// return Some(HookDecision::block(
/// format!("Content policy violation: contains '{}'", word)
/// ));
/// }
/// }
/// None // Allow clean prompts
/// }
/// ```
///
/// # Example: Automatic Context Enhancement
///
/// ```rust
/// use open_agent::{UserPromptSubmitEvent, HookDecision};
///
/// async fn add_context(event: UserPromptSubmitEvent) -> Option<HookDecision> {
/// // Add helpful context to every user prompt
/// let enhanced = format!(
/// "{}\n\n---\nContext: User timezone is UTC, current session started at 2025-11-07",
/// event.prompt
/// );
///
/// Some(HookDecision::modify_prompt(
/// enhanced,
/// "Added session context"
/// ))
/// }
/// ```
///
/// # Example: Usage Tracking
///
/// ```rust
/// use open_agent::{UserPromptSubmitEvent, HookDecision};
///
/// async fn track_usage(event: UserPromptSubmitEvent) -> Option<HookDecision> {
/// // Log every user interaction for analytics
/// println!(
/// "[ANALYTICS] User submitted prompt of {} characters at history depth {}",
/// event.prompt.len(),
/// event.history.len()
/// );
///
/// // Could also:
/// // - Update usage quotas
/// // - Send to analytics service
/// // - Check rate limits
///
/// None // Don't modify the prompt
/// }
/// ```
///
/// # Modification Behavior
///
/// If you return `HookDecision::modify_prompt()`, the modified prompt completely replaces
/// the original user input before the agent processes it. This is powerful but should be
/// used carefully to avoid confusing the user or the agent.