How to call custom action from another custom action

Hi All,

I am trying to call custom action from another custom action class in same file using tracker.trigger_followup_action method, but it’s giving me error.

It’s saying that

’Tracker’ object has not attribute 'trigger_followup_action’

2 Likes

Try returning a FollowupAction("name_of_the_action") event from the action server.

1 Like

@ameid I tried it. It’s going into the infinite loop. Should I share my code so you can get better understanding.

@prashant_kamble Yes please share your code.

Also, if you want, try explaining what you’re trying to achieve.

Yup.

Below is my actions file code :

class ActionGetEmpID(Action):
	def name(self):
		return 'action_get_empid'
		
	def run(self, dispatcher, tracker, domain):
		emp_code = tracker.get_slot('emp_code')
		password = tracker.get_slot('password')
		print("employee code ",emp_code)
		print("password ",password)

		try:
			print("employee code above upper() method  ",emp_code)
			emp_code = emp_code.upper()
			print("employee code inside action_get_empid ",emp_code)
		
			#Calling API to get profile info
    	
			#Working url in office
		
			response = requests.get(---)
	

			#Working url at home
		
			#response = requests.get(---))
		
    		#Getting Json response
    	

			data = response.json()
			#emp_id
			emp_id = str(data['emp_id']['emp_id'])
			#doj
			doj = str(data['joining_date'])
			#designation
			designation = str(data['designation_id']['designation_name'])
			#grade
			grade = str(data['grade_id']['grade_name'])
			#anual_ctc
			anual_ctc = str(data['ctc'])
			#gross_salary
			gross_salary = str(data['gross_salary'])
			#basic_salary
			basic_salary = str(data['basic_salary'])
			#uan_number
			uan_number = str(data['uan_number'])
			#pf_number
			pf_number = str(data['pf_number'])
			#esic_number
			esic_number = str(data['esic_number'])
			
			print('Gross Salary ',gross_salary)
			print('UAN Number ',uan_number)
			print('Employee id ',emp_id)

			# response1 = """Your Gross Salary : {}.""".format(gross_salary)
			# response2 = """Your Basic Salary : {}.""".format(basic_salary)
			response3 = """Your Employee ID is  : {}.""".format(emp_id)
			
			# response4 = """Your UAN Number : {}.""".format(uan_number)
			# response5 = """Your ESIC Number : {}.""".format(esic_number)
			# response6 = """Your Employee ID : {}.""".format(emp_id)
			# response7 = """Your Name : {}.""".format(first_name+" "+last_name)

			# #response = "Hi am message from action get profile info"
							
			# #dispatcher.utter_message(response1)
			# #dispatcher.utter_message(response2)
			dispatcher.utter_message(response3)
			dispatcher.utter_template("utter_continue_profile_service",tracker)
			#dispatcher.utter_message(response4)
			#dispatcher.utter_message(response5)
			#dispatcher.utter_message(response6)
			# dispatcher.utter_message(response7)
		except:
			print("Exception has occured")
			dispatcher.utter_template("utter_invalid_login", tracker)
	


class ActionCheckLoggedInOrNot(Action):
	def name(self):
		return 'action_check_logged_in_or_not'
		
	def run(self, dispatcher, tracker, domain):
		emp_code = tracker.get_slot('emp_code')
		password = tracker.get_slot('password')
		print("employee code is",emp_code)
		print("password is",password)

		current_intent =  tracker.latest_message['intent'].get('name')

		print("current intent ",current_intent)
		
		try:

			if emp_code is " " and password is " ":
				raise Exception('I know Python!')
			print("below first if")

			if emp_code is None and password is None:
				raise Exception('I know Python!')
			print("below second if")

			# for leave services
			if current_intent == 'leav_eli':
				tracker.trigger_followup_action('action_get_leave_eligibility')
			elif current_intent == 'leav_bal':
				tracker.trigger_followup_action('action_get_leave_balance')
			elif current_intent == 'leaves':
				dispatcher.utter_template("utter_leave_information", tracker)

			# for profile services
			if current_intent == 'empID':
				print("Calling action_get_empid")
				tracker.trigger_followup_action('action_get_empid')
			elif current_intent == 'DOJ':
				print("Calling action_get_DOJ")
				tracker.trigger_followup_action('action_get_DOJ')
			elif current_intent == 'designation':
				tracker.trigger_followup_action('action_get_designation')
			elif current_intent == 'grade':
				tracker.trigger_followup_action('action_get_grade')
			elif current_intent == 'annual_ctc':
				tracker.trigger_followup_action('action_get_annual_ctc')
			elif current_intent == 'gr_sal':
				tracker.trigger_followup_action('action_get_mgs')
			elif current_intent == 'bs_sal':
				tracker.trigger_followup_action('action_get_mbs')
			elif current_intent == 'uan':
				tracker.trigger_followup_action('action_get_uan')
			elif current_intent == 'esic':
				tracker.trigger_followup_action('action_get_esic')
			elif current_intent == 'pf':
				tracker.trigger_followup_action('action_get_pf')
			elif current_intent == 'prof_info':
				dispatcher.utter_template("utter_profile_information", tracker)

			print("below if statements")
				
			
		except Exception as e:
			print("Inside except block : action_check_login 1111111 ",str(e))
			dispatcher.utter_template("utter_service_failed_login_message", tracker)

	return [SlotSet('emp_code',emp_code),SlotSet('password',password)]

And also have look at my story.md file:

stories.md (2.7 KB)

What I am trying is call action_get_empid action from action_check_logged_in_or_not

Can you please try FollowupAction("name_of_the_action") then share your code?

