Action Parameters#
This section describes the special parameters automatically provided to actions by the NeMo Guardrails toolkit.
Special Parameters#
When you include these parameters in your action’s function signature, they are automatically populated:
Parameter |
Type |
Description |
|---|---|---|
|
|
Context data available to the action |
|
|
History of events in the conversation |
|
|
Access to the LLM instance |
|
|
The full configuration instance |
The context Parameter#
The context parameter provides access to conversation state and variables:
from typing import Optional
from nemoguardrails.actions import action
@action(is_system_action=True)
async def my_action(context: Optional[dict] = None):
# Access context variables
user_message = context.get("last_user_message")
bot_message = context.get("bot_message")
relevant_chunks = context.get("relevant_chunks")
return True
Common Context Variables#
Variable |
Description |
|---|---|
|
The most recent user message |
|
The current bot message (in output rails) |
|
The previous bot message |
|
Retrieved knowledge base chunks |
|
The canonical user intent |
|
The canonical bot intent |
Accessing Custom Context#
Custom context variables set in flows are also accessible:
# In a Colang flow
$user_preference = "dark_mode"
execute check_preference
@action()
async def check_preference(context: Optional[dict] = None):
preference = context.get("user_preference")
return preference == "dark_mode"
The events Parameter#
The events parameter provides the complete event history:
from typing import List, Optional
from nemoguardrails.actions import action
@action()
async def analyze_conversation(events: Optional[List[dict]] = None):
# Count user messages
user_messages = [
e for e in events
if e.get("type") == "UtteranceUserActionFinished"
]
return {"message_count": len(user_messages)}
Event Types#
Event Type |
Description |
|---|---|
|
User sent a message |
|
Bot started responding |
|
Bot finished responding |
|
System action started |
|
System action completed |
|
User intent was determined |
|
Bot intent was determined |
Event Structure Example#
{
"type": "UtteranceUserActionFinished",
"uid": "abc123",
"final_transcript": "Hello, how are you?",
"action_uid": "action_001",
"is_success": True
}
The llm Parameter#
The llm parameter provides direct access to the LLM instance:
from typing import Optional
from langchain.llms.base import BaseLLM
from nemoguardrails.actions import action
@action()
async def custom_llm_call(
prompt: str,
llm: Optional[BaseLLM] = None
):
"""Make a custom LLM call."""
if llm is None:
return "LLM not available"
response = await llm.agenerate([prompt])
return response.generations[0][0].text
Use Cases for LLM Access#
Custom prompt engineering
Multiple LLM calls within a single action
Specialized text processing
@action()
async def summarize_and_validate(
text: str,
llm: Optional[BaseLLM] = None
):
"""Summarize text and validate the summary."""
# First call: summarize
summary_prompt = f"Summarize this text: {text}"
summary = await llm.agenerate([summary_prompt])
summary_text = summary.generations[0][0].text
# Second call: validate
validation_prompt = f"Is this summary accurate? {summary_text}"
validation = await llm.agenerate([validation_prompt])
return {
"summary": summary_text,
"validation": validation.generations[0][0].text
}
The config Parameter#
The config parameter provides access to the full configuration:
from typing import Optional
from nemoguardrails import RailsConfig
from nemoguardrails.actions import action
@action()
async def check_config_setting(config: Optional[RailsConfig] = None):
"""Access configuration settings."""
# Access model configuration
models = config.models
main_model = next(
(m for m in models if m.type == "main"),
None
)
# Access custom config data
custom_data = config.custom_data
return {
"model_engine": main_model.engine if main_model else None,
"custom_data": custom_data
}
Configuration Access Examples#
@action()
async def get_active_rails(config: Optional[RailsConfig] = None):
"""Get list of active rails."""
rails_config = config.rails
return {
"input_rails": rails_config.input.flows if rails_config.input else [],
"output_rails": rails_config.output.flows if rails_config.output else []
}
Combining Multiple Parameters#
You can use multiple special parameters together:
@action(is_system_action=True)
async def advanced_check(
context: Optional[dict] = None,
events: Optional[List[dict]] = None,
llm: Optional[BaseLLM] = None,
config: Optional[RailsConfig] = None
):
"""Advanced action using multiple special parameters."""
# Get current message from context
message = context.get("last_user_message", "")
# Count previous interactions from events
interaction_count = len([
e for e in events
if e.get("type") == "UtteranceUserActionFinished"
])
# Check config for thresholds
max_interactions = config.custom_data.get("max_interactions", 100)
if interaction_count > max_interactions:
return False
# Use LLM for complex validation if needed
if needs_llm_check(message):
result = await llm.agenerate([f"Is this safe? {message}"])
return "yes" in result.generations[0][0].text.lower()
return True
Parameter Type Annotations#
Always use proper type annotations for special parameters:
from typing import Optional, List
from langchain.llms.base import BaseLLM
from nemoguardrails import RailsConfig
from nemoguardrails.actions import action
@action()
async def properly_typed_action(
# Regular parameters
query: str,
limit: int = 10,
# Special parameters with correct types
context: Optional[dict] = None,
events: Optional[List[dict]] = None,
llm: Optional[BaseLLM] = None,
config: Optional[RailsConfig] = None
):
"""Action with proper type annotations."""
pass