Skip to content

Conversation

@github-actions
Copy link

Motivation

Hook providers implementing input-side guardrails (PII detection, content moderation, prompt attack prevention) need access to input messages before they are added to the agent's conversation history. The BeforeInvocationEvent previously only provided a reference to the agent with no visibility into incoming messages, forcing guardrail implementations to hook on MessageAddedEvent instead—which runs after messages are already in memory and creates ordering dependencies with session/memory managers.

Resolves #8

Public API Changes

BeforeInvocationEvent now includes a writable messages attribute:

# Before: no access to input messages
class InputGuardrail(HookProvider):
    def register_hooks(self, registry: HookRegistry) -> None:
        registry.add_callback(BeforeInvocationEvent, self.check_input)
    
    async def check_input(self, event: BeforeInvocationEvent) -> None:
        # Could only access event.agent, no messages available
        pass

# After: can inspect and modify messages before processing
class InputGuardrail(HookProvider):
    def register_hooks(self, registry: HookRegistry) -> None:
        registry.add_callback(BeforeInvocationEvent, self.check_input)
    
    async def check_input(self, event: BeforeInvocationEvent) -> None:
        if event.messages is None:
            return
        for message in event.messages:
            if contains_pii(message["content"]):
                message["content"] = redact_pii(message["content"])

The messages attribute defaults to None for backward compatibility with deprecated code paths.

Use Cases

  • PII Redaction: Scan and redact sensitive information before messages are added to conversation history
  • Content Moderation: Filter toxic or inappropriate content before processing
  • Prompt Attack Prevention: Detect and block malicious prompt injection attempts early in the invocation lifecycle

docs/HOOKS.md Outdated
Comment on lines 25 to 70

## Input Guardrails with BeforeInvocationEvent

The `BeforeInvocationEvent` provides access to input messages through its `messages` attribute, enabling hooks to implement input-side guardrails that run before messages are added to the agent's conversation history.

### Use Cases

- **PII Detection/Redaction**: Scan and redact sensitive information before processing
- **Content Moderation**: Filter toxic or inappropriate content
- **Prompt Attack Prevention**: Detect and block malicious prompt injection attempts

### Example: Input Redaction Hook

```python
from strands import Agent
from strands.hooks import BeforeInvocationEvent, HookProvider, HookRegistry

class InputGuardrailHook(HookProvider):
def register_hooks(self, registry: HookRegistry) -> None:
registry.add_callback(BeforeInvocationEvent, self.check_input)

async def check_input(self, event: BeforeInvocationEvent) -> None:
if event.messages is None:
return

for message in event.messages:
if message.get("role") == "user":
content = message.get("content", [])
for block in content:
if "text" in block:
# Option 1: Redact in-place
block["text"] = redact_pii(block["text"])

# Option 2: Abort invocation by raising an exception
# if contains_malicious_content(block["text"]):
# raise ValueError("Malicious content detected")

agent = Agent(hooks=[InputGuardrailHook()])
agent("Process this message") # Guardrail runs before message is added to memory
```

### Key Behaviors

- `messages` defaults to `None` for backward compatibility (e.g., when invoked from deprecated methods)
- `messages` is writable, allowing hooks to modify content in-place
- The `AfterInvocationEvent` is always triggered even if a hook raises an exception, maintaining the paired event guarantee
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this. Its too specific for this document.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done - removed the Input Guardrails section from HOOKS.md.

Comment on lines 42 to 47
The messages attribute provides access to the input messages for this invocation,
allowing hooks to inspect or modify message content before processing. This is
particularly useful for implementing input guardrails (e.g., PII detection,
content moderation, prompt attack prevention) that need to run before messages
are added to the agent's conversation history.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this. the purpose of messages should be covered in the Attributes.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done - removed the detailed guardrails description from the docstring.

Comment on lines 55 to 56
to redact or transform content before processing. May be None for
backward compatibility or when invoked from deprecated methods.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
to redact or transform content before processing. May be None for
backward compatibility or when invoked from deprecated methods.
to redact or transform content before processing.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done - removed the backward compatibility note from the attribute description.

Comment on lines 180 to 184
def test_before_invocation_event_messages_set_on_init(agent, sample_messages):
"""Test that BeforeInvocationEvent.messages can be set on initialization."""
event = BeforeInvocationEvent(agent=agent, messages=sample_messages)
assert event.messages is sample_messages
assert event.messages == [{"role": "user", "content": [{"text": "Hello, agent!"}]}]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this since its a no-op test.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done - removed the no-op test.

@Unshure
Copy link
Owner

Unshure commented Jan 13, 2026

/strands

Add messages attribute to BeforeInvocationEvent to enable input-side
guardrails for PII detection, content moderation, and prompt attack
prevention. Hooks can now inspect and modify messages before they are
added to the agent's conversation history.

- Add writable messages attribute to BeforeInvocationEvent (None default)
- Pass messages parameter from _run_loop() to BeforeInvocationEvent
- Add unit tests for new messages attribute and writability
- Add integration tests for message modification use case
- Update docs/HOOKS.md with input guardrails documentation

Resolves #8
- Remove detailed Input Guardrails section from docs/HOOKS.md
- Simplify BeforeInvocationEvent docstring per review
- Remove backward compatibility note from messages attribute
- Remove no-op test for messages initialization
Comment on lines 244 to 246
# Verify BeforeInvocationEvent includes messages
before_event_2 = next(events)
assert isinstance(before_event_2, BeforeInvocationEvent)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason this can't be something like:

assert next(events) == BeforeInvocationEvent(agent=agent, messages=agent.messages[0:1])

That would be a lot more concise & readable

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! Updated to use the concise equality comparison pattern.

@Unshure
Copy link
Owner

Unshure commented Jan 14, 2026

/strands

Use concise equality comparison for BeforeInvocationEvent assertions
instead of verbose instance checks and property assertions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Expose input messages to BeforeInvocationEvent hook

3 participants