Skip to content

feat: agentic flows, error handling, API robustness, search, profile, event types, reschedule & more#41

Merged
dhairyashiil merged 23 commits into
devin/1773320873-smart-mention-booking-flowfrom
devin/1773429146-agentic-cancel-booking-flow
Mar 14, 2026
Merged

feat: agentic flows, error handling, API robustness, search, profile, event types, reschedule & more#41
dhairyashiil merged 23 commits into
devin/1773320873-smart-mention-booking-flowfrom
devin/1773429146-agentic-cancel-booking-flow

Conversation

@dhairyashiil
Copy link
Copy Markdown
Member

@dhairyashiil dhairyashiil commented Mar 13, 2026

Summary

Adds guided cancellation, reschedule, and confirm/decline flows to the chat agent, a comprehensive error handling & API robustness overhaul, booking search enhancement with attendee/date filtering, an "Am I Free?" availability flow, a profile management flow with Redis cache sync, an event type CRUD flow with expanded schemas, no-show/unlink account flows, a full agentic reschedule flow with slot exclusion and auto-confirmation, eliminates the keyword-based tool gating system entirely, adds exponential backoff retry logic with AbortSignal timeouts to all Cal.com API calls, gates agentic (AI-powered) features behind the Cal.com Organizations plan, and adds a get_event_type tool for fetching single event types — across 7 files (agent.ts, bot.ts, client.ts, types.ts, slack.ts, user-linking.ts, callback/route.ts).

Cancel booking flow

  1. client.tscancelBooking now accepts an optional cancelSubsequentBookings param, forwarded to the Cal.com API for recurring booking cancellation.
  2. agent.ts — system prompt — New ## Cancelling a Booking section with a 2-step flow (identify → confirm+reason), fast-path for clear intent, recurring booking handling, and batch cancellation capped at 3 per turn.
  3. agent.tscancel_booking tool — Fetches booking details via getBooking before cancelling, returns enriched response (title, start, end, attendees), adds cancelSubsequentBookings schema param.
  4. agent.tslist_bookings tool — Adds eventType (id/title/slug) and description to response.
  5. agent.tsget_booking tool — Same enrichment as list_bookings.

Reschedule booking flow

  1. agent.ts — system prompt — New ## Rescheduling a Booking section (~70 lines) with 4-step flow: identify booking → determine new time → check availability (mandatory, with bookingUidToReschedule) → confirm and reschedule. Includes fast-path, recurring booking handling (single occurrence only), and rescheduledBy auto-confirmation guidance.
  2. agent.tscheck_availability tool — Added optional bookingUidToReschedule param to Zod schema; passed through to getAvailableSlots() in both primary and extended (no-slots fallback) calls.
  3. agent.tscheck_availability_public tool — Same bookingUidToReschedule param added; passed through to getAvailableSlotsPublic() in both primary and extended calls.
  4. client.tsGetPublicSlotsParams — Added bookingUidToReschedule?: string; wired into query string in getAvailableSlotsPublic().
  5. agent.tsreschedule_booking tool — Enhanced: fetches original booking via getBooking before rescheduling (returns previousStart/previousEnd + newStart/newEnd + attendees), adds rescheduledBy param for auto-confirmation on confirmation-required event types. Description updated.
  6. types.tsCalcomBooking — Added recurringBookingUid: string | null to detect recurring bookings.
  7. agent.tslist_bookings + get_booking responses — Now surface recurringBookingUid in each booking object.
  8. agent.ts — CRITICAL RULES — Added rule 11: "NEVER call reschedule_booking without first checking availability. Always pass bookingUidToReschedule."

Confirm/decline booking flow

  1. agent.ts — system prompt — New ## Confirming or Declining a Booking section with the same patterns: 2-step flow (identify pending → confirm/decline), fast-path, batch cap at 3, and post-action guidance.
  2. agent.tsconfirm_booking tool — Fetches booking details via getBooking before confirming, returns enriched response with start/end/attendees.
  3. agent.tsdecline_booking tool — Same enrichment, plus returns reason in response.
  4. agent.ts — Behavior section — Replaced the old confirm/decline one-liner with a reference to the new dedicated section.

