An open protocol for AI agents to coordinate meetings over email. No server. No domain. No account. Pure p2p.
Every invite email also includes an "Add AgentMeet" link for viral adoption.
bash
cd ~/Dropbox/Dev/agentmeet && npm install
Requires Google Calendar and Gmail access (OAuth or MCP).
bash
bun run -e '
import { buildInvite } from "~/Dropbox/Dev/agentmeet/src/invite";
import { writeFileSync } from "fs";
const result = await buildInvite({
from: { name: "YOUR_NAME", email: "YOUR_EMAIL" },
to: "RECIPIENT_EMAIL",
meeting: {
title: "Meeting Title",
duration_minutes: 30,
notes: "Optional description",
},
slots: [
{ start: "2026-03-25T10:00:00+08:00", end: "2026-03-25T10:30:00+08:00" },
],
});
// result.subject = email subject line
// result.html = email body (HTML with embedded protocol payload)
// Send via Gmail API or any email service
'
typescript
import { parseAgentMeetEmail, isAgentMeetSubject } from "agentmeet";
// Check subject line
if (isAgentMeetSubject(emailSubject)) {
const payload = parseAgentMeetEmail(emailHtmlBody);
if (payload) {
console.log(payload.type); // INVITE | COUNTER | SELECT | CONFIRM
console.log(payload.request_id); // am_xxx
console.log(payload.selected_slots); // for SELECT type
}
}
typescript
import { getBusyPeriods, generateAvailableSlots, DEFAULT_PREFERENCES } from "agentmeet";
const busy = await getBusyPeriods(oauth2Client, startISO, endISO);
const slots = generateAvailableSlots(busy, startDate, endDate, 30, DEFAULT_PREFERENCES);
Four message types, embedded as HTML comments in email body:
TypeDirectionPurposeINVITEA -> BSender's available slotsCOUNTERB -> ARecipient's alternative slotsSELECTB -> ARecipient picks one or more slotsCONFIRMA -> BCalendar events created
Detection: subject starts with [AgentMeet], body contains <!-- agentmeet/v1.
Payload format:
html
<!-- agentmeet/v1
{
"protocol": "agentmeet",
"version": "0.1",
"type": "SELECT",
"request_id": "am_abc123",
"selected_slots": [{ "start": "ISO8601", "end": "ISO8601" }]
}
-->
Send INVITE to multiple recipients. Each responds with their available slots. The initiating agent finds the intersection and proposes the best overlap.
Each slot in the invite email is a mailto: link. Clicking it opens a pre-filled reply email with the SELECT payload. For group scheduling, a separate "I'm available for all of these" link lets recipients select multiple slots and delete the ones that don't work.
Default preferences (override per-invite):
yaml
working_hours:
start: "09:00"
end: "18:00"
timezone: "Asia/Taipei"
buffer_minutes: 15
max_slots_to_share: 5
blocked_days: ["saturday", "sunday"]
Protocol spec: PROTOCOL.md
Implementation: src/ (TypeScript)
License: Apache-2.0