Action Parameters#

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:

Parameter

Type

Description

context

dict

Context data available to the action

events

List[dict]

History of events in the conversation

llm

BaseLLM

Access to the LLM instance

config

RailsConfig

The full configuration instance

llm_task_manager

LLMTaskManager

Access to the LLM task manager for prompt rendering

state

State

The runtime state object (Colang 2.x only)

Important

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:

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

Availability

last_user_message

The most recent user message

Always available after user input

bot_message

The current bot message (in output rails)

Available in output rails

last_bot_message

The previous bot message

Available after first bot response

relevant_chunks

Retrieved knowledge base chunks

Only after retrieve_relevant_chunks runs

user_intent

The canonical user intent

Only after generate_user_intent runs

bot_intent

The canonical bot intent

Only 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
@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

UtteranceUserActionFinished

User sent a message

StartUtteranceBotAction

Bot started responding

UtteranceBotActionFinished

Bot finished responding

StartInternalSystemAction

System action started

InternalSystemActionFinished

System action completed

UserIntent

User intent was determined

BotIntent

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_core.language_models 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
    }

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:

from nemoguardrails import LLMRails, RailsConfig

config = RailsConfig.from_path("config")
rails = LLMRails(config)

rails.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:

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 []
    }

The llm_task_manager Parameter#

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

from typing import Optional
from nemoguardrails.actions import action
from nemoguardrails.llm.taskmanager import LLMTaskManager

@action()
async def custom_task(llm_task_manager: Optional[LLMTaskManager] = None):
    """Use the LLM task manager for prompt rendering."""
    pass

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_core.language_models import BaseLLM
from nemoguardrails import RailsConfig
from nemoguardrails.actions import action
from nemoguardrails.llm.taskmanager import LLMTaskManager

@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,
    llm_task_manager: Optional[LLMTaskManager] = None,
):
    """Action with proper type annotations."""
    pass