Error handling & API robustness

Part A — Fix misleading error messages:
18. bot.ts — Added friendlyCalcomError helper that maps CalcomApiError status codes (400/401/403/404/409/422/429/5xx) to user-friendly messages.
19. bot.tsCalcomApiError branch in withBotErrorHandling now runs after getCustomErrorMessage, so callers (e.g. the booking modal) can provide context-specific messages first. Previously CalcomApiError was caught before getCustomErrorMessage, making context-aware handlers like friendlyCalcomError(err, "booking") dead code.
20. bot.ts — Softened Slack auth error message: now says "I'm having trouble connecting to Slack" instead of the alarming "token has expired or been revoked".
21. slack.ts — Added isSlackAuthError guard to /cal slash command and retry_response action handlers (previously missing, causing false "token expired" messages).
22. slack.ts — Sanitized confirm_booking error: no longer exposes raw API error messages; shows status-specific messages (409 → "slot no longer available", 422 → "details incomplete").
23. slack.ts — App Home catch-all now only suggests "reconnect" on 401/403; otherwise shows "Could not load bookings. Please try again later."

Part B — Fix API schema mismatches:
24. client.ts — Fixed getAvailableSlots to use cal-api-version: 2024-09-04 (was using default 2024-08-13; /v2/slots endpoint requires 2024-09-04).
25. types.ts + agent.ts — Renamed responsesbookingFieldsResponses to match the OpenAPI spec. Removed phantom notes field from CreateBookingInput and CreatePublicBookingInput (notes should go via bookingFieldsResponses.notes).
26. client.ts — Added rescheduledBy param to rescheduleBooking for auto-confirm when rescheduler is the host.
27. client.ts — Added bookingUidToReschedule to GetSlotsParams to exclude the current booking from busy-time calculations during reschedule.

Part C — Structural improvements:
28. bot.ts + slack.ts — All 6 getCustomErrorMessage callbacks now check lastStreamErrorRef.current instanceof CalcomApiError and return friendlyCalcomError(...) messages, so stream errors from Cal.com API calls surface specific messages rather than generic fallbacks.

Booking search enhancement

  1. client.ts — Expanded GetBookingsParams with attendeeEmail, attendeeName, afterStart, beforeEnd, sortStart and wired them through as query params in getBookings().
  2. agent.tslist_bookings tool — Added all 5 new optional params to the Zod schema (attendeeEmail, attendeeName, afterStart, beforeEnd, sortStart) and passes them to getBookings().
  3. agent.ts — tool description — Updated to mention attendee/date filtering and notes that attendee filters only match attendees, not hosts.
  4. agent.ts — system prompt — New FINDING PAST MEETINGS WITH SOMEONE section with attendee/host fallback strategy: if attendee filters return no results, does an unfiltered call and scans the hosts field.
  5. agent.tslist_bookings + get_booking responses — Now include hosts array (name + email) alongside attendees, enabling the agent to find meetings where the person was the host.

"Am I Free?" availability flow

  1. agent.ts — system prompt — New ## Checking Your Availability / "Am I Free?" section with a 3-step flow: determine time range → fetch bookings via list_bookings with afterStart/beforeEnd → answer the question. Covers specific-time checks, daily schedules, weekly overviews, and edge cases (past dates, duration-based gaps, "block off" requests).
  2. agent.tscheck_busy_times tool description — Updated to note credential limitations and steer the agent toward list_bookings for availability checks.
  3. agent.ts — CRITICAL RULES — Added rule 10: "For 'am I free?' questions, use list_bookings with afterStart/beforeEnd date filters — do NOT use check_busy_times."

Profile management flow

  1. agent.ts — system prompt — New ## Profile Management section with guidance for viewing profile (use cached "Your Account" data, only call get_my_profile for full details), updating profile (confirm before changes, resolve timezone abbreviations to IANA, warn about email verification), field reference list, and fast-path for clear-intent updates.
  2. agent.tsupdate_profile tool — After a successful updateMe() call, syncs changed email and timeZone back to the LinkedUser in Redis via linkUser(). This fixes a stale cache bug where the system prompt's "Your Account" section and all subsequent timezone conversions would use outdated values after a profile update.
  3. agent.ts — imports — Added linkUser to imports from user-linking.
  4. agent.tsget_my_profile description — Updated to steer the agent toward using cached system prompt data for basic info (email, username, timezone) and only calling the API for full profile fields (bio, time format, week start, locale).
  5. agent.tsupdate_profile description — Updated to require user confirmation before calling and to use IANA timezone strings. Notes that email changes require verification.

