Custom actions allow you to execute Python code within your guardrails flows. Actions can perform external API calls, process data, update context, or trigger custom business logic.
from nemoguardrails.actions.actions import action, ActionResultfrom typing import Optional@action(is_system_action=True)async def create_event( event: dict, context: Optional[dict] = None,): """Creates an event for the bot based on the provided data. Args: event (dict): The input event data. context (Optional[dict]): The context for the action. Defaults to None. Returns: ActionResult: An action result containing the created event. """ event_dict = { "_type": event["_type"], **{k: v for k, v in event.items() if k != "_type"} } # Support for referring variables as values for k, v in event_dict.items(): if isinstance(v, str) and v[0] == "$": event_dict[k] = context.get(v[1:], None) if context else None return ActionResult(events=[event_dict])
import loggingimport osfrom typing import Optionalfrom urllib import parseimport aiohttpfrom nemoguardrails.actions import actionfrom nemoguardrails.actions.actions import ActionResultfrom nemoguardrails.utils import new_event_dictlog = logging.getLogger(__name__)APP_ID = os.environ.get("WOLFRAM_ALPHA_APP_ID")API_URL_BASE = f"https://api.wolframalpha.com/v2/result?appid={APP_ID}"@action(name="wolfram alpha request")async def wolfram_alpha_request( query: Optional[str] = None, context: Optional[dict] = None): """Makes a request to the Wolfram Alpha API. Args: query (Optional[str]): The query for Wolfram Alpha. Defaults to None. context (Optional[dict]): The context for the execution of the action. Returns: ActionResult or str: The result of the Wolfram Alpha request. Raises: Exception: If no query is provided to Wolfram Alpha. """ # If we don't have an explicit query, we take the last user message if query is None and context is not None: query = context.get("last_user_message") or "2+3" if query is None: raise Exception("No query was provided to Wolfram Alpha.") if APP_ID is None: return ActionResult( return_value=False, events=[ new_event_dict( "BotIntent", intent="inform wolfram alpha app id not set" ), new_event_dict( "StartUtteranceBotAction", script="Wolfram Alpha app ID is not set." ), new_event_dict("BotIntent", intent="stop"), ], ) url = API_URL_BASE + "&" + parse.urlencode({"i": query}) log.info(f"Wolfram Alpha: executing request for: {query}") async with aiohttp.ClientSession() as session: async with session.get(url) as resp: if resp.status != 200: log.info(f"Wolfram Alpha request failed : {query}") return ActionResult( return_value=False, events=[ new_event_dict( "BotIntent", intent="inform wolfram alpha not working" ), new_event_dict( "StartUtteranceBotAction", script="Apologies, but I cannot answer this question." ), new_event_dict("BotIntent", intent="stop"), ], ) result = await resp.text() log.info(f"Wolfram Alpha: the result was {result}.") return result
Create an actions.py file in your configuration directory:
config/├── config.yml├── rails.co└── actions.py
2
Define Your Action
from nemoguardrails.actions import actionfrom typing import Optional@action(name="check_database")async def check_database( user_id: str, context: Optional[dict] = None): """Check user information in database.""" # Your custom logic here user_data = await fetch_user_from_db(user_id) return user_data
3
Call from Colang
Reference the action in your .co files:
define flow verify user user provide user id $user_data = execute check_database(user_id=$user_id) if $user_data bot confirm user verified else bot inform user not found
Actions in actions.py are automatically registered when the configuration is loaded. No additional registration is needed.
# config/actions.pyfrom nemoguardrails.actions import action@action()async def custom_action_1(): """First custom action.""" pass@action()async def custom_action_2(): """Second custom action.""" pass# Both actions are automatically available in your rails