Action Parameters Reference

View as Markdown

This section describes the special parameters automatically provided to actions by the NeMo Guardrails library.

Special Parameters

When you include these parameters in your action’s function signature, they are automatically populated:

ParameterTypeDescription
contextdictContext data available to the action
eventsList[dict]History of events in the conversation
llmBaseLLMAccess to the LLM instance
configRailsConfigThe full configuration instance
llm_task_managerLLMTaskManagerAccess to the LLM task manager for prompt rendering
stateStateThe runtime state object (Colang 2.x only)

Special parameters are only injected for actions that run locally. When an actions_server_url is configured, non-system actions are sent to the remote server and do not receive these parameters. To ensure an action always receives special parameters, mark it with is_system_action=True. When no actions server is configured, all actions run locally and receive these parameters regardless of is_system_action.

The context Parameter

The context parameter provides access to conversation state and variables:

1from typing import Optional
2from nemoguardrails.actions import action
3
4@action(is_system_action=True)
5async def my_action(context: Optional[dict] = None):
6 # Access context variables
7 user_message = context.get("last_user_message")
8 bot_message = context.get("bot_message")
9 relevant_chunks = context.get("relevant_chunks")
10
11 return True

Common Context Variables

VariableDescriptionAvailability
last_user_messageThe most recent user messageAlways available after user input
bot_messageThe current bot message (in output rails)Available in output rails
last_bot_messageThe previous bot messageAvailable after first bot response
relevant_chunksRetrieved knowledge base chunksOnly after retrieve_relevant_chunks runs
user_intentThe canonical user intentOnly after generate_user_intent runs
bot_intentThe canonical bot intentOnly after generate_next_steps runs

Accessing Custom Context

Custom context variables set in flows are also accessible:

# In a Colang flow
$user_preference = "dark_mode"
execute check_preference
1@action()
2async def check_preference(context: Optional[dict] = None):
3 preference = context.get("user_preference")
4 return preference == "dark_mode"

The events Parameter

The events parameter provides the complete event history:

1from typing import List, Optional
2from nemoguardrails.actions import action
3
4@action()
5async def analyze_conversation(events: Optional[List[dict]] = None):
6 # Count user messages
7 user_messages = [
8 e for e in events
9 if e.get("type") == "UtteranceUserActionFinished"
10 ]
11
12 return {"message_count": len(user_messages)}

Event Types

Event TypeDescription
UtteranceUserActionFinishedUser sent a message
StartUtteranceBotActionBot started responding
UtteranceBotActionFinishedBot finished responding
StartInternalSystemActionSystem action started
InternalSystemActionFinishedSystem action completed
UserIntentUser intent was determined
BotIntentBot intent was determined

Event Structure Example

1{
2 "type": "UtteranceUserActionFinished",
3 "uid": "abc123",
4 "final_transcript": "Hello, how are you?",
5 "action_uid": "action_001",
6 "is_success": True
7}

The llm Parameter

The llm parameter provides direct access to the LLM instance:

1from typing import Optional
2from langchain_core.language_models import BaseLLM
3from nemoguardrails.actions import action
4
5@action()
6async def custom_llm_call(
7 prompt: str,
8 llm: Optional[BaseLLM] = None
9):
10 """Make a custom LLM call."""
11 if llm is None:
12 return "LLM not available"
13
14 response = await llm.agenerate([prompt])
15 return response.generations[0][0].text

Use Cases for LLM Access

  • Custom prompt engineering
  • Multiple LLM calls within a single action
  • Specialized text processing
1@action()
2async def summarize_and_validate(
3 text: str,
4 llm: Optional[BaseLLM] = None
5):
6 """Summarize text and validate the summary."""
7 # First call: summarize
8 summary_prompt = f"Summarize this text: {text}"
9 summary = await llm.agenerate([summary_prompt])
10 summary_text = summary.generations[0][0].text
11
12 # Second call: validate
13 validation_prompt = f"Is this summary accurate? {summary_text}"
14 validation = await llm.agenerate([validation_prompt])
15
16 return {
17 "summary": summary_text,
18 "validation": validation.generations[0][0].text
19 }

Action-Specific LLM

You can register a dedicated LLM for a specific action using the {action_name}_llm naming convention. When registered, it overrides the default llm parameter for that action:

1from nemoguardrails import LLMRails, RailsConfig
2
3config = RailsConfig.from_path("config")
4rails = LLMRails(config)
5
6rails.register_action_param("my_custom_action_llm", specialized_llm)

When my_custom_action runs and requests the llm parameter, it receives specialized_llm instead of the default LLM.

The config Parameter

The config parameter provides access to the full configuration:

1from typing import Optional
2from nemoguardrails import RailsConfig
3from nemoguardrails.actions import action
4
5@action()
6async def check_config_setting(config: Optional[RailsConfig] = None):
7 """Access configuration settings."""
8 # Access model configuration
9 models = config.models
10 main_model = next(
11 (m for m in models if m.type == "main"),
12 None
13 )
14
15 # Access custom config data
16 custom_data = config.custom_data
17
18 return {
19 "model_engine": main_model.engine if main_model else None,
20 "custom_data": custom_data
21 }

Configuration Access Examples

1@action()
2async def get_active_rails(config: Optional[RailsConfig] = None):
3 """Get list of active rails."""
4 rails_config = config.rails
5
6 return {
7 "input_rails": rails_config.input.flows if rails_config.input else [],
8 "output_rails": rails_config.output.flows if rails_config.output else []
9 }

The llm_task_manager Parameter

The llm_task_manager parameter provides access to prompt rendering and LLM task management:

1from typing import Optional
2from nemoguardrails.actions import action
3from nemoguardrails.llm.taskmanager import LLMTaskManager
4
5@action()
6async def custom_task(llm_task_manager: Optional[LLMTaskManager] = None):
7 """Use the LLM task manager for prompt rendering."""
8 pass

Combining Multiple Parameters

You can use multiple special parameters together:

1@action(is_system_action=True)
2async def advanced_check(
3 context: Optional[dict] = None,
4 events: Optional[List[dict]] = None,
5 llm: Optional[BaseLLM] = None,
6 config: Optional[RailsConfig] = None
7):
8 """Advanced action using multiple special parameters."""
9 # Get current message from context
10 message = context.get("last_user_message", "")
11
12 # Count previous interactions from events
13 interaction_count = len([
14 e for e in events
15 if e.get("type") == "UtteranceUserActionFinished"
16 ])
17
18 # Check config for thresholds
19 max_interactions = config.custom_data.get("max_interactions", 100)
20
21 if interaction_count > max_interactions:
22 return False
23
24 # Use LLM for complex validation if needed
25 if needs_llm_check(message):
26 result = await llm.agenerate([f"Is this safe? {message}"])
27 return "yes" in result.generations[0][0].text.lower()
28
29 return True

Parameter Type Annotations

Always use proper type annotations for special parameters:

1from typing import Optional, List
2from langchain_core.language_models import BaseLLM
3from nemoguardrails import RailsConfig
4from nemoguardrails.actions import action
5from nemoguardrails.llm.taskmanager import LLMTaskManager
6
7@action()
8async def properly_typed_action(
9 # Regular parameters
10 query: str,
11 limit: int = 10,
12 # Special parameters with correct types
13 context: Optional[dict] = None,
14 events: Optional[List[dict]] = None,
15 llm: Optional[BaseLLM] = None,
16 config: Optional[RailsConfig] = None,
17 llm_task_manager: Optional[LLMTaskManager] = None,
18):
19 """Action with proper type annotations."""
20 pass