dbe387890f | ||
---|---|---|
.. | ||
src | ||
.env.example | ||
README.md | ||
next-env.d.ts | ||
next.config.js | ||
package.json | ||
tsconfig.json |
README.md
Cal.ai
Welcome to Cal.ai!
This app lets you chat with your calendar via email:
- Turn informal emails into bookings eg. forward "wanna meet tmrw at 2pm?"
- List and rearrange your bookings eg. "clear my afternoon"
- Answer basic questions about your busiest times eg. "how does my Tuesday look?"
The core logic is contained in agent/route.ts. Here, a LangChain Agent Executor is tasked with following your instructions. Given your last-known timezone, working hours, and busy times, it attempts to CRUD your bookings.
The AI agent can only choose from a set of tools, without ever seeing your API key.
Emails are cleaned and routed in receive/route.ts using MailParser.
Incoming emails are routed by email address. Addresses are verified by DKIM record, making them hard to spoof.
Getting Started
Development
If you haven't yet, please run the root setup steps.
Before running the app, please see env.mjs for all required environment variables. Run cp .env.example .env
in this folder to get started. You'll need:
- An OpenAI API key with access to GPT-4
- A SendGrid API key
- A default sender email (for example,
me@dev.example.com
) - The Cal.ai app's ID and URL (see add.ts)
- A unique value for
PARSE_KEY
withopenssl rand -hex 32
To stand up the API and AI apps simultaneously, simply run yarn dev:ai
.
Agent Architecture
The scheduling agent in agent/route.ts calls an LLM (in this case, GPT-4) in a loop to accomplish a multi-step task. We use an OpenAI Functions agent, which is fine-tuned to output text suited for passing to tools.
Tools (eg. createBooking
) are simply JavaScript methods wrapped by Zod schemas, telling the agent what format to output.
Here is the full architecture:
Email Router
To expose the AI app, run ngrok http 3000
(or the AI app's port number) in a new terminal. You may need to install nGrok.
To forward incoming emails to the serverless function at /agent
, we use SendGrid's Inbound Parse.
- Ensure you have a SendGrid account
- Ensure you have an authenticated domain. Go to Settings > Sender Authentication > Authenticate. For DNS host, select
I'm not sure
. Click Next and add your domain, eg.example.com
. Choose Manual Setup. You'll be given three CNAME records to add to your DNS settings, eg. in Vercel Domains. After adding those records, click Verify. To troubleshoot, see the full instructions. - Authorize your domain for email with MX records: one with name
[your domain].com
and valuemx.sendgrid.net.
, and another with namebounces.[your domain].com
and valuefeedback-smtp.us-east-1.amazonses.com
, both with priority10
if prompted. - Go to Settings > Inbound Parse > Add Host & URL. Choose your authenticated domain.
- In the Destination URL field, use the nGrok URL from above along with the path,
/api/receive
, and one param,parseKey
, which lives in this app's .env underPARSE_KEY
. The full URL should look likehttps://abc.ngrok.io/api/receive?parseKey=ABC-123
. - Activate "POST the raw, full MIME message".
- Send an email to
[anyUsername]@example.com
. You should see a ping on the nGrok listener and server. - Adjust the logic in receive/route.ts, save to hot-reload, and send another email to test the behaviour.
Please feel free to improve any part of this architecture!