Hi everyone,
I’m building a production-grade WhatsApp AI Agent for a Hospital Management System (BluelineMD) using n8n, and I’d like some architectural guidance from the community.
Goal
The AI should behave like a hospital receptionist and help patients with:
- Login
- Book Appointment
- Cancel Appointment
- Reschedule Appointment
- View Appointments
- Doctor Availability
- Hospital Information
The backend already exposes REST APIs for all these operations.
Current Architecture
WhatsApp Trigger
│
▼
Load Session (Supabase)
│
▼
AI Agent
│
├── BLMD_API_Registry Tool
│
└── Hospital_API_Executor Tool
│
▼
Update Session
│
▼
Reply to WhatsApp
Tools
1. BLMD_API_Registry
This is a Supabase table containing all API metadata.
Example row:
operation
appointment.getDoctors
url
https://api.abc.com/getDoctors
method
POST
headers
...
query_parameters
...
request_body
{
"healthCenterId":"",
"branchId":"",
"specialityId":""
}
The AI never hardcodes URLs.
It always retrieves API definitions from this registry.
2. Hospital_API_Executor
This is an Execute Workflow AI Tool.
Input
{
"action_type":"",
"payload":{},
"api_definition":{}
}
The subflow performs the HTTP request and returns the response.
Session Storage
We store session data in Supabase.
Current session contains things like:
{
"mobile_number":"",
"token":"",
"login_time":"",
"current_operation":"",
"working_payload":{},
"api_definition":{},
"patient_id":"",
"health_center_id":"",
"branch_id":"",
"speciality_id":"",
"doctor_id":"",
"service_id":"",
"slot_id":"",
"appointment_id":""
}
Every WhatsApp message loads this session before the AI runs.
Appointment Flow
Booking requires multiple APIs.
appointment.getHealthCenters
↓
appointment.getAllBranches
↓
appointment.getSpecialities
↓
appointment.getDoctors
↓
appointment.getAllServices
↓
appointment.getAllSlots
↓
appointment.createApptOrder
Each API depends on the previous API.
Example
Health Center
↓
Health Center ID
↓
Branches API
↓
Branch ID
↓
Speciality API
↓
Doctor API
Authentication
If token doesn’t exist
or
token expired (>24 hours)
the AI should automatically perform
patient.login
Then continue the original operation.
Biggest Problem
The AI Agent decides:
operation
↓
BLMD_API_Registry
↓
Ask missing fields
↓
Hospital_API_Executor
Everything happens inside ONE AI Agent execution.
Because of that,
I cannot update Supabase in the middle of the reasoning.
Example
AI determines
appointment.getHealthCenters
I would like to immediately save
current_operation
working_payload
api_definition
before continuing.
But there is no opportunity to update Supabase during AI reasoning.
Second Problem
Suppose the flow is
appointment.getHealthCenters
User selects
Apollo Hospital
Now I need
appointment.getAllBranches
Question:
Who should determine the next operation?
Should
- AI decide?
- Workflow decide?
- Subflow decide?
- BLMD_API_Registry store next_operation?
I’m unsure which architecture is best.
Third Problem
The AI Agent collects request_body fields.
Example
{
"email":"",
"password":""
}
User enters
email
AI asks
password
After password is received,
AI calls Hospital_API_Executor.
This works.
But if the AI execution fails halfway,
the partially collected payload is lost unless I persist it.
Again,
I cannot update Supabase while the AI is still reasoning.
Fourth Problem
Every WhatsApp message starts a completely new workflow execution.
So every execution must know
- current operation
- collected payload
- API definition
- login token
I’m loading them from Supabase.
But I’m unsure what is considered best practice with n8n AI Agents.
Current Ideas
Option 1
Single AI Agent
Pros
- Simple
Cons
- Cannot persist state during reasoning
Option 2
Split into two AI Agents
AI 1
Intent + State Manager
Returns
{
"operation":"",
"login_required":true,
"next_operation":""
}
Workflow saves session.
Then
AI 2
Conversation + Tool Execution
Uses
- BLMD_API_Registry
- Hospital_API_Executor
This seems cleaner.
Option 3
Don’t let AI manage workflow state.
Instead,
Use Code nodes and IF nodes to manage
- current_operation
- next_operation
- session
and let AI only handle conversation.
Questions
I’d appreciate guidance on the following:
- Is using two AI Agents a good pattern for this type of application?
- How do you manage long-running, multi-turn conversations with n8n AI Agents?
- Where do you persist conversation state during a multi-step process?
*
Inside AI memory?
*
Supabase?
*
Workflow variables?
*
Another approach? - How do you handle partial payload collection if the AI execution fails before calling the tool?
- Should the AI determine the next operation, or should the workflow handle that with a state machine?
- Is there a recommended pattern for building stateful AI workflows in n8n where multiple API calls depend on previous user selections?