Content
```markdown
# Appointment Booking System - A2A with Human-in-Loop
A multi-agent system demonstrating Agent-to-Agent (A2A) communication with human-in-the-loop workflow using Amazon Bedrock AgentCore Runtime.
## Overview
This example shows how to build an appointment booking system with two agents:
- **Appointment Agent**: Manages doctor availability and performs real timezone conversions
- **Orchestrator Agent**: Handles user requests, calls the appointment agent via A2A, and manages the confirmation workflow
## Key Features
1. **JSON Input**: Structured request payloads with timezone and preferences
2. **A2A Communication**: Orchestrator calls appointment agent using boto3 invoke
3. **Human-in-Loop**: Two-step workflow (request then confirm) without blocking execution
4. **Real Timezone Conversion**: Accurate timezone math that LLMs cannot perform reliably
## Prerequisites
- Python 3.10 or higher
- AWS CLI configured with credentials
- `agentcore` CLI installed: `pip install bedrock-agentcore-starter-toolkit`
## Deployment Instructions
### Step 1: Deploy Appointment Agent
```bash
cd appointment_agent
agentcore configure -e appointment_agent.py
agentcore launch
```
Save the **Agent ARN** from the output:
```
Agent ARN: arn:aws:bedrock-agentcore:us-east-1:ACCOUNT_ID:runtime/appointment_agent-XXXXX
```
### Step 2: Update Orchestrator with Appointment Agent ARN
Edit `orchestrator_agent/orchestrator_agent.py` line 7:
```python
APPOINTMENT_AGENT_ARN = "arn:aws:bedrock-agentcore:us-east-1:ACCOUNT_ID:runtime/appointment_agent-XXXXX"
```
### Step 3: Deploy Orchestrator Agent
```bash
cd ../orchestrator_agent
agentcore configure -e orchestrator_agent.py
agentcore launch
```
Save the **Agent ARN** from the output:
```
Agent ARN: arn:aws:bedrock-agentcore:us-east-1:ACCOUNT_ID:runtime/orchestrator_agent-XXXXX
```
### Step 4: Update Test Client with Orchestrator ARN
Edit `client/test_client.py` line 4:
```python
ORCHESTRATOR_ARN = "arn:aws:bedrock-agentcore:us-east-1:ACCOUNT_ID:runtime/orchestrator_agent-XXXXX"
```
### Step 5: Run the Test
```bash
cd ../client
pip install boto3
python test_client.py
```
## How It Works
### First Invocation: Request Appointment
```json
{
"user_timezone": "Europe/London",
"preferred_time": "14:00",
"step": "request"
}
```
The orchestrator calls the appointment agent via A2A, gets available slots, and returns options for confirmation.
### Second Invocation: Confirm Booking
```json
{
"step": "confirm",
"confirmed": true,
"slot_id": "Dr._Smith_Monday_09:00"
}
```
The orchestrator processes the confirmation and returns a booking confirmation.
## Sample Output
```
python test_client.py
================================================================================
Appointment Booking System - Human-in-Loop + A2A Demo
================================================================================
STEP 1: Requesting appointment...
================================================================================
Request: {
"user_timezone": "Europe/London",
"preferred_time": "14:00",
"step": "request"
}
I see you want to book a doctor appointment.
I found availability with Dr. Smith (General Practice).
Monday at 14:00 (your local time in Europe/London)
Duration: 30 minutes
Doctor's local time: 09:00 America/New_York
Would you like to confirm this appointment?
================================================================================
Response Data:
{
"result": "I see you want to book a doctor appointment.\n\nI found availability with Dr. Smith (General Practice).\n\nMonday at 14:00 (your local time in Europe/London)\nDuration: 30 minutes\nDoctor's local time: 09:00 America/New_York\n\nWould you like to confirm this appointment?",
"awaiting_confirmation": true,
"proposed_slot": {
"doctor": "Dr. Smith",
"day": "Monday",
"time_user_local": "14:00",
"timezone": "Europe/London",
"slot_id": "Dr._Smith_Monday_09:00"
},
"other_available_slots": [
{
"doctor": "Dr. Smith",
"specialty": "General Practice",
"day": "Monday",
"time_doctor_local": "10:00",
"time_user_local": "15:00",
"timezone_doctor": "America/New_York",
"timezone_user": "Europe/London",
"duration_mins": 30,
"slot_id": "Dr._Smith_Monday_10:00"
},
{
"doctor": "Dr. Johnson",
"specialty": "General Practice",
"day": "Monday",
"time_doctor_local": "11:00",
"time_user_local": "16:00",
"timezone_doctor": "America/New_York",
"timezone_user": "Europe/London",
"duration_mins": 30,
"slot_id": "Dr._Johnson_Monday_11:00"
}
],
"next_step_instructions": {
"to_confirm": {
"step": "confirm",
"confirmed": true,
"slot_id": "Dr._Smith_Monday_09:00"
},
"to_decline": {
"step": "confirm",
"confirmed": false,
"slot_id": "Dr._Smith_Monday_09:00"
}
}
}
================================================================================
STEP 2: User confirms appointment...
================================================================================
Confirmation: {
"step": "confirm",
"confirmed": true,
"slot_id": "Dr._Smith_Monday_09:00"
}
Appointment confirmed!
Confirmation ID: APT-ay_09:00
Doctor: Dr. Smith
Day: Monday
Time: 09:00
You will receive a confirmation email shortly with appointment details.
Please arrive 10 minutes early for check-in.
================================================================================
Final Response:
{
"result": "Appointment confirmed!\n\nConfirmation ID: APT-ay_09:00\nDoctor: Dr. Smith\nDay: Monday\nTime: 09:00\n\nYou will receive a confirmation email shortly with appointment details.\nPlease arrive 10 minutes early for check-in.",
"booking_confirmed": true,
"confirmation_id": "APT-ay_09:00",
"slot_id": "Dr._Smith_Monday_09:00",
"status": "CONFIRMED"
}
================================================================================
Demo Complete
================================================================================
This demonstrated:
1. JSON input with structured data (user_timezone, preferred_time)
2. A2A communication (orchestrator to appointment agent)
3. Human-in-loop (request, user confirms, booking)
4. Real timezone conversion (LLMs cannot do this accurately)
================================================================================
```
## Why This Pattern
This demonstrates how to handle human feedback in AgentCore Runtime without using `input()`, which doesn't work in containerized environments. The solution is to break the workflow into separate invocations where the agent returns and waits for the next request.
```