에이전트 캘린더가 Google 및 Microsoft와 통신하기 위해 ICS를 사용하는 방법
요약
AI 에이전트가 Google, Microsoft, Apple 캘린더와 상호 운용하기 위해 iCalendar(ICS) 프로토콜을 활용하는 원리를 설명합니다. Nylas의 Agent Accounts를 통해 API 연동 없이도 이메일 기반의 표준 프로토콜로 자연스러운 일정 관리가 가능함을 보여줍니다.
핵심 포인트
- ICS 프로토콜을 통해 에이전트와 인간 사용자 간의 캘린더 상호 운용성 확보
- API 통합 대신 이메일 메시지 교환을 통한 네이티브한 일정 관리 구현
- Nylas Agent Accounts를 활용한 Google 및 Microsoft 365 연동 방식
- 웹훅(webhook)을 통한 참가자 응답 상태의 자동 업데이트 메커니즘
RSVP는 정확히 세 가지 값, 즉 yes, no, 또는 maybe를 가질 수 있습니다. 이 작은 어휘와 iCalendar (iCalendar)라고 불리는 30년 된 텍스트 형식은, AI 에이전트가 소유한 캘린더가 Google Calendar, Microsoft 365, Apple Calendar에서 실제 사람들이 수락하는 회의를 주최할 수 있는 이유 그 자체입니다. 이때 해당 클라이언트들은 상대방 참가자가 소프트웨어라는 사실을 알 필요도, 신경 쓸 필요도 없습니다.
현재 베타 버전인 프로그래밍 방식의 메일함인 Nylas Agent Accounts는 각각 실제 캘린더를 함께 제공합니다. Google 연동도, Microsoft Graph 어댑터도, 제공자별 코드도 필요하지 않습니다. 상호 운용성 (interop)은 프로토콜 계층 (protocol layer)에서 발생하며, 그 원리를 이해할 가치가 있습니다.
아무도 발명할 필요가 없었던 프로토콜
Agent Account가 이벤트를 생성하면, 초대장은 ICS REQUEST로 발송됩니다. 이벤트를 취소하면 참가자들은 ICS CANCEL을 받게 됩니다. 초대에 응답하면 주최자는 ICS REPLY를 받습니다. 모든 주요 캘린더 클라이언트는 이미 이 방언을 사용하고 있으므로, 에이전트의 이벤트는 어디에서나 네이티브(native)하게 보입니다. 즉, 번역할 것이 아무것도 없습니다.
그것이 바로 핵심 비결입니다. 캘린더 상호 운용성 (interop)은 API 문제가 아니라 이메일 문제입니다. 초대, 업데이트, 응답은 메일함 사이의 메시지로 전달되며, 모든 Agent Account는 기본 캘린더가 연결된 실제 메일함이므로, 동료와 마찬가지로 해당 교환 과정에 참여하게 됩니다.
에이전트가 주최할 때
notify_participants=true를 사용하여 이벤트를 생성하면, 각 참가자는 에이전트 자신의 이메일 주소로부터 초대를 받게 됩니다:
curl --request POST \
--url "https://api.us.nylas.com/v3/grants/<GRANT_ID>/events?calendar_id=primary¬ify_participants=true" \
--header "Authorization: Bearer <NYLAS_API_KEY>" \
...
여기서부터는 서비스 제공업체(providers)가 핵심적인 작업을 수행합니다. Google Calendar 사용자는 Gmail에서 초대를 확인하고 Yes를 클릭하며, Google은 응답을 에이전트의 사서함으로 자동으로 다시 보냅니다. Outlook과 Apple Calendar도 Accept/Decline/Tentative를 통해 동일한 방식으로 동작합니다. 각 응답은 에이전트의 받은 편지함(inbox)에 도착하여 파싱(parsing)되며, 이벤트의 participants[].status가 자동으로 업데이트됩니다. event.updated 웹훅(webhook)이 실행되므로, 에이전트는 이메일을 직접 읽지 않고도 누가 수락했는지 알 수 있습니다.
업데이트와 삭제도 동일한 경로를 따릅니다. PUT /events/{id}는 모든 참가자의 캘린더에 변경 사항을 푸시하며, DELETE /events/{id}는 notify_participants=true인 경우 취소 알림을 보냅니다. 일정 재조정(reschedule)은 다음과 같습니다:
curl --request PUT \
--url "https://api.us.nylas.com/v3/grants/<GRANT_ID>/events/<EVENT_ID>?calendar_id=primary¬ify_participants=true" \
--header "Authorization: Bearer <NYLAS_API_KEY>" \
...
새로운 시간은 Alice와 Bob이 확인하는 모든 캘린더에 나타납니다. 단순한 시간 변경을 위해 다시 초대를 보내거나 수동으로 수락하는 번거로운 과정이 필요 없습니다.
에이전트가 나중에 공지할 이벤트를 미리 준비하거나, 누구에게도 스팸을 보내지 않고 과거 데이터를 채워 넣는(backfilling) 경우처럼 조용한 변경이 필요할 때는 notify_participants=false를 전달하세요. 하지만 삭제 시에는 주의해야 합니다. 알림 없이 이벤트를 취소하면 회의가 모든 참가자의 캘린더에 그대로 남아 있게 되어, 참가자들이 에이전트가 더 이상 인지하지 못하는 회의에 참석하게 될 수 있습니다. 특별한 이유가 없다면 알림과 함께 삭제하세요.
에이전트가 초대받을 때
역방향은 코드가 전혀 필요하지 않습니다. 누군가가 회의에 에이전트의 주소를 추가하면, 해당 사용자의 캘린더가 초대를 메일로 보내고, 플랫폼이 이를 파싱하여 에이전트의 기본(primary) 캘린더에 일치하는 이벤트로 생성합니다. 이벤트는 에이전트가 status: "noreply" 상태의 참가자로 등록되고, 주최자(organizer)는 초대를 보낸 사람으로 설정된 상태로 도착합니다.
세 가지 웹훅 트리거(webhook triggers) — event.created, event.updated, event.deleted — 는 에이전트가 직접 생성했든, 초대에 응답하는 사람이 생성했든 상관없이 에이전트 캘린더에서 발생하는 모든 변경 사항을 다룹니다. 실질적인 이점은 다음과 같습니다: 모든 스케줄링 로직을 event.created를 기반으로 구동할 수 있으며, 초대 이메일을 검사할 필요가 전혀 없다는 것입니다. 이벤트(event) 객체에는 이미 주최자(organizer), 참가자(participants), 시간(times), 그리고 설명(description)이 포함되어 있습니다.
RSVP는 이메일이 아니라 캘린더 메시지입니다
피해야 할 실수 중 하나는 에이전트가 초대 이메일에 "좋아요!"라고 _답장(reply to the invite email)_을 보내는 것입니다. 그렇게 하면 그 누구의 캘린더도 업데이트되지 않습니다. 올바른 방법은 전용 엔드포인트(endpoint)를 사용하는 것입니다:
curl --request POST \
--url "https://api.us.nylas.com/v3/grants/<GRANT_ID>/events/<EVENT_ID>/send-rsvp?calendar_id=primary" \
--header "Authorization: Bearer <NYLAS_API_KEY>" \
...
이렇게 하면 적절한 ICS REPLY가 전송되므로, 주최자는 다른 모든 참석자 옆에 에이전트가 "수락(accepted)" 상태인 것을 볼 수 있으며, 다른 참가자들의 캘린더에도 해당 변경 사항이 자동으로 반영됩니다.
알아두면 좋은 예외 사례(Edge cases)
캘린더 문서(calendar docs)를 처음 읽었을 때 저를 놀라게 했던 몇 가지 동작들이 있습니다:
- 모든 초대장이 일종의 방식으로 두 번 발생합니다. 인바운드 초대장은
event.created(파싱된 이벤트)와message.created(초장이 포함된 이메일)를 모두 트리거합니다. 로직을 실행할 때는 하나만 선택하고 나머지는 무시해야 하며, 그렇지 않으면 중복 처리될 수 있습니다. - 역제안 (Counter-proposing)은 일급 객체(first-class)가 아닙니다. 현재
시간을 주고받으며 협상하는 것은 어떨까요? 바로 이 지점에서 단순한 Events API의 역할이 끝나고 Scheduler가 시작됩니다. Events API는 에이전트가 이미 시간을 알고 있고 단순히 이벤트를 생성하거나 초대를 수락해야 할 때 적합합니다. 반면 Scheduler는 제안-선택-예약 (propose-pick-book)의 왕복 과정을 처리하며, 에이전트 계정 (Agent Accounts)과 함께 작동합니다.
직접 시도해보기
프로토콜 수준의 설계 덕분에 여러분의 스케줄링 에이전트는 수십 년간 축적된 캘린더 상호 운용성 (interop)을 별도의 비용 없이 그대로 물려받습니다. 즉, 제공자별 SDK가 필요하지 않고, 플랫폼마다 웹훅 어댑터 (webhook adapters)를 만들 필요도 없습니다. 이를 확인하는 가장 빠른 방법은 다음과 같습니다: 퀵스타트 (quickstart)를 실행하고, 본인을 참가자로 하여 이벤트를 생성한 뒤, 본인의 Google 또는 Outlook 캘린더에서 이를 수락해 보세요. '예'를 클릭했을 때 event.updated 웹훅 (webhook)이 도착하는 것을 확인해 보세요. 그 과정이 조금은 기묘하게 느껴지지 않았는지 저에게 알려주세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기