Event type CRUD flow

  1. agent.ts — system prompt — New ## Managing Event Types section with guidance for creating (auto-generate slug from title, show booking URL after creation), updating (identify → confirm → update), deleting (always confirm first, warn irreversible), listing (show booking URLs), and common requests (hide/unhide, buffers, notice, slot intervals). Redirects advanced settings to the web UI.
  2. agent.ts — CRITICAL RULES — Relaxed rule ci: add 6 new workflows, Blacksmith runners, and CI speed optimizations #9 from "NEVER call unless explicitly asked" to "NEVER call during a booking flow or unless explicitly asked to manage an event type. For delete, ALWAYS confirm first." Keeps the safety guard for booking flows without making the tools sound forbidden.
  3. agent.tscreate_event_type tool — Added minimumBookingNotice, beforeEventBuffer, afterEventBuffer, slotInterval, scheduleId to Zod schema. Updated description to mention buffers/notice/intervals.
  4. agent.tsupdate_event_type tool — Same 5 new fields added to Zod schema. Execute function refactored to use { eventTypeId, ...rest } destructuring. Updated description to list all configurable fields.
  5. agent.tsdelete_event_type tool — Description updated to "This is irreversible -- always confirm with the user first."
  6. types.ts — Added minimumBookingNotice, beforeEventBuffer, afterEventBuffer, slotInterval, scheduleId to both CreateEventTypeInput and UpdateEventTypeInput interfaces.
  7. agent.tslist_event_types tool — Now fetches LinkedUser in parallel with the access token and includes bookingUrl ({CALCOM_APP_URL}/{username}/{slug}) in each event type's response.

No-show & unlink account flows

  1. client.tsmarkNoShow — Now accepts optional host (boolean) and attendees (array of { email, absent }) parameters and passes them in the request body. Previously sent an empty POST body which the API likely ignored.
  2. agent.tsmark_no_show tool — Expanded schema with host (boolean, mark host as absent) and attendeeEmails (string array, emails of absent attendees). Execute function maps emails to { email, absent: true } objects before calling client. Description updated to explain host vs attendee no-show marking.
  3. agent.ts — system prompt — New MARKING NO-SHOWS section: identify past booking → ask who was absent (host or attendee, skip if clear from context) → call mark_no_show → confirm. Notes that no-shows only work for past bookings.
  4. agent.tsunlink_account tool description — Updated from bare "Unlink the user's Cal.com account." to include consequences (removes OAuth connection, re-auth required) and "always confirm before calling".
  5. agent.ts — system prompt — New UNLINKING ACCOUNT section: always confirm with explicit warning about consequences → on "yes" call unlink_account → confirm disconnection and explain how to reconnect.

Eliminate keyword-based tool gating

  1. agent.ts — Deleted CORE_TOOL_NAMES, ADMIN_KEYWORDS, detectToolSet(), and filterTools() entirely. All 28+ tools are now always exposed to the model. The system prompt's critical rules are the guardrail against misuse, not keyword filtering.
  2. agent.ts — Removed toolSet from AgentStreamOptions interface. runAgentStream now directly uses createCalTools() output without filtering.
  3. bot.ts — Removed all detectToolSet() calls and toolSet arguments from the 3 runAgentStream call sites (telegram freeform, mention handler, thread follow-up). Removed detectToolSet import.

