modify_event
Edit existing calendar events by updating details such as title, time, location, attendees, and description. Designed for Google Workspace users to manage events efficiently.
Instructions
Modifies an existing event.
Args:
user_google_email (str): The user's Google email address. Required.
event_id (str): The ID of the event to modify.
calendar_id (str): Calendar ID (default: 'primary').
summary (Optional[str]): New event title.
start_time (Optional[str]): New start time (RFC3339, e.g., "2023-10-27T10:00:00-07:00" or "2023-10-27" for all-day).
end_time (Optional[str]): New end time (RFC3339, e.g., "2023-10-27T11:00:00-07:00" or "2023-10-28" for all-day).
description (Optional[str]): New event description.
location (Optional[str]): New event location.
attendees (Optional[List[str]]): New attendee email addresses.
timezone (Optional[str]): New timezone (e.g., "America/New_York").
Returns:
str: Confirmation message of the successful event modification with event link.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| attendees | No | ||
| calendar_id | No | primary | |
| description | No | ||
| end_time | No | ||
| event_id | Yes | ||
| location | No | ||
| service | Yes | ||
| start_time | No | ||
| summary | No | ||
| timezone | No | ||
| user_google_email | Yes |
Implementation Reference
- gcalendar/calendar_tools.py:655-655 (registration)Registers the 'modify_event' function as a server tool using the @server.tool() decorator from core.server.@server.tool()
- gcalendar/calendar_tools.py:658-696 (schema)The function signature and comprehensive docstring define the schema for the 'modify_event' tool inputs, including optional parameters for event fields, reminders, transparency, and Google Meet.async def modify_event( service, user_google_email: str, event_id: str, calendar_id: str = "primary", summary: Optional[str] = None, start_time: Optional[str] = None, end_time: Optional[str] = None, description: Optional[str] = None, location: Optional[str] = None, attendees: Optional[List[str]] = None, timezone: Optional[str] = None, add_google_meet: Optional[bool] = None, reminders: Optional[Union[str, List[Dict[str, Any]]]] = None, use_default_reminders: Optional[bool] = None, transparency: Optional[str] = None, ) -> str: """ Modifies an existing event. Args: user_google_email (str): The user's Google email address. Required. event_id (str): The ID of the event to modify. calendar_id (str): Calendar ID (default: 'primary'). summary (Optional[str]): New event title. start_time (Optional[str]): New start time (RFC3339, e.g., "2023-10-27T10:00:00-07:00" or "2023-10-27" for all-day). end_time (Optional[str]): New end time (RFC3339, e.g., "2023-10-27T11:00:00-07:00" or "2023-10-28" for all-day). description (Optional[str]): New event description. location (Optional[str]): New event location. attendees (Optional[List[str]]): New attendee email addresses. timezone (Optional[str]): New timezone (e.g., "America/New_York"). add_google_meet (Optional[bool]): Whether to add or remove Google Meet video conference. If True, adds Google Meet; if False, removes it; if None, leaves unchanged. reminders (Optional[Union[str, List[Dict[str, Any]]]]): JSON string or list of reminder objects to replace existing reminders. Each should have 'method' ("popup" or "email") and 'minutes' (0-40320). Max 5 reminders. Example: '[{"method": "popup", "minutes": 15}]' or [{"method": "popup", "minutes": 15}] use_default_reminders (Optional[bool]): Whether to use calendar's default reminders. If specified, overrides current reminder settings. transparency (Optional[str]): Event transparency for busy/free status. "opaque" shows as Busy, "transparent" shows as Available/Free. If None, preserves existing transparency setting. Returns: str: Confirmation message of the successful event modification with event link. """
- gcalendar/calendar_tools.py:658-859 (handler)Core handler logic for modifying Google Calendar events. Constructs update payload from optional parameters, preserves existing data, handles special features like reminders, transparency, and Google Meet, then executes the Google Calendar API update.async def modify_event( service, user_google_email: str, event_id: str, calendar_id: str = "primary", summary: Optional[str] = None, start_time: Optional[str] = None, end_time: Optional[str] = None, description: Optional[str] = None, location: Optional[str] = None, attendees: Optional[List[str]] = None, timezone: Optional[str] = None, add_google_meet: Optional[bool] = None, reminders: Optional[Union[str, List[Dict[str, Any]]]] = None, use_default_reminders: Optional[bool] = None, transparency: Optional[str] = None, ) -> str: """ Modifies an existing event. Args: user_google_email (str): The user's Google email address. Required. event_id (str): The ID of the event to modify. calendar_id (str): Calendar ID (default: 'primary'). summary (Optional[str]): New event title. start_time (Optional[str]): New start time (RFC3339, e.g., "2023-10-27T10:00:00-07:00" or "2023-10-27" for all-day). end_time (Optional[str]): New end time (RFC3339, e.g., "2023-10-27T11:00:00-07:00" or "2023-10-28" for all-day). description (Optional[str]): New event description. location (Optional[str]): New event location. attendees (Optional[List[str]]): New attendee email addresses. timezone (Optional[str]): New timezone (e.g., "America/New_York"). add_google_meet (Optional[bool]): Whether to add or remove Google Meet video conference. If True, adds Google Meet; if False, removes it; if None, leaves unchanged. reminders (Optional[Union[str, List[Dict[str, Any]]]]): JSON string or list of reminder objects to replace existing reminders. Each should have 'method' ("popup" or "email") and 'minutes' (0-40320). Max 5 reminders. Example: '[{"method": "popup", "minutes": 15}]' or [{"method": "popup", "minutes": 15}] use_default_reminders (Optional[bool]): Whether to use calendar's default reminders. If specified, overrides current reminder settings. transparency (Optional[str]): Event transparency for busy/free status. "opaque" shows as Busy, "transparent" shows as Available/Free. If None, preserves existing transparency setting. Returns: str: Confirmation message of the successful event modification with event link. """ logger.info( f"[modify_event] Invoked. Email: '{user_google_email}', Event ID: {event_id}" ) # Build the event body with only the fields that are provided event_body: Dict[str, Any] = {} if summary is not None: event_body["summary"] = summary if start_time is not None: event_body["start"] = ( {"date": start_time} if "T" not in start_time else {"dateTime": start_time} ) if timezone is not None and "dateTime" in event_body["start"]: event_body["start"]["timeZone"] = timezone if end_time is not None: event_body["end"] = ( {"date": end_time} if "T" not in end_time else {"dateTime": end_time} ) if timezone is not None and "dateTime" in event_body["end"]: event_body["end"]["timeZone"] = timezone if description is not None: event_body["description"] = description if location is not None: event_body["location"] = location if attendees is not None: event_body["attendees"] = [{"email": email} for email in attendees] # Handle reminders if reminders is not None or use_default_reminders is not None: reminder_data = {} if use_default_reminders is not None: reminder_data["useDefault"] = use_default_reminders else: # Preserve existing event's useDefault value if not explicitly specified try: existing_event = service.events().get(calendarId=calendar_id, eventId=event_id).execute() reminder_data["useDefault"] = existing_event.get("reminders", {}).get("useDefault", True) except Exception as e: logger.warning(f"[modify_event] Could not fetch existing event for reminders: {e}") reminder_data["useDefault"] = True # Fallback to True if unable to fetch # If custom reminders are provided, automatically disable default reminders if reminders is not None: if reminder_data.get("useDefault", False): reminder_data["useDefault"] = False logger.info("[modify_event] Custom reminders provided - disabling default reminders") validated_reminders = _parse_reminders_json(reminders, "modify_event") if reminders and not validated_reminders: logger.warning("[modify_event] Reminders provided but failed validation. No custom reminders will be set.") elif validated_reminders: reminder_data["overrides"] = validated_reminders logger.info(f"[modify_event] Updated reminders with {len(validated_reminders)} custom reminders") event_body["reminders"] = reminder_data # Handle transparency validation _apply_transparency_if_valid(event_body, transparency, "modify_event") if ( timezone is not None and "start" not in event_body and "end" not in event_body ): # If timezone is provided but start/end times are not, we need to fetch the existing event # to apply the timezone correctly. This is a simplification; a full implementation # might handle this more robustly or require start/end with timezone. # For now, we'll log a warning and skip applying timezone if start/end are missing. logger.warning( "[modify_event] Timezone provided but start_time and end_time are missing. Timezone will not be applied unless start/end times are also provided." ) if not event_body: message = "No fields provided to modify the event." logger.warning(f"[modify_event] {message}") raise Exception(message) # Log the event ID for debugging logger.info( f"[modify_event] Attempting to update event with ID: '{event_id}' in calendar '{calendar_id}'" ) # Get the existing event to preserve fields that aren't being updated try: existing_event = await asyncio.to_thread( lambda: service.events().get(calendarId=calendar_id, eventId=event_id).execute() ) logger.info( "[modify_event] Successfully retrieved existing event before update" ) # Preserve existing fields if not provided in the update _preserve_existing_fields(event_body, existing_event, { "summary": summary, "description": description, "location": location, "attendees": attendees }) # Handle Google Meet conference data if add_google_meet is not None: if add_google_meet: # Add Google Meet request_id = str(uuid.uuid4()) event_body["conferenceData"] = { "createRequest": { "requestId": request_id, "conferenceSolutionKey": { "type": "hangoutsMeet" } } } logger.info(f"[modify_event] Adding Google Meet conference with request ID: {request_id}") else: # Remove Google Meet by setting conferenceData to empty event_body["conferenceData"] = {} logger.info("[modify_event] Removing Google Meet conference") elif 'conferenceData' in existing_event: # Preserve existing conference data if not specified event_body["conferenceData"] = existing_event["conferenceData"] logger.info("[modify_event] Preserving existing conference data") except HttpError as get_error: if get_error.resp.status == 404: logger.error( f"[modify_event] Event not found during pre-update verification: {get_error}" ) message = f"Event not found during verification. The event with ID '{event_id}' could not be found in calendar '{calendar_id}'. This may be due to incorrect ID format or the event no longer exists." raise Exception(message) else: logger.warning( f"[modify_event] Error during pre-update verification, but proceeding with update: {get_error}" ) # Proceed with the update updated_event = await asyncio.to_thread( lambda: service.events() .update(calendarId=calendar_id, eventId=event_id, body=event_body, conferenceDataVersion=1) .execute() ) link = updated_event.get("htmlLink", "No link available") confirmation_message = f"Successfully modified event '{updated_event.get('summary', summary)}' (ID: {event_id}) for {user_google_email}. Link: {link}" # Add Google Meet information if conference was added if add_google_meet is True and "conferenceData" in updated_event: conference_data = updated_event["conferenceData"] if "entryPoints" in conference_data: for entry_point in conference_data["entryPoints"]: if entry_point.get("entryPointType") == "video": meet_link = entry_point.get("uri", "") if meet_link: confirmation_message += f" Google Meet: {meet_link}" break elif add_google_meet is False: confirmation_message += " (Google Meet removed)" logger.info( f"Event modified successfully for {user_google_email}. ID: {updated_event.get('id')}, Link: {link}" ) return confirmation_message
- gcalendar/calendar_tools.py:28-84 (helper)Helper to parse and validate custom reminders JSON/list input. Used in modify_event for the 'reminders' parameter.def _parse_reminders_json(reminders_input: Optional[Union[str, List[Dict[str, Any]]]], function_name: str) -> List[Dict[str, Any]]: """ Parse reminders from JSON string or list object and validate them. Args: reminders_input: JSON string containing reminder objects or list of reminder objects function_name: Name of calling function for logging Returns: List of validated reminder objects """ if not reminders_input: return [] # Handle both string (JSON) and list inputs if isinstance(reminders_input, str): try: reminders = json.loads(reminders_input) if not isinstance(reminders, list): logger.warning(f"[{function_name}] Reminders must be a JSON array, got {type(reminders).__name__}") return [] except json.JSONDecodeError as e: logger.warning(f"[{function_name}] Invalid JSON for reminders: {e}") return [] elif isinstance(reminders_input, list): reminders = reminders_input else: logger.warning(f"[{function_name}] Reminders must be a JSON string or list, got {type(reminders_input).__name__}") return [] # Validate reminders if len(reminders) > 5: logger.warning(f"[{function_name}] More than 5 reminders provided, truncating to first 5") reminders = reminders[:5] validated_reminders = [] for reminder in reminders: if not isinstance(reminder, dict) or "method" not in reminder or "minutes" not in reminder: logger.warning(f"[{function_name}] Invalid reminder format: {reminder}, skipping") continue method = reminder["method"].lower() if method not in ["popup", "email"]: logger.warning(f"[{function_name}] Invalid reminder method '{method}', must be 'popup' or 'email', skipping") continue minutes = reminder["minutes"] if not isinstance(minutes, int) or minutes < 0 or minutes > 40320: logger.warning(f"[{function_name}] Invalid reminder minutes '{minutes}', must be integer 0-40320, skipping") continue validated_reminders.append({ "method": method, "minutes": minutes }) return validated_reminders
- gcalendar/calendar_tools.py:113-128 (helper)Helper to preserve existing event fields (summary, description, location, attendees) when not explicitly updated in modify_event.def _preserve_existing_fields(event_body: Dict[str, Any], existing_event: Dict[str, Any], field_mappings: Dict[str, Any]) -> None: """ Helper function to preserve existing event fields when not explicitly provided. Args: event_body: The event body being built for the API call existing_event: The existing event data from the API field_mappings: Dict mapping field names to their new values (None means preserve existing) """ for field_name, new_value in field_mappings.items(): if new_value is None and field_name in existing_event: event_body[field_name] = existing_event[field_name] logger.info(f"[modify_event] Preserving existing {field_name}") elif new_value is not None: event_body[field_name] = new_value