Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .changeset/seven-rules-invent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
---

Allow working group leaders to schedule meetings for groups they lead via Addie. Added meeting and event tools documentation to Addie's system prompt.
34 changes: 30 additions & 4 deletions server/src/addie/mcp/meeting-tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,14 @@ export async function canScheduleMeetings(slackUserId: string): Promise<boolean>
const isAdmin = await isSlackUserAdmin(slackUserId);
if (isAdmin) return true;

// TODO: Check if user is a working group leader
// For now, only admins can schedule
// Check if user is a leader of any working group
// getCommitteesLedByUser handles both Slack user IDs and WorkOS user IDs
const ledGroups = await workingGroupDb.getCommitteesLedByUser(slackUserId);
if (ledGroups.length > 0) {
logger.debug({ slackUserId, groupCount: ledGroups.length }, 'User is a working group leader');
return true;
}

return false;
}

Expand Down Expand Up @@ -298,11 +304,11 @@ export function createMeetingToolHandlers(
if (slackUserId) {
const canSchedule = await canScheduleMeetings(slackUserId);
if (!canSchedule) {
return '⚠️ You need to be an admin or working group leader to schedule meetings.';
return '⚠️ You need to be an admin or committee leader to schedule meetings.';
}
} else if (memberContext) {
if (memberContext.org_membership?.role !== 'admin') {
return '⚠️ You need admin or working group leader access to schedule meetings.';
return '⚠️ You need to be an admin or committee leader to schedule meetings.';
}
}
return null;
Expand All @@ -324,6 +330,26 @@ export function createMeetingToolHandlers(
return `❌ Working group not found: "${workingGroupSlug}". Check the slug and try again.`;
}

// Non-admin users can only schedule meetings for groups they lead
// This check runs for both Slack and web channels
const userId = getUserId();
if (userId) {
// Determine admin status from either Slack or web context
let isAdmin = false;
if (slackUserId) {
isAdmin = await isSlackUserAdmin(slackUserId);
} else if (memberContext?.org_membership?.role === 'admin') {
isAdmin = true;
}

if (!isAdmin) {
const isGroupLeader = await workingGroupDb.isLeader(workingGroup.id, userId);
if (!isGroupLeader) {
return `⚠️ You can only schedule meetings for committees you lead. You're not a leader of "${workingGroup.name}".`;
}
}
}

// Parse start time
const startTime = new Date(startTimeStr);
if (isNaN(startTime.getTime())) {
Expand Down
22 changes: 22 additions & 0 deletions server/src/addie/prompts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,28 @@ When users set up agents or publishers, walk through the full verification chain
- update_committee_document: Update a tracked document (leader only)
- delete_committee_document: Remove a tracked document (leader only)

**Events (available to admins and committee leads):**
- create_event: Create an AAO event (meetup, webinar, summit, workshop, conference). Creates in both Luma (registration) and AAO website. Required: title, start_time, event_type. Optional: description, end_time, timezone, venue details, virtual_url, max_attendees.
- list_events: List events personalized for the user (events they're registered for, chapter events, industry gatherings, global summits). Use include_past=true to show past events.
- get_event_details: Get details about a specific event including registration counts
- manage_event_registrations: List, approve, or export event registrations
- update_event: Modify event details

**Meetings (available to admins and committee leaders):**
- schedule_meeting: Schedule a committee meeting with Zoom and calendar invites. Requires working_group_slug, title, and start_time (ISO format). Optional: description, agenda, duration_minutes, timezone, topic_slugs. Creates Zoom link and sends calendar invites to committee members.
- list_upcoming_meetings: List upcoming meetings. Can filter by working_group_slug.
- get_my_meetings: Get the user's upcoming meetings
- get_meeting_details: Get details about a specific meeting including attendees and RSVP status
- rsvp_to_meeting: RSVP to a meeting (accepted, declined, tentative)
- cancel_meeting: Cancel a scheduled meeting (sends cancellation notices)
- add_meeting_attendee: Add someone to a meeting by email
- update_topic_subscriptions: Update which meeting topics a user is subscribed to in a working group

Example meeting scenarios:
- "Schedule a technical working group call for next Tuesday at 2pm ET" → Use schedule_meeting with working_group_slug="technical", appropriate title and start_time
- "What meetings do I have coming up?" → Use get_my_meetings
- "Set up a recurring weekly call for governance" → Note: Recurring meetings must be scheduled one at a time currently, or use Google Calendar's recurring feature directly

**Member Profile:**
- get_my_profile: Show user's profile
- update_my_profile: Update profile fields (user-scoped)
Expand Down