The mechanism
Hooks let application code react at defined points in the agent lifecycle. They are useful for metrics, validation and policy integration because they observe the actual loop rather than trying to infer behavior from the final answer. A before-tool event can identify the requested operation; an after-tool event can record an outcome. Neither should automatically log the full payload.
For ParcelOps, the first hook records which tool was selected. It deliberately omits incident content and credentials. Later, a policy component may use authenticated request context to reject an operation. The destination service must still enforce its own authorization: a hook inside one application process should not be the only protection for a shared system.
A worked instrumentation hook
Local configuration; inference occurs only when the agent is invoked. The current Python API supports registering a typed callback with agent.add_hook. This example is observation only and does not claim to enforce a deny policy.
from strands import Agent
from strands.hooks import BeforeToolCallEvent
selected_tools = []
def record_selection(event: BeforeToolCallEvent) -> None:
selected_tools.append(event.tool_use["name"])
agent = Agent(model=model, tools=[lookup_incident], callback_handler=None)
agent.add_hook(record_selection, BeforeToolCallEvent)
In a real service, use a request-scoped sink rather than a shared global list. The global list is intentionally small teaching code. Concurrent requests otherwise mix evidence, and a long-lived process retains an ever-growing collection. Attach a correlation identifier supplied by trusted middleware and limit what is retained.
Hook ordering and supported mutations are API-specific. Before writing a policy hook, inspect the event reference for your pinned release and test the exact behavior. Do not invent a deny=True field because another framework uses it. A hook that records “denied” while the tool still executes is worse than a clearly missing control.
Practice: prove observation and enforcement separately
Offline design. Draw two test cases. In the first, a harmless read runs and produces a selection event. In the second, a proposed write is denied by your application policy and a spy implementation confirms zero calls. The second assertion is the critical evidence: a log line alone cannot prove prevention.
Expected observation: an audit event and an enforcement decision are distinct artifacts. The audit should record a stable policy outcome and request reference; the executor should receive nothing when access is denied. Add a case where the audit sink is unavailable and decide whether the operation fails closed or continues under an explicitly documented policy.
Finally, test that redaction occurs before data enters the log sink. Redacting only the displayed dashboard leaves sensitive values in storage and exports. Use synthetic secret-shaped strings as canaries, not real credentials.
Troubleshooting and trade-offs
A callback that performs slow network work can increase every tool call’s latency. Prefer bounded local collection and an approved asynchronous export path where appropriate. A callback that raises unexpectedly may disrupt the loop; decide which errors should stop work and test that behavior.
Too many independent hooks can create hidden ordering dependencies. Document each hook’s purpose, data access and failure behavior. Keep business authorization centralized enough that reviewers can understand it, while retaining destination checks as a separate boundary.
Interview practice
How do you prove a deny policy actually prevented a tool call?
Use a controlled spy or authoritative destination record to verify that the implementation was not invoked. Correlate the denied decision with the request. A policy log alone is insufficient.
What should a hook log by default?
Minimal metadata such as request reference, tool name, duration and outcome category. Payload capture should be separately justified, redacted and access-controlled.
Completion check
Explain one observation hook and one enforcement test without confusing them. Define what happens if logging fails, and identify the destination authorization that remains necessary.
Sources and version notes
Checked 6 October 2026. Python examples target strands-agents==1.58.0 unless labelled otherwise. Live documentation can change; compare your installed version before adapting an example.
Make the understanding yours.
Use the completion check above. Mark this chapter when you can explain the mechanism and its limits.
Self-assessed reading progress. This does not certify that a lab ran or a system is secure.