yup sure.

Below is the code for actions.py for class ActionCheckLoggedInOrNot::

class ActionCheckLoggedInOrNot(Action):
	def name(self):
		return 'action_check_logged_in_or_not'
		
	def run(self, dispatcher, tracker, domain):
		emp_code = tracker.get_slot('emp_code')
		password = tracker.get_slot('password')
		print("employee code is",emp_code)
		print("password is",password)

		current_intent =  tracker.latest_message['intent'].get('name')

		print("current intent ",current_intent)
		
		try:

			if emp_code is " " and password is " ":
				raise Exception('I know Python!')
			print("below first if")

			if emp_code is None and password is None:
				raise Exception('I know Python!')
			print("below second if")

			# for leave services
			if current_intent == 'leav_eli':
				tracker.trigger_followup_action('action_get_leave_eligibility')
			elif current_intent == 'leav_bal':
				tracker.trigger_followup_action('action_get_leave_balance')
			elif current_intent == 'leaves':
				dispatcher.utter_template("utter_leave_information", tracker)

			# for profile services
			if current_intent == 'empID':
				print("Calling action_get_empid")
				FollowupAction("action_get_empid")
				#tracker.trigger_followup_action('action_get_empid')
			elif current_intent == 'DOJ':
				print("Calling action_get_DOJ")
				tracker.trigger_followup_action('action_get_DOJ')
			elif current_intent == 'designation':
				tracker.trigger_followup_action('action_get_designation')
			elif current_intent == 'grade':
				tracker.trigger_followup_action('action_get_grade')
			elif current_intent == 'annual_ctc':
				tracker.trigger_followup_action('action_get_annual_ctc')
			elif current_intent == 'gr_sal':
				tracker.trigger_followup_action('action_get_mgs')
			elif current_intent == 'bs_sal':
				tracker.trigger_followup_action('action_get_mbs')
			elif current_intent == 'uan':
				tracker.trigger_followup_action('action_get_uan')
			elif current_intent == 'esic':
				tracker.trigger_followup_action('action_get_esic')
			elif current_intent == 'pf':
				tracker.trigger_followup_action('action_get_pf')
			elif current_intent == 'prof_info':
				dispatcher.utter_template("utter_profile_information", tracker)

			print("below if statements")
				
			
		except Exception as e:
			print("Inside except block : action_check_login 1111111 ",str(e))
			dispatcher.utter_template("utter_service_failed_login_message", tracker)

Is here a solution for, because with me it just says: AttributeError: ‘Tracker’ object has no attribute ‘trigger_followup_action’

Hi, You are getting this error because the tracker object of run function is a rasa_sdk tracker which does not contain trigger_followup_action. The method trigger_followup_action is part of DialogueStateTracker which is a class of rasa.core.trackers. I suggest you return an event for calling a followup action like below:

class ActionHelloWorld(Action):

    def name(self) -> Text:
        return "action_hello_world"

    def run(self, dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:

        dispatcher.utter_message("Hello World!")

        return [rasa_sdk.events.FollowupAction("your_custom_action")]
5 Likes

Continuing the discussion from How to call custom action from another custom action:

2019-11-22 01:50:07 INFO rasa_sdk.endpoint - Starting action endpoint server… 2019-11-22 01:50:07 INFO rasa_sdk.executor - Registered function for ‘action_search_productdetails’. 2019-11-22 01:50:07 INFO rasa_sdk.executor - Registered function for ‘action_suggest’. 2019-11-22 01:50:07 INFO rasa_sdk.endpoint - Action endpoint is up and running on http (‘0.0.0.0’, 5055)

after executing the action file i got above response

can any one help me please

Hi, did you manage to solve this? I’m looking for the exact same thing.

hey i add this to my code and than it worked:

from rasa_sdk.events import FollowupAction

I am getting same error when I am calling custom action from another action - It’s going into the infinite loop

Can I use a response as a followup action like "return [FollowupAction(‘utter_get_requestid’)]???

@btotharye @JiteshGaikwad

yes you can use responses in followup actions

from typing import Any, Text, Dict, List

from rasa_sdk import Action, Tracker

from rasa_sdk.executor import CollectingDispatcher

from rasa_sdk.events import FollowupAction

from rasa.core.trackers import DialogueStateTracker

class ActionHelloWorld(Action):

def name(self) -> Text:

    return "action_hello_world"

def run(self, dispatcher: CollectingDispatcher,

        tracker: DialogueStateTracker,

        domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:

    dispatcher.utter_message(text="Hello World!")

    print("Hello world action running")

    return [FollowupAction('utter_followup_response')]

class ActionFollowCheck(Action):

def name(self) -> Text:

    return "action_followup_check"

def run(self, dispatcher: CollectingDispatcher,

        tracker: Tracker,

        domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:

    dispatcher.utter_message(text="this is action after hello world")

    print("Followup action running")

    return []
1 Like

thanks @Sharada201. will try it

Hello Piyush,

You can try with attached files of action.py and stories.md as a referece. I have written sample code for followup action. You will get solution for your problem. I have written actions “action_hello_world” and “action_followup_check”. In stories.md file you will get that I only called “action_hello_world”.

stories:

happy path

  • greet

    • action_hello_world

actions.py (1.3 KB)

1 Like

I have a code similar and imports the next classes: I resolved my problem.

from rasa_sdk.events import ActionExecuted

from rasa_sdk.events import UserUttered

my code is

return [ActionExecuted("action_listen")] + [UserUttered("/indentity", { 
		"intent": {"confidence": 1, "name": "indentity"}, 
		"entities": [] 
		})]