API retry and timeouts

  1. client.ts — Added constants: FETCH_TIMEOUT_MS (10s), MAX_RETRIES (2 = 3 total attempts), RETRY_BASE_MS (500ms), RETRY_MULTIPLIER (3), RETRYABLE_STATUS_CODES (500, 502, 503, 504).
  2. client.ts — Added fetchWithRetry() helper that wraps fetch with AbortSignal.timeout(FETCH_TIMEOUT_MS), retries on server errors (5xx) and network/timeout errors with exponential backoff (500ms → 1500ms), and throws CalcomApiError with code "FETCH_RETRY_EXHAUSTED" after all attempts fail. Added sleep() helper.
  3. client.ts — Updated calcomFetch to accept an optional retries parameter (default MAX_RETRIES) and use fetchWithRetry instead of raw fetch.
  4. client.tsAll mutating calls (POST/PATCH/DELETE) now pass retries: 0 — timeout protection only, no retry. This includes: createBooking, createBookingPublic, addBookingAttendee, cancelBooking, rescheduleBooking, updateMe, createSchedule, updateSchedule, deleteSchedule, confirmBooking, declineBooking, createEventType, updateEventType, deleteEventType, markNoShow. Only GET calls use full retry.
  5. client.ts — Replaced raw fetch() with fetchWithRetry() in 3 public (unauthenticated) functions: getAvailableSlotsPublic (full retry), createBookingPublic (retries: 0), getEventTypesByUsername (full retry).

get_event_type tool

  1. client.ts — Fixed getEventType to normalize the length field (raw.length ?? raw.lengthInMinutes ?? 0), matching the existing getEventTypes behavior.
  2. agent.ts — Added get_event_type tool definition (import, Zod schema, execute function) for fetching a single event type by ID. Returns bookingFields, duration, description, bookingUrl, etc. Added system prompt guidance in CUSTOM BOOKING FIELDS and UPDATING AN EVENT TYPE sections.

Org plan agentic gating

  1. user-linking.ts — Added calcomOrganizationId and calcomOrgIsPlatform to LinkedUser interface. Added isOrgPlanUser() helper that returns true when calcomOrganizationId != null && calcomOrgIsPlatform === false. Org metadata is re-synced via /v2/me on every token refresh (non-fatal on failure).
  2. callback/route.ts — Expanded local CalcomMe to capture organizationId and organization.isPlatform at OAuth link time.
  3. client.ts — Updated shared CalcomMe interface with organizationId and organization fields.
  4. bot.ts — Added org plan check in runAgentHandler() after token validation — covers all agentic paths (Slack mentions, Telegram DMs/mentions, thread follow-ups). After getValidAccessToken, re-reads LinkedUser from Redis so freshly synced org data is used. Slack upgrade message is wrapped in withSlackToken to avoid not_authed errors.
  5. handlers/slack.ts — Gated the two direct runAgentStream calls that bypass runAgentHandler: /cal book @user fallback (no modal) and /cal <natural language> default case. The default case correctly shows the OAuth link prompt for unlinked users instead of conflating with the upgrade message.

Gating logic (from /v2/me response):

organizationId isPlatform Agentic?
null No
non-null true No (Platform/API tier)
non-null false Yes (Org plan)

Code quality improvements

  1. agent.ts + user-linking.ts — Extracted named constants replacing magic numbers: MAX_HISTORY_MESSAGES, MAX_AGENT_STEPS, MAX_SLOTS_RETURNED, MAX_NEXT_AVAILABLE_SLOTS, EXTENDED_SEARCH_DAYS, MS_PER_DAY, LINKED_USER_TTL_SECONDS, BOOKING_FLOW_TTL_SECONDS, TOOL_CONTEXT_TTL_SECONDS, REFRESH_LOCK_WAIT_MS, REFRESH_LOCK_TTL_SECONDS.

Other changes (from prior pushes)

  • isAIToolCallError now catches "tool choice is none" errors
  • onError broadened to store all stream errors in onErrorRef (not just rate-limit and tool-call); preserves original Error instances for instanceof checks
  • Custom booking fields prompt: bookingFieldsResponses must never be empty {} for required fields; default "Notes" slug is "notes"
  • bookingFieldsResponses type tightened from Record<string, unknown> to Record<string, string>

Updates since last revision

