Skip to content

Conversation

Udit-takkar
Copy link
Contributor

@Udit-takkar Udit-takkar commented Jun 15, 2025

What does this PR do?

This PR introduces a comprehensive AI phone system that enables users to create AI agents, manage phone numbers, and integrate AI-powered calls into Cal.com workflows

Screenshot 2025-08-04 at 9 37 35 PM

Screenshot 2025-08-04 at 9 37 47 PM

I have used Repository Pattern for database queries (one place instead of scattered), Strategy Pattern so all AI providers work identically (easy to swap), Factory Pattern to create the right provider automatically, Service Pattern to bundle complex operations.

Core AI Phone Capabilities

  • AI Agent Management: Create, configure, and manage AI agents with custom prompts and voices
  • Phone Number Provisioning: Purchase and manage phone numbers through Stripe integration
  • Workflow Integration: AI phone calls as workflow steps with multiple trigger types

Workflow Integration

  • Multiple Triggers: BEFORE_EVENT, AFTER_EVENT, NEW_EVENT, RESCHEDULE_EVENT, CANCELLED_EVENT
  • Dynamic Variables: Automatic injection of booking data (guest name, event details, etc.)
  • Scheduling: Time-based triggers (X hours/minutes before/after events)

Billing & Credits

  • Credit-Based System: 5 credits minimum for AI phone calls
  • Stripe Integration: Monthly phone number subscriptions via Stripe checkout
  • Usage-Based Billing: Automatic credit deduction via webhooks after call completion
  • Team Support: Both personal and team-based billing

More in https://github.com/calcom/cal.com/pull/21827/files#r2251947957

Mandatory Tasks (DO NOT REMOVE)

  • I have self-reviewed the code (A decent size PR without self-review might be rejected).
  • N/A I have updated the developer docs in /docs if this PR makes changes that would require a documentation change. If N/A, write N/A here and check the checkbox.
  • I confirm automated tests are in place that prove my fix is effective or that my feature works.

How should this be tested?

Environment Variables Required

RETELL_AI_KEY=your_retell_ai_api_key
STRIPE_PHONE_NUMBER_MONTHLY_PRICE_ID=price_xxxxxxxxxxxx

  1. Create a workflow and select cal ai voice agent as action and click on setup
    https://github.com/user-attachments/assets/bc66ea5f-4b90-493b-93f3-3d8939d16bf5

  2. Click on edit and go to Phone Number tab to buy/import phone number

Screen.Recording.2025-08-05.at.12.59.01.AM.mov
  1. Now you can activate this on some event types and you see a new phone number input on the booking page (Just like SMS reminder workflow action)

Screenshot 2025-08-05 at 1 02 57 AM

Then you can fill any US based phone number then you see that a task is created in tasker which can be executed if you run tasker


Summary by cubic

Added a self-serve feature for creating and managing AI-powered phone agents for event types, including phone number purchase, agent setup, and test calls.

  • New Features
    • Users can buy dedicated phone numbers and assign them to event types.
    • Added UI to configure phone agents and trigger test calls.
    • New backend endpoints and database tables to support phone number management and agent configuration.

@github-actions github-actions bot added the ❗️ migrations contains migration files label Jun 15, 2025
@keithwillcode keithwillcode added core area: core, team members only enterprise area: enterprise, audit log, organisation, SAML, SSO labels Jun 15, 2025
Copy link

vercel bot commented Jun 16, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

2 Skipped Deployments
Name Status Preview Comments Updated (UTC)
cal ⬜️ Ignored (Inspect) Visit Preview Aug 7, 2025 8:57am
cal-eu ⬜️ Ignored (Inspect) Visit Preview Aug 7, 2025 8:57am

Copy link

delve-auditor bot commented Jun 24, 2025

No security or compliance issues detected. Reviewed everything up to b1b9aac.

Security Overview
  • 🔎 Scanned files: 53 changed file(s)
Detected Code Changes

The diff is too large to display a summary of code changes.

Reply to this PR with @delve-auditor followed by a description of what change you want and we'll auto-submit a change to this PR to implement it.

Comment on lines 124 to 139
makeSelfServePhoneCall: authedProcedure
.input(z.object({ eventTypeId: z.number(), numberToCall: z.string() }))
.mutation(async ({ ctx, input }) => {
const { eventTypeId, numberToCall } = input;
console.log("makeSelfServePhoneCall", ctx, input);

const { handleCreateSelfServePhoneCall } = await import(
"@calcom/features/ee/cal-ai-phone/handleCreateSelfServePhoneCall"
);
const call = await handleCreateSelfServePhoneCall({
userId: ctx.user.id,
eventTypeId,
numberToCall,
});
return call;
}),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Endpoint for making phone call

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/features/ee/billing/api/webhook/_customer.subscription.updated.ts (1)

