Skip to content

Commit 209d289

Browse files
authored
feat: simplify agent booking flow — pre-resolution, tool filtering, Redis persistence (#32)
* feat: smart @mention booking flow with multi-attendee support - Rewrite booking flow in system prompt to clarification-first logic with fast-path for fully-specified requests - Add guestEmails field to book_meeting tool for email-only additional attendees (Strategy A: guests array in initial POST) - Add add_booking_attendee tool for full attendee records with name + timezone after booking (Strategy B: POST /bookings/{uid}/attendees) - Add AddAttendeeInput type and addBookingAttendee() client function - Add guests field to CreateBookingInput type - Relax CRITICAL RULES to support multi-step booking flows and re-calling check_availability for alternative slots - Update check_availability description to allow re-calls - Bump MAX_STEPS from 10 to 15 for multi-attendee flows - Update Available Capabilities to list add_booking_attendee * fix * refactor: simplify agent booking flow with pre-resolution, tool filtering, and Redis persistence - Remove check_account_linked tool (bot.ts already checks before agent) - Pre-resolve Slack @mentions to name+email before calling agent - Inject linked user context (email/timezone/username) into system prompt - Rewrite system prompt with checklist-based single-decision booking - Persist tool results in Redis (keyed by threadId, 30min TTL) - Context-aware tool filtering: CORE (7 booking tools) vs EXTENDED (admin) - Add loop guard: force text if same tool called 3x with identical args - Reduce MAX_STEPS from 15 to 8 (agent needs 3-4 steps with optimizations) * update * update 2 * fix: booking flow — timezone-aware dates, tighter loop guard, ASAP handling, tool context reuse - Replace bare ISO timestamp with timezone-aware date in system prompt - Add explicit past-date comparison rule against user's timezone - Lower loop guard threshold from 3 to 2 identical calls - Reduce MAX_STEPS from 8 to 6 - Rewrite tool context injection: user role, deduplicate by tool name, inject at start of history - Add ASAP/urgency shortcut section to booking flow - Add duration mismatch detection rule - Strengthen tool usage rules (no same tool twice per step, must use returned data) - Add single event type auto-select logic * update the code * feat: add attendee calendar booking flow — list_event_types_by_username tool - Add getEventTypesByUsername() to calcom/client.ts (public API, no auth needed) - Add list_event_types_by_username tool to agent createCalTools - Add list_event_types_by_username to CORE_TOOL_NAMES - Add WHOSE CALENDAR TO USE section to system prompt booking flow * update code * update * fix: prevent false-positive Slack auth error + add custom booking field support Fix 1: Updated getCustomErrorMessage in all 3 handlers to return generic error when lastStreamErrorRef is set and caught error is Slack auth error. Fix 2a: Added responses?: Record<string, unknown> to CreateBookingInput and CreatePublicBookingInput types. Fix 2b: Added responses parameter to book_meeting and book_meeting_public tool schemas, passed through to API calls. Fix 2c: Included bookingFields in list_event_types_by_username response. Fix 2d: Added CUSTOM BOOKING FIELDS section to system prompt instructing agent to collect required custom field values and pass as responses. Fix 3: Hardened postAgentStream to re-throw generic error when Slack auth error is secondary to an agent stream failure. Also fixed duplicate rule #6 numbering in CRITICAL RULES. * fix: replace non-null assertions with nullish coalescing in check_availability_public * revert the prod url in manifest * fix: encrypt tool-context in Redis + pass metadata for webhook notification routing 1. Encrypt tool-context entries in Redis using existing encryptData/decryptData (PII protection for attendee names, emails, booking details). Legacy plaintext entries are handled gracefully by decryptData. 2. Added metadata?: Record<string, string> to CreatePublicBookingInput. 3. Added platform parameter to createCalTools, threaded from runAgentStream. 4. Both book_meeting and book_meeting_public now pass metadata with slack_team_id/slack_user_id or telegram_chat_id so Cal.com webhooks can route notifications back to the correct Slack/Telegram user. * feat: agentic flows, error handling, API robustness, search, profile, event types, reschedule & more (#41) * feat: agentic cancel booking flow — enriched responses, recurring support, guided prompt * feat: agentic confirm/decline flow — enriched responses, guided prompt, batch support * update code * fix: error handling & API robustness — CalcomApiError classifier, friendly messages, schema fixes Part A: Fix misleading error messages - A1: Add isCalcomApiError classifier + friendlyCalcomError helper with status-specific messages - A2: Add isSlackAuthError guard to /cal slash command and retry_response handlers - A3: Soften Slack auth error message (less alarming, directs to admin) - A4: Sanitize confirm_booking error (don't expose raw API errors) - A5: Fix App Home catch-all to only suggest reconnecting on 401/403 Part B: Fix API schema mismatches - B1: Fix getAvailableSlots to use cal-api-version 2024-09-04 - B2: Rename responses → bookingFieldsResponses (matches OpenAPI spec) - B3: Add rescheduledBy param to rescheduleBooking for auto-confirm - B4: Add bookingUidToReschedule to GetSlotsParams for reschedule flow - B5: Remove phantom notes field from CreateBookingInput types Part C: Structural improvements - C1: Add CalcomApiError awareness to all getCustomErrorMessage callbacks - C2: Centralized friendlyCalcomError helper in bot.ts * update * feat: booking search enhancement — attendee/date filtering, sorting, past meeting lookup - Expand GetBookingsParams with attendeeEmail, attendeeName, afterStart, beforeEnd, sortStart - Pass new params through in getBookings() query string - Add all new params to list_bookings tool Zod schema - Update list_bookings description to mention attendee and date range filtering - Add FINDING PAST MEETINGS WITH SOMEONE section to system prompt * update - pass hosts * feat: 'Am I Free?' flow — availability prompt section, check_busy_times steering, critical rule - Add 'Checking Your Availability / Am I Free?' system prompt section with 3-step flow (determine time range, fetch bookings, answer question) and edge cases - Update check_busy_times description to note credential limitations and steer toward list_bookings - Add rule 10 to CRITICAL RULES: use list_bookings for availability checks * feat: profile management flow — system prompt guidance, Redis cache sync, tool descriptions - Add 'Profile Management' system prompt section with viewing/updating guidance, timezone abbreviation resolution, email verification warning, and fast-path - Sync email/timezone changes back to Redis via linkUser() after update_profile to prevent stale cache in system prompt and timezone conversions - Add linkUser import from user-linking - Update get_my_profile description to steer toward cached data for basic info - Update update_profile description to require confirmation and IANA timezones * feat: event type CRUD flow — prompt guidance, expanded schemas, booking URLs - Add 'Managing Event Types' system prompt section with create/update/delete/list guidance, slug generation, common requests, and advanced settings redirect - Relax critical rule #9 to guard booking flows only, not explicit user requests - Add minimumBookingNotice, beforeEventBuffer, afterEventBuffer, slotInterval, scheduleId to create_event_type and update_event_type tool schemas + types - Update create/update/delete tool descriptions for clarity - Include bookingUrl in list_event_types response using linked user's username * feat: no-show and unlink flows — mark_no_show body fix, expanded schema, prompt guidance * feat: agentic reschedule flow — prompt guidance, slot exclusion, rescheduledBy, recurring detection * feat: promote event type CRUD tools to CORE_TOOL_NAMES, remove stale ADMIN_KEYWORDS * refactor: eliminate keyword-based tool gating — always expose all tools * feat: add fetchWithRetry with exponential backoff and timeouts to all Cal.com API calls * feat: schedule availability tools — expose availability/overrides, enrich descriptions, add prompt section * feat: include bookingFields in list_event_types response to fix own-calendar booking with custom fields * feat: add skip param and hasMore pagination flag to list_bookings tool * feat: enrich tool descriptions for get_booking, confirm/decline, and schedule tools * feat: actionable error messages — overhaul friendlyCalcomError, consolidate CalcomApiError handling via deps * refactor: extract duplicates and magic numbers across agent, bot, and user-linking * feat: add get_event_type tool + gate agentic features behind org plan (#42) * feat: add get_event_type tool for fetching single event type details * fix: align get_event_type tool description with actual response fields * feat: gate agentic features behind Cal.com Organizations plan * fix: address review comments — org sync on refresh, split link check, withSlackToken wrapper * fix: disable retries for mutating API calls, reorder error handlers, re-read linked user after refresh
1 parent b22fe12 commit 209d289

8 files changed

Lines changed: 2188 additions & 424 deletions

File tree

apps/chat/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,4 @@ yarn-error.log*
4040
# typescript
4141
*.tsbuildinfo
4242
next-env.d.ts
43+
.env*.local

apps/chat/app/api/auth/calcom/callback/route.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ interface CalcomMe {
2323
email: string;
2424
name: string;
2525
timeZone: string;
26+
organizationId: number | null;
27+
organization?: { isPlatform: boolean; id: number };
2628
}
2729

2830
export async function GET(request: Request) {
@@ -74,6 +76,8 @@ export async function GET(request: Request) {
7476
calcomUsername: me.username,
7577
calcomTimeZone: me.timeZone,
7678
linkedAt: new Date().toISOString(),
79+
calcomOrganizationId: me.organizationId ?? null,
80+
calcomOrgIsPlatform: me.organization?.isPlatform ?? null,
7781
};
7882

7983
await linkUser(payload.teamId, payload.userId, linkedUser);

apps/chat/lib/agent.ts

Lines changed: 1250 additions & 173 deletions
Large diffs are not rendered by default.

apps/chat/lib/bot.ts

Lines changed: 526 additions & 208 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)