File size: 5,985 Bytes
2814194
 
 
 
 
 
 
 
 
e43b10e
 
15f3b01
e43b10e
01ed642
2814194
 
 
 
 
e43b10e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4aab3e0
 
 
 
 
 
 
15f3b01
4aab3e0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2814194
 
d24e07b
2143a90
2814194
 
15f3b01
d24e07b
2814194
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
from fastapi import FastAPI, Form
from fastapi.responses import Response
from twilio.twiml.messaging_response import MessagingResponse
from dotenv import load_dotenv
from agno.agent import Agent
from agno.models.google import Gemini
from agno.tools.googlecalendar import GoogleCalendarTools
import datetime
from zoneinfo import ZoneInfo
import gspread
from google.oauth2.service_account import Credentials
from agno.storage.sqlite import SqliteStorage
from agno.tools import tool
import os

load_dotenv()

app = FastAPI()

SERVICE_ACCOUNT_FILE = 'hybrid-subject-456511-t8-2eb6032818f8.json'
SCOPES = ['https://www.googleapis.com/auth/spreadsheets', 'https://www.googleapis.com/auth/drive']
credentials = Credentials.from_service_account_file(SERVICE_ACCOUNT_FILE, scopes=SCOPES)
gc = gspread.authorize(credentials)
spreadsheet = gc.open_by_url('https://docs.google.com/spreadsheets/d/1LfeH3lueDz7686bSzhNT_4bq75U0cmsLlcx4PaxEZE4/edit')
worksheet = spreadsheet.get_worksheet(0)

def log_before_call(fc):
    """Pre-hook: Log arguments before calling the tool"""
    print(f"πŸ“‹ Adding appointment with details: {fc.arguments}")

def log_after_call(fc):
    """Post-hook: Log result after calling the tool"""
    print(f"βœ… Appointment tool completed with result: {fc.result}")

@tool(
    name="add_patient_appointment",
    description="Add a patient's appointment to the worksheet",
    show_result=True,
    stop_after_tool_call=True,
    pre_hook=log_before_call,
    post_hook=log_after_call,
    cache_results=False  # usually better off for dynamic actions like this
)
def add_appointment(name: str, reason: str, datetime_str: str, contact: str) -> str:
    """
    Add a new appointment entry.

    Args:
        name (str): Patient's name
        reason (str): Reason for appointment
        datetime_str (str): Date and time range (e.g., "11/7/2025 - 2 PM to 4 PM")
        contact (str): Contact information (email or phone)

    Returns:
        str: Confirmation message
    """
    new_row = [name, reason, datetime_str, contact]
    try:
        worksheet.append_row(new_row)
        return f"πŸ—“οΈ Appointment added for {name} on {datetime_str} for '{reason}'. Contact: {contact}"
    except Exception as e:
        return f"❌ Error adding appointment: {str(e)}"

agent = Agent(
    model=Gemini(
        id="gemini-2.5-pro-exp-03-25",
        api_key=os.getenv("gemini_key")
    ),
    tools=[GoogleCalendarTools(credentials_path="./credentials.json",token_path="./token.json"),
          add_appointment],
    storage=SqliteStorage(table_name="agent_sessions", db_file="./agent_storage.db"),
    show_tool_calls=True,
    instructions=[
            f"""
            You are a helpful assistant. Today is {datetime.datetime.now(ZoneInfo("Asia/Kolkata"))} and the user's timezone is Asia/Kolkata.
            Your role is to assist users in booking appointments with doctors and adding events to Google Calendar.

            Your tasks include:
                - Retrieving a doctor's scheduled events from a specified date and time.
                - Creating calendar events based on provided details.

            Hospital Details:
                - Hospital Name: ABC Hospital
                - Hospital Address: 123, ABC Street, New York, NY, USA
                - Hospital Phone: +91 12345 67890
                - Operating Hours: 9 AM to 5 PM

            Doctor Details:

            - Doctor 1:
                - Email: [email protected]
                - Name: Dr. Shrey Lakhani
                - Phone: +91 88669 88667
                - Address: 123, ABC Street, City, State, Country

            - Doctor 2:
                - Email: [email protected]
                - Name: Dr. Ketan Rupala
                - Phone: +91 88669 88666
                - Address: 123, ABC Street, City, State, Country

            Notes:
                - Doctors are available from 9 AM to 5 PM.
                - Always add the doctor as an attendee in the calendar event.
                - Ask the user for their email address to add them as an attendee.
                - Ask for the user's phone number for contact purposes.
                - Ask for the user's name to include in the event title.
                - Include the reason for the appointment in the event description.
                - Always ask for user confirmation before booking an appointment.
                - Always ask for user confirmation before creating an event.
                - Always add Entry in Google Sheet for the appointment using the add_appointment function.
                - Always generate conciess and clear short response.

            Be polite, upbeat, and positive at all times.

            If the user is asking about today's appointments, only list today's events.

            Your goal is to gather the necessary information from the user to create a calendar event, and make sure to include the doctor as an attendee.
            """
    ],
    add_datetime_to_instructions=True,
    add_history_to_messages=True,
    markdown=True,
    num_history_responses=20,
    description="You are a friendly and professional virtual assistant, dedicated to helping users book appointments with doctors. As a representative of the hospital, you always respond with politeness, positivity, and enthusiasm. Before finalizing any appointment, you ensure to ask the user for confirmation, making sure everything is clear and agreed upon.",
)

@app.post("/sms")
async def sms_reply(Body: str = Form(...), From: str = Form(...)):
    
    print(f"Received message: {Body}")

    try:
        bot_response = agent.run(Body, markdown=True, session_id=From).content
        print(f"Received sent: {bot_response}")
    except Exception as e:
        bot_response = f"Oops! Something went wrong: {str(e)}"

    twilio_response = MessagingResponse()
    twilio_response.message(bot_response)
    return Response(content=str(twilio_response), media_type="application/xml")