40-63: Add validation for subscription status.

The status mapping logic is well-implemented, but consider adding validation for subscription.status to handle cases where it might be undefined or null.

  const statusMap: Record<string, PhoneNumberSubscriptionStatus> = {
    active: PhoneNumberSubscriptionStatus.ACTIVE,
    past_due: PhoneNumberSubscriptionStatus.PAST_DUE,
    cancelled: PhoneNumberSubscriptionStatus.CANCELLED,
    incomplete: PhoneNumberSubscriptionStatus.INCOMPLETE,
    incomplete_expired: PhoneNumberSubscriptionStatus.INCOMPLETE_EXPIRED,
    trialing: PhoneNumberSubscriptionStatus.TRIALING,
    unpaid: PhoneNumberSubscriptionStatus.UNPAID,
  };

- const subscriptionStatus = statusMap[subscription.status] || PhoneNumberSubscriptionStatus.UNPAID;
+ const subscriptionStatus = subscription.status 
+   ? statusMap[subscription.status] || PhoneNumberSubscriptionStatus.UNPAID
+   : PhoneNumberSubscriptionStatus.UNPAID;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 70c18b8 and 953001f.

📒 Files selected for processing (3)
  • apps/web/app/api/phone-numbers/subscription/success/route.ts (1 hunks)
  • packages/features/ee/billing/api/webhook/_checkout.session.completed.ts (2 hunks)
  • packages/features/ee/billing/api/webhook/_customer.subscription.updated.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/web/app/api/phone-numbers/subscription/success/route.ts
  • packages/features/ee/billing/api/webhook/_checkout.session.completed.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.ts

📄 CodeRabbit Inference Engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/features/ee/billing/api/webhook/_customer.subscription.updated.ts
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • packages/features/ee/billing/api/webhook/_customer.subscription.updated.ts
🧠 Learnings (4)
📓 Common learnings
Learnt from: Udit-takkar
PR: calcom/cal.com#21827
File: packages/lib/server/repository/phoneNumber.ts:153-160
Timestamp: 2025-08-05T13:17:23.491Z
Learning: In the Cal.com Cal AI phone feature, the deletePhoneNumber repository method validation is properly handled in the service layer (RetellAIService.deletePhoneNumber) which validates user ownership and authorization before calling the repository method. The repository layer correctly focuses on data access only.
📚 Learning: the office365calendar webhook handler in packages/app-store/office365calendar/api/webhook.ts is spec...
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/app-store/office365calendar/api/webhook.ts:120-123
Timestamp: 2025-07-18T17:57:16.395Z
Learning: The office365calendar webhook handler in packages/app-store/office365calendar/api/webhook.ts is specifically designed for Office365 calendar integration, not as a generic webhook handler. Therefore, it's safe to assume that fetchAvailabilityAndSetCache method will be implemented in the Office365CalendarService, making explicit validation checks unnecessary.

Applied to files:

  • packages/features/ee/billing/api/webhook/_customer.subscription.updated.ts
📚 Learning: applies to **/*.ts : for prisma queries, only select data you need; never use `include`, always use ...
Learnt from: CR
PR: calcom/cal.com#0
File: .cursor/rules/review.mdc:0-0
Timestamp: 2025-07-28T11:50:23.946Z
Learning: Applies to **/*.ts : For Prisma queries, only select data you need; never use `include`, always use `select`

Applied to files:

  • packages/features/ee/billing/api/webhook/_customer.subscription.updated.ts
📚 Learning: applies to **/*.ts : ensure the `credential.key` field is never returned from trpc endpoints or apis...
Learnt from: CR
PR: calcom/cal.com#0
File: .cursor/rules/review.mdc:0-0
Timestamp: 2025-07-28T11:50:23.946Z
Learning: Applies to **/*.ts : Ensure the `credential.key` field is never returned from tRPC endpoints or APIs

Applied to files:

  • packages/features/ee/billing/api/webhook/_customer.subscription.updated.ts
🧬 Code Graph Analysis (1)
packages/features/ee/billing/api/webhook/_customer.subscription.updated.ts (1)
packages/features/ee/billing/api/webhook/__handler.ts (2)
  • SWHMap (10-14)
  • HttpCode (25-29)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (3)
packages/features/ee/billing/api/webhook/_customer.subscription.updated.ts (3)

1-8: LGTM! Proper imports and type definitions.

The imports are well-organized and the type definition using SWHMap provides good type safety for Stripe webhook data.