Addressed review comments in the latest commit:

  1. Disabled retries for ALL mutating API calls (client.ts): Previously only createBooking, createBookingPublic, and addBookingAttendee had retries: 0. Now all POST/PATCH/DELETE calls (cancel, reschedule, confirm, decline, updateMe, create/update/deleteSchedule, create/update/deleteEventType, markNoShow) also pass retries: 0. A timed-out cancel or reschedule will no longer silently retry and potentially create duplicates.

  2. Reordered error handlers in withBotErrorHandling (bot.ts): Moved the CalcomApiError catch block after getCustomErrorMessage. Previously, a 409 booking conflict in the Slack modal was caught by the generic CalcomApiError handler before the modal's context-aware friendlyCalcomError(err, "booking") could run — that handler was effectively dead code. Now callers get first crack at providing context-specific messages.

  3. Re-read linked user after token refresh (bot.ts): Changed const linked to let linked in runAgentHandler. After getValidAccessToken (which may have refreshed the token and synced org data via /v2/me), the linked user is re-read from Redis so the org-plan gate uses fresh data instead of the stale snapshot from before the refresh.

Review & Testing Checklist for Human

  • Org plan gating correctness: Verify that /v2/me returns organizationId and organization.isPlatform with the cal-api-version: 2024-08-13 header. Test with a free user (should see upgrade message on @mention / /cal how are you), an Org plan user (should get AI response), and a Platform API-tier user (should see upgrade message). Verify all three can still use /cal bookings, /cal help, /cal availability.
  • Existing linked users post-deploy: Users linked before this feature have undefined for org fields in Redis and will be treated as non-org (blocked from agentic) until their next token refresh (roughly hourly for active users) or re-link. Decide if this grace period is acceptable or if a migration is needed.
  • Extra /v2/me call on every token refresh (user-linking.ts): Adds one API call per token refresh (~1/hour per active user). Non-fatal on failure. Confirm this overhead is acceptable.
  • responsesbookingFieldsResponses rename is the highest-risk change. The OpenAPI spec says bookingFieldsResponses, but if the live API silently accepts responses as an alias and does NOT accept bookingFieldsResponses, all bookings with custom fields will break. Test a real booking with custom fields (including the notes field) end-to-end to confirm the API accepts bookingFieldsResponses.
  • All 28+ tools always exposed (keyword gating removed). Verify the model doesn't call admin tools (schedules, no-show, unlink, etc.) inappropriately during simple booking conversations. The system prompt's critical rules are the only guardrail now.
  • Retry logic: ALL mutating calls now have retries: 0. Verify that slow-but-successful API responses (>10s) don't get prematurely aborted by the AbortSignal.timeout(10_000). If Cal.com cancel/reschedule endpoints sometimes take >10s, users will see timeout errors. Previously cancel/reschedule/confirm/decline retried on timeout — now they don't.
  • Error handler reorder in withBotErrorHandling: Verify that getCustomErrorMessage callbacks in the Slack modal flow (friendlyCalcomError(err, "booking")) now correctly handle 409 conflicts with the context-aware "booking" message, and that generic CalcomApiError still works as a fallback for paths without a custom handler.
  • recurringBookingUid on CalcomBooking — Verify the API returns this field on booking objects. If not, recurring booking detection in reschedule prompts won't fire.
  • bookingUidToReschedule query param — Verify the /v2/slots API accepts this parameter. If silently ignored, the original time slot appears as "busy" during reschedule.
  • rescheduledBy in rescheduleBooking — Verify the API accepts this in the POST /v2/bookings/{uid}/reschedule body for auto-confirmation.
  • markNoShow request bodyPOST /v2/bookings/{uid}/mark-absent now receives { host, attendees }. Verify the API accepts this shape.
  • Redis cache sync after profile update — After changing timezone via the bot, verify the system prompt's "Your Account" reflects the new timezone on the next message.
  • Test reschedule, cancel, confirm/decline flows end-to-end in Slack — including fast-path, recurring, and batch scenarios.
  • Test error handling — Trigger a Cal.com 400 (should not say "token expired"), 409 on confirm_booking (should say "slot no longer available"), App Home when API is down (should say "try again later" not "reconnect").

Notes

@devin-ai-integration
Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 13, 2026

Deployment failed with the following error:

