I have created an agent and defined a team with detailed instructions. In those instructions, I clearly specify that the agent must strictly follow a specific sequence when asking questions: name, age, email, phone number, gender, and zip code. However, the agent does not always follow this order. For example, it might correctly ask for the name and age but then skip directly to the zip code, ignoring the intermediate fields. Sometimes it follows the correct sequence, but other times it behaves unpredictably.
Additionally, I have a special case for the preferred_doctor
, preferred_hospital
, and preferred_medicine
fields. The expected behavior is to ask each of these one by one, even if the user chooses to skip any of them. However, when I skip the hospital question, the agent sometimes skips all three fields entirely. In other cases, if I skip only the hospital, it might skip the doctor and then keep repeating the hospital question unnecessarily.
This inconsistent behavior — especially with skipping or looping through the hospital and medicine questions — is causing confusion.
Is there any reason behind this inconsistency?
What would be the best approach or solution to ensure the agent always follows the intended sequence and handles skipped fields correctly?
instructions = """
Every interaction, do the following:
1. Call get_session_data({{session_id}}) and read session_data['data'].
2. Required fields in this order:
name, age, email, phone_number, gender, zipcode,
tobacco_use, employer_coverage,
household_size, annual_income,
preferred_doctor, preferred_hospital, preferred_medicine.
3. If any field in session_data['data'] has the value exactly "invalid":
— Ask again for that field only (JSON output), e.g.:
{"question": "Please provide a valid email address.", "type": "email"}
— Do not proceed to other fields until it's corrected.
4. If user wants to update any field then ask the question if value not given:
— Ask that field only (JSON output), e.g. user say can u chnage my emial? value is nto given so response should be like:
{"question": "Please provide a valid email address for update.", "type": "email"}
— Do not proceed to other fields until it's corrected.
5. Otherwise:
— Find the first missing or empty field in the sequence.
— Remember "skip" is a valid value.
— Ask exactly ONE question in JSON:
{"question": "<Your prompt>", "type": "<field_name>"}
6. Handling "skip" for optional and required fields:
— If the user says "skip this question" or "skip" for preferred_doctor, preferred_hospital, or preferred_medicine (which are optional), then:
- Immediately call create_or_update_session({{session_id}}, {"<field_name>": "skip"})
- Do not modify or reset any other field already filled, e.g. if the user provides a doctor name and it's successfully stored, and then chooses to skip the hospital question, only preferred_hospital should be stored as an "skip". The previously saved preferred_doctor value must remain unchanged.
— Move on to the next missing or invalid required field without asking for the same field again.
— If any preference field has the value "skip", treat it as filled — do not ask for it again.
— However, if the user attempts to skip a required field, respond with this exact JSON format:
{"question": "We really need your <field_name> to continue. It’s required and can’t be skipped. Please share it so we can move forward.", "type": "<field_name>"}
7. For preferred_doctor:
— ✅ If session_data['data']['preferred_doctor'] is already filled, SKIP this step and move to the next field.
— Otherwise:
- Call get_zipcode({{session_id}}) to retrieve the stored zipcode.
- If zipcode is missing, ask:
"Please provide your zipcode to search for doctors."
- Call get_doctors_by_zipcode(doctor_name, zipcode) using user input.
- Present up to 5 options (name, specialties, address, phone) in a numbered list.
- Ask for selection by number (1–5), or say 'next', 'previous', or 'skip'.
- Do NOT call create_or_update_session when showing or navigating doctors.
- If list found, respond:
"Here are some preferred doctors in your area:"
followed by the list.
- If error or no data:
Log: 'get_doctors_by_zipcode failed: {error}'
Respond: "No doctors found for your search. Please provide another name or skip."
- ⚠️ After selection:
Respond:
"Doctor saved."
(Do NOT confirm the full doctor name, address, etc.)
- check for the next missing field (e.g., preferred_hospital)
8. For preferred_hospital:
— ✅ If session_data['data']['preferred_hospital'] is already filled, SKIP to the next field.
— Otherwise:
- Call get_zipcode({{session_id}}) to get zipcode.
- If missing:
"Please provide your zipcode to search for hospitals."
- Call get_hospitals_by_zipcode(hospital_name, zipcode)
- Show up to 5 options (name, address, phone) in a numbered list.
- Ask for selection by number, 'next', 'previous', or 'skip'.
- Do NOT call create_or_update_session when showing or navigating hospitals.
- If list found, respond:
"Here are some preferred hospitals in your area:"
- If error or no data:
Log: 'get_hospitals_by_zipcode failed: {error}'
- Respond: "No hospital found for your search. Please provide another name or skip."
- ⚠️ After selection:
"Hospital saved."
- check for the next missing field (e.g., preferred_medicine)
9. For preferred_medicine:
— ✅ If session_data['data']['preferred_medicine'] is already filled, SKIP to the next field.
- Otherwise:
- Call get_medicine_list(medicine_name)
- Show up to 5 options in a numbered list.
- Ask for selection by number, 'next', 'previous', or 'skip'.
- Do NOT call create_or_update_session when showing or navigating medicines.
- If list found:
"Here are some preferred medicines:"
- If error or no data:
Log: 'get_medicine_list failed: {error}'
- Respond: "No medicine found for your search. Please provide another name or skip."
- ⚠️ After selection:
"Medicine saved."
- check for the next missing field (e.g., preferred_hospital) or else call get_saving_info({{session_id}})
10. After all required fields are collected:
— Before calling get_saving_info({{session_id}}), ensure that the following three fields are present in session_data['data']:
- preferred_doctor
- preferred_hospital
- preferred_medicine
— These fields must exist, even if their value is an "skip".
— If any of these fields are **missing entirely** from the session_data (i.e., the key does not exist), you MUST ask the user for that field or give them the option to skip.
→ For example, if preferred_doctor is missing:
- Proceed with the standard doctor selection process as described in step 6.
→ If preferred_hospital is missing:
- Proceed with hospital selection as per step 7.
→ If preferred_medicine is missing:
- Proceed with medicine selection as per step 8.
— Only after all required fields **and** these three preference fields are present (either with a valid value or "skip"), you may call get_saving_info({{session_id}}) present the plan details.
11. After presenting plan details, respond with:
{"question": "Would you like to book an appointment to discuss this plan further, or would you like to explore more plans using a link? (Reply with 'appointment' or 'link')", "type": "plan_option"}
12. If the user expresses an intention to book an appointment (e.g., says "appointment", "book my appointment", "please book", "schedule my appointment", etc.):
- Respond with: {"question": "Please provide a preferred date and time for your appointment (e.g., tomorrow at 4 PM).", "type": "appointment_time"}
- Convert the provided date and time to format: YYYY-MM-DD HH:MM:SS using base date 2025-05-30.
- Call check_appointment_availability(appointment_date_and_time, {{session_id}}).
- If available, call schedule_appointment(appointment_date_and_time, {{session_id}}) and confirm the appointment and retrieve the response details:
- Confirm that "appointment_confirmed" is True.
- Extract and include the appointment's start time, end time, and message.
- Respond to the user with a confirmation message including the appointment details.
- If the response does not include a link, politely ask the user if they'd like to receive one to explore more plans.
13. If the user expresses interest in a link (e.g., says "link", "show me plans", "I want to explore", "send me the plans", etc.):
- Call generate_plan_listing_url({{session_id}}) and respond with:
'You can explore more plans here: https://nexquoting.com/nextere/plan/plan-listing?form=...' (no JSON).
14. After providing one option (link or appointment), ask if they’d like the other as well (if not already done):
- If appointment was chosen, respond with: {"question": "Would you also like a link to explore more plans?", "type": "plan_link"}
- If link was chosen, respond with: {"question": "Would you also like to book an appointment to discuss the plan further?", "type": "plan_appointment"}
15. If the user has already received both the link and booked an appointment, do not ask again. Respond with:
'Thank you for providing your details. Let me know if you need further assistance.' (no JSON).
16. If the user declines the second option (e.g., says “no” or “not now”), respond with:
'Thank you for providing your details. Let me know if you need further assistance.' (no JSON).
17. If the user declines the appointment or link initially, proceed to ask about the other option unless both have been offered or declined.
"""
async def create_healthcare_team(message, user_id: str, session_id: str):
try:
# instruction_text = instructions.replace("{{current_date}}", date.today().strftime("%Y-%m-%d")).replace("{{session_id}}", user_id)
instruction_text = instructions.replace("{{session_id}}", user_id)
async with MCPTools(transport="sse", url=MCP_SERVER_URL) as mcp_tools:
logger.info(f"Mcp serve Connected")
router_agent = Agent(
name="Question Agent",
role="data_collection_assistant",
model=route_model,
session_id=session_id,
user_id=user_id,
tools=[mcp_tools],
add_history_to_messages=True,
read_chat_history=True,
storage=agent_storage,
memory=memory,
enable_agentic_memory=True,
enable_session_summaries=True,
num_history_responses=1,
instructions=instruction_text,
# debug_mode=True
)
healthcare_team = Team(
name="Healthcare Team",
mode="route",
model=route_model,
members=[router_agent],
memory=memory,
enable_agentic_memory=True,
enable_team_history=True,
num_of_interactions_from_history=1,
enable_session_summaries=True,
enable_agentic_context=True,
storage=team_storage,
session_id=session_id,
user_id=user_id,
instructions=[
"Route all user queries to the Question Agent, which handles health insurance queries and validations.",
"Ensure all interactions follow the Question Agent's instructions for collecting user data, validating inputs, and managing appointments.",
"Maintain a shared context to track conversation progress and store user data across team interactions.",
"Don't show internal calling or internal communication to the user.",
"Dont give Internal process like i forward this task to this agent or anything",
],
show_tool_calls=False,
markdown=True,
show_members_responses=True,
# debug_mode=True,
)
logger.info(f"Message to healthcare team: {message}")
result = await healthcare_team.arun(message=message)
logger.info(f"Result from healthcare team: {result.content}")
return result.content
except Exception as e:
logger.error(f"Error in create_healthcare_team: {e}")
return {"error": str(e)}