9-32: LGTM! Proper error handling and optimized database queries.

The handler correctly validates the subscription ID and uses the select clause to fetch only required fields, addressing previous optimization concerns. The HTTP 202 status for "Phone number not found" is appropriate for webhook handlers.


34-39: LGTM! Proper TypeScript types replace previous any usage.

The function signature now uses proper TypeScript types instead of any, significantly improving type safety and maintainability. This addresses the previous concern about type definitions.

@CarinaWolli
Copy link
Member

CarinaWolli commented Aug 6, 2025

Screenshot 2025-08-06 at 10 24 58 AM
  • The template uses variables that are not available in the "Add Variable" dropdown {{curren_time}} {{name}} {{email}}
  1. After all questions answered, call function end_call to hang up.
  • -What if the user removes this line? What does the "end_call" function do?

    • Maybe we add the information somewhere what the functions like check_availability book_appointment and end_call do (will talk to @ciaranha about that)
  • deleteAllWorkflowReminders does not handle the AI_PHONE_CALL workflow method, which results in an error

  • We are not deleting Agents from the db when deleting workflows

name="phoneNumber"
control={phoneNumberForm.control}
render={({ field: { value } }) => (
<TextField
Copy link
Member

Choose a reason for hiding this comment

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

Can we at least fix the placeholder? Placeholder doesn't include country code
Screenshot 2025-08-06 at 10 59 02 AM

Also what is this phone number? (208) 878-2105, doesn't look like a test phone number

@Udit-takkar Udit-takkar marked this pull request as draft August 6, 2025 10:58
@Udit-takkar
Copy link
Contributor Author

Udit-takkar commented Aug 6, 2025

Can we at least fix the placeholder? Placeholder doesn't include country code

Ok I'll update the placeholder.

Edit: It's already updated. I think you are on previous commit

@Udit-takkar
Copy link
Contributor Author

Udit-takkar commented Aug 7, 2025

-What if the user removes this line? What does the "end_call" function do?

end_call is function needed by voice agent to end the call. If the user removes this line then call can be still end if no activity for 10 minutes, user hangs up, any other request fails etc.

@CarinaWolli
Copy link
Member

end_call is function needed by voice agent to end the call. If the user removes this line then call can be still end if no activity for 10 minutes, user hangs up, any other request fails etc.

Can't we add this always to the template by default, hidden from the user? I feel like we alway want to end the call at the end of the template, no?

@Udit-takkar
Copy link
Contributor Author

Can't we add this always to the template by default, hidden from the user? I feel like we alway want to end the call at the end of the template, no?

yes end_call should be there for every prompt but it should be customizable when user wants the agent to end the call. For:-
some people can add "Ask customer if they have any other question if no then end_call" or "Say xyz and then end_call"

@CarinaWolli
Copy link
Member

yes end_call should be there for every prompt but it should be customizable when user wants the agent to end the call. For:-
some people can add "Ask customer if they have any other question if no then end_call" or "Say xyz and then end_call"

But can we make sure in case the user doesn't add end_call, it will still end the call by default when the end of prompt is reached? Or is this already done?

/>
)}
</div>
<TextArea
Copy link
Member

Choose a reason for hiding this comment

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

Can we format this as it is in the design?

Yours:
Screenshot 2025-08-08 at 2 39 58 PM

Figma:
Screenshot 2025-08-08 at 2 39 05 PM

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay.

@CarinaWolli
Copy link
Member

Maybe we add the information somewhere what the functions like check_availability book_appointment and end_call do (will talk to @ciaranha about that)

@ciaranha will update designs for that. We should highlight the functions and provide some details below

@ciaranha
Copy link
Member

ciaranha commented Aug 8, 2025

Maybe we add the information somewhere what the functions like check_availability book_appointment and end_call do (will talk to @ciaranha about that)

@ciaranha will update designs for that. We should highlight the functions and provide some details below

@CarinaWolli do you mean this?
CleanShot 2025-08-08 at 14 19 36@2x

@Udit-takkar Udit-takkar mentioned this pull request Aug 9, 2025
11 tasks
@CarinaWolli CarinaWolli modified the milestones: v5.6, v5.7 Aug 18, 2025
@Udit-takkar
Copy link
Contributor Author

PRs are merged now

@Udit-takkar Udit-takkar closed this Sep 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ai area: AI, cal.ai core area: core, team members only enterprise area: enterprise, audit log, organisation, SAML, SSO ❗️ .env changes contains changes to env variables ✨ feature New feature or request High priority Created by Linear-GitHub Sync ❗️ migrations contains migration files
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants