Context not shared across sub-agents despite same thread_id
Setup
A supervisor agent created with create_agent
Multiple sub-agents created with create_agent (patient_agent, appt_agent, book_appointment)
You expose each sub-agent to the supervisor as a tool, and you pass the same thread_id (from runtime.config["configurable"]["thread_id"]) to each sub-agent.
Behavior Goal
User asks for patient info → patient agent may ask for patient id / mobile / name+dob → user provides it → patient agent fetches and responds.
Later in the same thread, user asks for appointment details → appointment agent should reuse the patient identifier already provided, and not ask again.
Main Issue
Context is not shared across sub-agents, even though thread id is the same.
patient_agent = patient_information_retrieval_agent(
patient_info_tools, language_id, checkpointer
)
appt_agent = appointment_management_agent(
appointment_tools, language_id, checkpointer
)
book_appointment = book_appointment_agent(
book_appointment_tools, language_id, checkpointer
)
# ✅ Tools that call the sub-agent instances (closures)
@tool(return_direct=True)
async def fetch_patient_information_tool(request: str, runtime: ToolRuntime) -> str:
"""
Use this tool to retrieve patient information such as name, mobile number,
date of birth, or address.
This tool handles ONLY patient personal information queries. Call this when
the user asks about their personal details or provides a patient ID to retrieve
information.
Args:
request: The user's request for patient information
"""
root_thread_id = runtime.config["configurable"]["thread_id"]
logger.info(f"Root Thread ID: {root_thread_id}")
patient_info_config = {
"configurable": {"thread_id": root_thread_id},
# "metadata": {"sub_agent": "patient_info", "tool_name": "get_patient_info_tool"}
}
logger.info(f"Using patient_info_config: {patient_info_config}")
result = await patient_agent.ainvoke(
{"messages": [{"role": "user", "content": request}]},
config=patient_info_config
)
response = extract_last_ai_message(result)
logger.info(f"✅ get_patient_info_tool returning: {response[:200]}…")
return response
@tool(return_direct=True)
async def manage_appointment_tool(request: str, runtime: ToolRuntime) -> str:
"""
Use this tool to manage appointments including viewing, booking, canceling,
sending appointment details via message or whatsapp, or sending project location
via message or whatsapp.
This tool handles ALL appointment-management tasks. Call this when the user asks
about appointments details, sending appointment details via message or whatsapp,
sending project location via message or whatsapp, or wants to cancel or confirm an
appointment.
Args:
request: The user's appointment-related request
"""
root_thread_id = runtime.config["configurable"]["thread_id"]
appointment_management_config = {
"configurable": {"thread_id": root_thread_id},
}
result = await appt_agent.ainvoke(
{"messages": [{"role": "user", "content": request}]},
config=appointment_management_config
)
response = extract_last_ai_message(result)
logger.info(f"✅ manage_appointment_tool returning: {response[:200]}…")
return response
@tool(return_direct=True)
async def book_appointment_tool(request: str, runtime: ToolRuntime) -> str:
"""
Use this tool to book new appointments including selecting projects, clinics,
doctors, and time slots.
This tool handles ALL new appointment booking tasks. Call this when the user
wants to book an appointment.
Args:
request: The user's booking-related request
"""
root_thread_id = runtime.config["configurable"]["thread_id"]
book_appointment_config = {
"configurable": {"thread_id": root_thread_id},
}
result = await book_appointment.ainvoke(
{"messages": [{"role": "user", "content": request}]},
config=book_appointment_config
)
response = extract_last_ai_message(result)
logger.info(f"✅ book_appointment_tool returning: {response[:200]}…")
return response
# Log registered tools
logger.info(
"📋 Registering supervisor tools: "
"fetch_patient_information_tool, manage_appointment_tool, book_appointment_tool"
)
supervisor = create_agent(
model=model,
system_prompt=supervisor_prompt,
tools=[fetch_patient_information_tool, manage_appointment_tool, book_appointment_tool],
checkpointer=checkpointer
)
return supervisor, mcp, checkpointer_context
def patient_information_retrieval_agent(tools, language_id, checkpointer=None):
"""
Create a patient information retrieval agent.
"""
logger.info(f"Creating patient information retrieval agent with checkpointer: {checkpointer}")
prompt_folder = "english_prompts" if language_id == 2 else "arabic_prompts"
prompt_path = os.path.join(
os.path.dirname(__file__),
"..", "prompts", prompt_folder,
"patient_information_retrieval_prompt.yml"
)
logger.info(f"Loading patient information retrieval prompt with language id: {language_id}")
with open(prompt_path, "r", encoding="utf-8") as f:
prompts = yaml.safe_load(f)
return create_agent(
model=model,
tools=tools,
system_prompt=prompts["patient_information_retrieval_prompt"].format(
LANGUAGE_ID=language_id
),
name="patient_information_retrieval_agent",
checkpointer=checkpointer
)
