Hooks¶
Contract¶
HookProvider ¶
Bases: ABC
Abstract base class for hook providers.
Hook providers implement lifecycle callbacks that are invoked during agent execution. Multiple providers can be registered, with execution order determined by priority (lower = earlier).
Example
class MyLoggingHook(HookProvider): @property def priority(self) -> int: return HookPriority.OBSERVABILITY_DEFAULT
async def on_before_invocation(
self, prompt: str, state: AgentState
) -> AgentState:
print(f"Starting: {prompt[:50]}...")
return state
async def on_after_invocation(
self, state: AgentState, success: bool
) -> None:
print(f"Completed: success={success}")
priority
abstractmethod
property
¶
Hook priority (lower = earlier execution).
Use HookPriority constants for standard ranges.
on_before_invocation
async
¶
Called before agent starts processing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prompt
|
str
|
The user prompt being processed |
required |
state
|
AgentState
|
Current agent state |
required |
Returns:
| Type | Description |
|---|---|
AgentState
|
Potentially modified agent state |
Source code in src/locus/hooks/provider.py
on_after_invocation
async
¶
Called after agent completes processing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
state
|
AgentState
|
Final agent state |
required |
success
|
bool
|
Whether execution completed successfully |
required |
on_before_tool_call
async
¶
Called before tool execution.
Modify event.arguments to change tool inputs. Set event.cancel = True or a string reason to skip execution. event.tool_name and event.tool_call_id are read-only.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
BeforeToolCallEvent
|
Write-protected event. Writable: arguments, cancel. |
required |
Source code in src/locus/hooks/provider.py
on_after_tool_call
async
¶
Called after tool execution.
Set event.retry = True to re-execute the tool. Set event.result to replace the tool result. event.tool_name and event.error are read-only.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
AfterToolCallEvent
|
Write-protected event. Writable: result, retry. |
required |
Source code in src/locus/hooks/provider.py
on_iteration_start
async
¶
Called at the start of each agent iteration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
iteration
|
int
|
Current iteration number (0-indexed) |
required |
state
|
AgentState
|
Current agent state |
required |
Source code in src/locus/hooks/provider.py
on_iteration_end
async
¶
Called at the end of each agent iteration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
iteration
|
int
|
Current iteration number (0-indexed) |
required |
state
|
AgentState
|
Current agent state |
required |
on_before_model_call
async
¶
Called before each model.complete() call.
Modify event.messages to change what the model sees. event.tools is read-only (inspect only).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
BeforeModelCallEvent
|
Write-protected event. Writable: messages. |
required |
Source code in src/locus/hooks/provider.py
on_after_model_call
async
¶
Called after each model.complete() call.
Set event.retry = True to discard response and re-call. Set event.response to replace the response. event.messages is read-only.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
AfterModelCallEvent
|
Write-protected event. Writable: response, retry. |
required |
Source code in src/locus/hooks/provider.py
register_hooks ¶
Return which hooks this provider implements.
Returns:
| Type | Description |
|---|---|
dict[str, bool]
|
Dictionary mapping hook names to whether they are implemented. |
dict[str, bool]
|
Useful for optimization - registry can skip calling unimplemented hooks. |
Source code in src/locus/hooks/provider.py
HookRegistry ¶
Registry for managing hook providers.
The registry maintains a priority-ordered list of hook providers and dispatches lifecycle events to them in order.
Example
registry = HookRegistry() registry.add_provider(LoggingHook()) registry.add_provider(GuardrailsHook())
During agent execution¶
state = await registry.emit_before_invocation(prompt, state)
... agent runs ...¶
await registry.emit_after_invocation(state, success=True)
Initialize empty hook registry.
Source code in src/locus/hooks/registry.py
add_provider ¶
Register a hook provider.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
provider
|
HookProvider
|
Hook provider to register |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If provider with same name already registered |
Source code in src/locus/hooks/registry.py
remove_provider ¶
Remove a hook provider by name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Name of the provider to remove |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if provider was removed, False if not found |
Source code in src/locus/hooks/registry.py
get_provider ¶
Get a hook provider by name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Name of the provider to find |
required |
Returns:
| Type | Description |
|---|---|
HookProvider | None
|
The provider if found, None otherwise |
Source code in src/locus/hooks/registry.py
__len__ ¶
__contains__ ¶
emit_before_invocation
async
¶
Emit before_invocation event to all providers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prompt
|
str
|
User prompt being processed |
required |
state
|
AgentState
|
Current agent state |
required |
Returns:
| Type | Description |
|---|---|
AgentState
|
Potentially modified agent state |
Source code in src/locus/hooks/registry.py
emit_after_invocation
async
¶
Emit after_invocation event to all providers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
state
|
AgentState
|
Final agent state |
required |
success
|
bool
|
Whether execution completed successfully |
required |
Source code in src/locus/hooks/registry.py
emit_before_tool_call
async
¶
Emit before_tool_call event to all providers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tool_name
|
str
|
Name of the tool being called |
required |
arguments
|
dict[str, Any]
|
Tool arguments |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Potentially modified arguments |
Source code in src/locus/hooks/registry.py
emit_after_tool_call
async
¶
emit_after_tool_call(tool_name: str, result: Any, error: str | None, *, tool_call_id: str = '', arguments: dict[str, Any] | None = None) -> None
Emit after_tool_call event to all providers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tool_name
|
str
|
Name of the tool that was called |
required |
result
|
Any
|
Tool result (if successful) |
required |
error
|
str | None
|
Error message (if failed) |
required |
tool_call_id
|
str
|
ID of the tool call (correlates with BeforeToolCallEvent). |
''
|
arguments
|
dict[str, Any] | None
|
Arguments the tool was invoked with (post-hook mutation). |
None
|
Source code in src/locus/hooks/registry.py
emit_iteration_start
async
¶
Emit iteration_start event to all providers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
iteration
|
int
|
Current iteration number |
required |
state
|
AgentState
|
Current agent state |
required |
Source code in src/locus/hooks/registry.py
emit_iteration_end
async
¶
Emit iteration_end event to all providers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
iteration
|
int
|
Current iteration number |
required |
state
|
AgentState
|
Current agent state |
required |
Source code in src/locus/hooks/registry.py
emit_before_model_call
async
¶
Emit before_model_call event to all providers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
messages
|
list[Any]
|
Messages about to be sent to the model |
required |
tools
|
list[dict[str, Any]] | None
|
Tool schemas (if any) |
required |
Returns:
| Type | Description |
|---|---|
list[Any]
|
Potentially modified messages list |
Source code in src/locus/hooks/registry.py
emit_after_model_call
async
¶
Emit after_model_call event to all providers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
response
|
Any
|
The ModelResponse from the model |
required |
messages
|
list[Any]
|
The messages that were sent |
required |
Returns:
| Type | Description |
|---|---|
Any
|
Potentially modified response |
Source code in src/locus/hooks/registry.py
emit
async
¶
Generic event emission for custom hook points.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_name
|
str
|
Name of the hook method to call |
required |
*args
|
Any
|
Positional arguments to pass |
()
|
**kwargs
|
Any
|
Keyword arguments to pass |
{}
|
Returns:
| Type | Description |
|---|---|
Any
|
Result from the last provider that returned a non-None value |
Source code in src/locus/hooks/registry.py
Built-in hooks¶
LoggingHook ¶
LoggingHook(level: int = logging.INFO, logger_name: str = 'locus.agent', extra: dict[str, Any] | None = None, log_arguments: bool = False, log_results: bool = False, priority: int = HookPriority.OBSERVABILITY_DEFAULT)
Bases: HookProvider
Hook provider that logs all lifecycle events.
Provides structured logging for agent execution with configurable log levels and optional extra context.
Example
Basic usage¶
registry.add_provider(LoggingHook())
With custom log level¶
registry.add_provider(LoggingHook(level=logging.DEBUG))
With structured context¶
registry.add_provider(LoggingHook( extra={"environment": "production", "service": "my-agent"} ))
Initialize logging hook.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
level
|
int
|
Logging level (default: INFO) |
INFO
|
logger_name
|
str
|
Name for the logger |
'locus.agent'
|
extra
|
dict[str, Any] | None
|
Extra context to include in all log records |
None
|
log_arguments
|
bool
|
Whether to log tool arguments (may contain sensitive data) |
False
|
log_results
|
bool
|
Whether to log tool results (may be verbose) |
False
|
priority
|
int
|
Hook priority |
OBSERVABILITY_DEFAULT
|
Source code in src/locus/hooks/builtin/logging.py
on_before_invocation
async
¶
Log invocation start.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prompt
|
str
|
User prompt |
required |
state
|
AgentState
|
Agent state |
required |
Returns:
| Type | Description |
|---|---|
AgentState
|
Unchanged state |
Source code in src/locus/hooks/builtin/logging.py
on_after_invocation
async
¶
Log invocation completion.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
state
|
AgentState
|
Final agent state |
required |
success
|
bool
|
Whether execution succeeded |
required |
Source code in src/locus/hooks/builtin/logging.py
on_before_tool_call
async
¶
Log tool call start.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
BeforeToolCallEvent
|
Write-protected event carrying |
required |
Source code in src/locus/hooks/builtin/logging.py
on_after_tool_call
async
¶
Log tool call completion.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
AfterToolCallEvent
|
Write-protected event carrying |
required |
Source code in src/locus/hooks/builtin/logging.py
on_iteration_start
async
¶
Log iteration start.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
iteration
|
int
|
Iteration number |
required |
state
|
AgentState
|
Current state |
required |
Source code in src/locus/hooks/builtin/logging.py
on_iteration_end
async
¶
Log iteration end.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
iteration
|
int
|
Iteration number |
required |
state
|
AgentState
|
Current state |
required |
Source code in src/locus/hooks/builtin/logging.py
on_before_model_call
async
¶
Called before each model.complete() call.
Modify event.messages to change what the model sees. event.tools is read-only (inspect only).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
BeforeModelCallEvent
|
Write-protected event. Writable: messages. |
required |
Source code in src/locus/hooks/provider.py
on_after_model_call
async
¶
Called after each model.complete() call.
Set event.retry = True to discard response and re-call. Set event.response to replace the response. event.messages is read-only.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
AfterModelCallEvent
|
Write-protected event. Writable: response, retry. |
required |
Source code in src/locus/hooks/provider.py
register_hooks ¶
Return which hooks this provider implements.
Returns:
| Type | Description |
|---|---|
dict[str, bool]
|
Dictionary mapping hook names to whether they are implemented. |
dict[str, bool]
|
Useful for optimization - registry can skip calling unimplemented hooks. |
Source code in src/locus/hooks/provider.py
StructuredLoggingHook ¶
StructuredLoggingHook(level: int = logging.INFO, logger_name: str = 'locus.agent.structured', extra: dict[str, Any] | None = None, include_timestamps: bool = True, priority: int = HookPriority.OBSERVABILITY_DEFAULT)
Bases: LoggingHook
Logging hook with JSON-structured output.
Extends LoggingHook to emit structured JSON logs suitable for log aggregation systems like ELK, Datadog, or CloudWatch.
Example
import json import logging
Configure JSON handler¶
handler = logging.StreamHandler() handler.setFormatter(JsonFormatter()) logging.getLogger("locus.agent").addHandler(handler)
registry.add_provider(StructuredLoggingHook())
Initialize structured logging hook.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
level
|
int
|
Logging level |
INFO
|
logger_name
|
str
|
Logger name |
'locus.agent.structured'
|
extra
|
dict[str, Any] | None
|
Extra context for all logs |
None
|
include_timestamps
|
bool
|
Whether to include ISO timestamps |
True
|
priority
|
int
|
Hook priority |
OBSERVABILITY_DEFAULT
|
Source code in src/locus/hooks/builtin/logging.py
on_before_invocation
async
¶
Log invocation start.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prompt
|
str
|
User prompt |
required |
state
|
AgentState
|
Agent state |
required |
Returns:
| Type | Description |
|---|---|
AgentState
|
Unchanged state |
Source code in src/locus/hooks/builtin/logging.py
on_after_invocation
async
¶
Log invocation completion.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
state
|
AgentState
|
Final agent state |
required |
success
|
bool
|
Whether execution succeeded |
required |
Source code in src/locus/hooks/builtin/logging.py
on_before_tool_call
async
¶
Log tool call start.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
BeforeToolCallEvent
|
Write-protected event carrying |
required |
Source code in src/locus/hooks/builtin/logging.py
on_after_tool_call
async
¶
Log tool call completion.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
AfterToolCallEvent
|
Write-protected event carrying |
required |
Source code in src/locus/hooks/builtin/logging.py
on_iteration_start
async
¶
Log iteration start.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
iteration
|
int
|
Iteration number |
required |
state
|
AgentState
|
Current state |
required |
Source code in src/locus/hooks/builtin/logging.py
on_iteration_end
async
¶
Log iteration end.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
iteration
|
int
|
Iteration number |
required |
state
|
AgentState
|
Current state |
required |
Source code in src/locus/hooks/builtin/logging.py
on_before_model_call
async
¶
Called before each model.complete() call.
Modify event.messages to change what the model sees. event.tools is read-only (inspect only).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
BeforeModelCallEvent
|
Write-protected event. Writable: messages. |
required |
Source code in src/locus/hooks/provider.py
on_after_model_call
async
¶
Called after each model.complete() call.
Set event.retry = True to discard response and re-call. Set event.response to replace the response. event.messages is read-only.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
AfterModelCallEvent
|
Write-protected event. Writable: response, retry. |
required |
Source code in src/locus/hooks/provider.py
register_hooks ¶
Return which hooks this provider implements.
Returns:
| Type | Description |
|---|---|
dict[str, bool]
|
Dictionary mapping hook names to whether they are implemented. |
dict[str, bool]
|
Useful for optimization - registry can skip calling unimplemented hooks. |
Source code in src/locus/hooks/provider.py
TelemetryHook ¶
TelemetryHook(service_name: str = 'locus-agent', tracer_name: str = 'locus.hooks.telemetry', meter_name: str = 'locus.hooks.telemetry', record_arguments: bool = False, record_results: bool = False, priority: int = HookPriority.OBSERVABILITY_MIN + 10)
Bases: HookProvider
Hook provider for OpenTelemetry tracing and metrics.
Provides automatic instrumentation for: - Trace spans for agent invocations and iterations - Trace spans for tool calls - Metrics for invocation duration, tool call counts, etc.
Requires the telemetry extra: pip install locus[telemetry]
Example
from opentelemetry import trace from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import ConsoleSpanExporter, BatchSpanProcessor
Configure OpenTelemetry¶
provider = TracerProvider() provider.add_span_processor(BatchSpanProcessor(ConsoleSpanExporter())) trace.set_tracer_provider(provider)
Add telemetry hook¶
registry.add_provider(TelemetryHook())
Initialize telemetry hook.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
service_name
|
str
|
Service name for telemetry |
'locus-agent'
|
tracer_name
|
str
|
Name for the OpenTelemetry tracer |
'locus.hooks.telemetry'
|
meter_name
|
str
|
Name for the OpenTelemetry meter |
'locus.hooks.telemetry'
|
record_arguments
|
bool
|
Whether to record tool arguments as span attributes |
False
|
record_results
|
bool
|
Whether to record tool results as span attributes |
False
|
priority
|
int
|
Hook priority (default: early in observability range) |
OBSERVABILITY_MIN + 10
|
Raises:
| Type | Description |
|---|---|
ImportError
|
If OpenTelemetry is not installed |
Source code in src/locus/hooks/builtin/telemetry.py
on_before_invocation
async
¶
Start invocation span.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prompt
|
str
|
User prompt |
required |
state
|
AgentState
|
Agent state |
required |
Returns:
| Type | Description |
|---|---|
AgentState
|
Unchanged state |
Source code in src/locus/hooks/builtin/telemetry.py
on_after_invocation
async
¶
End invocation span.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
state
|
AgentState
|
Final agent state |
required |
success
|
bool
|
Whether execution succeeded |
required |
Source code in src/locus/hooks/builtin/telemetry.py
on_before_tool_call
async
¶
Start tool call span.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
BeforeToolCallEvent
|
Write-protected event carrying |
required |
Source code in src/locus/hooks/builtin/telemetry.py
on_after_tool_call
async
¶
End tool call span.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
AfterToolCallEvent
|
Write-protected event carrying |
required |
Source code in src/locus/hooks/builtin/telemetry.py
on_iteration_start
async
¶
Start iteration span.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
iteration
|
int
|
Iteration number |
required |
state
|
AgentState
|
Current state |
required |
Source code in src/locus/hooks/builtin/telemetry.py
on_iteration_end
async
¶
End iteration span.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
iteration
|
int
|
Iteration number |
required |
state
|
AgentState
|
Current state |
required |
Source code in src/locus/hooks/builtin/telemetry.py
on_before_model_call
async
¶
Called before each model.complete() call.
Modify event.messages to change what the model sees. event.tools is read-only (inspect only).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
BeforeModelCallEvent
|
Write-protected event. Writable: messages. |
required |
Source code in src/locus/hooks/provider.py
on_after_model_call
async
¶
Called after each model.complete() call.
Set event.retry = True to discard response and re-call. Set event.response to replace the response. event.messages is read-only.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
AfterModelCallEvent
|
Write-protected event. Writable: response, retry. |
required |
Source code in src/locus/hooks/provider.py
register_hooks ¶
Return which hooks this provider implements.
Returns:
| Type | Description |
|---|---|
dict[str, bool]
|
Dictionary mapping hook names to whether they are implemented. |
dict[str, bool]
|
Useful for optimization - registry can skip calling unimplemented hooks. |
Source code in src/locus/hooks/provider.py
NoOpTelemetryHook ¶
Bases: HookProvider
No-op telemetry hook for when OpenTelemetry is not available.
This hook does nothing but can be used as a drop-in replacement for TelemetryHook when telemetry is disabled.
Initialize no-op hook.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
priority
|
int
|
Hook priority |
OBSERVABILITY_MIN + 10
|
Source code in src/locus/hooks/builtin/telemetry.py
on_before_invocation
async
¶
Called before agent starts processing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prompt
|
str
|
The user prompt being processed |
required |
state
|
AgentState
|
Current agent state |
required |
Returns:
| Type | Description |
|---|---|
AgentState
|
Potentially modified agent state |
Source code in src/locus/hooks/provider.py
on_after_invocation
async
¶
Called after agent completes processing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
state
|
AgentState
|
Final agent state |
required |
success
|
bool
|
Whether execution completed successfully |
required |
on_before_tool_call
async
¶
Called before tool execution.
Modify event.arguments to change tool inputs. Set event.cancel = True or a string reason to skip execution. event.tool_name and event.tool_call_id are read-only.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
BeforeToolCallEvent
|
Write-protected event. Writable: arguments, cancel. |
required |
Source code in src/locus/hooks/provider.py
on_after_tool_call
async
¶
Called after tool execution.
Set event.retry = True to re-execute the tool. Set event.result to replace the tool result. event.tool_name and event.error are read-only.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
AfterToolCallEvent
|
Write-protected event. Writable: result, retry. |
required |
Source code in src/locus/hooks/provider.py
on_iteration_start
async
¶
Called at the start of each agent iteration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
iteration
|
int
|
Current iteration number (0-indexed) |
required |
state
|
AgentState
|
Current agent state |
required |
Source code in src/locus/hooks/provider.py
on_iteration_end
async
¶
Called at the end of each agent iteration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
iteration
|
int
|
Current iteration number (0-indexed) |
required |
state
|
AgentState
|
Current agent state |
required |
on_before_model_call
async
¶
Called before each model.complete() call.
Modify event.messages to change what the model sees. event.tools is read-only (inspect only).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
BeforeModelCallEvent
|
Write-protected event. Writable: messages. |
required |
Source code in src/locus/hooks/provider.py
on_after_model_call
async
¶
Called after each model.complete() call.
Set event.retry = True to discard response and re-call. Set event.response to replace the response. event.messages is read-only.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
AfterModelCallEvent
|
Write-protected event. Writable: response, retry. |
required |
Source code in src/locus/hooks/provider.py
register_hooks ¶
Return which hooks this provider implements.
Returns:
| Type | Description |
|---|---|
dict[str, bool]
|
Dictionary mapping hook names to whether they are implemented. |
dict[str, bool]
|
Useful for optimization - registry can skip calling unimplemented hooks. |
Source code in src/locus/hooks/provider.py
ModelRetryHook ¶
ModelRetryHook(max_retries: int = 3, initial_delay: float = 1.0, max_delay: float = 30.0, backoff_factor: float = 2.0, retry_on_empty: bool = True, priority: int = HookPriority.DEFAULT)
Bases: HookProvider
Retry model calls on throttle/rate limit with exponential backoff.
Catches empty responses and rate limit indicators, sets event.retry=True to trigger automatic re-invocation with increasing delays.
Works with all providers (OCI, OpenAI, Anthropic, Ollama).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
max_retries
|
int
|
Maximum retry attempts per model call. |
3
|
initial_delay
|
float
|
First retry delay in seconds. |
1.0
|
max_delay
|
float
|
Maximum delay between retries. |
30.0
|
backoff_factor
|
float
|
Multiplier for each subsequent delay. |
2.0
|
retry_on_empty
|
bool
|
Retry when model returns empty content. |
True
|
Source code in src/locus/hooks/builtin/retry.py
on_before_model_call
async
¶
on_after_model_call
async
¶
Check response and retry if needed.
Source code in src/locus/hooks/builtin/retry.py
on_before_invocation
async
¶
Called before agent starts processing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prompt
|
str
|
The user prompt being processed |
required |
state
|
AgentState
|
Current agent state |
required |
Returns:
| Type | Description |
|---|---|
AgentState
|
Potentially modified agent state |
Source code in src/locus/hooks/provider.py
on_after_invocation
async
¶
Called after agent completes processing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
state
|
AgentState
|
Final agent state |
required |
success
|
bool
|
Whether execution completed successfully |
required |
on_before_tool_call
async
¶
Called before tool execution.
Modify event.arguments to change tool inputs. Set event.cancel = True or a string reason to skip execution. event.tool_name and event.tool_call_id are read-only.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
BeforeToolCallEvent
|
Write-protected event. Writable: arguments, cancel. |
required |
Source code in src/locus/hooks/provider.py
on_after_tool_call
async
¶
Called after tool execution.
Set event.retry = True to re-execute the tool. Set event.result to replace the tool result. event.tool_name and event.error are read-only.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
AfterToolCallEvent
|
Write-protected event. Writable: result, retry. |
required |
Source code in src/locus/hooks/provider.py
on_iteration_start
async
¶
Called at the start of each agent iteration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
iteration
|
int
|
Current iteration number (0-indexed) |
required |
state
|
AgentState
|
Current agent state |
required |
Source code in src/locus/hooks/provider.py
on_iteration_end
async
¶
Called at the end of each agent iteration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
iteration
|
int
|
Current iteration number (0-indexed) |
required |
state
|
AgentState
|
Current agent state |
required |
register_hooks ¶
Return which hooks this provider implements.
Returns:
| Type | Description |
|---|---|
dict[str, bool]
|
Dictionary mapping hook names to whether they are implemented. |
dict[str, bool]
|
Useful for optimization - registry can skip calling unimplemented hooks. |
Source code in src/locus/hooks/provider.py
GuardrailsHook ¶
GuardrailsHook(config: GuardrailConfig | None = None, on_violation: Callable[[GuardrailViolation], None] | None = None, priority: int = HookPriority.SECURITY_DEFAULT)
Bases: HookProvider
Hook provider for security guardrails.
Provides: - Input validation and filtering - Output sanitization - PII detection and redaction - Dangerous content blocking - Tool allowlist/blocklist enforcement
Example
config = GuardrailConfig( block_dangerous_tools=frozenset({"shell", "exec"}), default_action=GuardrailAction.BLOCK, ) registry.add_provider(GuardrailsHook(config))
Initialize guardrails hook.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
GuardrailConfig | None
|
Guardrail configuration |
None
|
on_violation
|
Callable[[GuardrailViolation], None] | None
|
Callback for violations (receives GuardrailViolation) |
None
|
priority
|
int
|
Hook priority (default: middle of security range) |
SECURITY_DEFAULT
|
Source code in src/locus/hooks/builtin/guardrails.py
clear_violations ¶
on_before_invocation
async
¶
Validate input prompt.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prompt
|
str
|
User prompt |
required |
state
|
AgentState
|
Agent state |
required |
Returns:
| Type | Description |
|---|---|
AgentState
|
State, potentially with metadata about violations |
Raises:
| Type | Description |
|---|---|
ValueError
|
If prompt is blocked |
Source code in src/locus/hooks/builtin/guardrails.py
on_before_tool_call
async
¶
Validate tool call.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
BeforeToolCallEvent
|
Write-protected event. The hook may mutate
|
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If tool is blocked |
Source code in src/locus/hooks/builtin/guardrails.py
on_after_tool_call
async
¶
Validate tool result.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
AfterToolCallEvent
|
Write-protected event carrying |
required |
Source code in src/locus/hooks/builtin/guardrails.py
on_after_invocation
async
¶
Called after agent completes processing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
state
|
AgentState
|
Final agent state |
required |
success
|
bool
|
Whether execution completed successfully |
required |
on_iteration_start
async
¶
Called at the start of each agent iteration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
iteration
|
int
|
Current iteration number (0-indexed) |
required |
state
|
AgentState
|
Current agent state |
required |
Source code in src/locus/hooks/provider.py
on_iteration_end
async
¶
Called at the end of each agent iteration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
iteration
|
int
|
Current iteration number (0-indexed) |
required |
state
|
AgentState
|
Current agent state |
required |
on_before_model_call
async
¶
Called before each model.complete() call.
Modify event.messages to change what the model sees. event.tools is read-only (inspect only).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
BeforeModelCallEvent
|
Write-protected event. Writable: messages. |
required |
Source code in src/locus/hooks/provider.py
on_after_model_call
async
¶
Called after each model.complete() call.
Set event.retry = True to discard response and re-call. Set event.response to replace the response. event.messages is read-only.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
AfterModelCallEvent
|
Write-protected event. Writable: response, retry. |
required |
Source code in src/locus/hooks/provider.py
register_hooks ¶
Return which hooks this provider implements.
Returns:
| Type | Description |
|---|---|
dict[str, bool]
|
Dictionary mapping hook names to whether they are implemented. |
dict[str, bool]
|
Useful for optimization - registry can skip calling unimplemented hooks. |
Source code in src/locus/hooks/provider.py
SteeringHook ¶
SteeringHook(model: Any, policy: str = '', evaluate_tools: bool = True, evaluate_responses: bool = False, interrupt_tools: set[str] | None = None, priority: int = HookPriority.SECURITY_DEFAULT)
Bases: HookProvider
LLM-powered steering for real-time agent guidance.
Evaluates each tool call before execution using a separate LLM. The steering model decides whether to proceed, guide (cancel with feedback), or interrupt (pause for human).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
Any
|
LLM for steering decisions (can be smaller/cheaper than main model). |
required |
policy
|
str
|
Natural language policy the agent must follow. |
''
|
evaluate_tools
|
bool
|
If True, evaluate tool calls before execution. |
True
|
evaluate_responses
|
bool
|
If True, evaluate model responses after generation. |
False
|
interrupt_tools
|
set[str] | None
|
Tools that always require human approval. |
None
|
Source code in src/locus/hooks/builtin/steering.py
on_before_tool_call
async
¶
Evaluate tool call before execution.
Source code in src/locus/hooks/builtin/steering.py
on_before_model_call
async
¶
on_after_model_call
async
¶
Optionally evaluate model responses.
Source code in src/locus/hooks/builtin/steering.py
on_before_invocation
async
¶
Called before agent starts processing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prompt
|
str
|
The user prompt being processed |
required |
state
|
AgentState
|
Current agent state |
required |
Returns:
| Type | Description |
|---|---|
AgentState
|
Potentially modified agent state |
Source code in src/locus/hooks/provider.py
on_after_invocation
async
¶
Called after agent completes processing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
state
|
AgentState
|
Final agent state |
required |
success
|
bool
|
Whether execution completed successfully |
required |
on_after_tool_call
async
¶
Called after tool execution.
Set event.retry = True to re-execute the tool. Set event.result to replace the tool result. event.tool_name and event.error are read-only.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
AfterToolCallEvent
|
Write-protected event. Writable: result, retry. |
required |
Source code in src/locus/hooks/provider.py
on_iteration_start
async
¶
Called at the start of each agent iteration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
iteration
|
int
|
Current iteration number (0-indexed) |
required |
state
|
AgentState
|
Current agent state |
required |
Source code in src/locus/hooks/provider.py
on_iteration_end
async
¶
Called at the end of each agent iteration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
iteration
|
int
|
Current iteration number (0-indexed) |
required |
state
|
AgentState
|
Current agent state |
required |
register_hooks ¶
Return which hooks this provider implements.
Returns:
| Type | Description |
|---|---|
dict[str, bool]
|
Dictionary mapping hook names to whether they are implemented. |
dict[str, bool]
|
Useful for optimization - registry can skip calling unimplemented hooks. |