You don't have permission to create a Preview Deployment for this Vercel project: cal-companion-chat.

View Documentation: https://vercel.com/docs/accounts/team-members-and-roles

@devin-ai-integration devin-ai-integration Bot changed the title feat: agentic cancel booking flow — enriched responses, recurring support, guided prompt feat: agentic cancel & confirm/decline flows — enriched responses, guided prompts Mar 13, 2026
…endly 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
@devin-ai-integration devin-ai-integration Bot changed the title feat: agentic cancel & confirm/decline flows — enriched responses, guided prompts feat: agentic flows, error handling & API robustness Mar 13, 2026
…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
@devin-ai-integration devin-ai-integration Bot changed the title feat: agentic flows, error handling & API robustness feat: agentic flows, error handling, API robustness & booking search Mar 13, 2026
…es 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
…ync, 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
@devin-ai-integration devin-ai-integration Bot changed the title feat: agentic flows, error handling, API robustness & booking search feat: agentic flows, error handling, API robustness, booking search & profile management Mar 13, 2026
…ng 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
@devin-ai-integration devin-ai-integration Bot changed the title feat: agentic flows, error handling, API robustness, booking search & profile management feat: agentic flows, error handling, API robustness, search, profile & event types Mar 13, 2026
@devin-ai-integration devin-ai-integration Bot changed the title feat: agentic flows, error handling, API robustness, search, profile & event types feat: agentic flows, error handling, API robustness, search, profile, event types & no-show/unlink Mar 13, 2026
@devin-ai-integration devin-ai-integration Bot changed the title feat: agentic flows, error handling, API robustness, search, profile, event types & no-show/unlink feat: agentic flows, error handling, API robustness, search, profile, event types, reschedule & more Mar 13, 2026
@dhairyashiil dhairyashiil marked this pull request as ready for review March 13, 2026 22:30
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 6 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/chat/lib/handlers/slack.ts">

<violation number="1" location="apps/chat/lib/handlers/slack.ts:944">
P2: This booking-specific Cal.com error mapping never runs because `withBotErrorHandling` handles `CalcomApiError` before `getCustomErrorMessage`. As written, 409 booking conflicts still fall back to the generic Cal.com conflict message instead of the new slot-unavailable text.</violation>
</file>

<file name="apps/chat/lib/calcom/client.ts">

<violation number="1" location="apps/chat/lib/calcom/client.ts:84">
P1: Default retries now reissue mutating Cal.com requests, so timeouts/5xxs can duplicate creates or replay cancel/reschedule actions.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread apps/chat/lib/calcom/client.ts
Comment thread apps/chat/lib/handlers/slack.ts
…#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
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 6 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/chat/lib/bot.ts">

<violation number="1" location="apps/chat/lib/bot.ts:840">
P2: Re-read the linked user after token refresh before enforcing the org-plan gate.</violation>
</file>

<file name="apps/chat/lib/user-linking.ts">

<violation number="1" location="apps/chat/lib/user-linking.ts:218">
P1: Persist the refreshed tokens before calling `getMe()`. Doing another retried API call inside the refresh lock can make concurrent requests return `null` or trigger a second refresh.</violation>
</file>

<file name="apps/chat/lib/handlers/slack.ts">

<violation number="1" location="apps/chat/lib/handlers/slack.ts:525">
P1: This org-plan gate will falsely block already-linked organizations users whose cached Redis record predates the new org fields.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread apps/chat/lib/user-linking.ts
Comment thread apps/chat/lib/handlers/slack.ts
Comment thread apps/chat/lib/bot.ts
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/chat/lib/calcom/client.ts">

<violation number="1" location="apps/chat/lib/calcom/client.ts:325">
P2: Passing `0` here disables the new retry/backoff logic, so transient Cal.com 5xx or timeout failures still break this mutation after one attempt.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread apps/chat/lib/calcom/client.ts
@dhairyashiil dhairyashiil merged commit d69fae5 into devin/1773320873-smart-mention-booking-flow Mar 14, 2026
6 of 8 checks passed
emrysal pushed a commit that referenced this pull request Mar 14, 2026
…edis 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant