민아는 AI에게 세 사람이 모두 비는 30분을 찾아 달라고 했어요. 시간은 금방 찾았지만, 민아가 검토하기도 전에 고객에게 초대장이 갔어요. 팀장 캘린더에는 바쁜 일정이 생겼고, 회의 제목에는 내부에서만 쓰던 임시 표현까지 들어갔어요.

시간 계산이 틀린 게 아니에요. ‘회의를 잡아 줘’라는 한 문장 안에 빈 시간 읽기, 후보 만들기, 다른 사람에게 초대 보내기를 한꺼번에 넣은 게 문제예요. 앞의 두 단계는 개인 영역에서 되돌릴 수 있지만, 마지막 단계는 다른 사람의 받은편지함과 캘린더에 흔적을 남겨요. 가능한 시간을 찾았다는 사실은 민아를 대신해 주최자가 될 권한까지 받았다는 뜻이 아니에요.

일정 조율을 세 가지 행동으로 나눠요

첫 번째는 읽기 전용 조회예요. 필요한 건 바쁜 구간, 근무 시간, 시간대예요. 일정 제목이나 설명까지 읽을 이유는 없어요. 후보 두 개를 돌려주면 이 단계는 끝나요.

두 번째는 개인 초안이나 임시 일정이에요. 사용자만 보는 곳에 있고 아무에게도 알림이 가지 않아야 해요. Microsoft의 Graph 권한 안내는 Calendar.ReadWrite가 없을 때 ‘내 캘린더에 일정 추가’ deep link를 대안으로 제시해요.

세 번째는 참석자가 있는 일정을 보내는 행동이에요. Google Calendar의 events.insert는 참석자 목록을 쓰기 필드로 받고 sendUpdates로 알림 범위를 정해요. Microsoft Graph도 전송 시 모든 참석자에게 초대장이 간다고 명시해요. 이때부터는 외부 행동이에요.

앱에 준 권한과 이번에 맡긴 일을 구분해요

OAuth scope는 앱이 가질 수 있는 능력을 정하지만, 지금 이 회의에서 어디까지 실행할지는 정하지 않아요. Google은 기능에 필요한 가장 좁은 scope를 요청하라고 하고, Microsoft도 읽기 권한과 Calendars.ReadWrite를 구분해요. 일정 쓰기 기능이 꼭 필요한 제품이라도 실행할 때는 후보 제안, 개인 임시 일정, 참석자 초대를 따로 판단해야 해요.

이번 실행에서 AI에게 어디까지 맡겼나요?。공통 빈 시간 비교만:최소한의 free/busy만 읽고 후보 몇 개를 돌려줘요. 일정도 알림도 만들지 않아요。내 시간 임시 확보까지:참석자 없이 내 캘린더에만 보이는 미확정 일정을 만들어요。지정한 참석자 초대까지:전체 실행 내용을 미리 보여 주고, 그 값에 묶인 승인을 받은 뒤 한 번만 실행해요
이번 실행에서 AI에게 어디까지 맡겼나요?
공통 빈 시간 비교만
최소한의 free/busy만 읽고 후보 몇 개를 돌려줘요. 일정도 알림도 만들지 않아요
내 시간 임시 확보까지
참석자 없이 내 캘린더에만 보이는 미확정 일정을 만들어요
지정한 참석자 초대까지
전체 실행 내용을 미리 보여 주고, 그 값에 묶인 승인을 받은 뒤 한 번만 실행해요
  1. 이번 실행에서 AI에게 어디까지 맡겼나요?
  2. 공통 빈 시간 비교만최소한의 free/busy만 읽고 후보 몇 개를 돌려줘요. 일정도 알림도 만들지 않아요
  3. 내 시간 임시 확보까지참석자 없이 내 캘린더에만 보이는 미확정 일정을 만들어요
  4. 지정한 참석자 초대까지전체 실행 내용을 미리 보여 주고, 그 값에 묶인 승인을 받은 뒤 한 번만 실행해요

이 분기는 도구 계층에서 지켜야 해요. 빈 시간 agent에는 초대 도구를 주지 않고, 조회·개인 임시 일정·초대를 분리해요. OWASP도 읽기와 쓰기를 나누고, 외부 행동을 미리 보여 주며, 승인을 행위자·도구·대상·매개변수·만료에 묶으라고 권해요.

광고

회의 제목보다 영향을 받는 사람을 먼저 보여 줘요

“이 회의를 만들까요?”만으로는 부족해요. 주최 계정과 캘린더, 참석자와 역할, 시작·종료, 시간대, 반복, 제목, 장소, 공개 범위, 알림 대상, 승인 만료, 중복 방지 ID를 한 화면에 보여 줘요. 승인은 이 조합에 묶고 하나라도 바뀌면 다시 확인해요. 일반 로그에는 전체 이메일 대신 통제된 ID와 마스킹 정보를 남겨요.

Microsoft의 일정 생성 예시는 불필요한 재시도를 줄이려고 transactionId를 사용해요. 시간 초과는 첫 요청 실패의 증거가 아니에요. agent는 같은 ID로 상태를 읽고, 생성 여부를 모르면 다시 보내지 말고 사람에게 넘겨요.

처음에는 후보 두 개만 돌려주게 해요

첫 주에는 필요한 free/busy만 읽고, 시간대와 충돌 근거가 붙은 후보 두 개를 보여 준 뒤 멈춰요. 설명, 일정 생성, 알림은 제외해요. 먼저 시간대, 자정 넘김, 근무 시간, 미확정 일정 문제를 찾아요.

다음에는 개인 임시 일정을 시험하고 참석자 초대는 마지막에 넣어요. 주최 계정, 허용 도메인, 인원, 길이, 시간대를 제한해요. 권한이 없으면 사람이 후보를 넣거나 deep link를 쓰면 돼요. 클릭 한 번을 위해 읽기 능력을 대리 발송 권한으로 넓힐 이유는 없어요.

이 원칙은 받은 일정이 곧 수락한 약속은 아니라는 구분의 반대편에 있어요. 초대를 받는 사람에게는 수락할 권리가 있고, 보내는 사람에게는 자기 이름으로 무엇을 보낼지 정할 권리가 있어요. 이메일, 파일, 결제 도구까지 같은 선을 적용하려면 상시 AI의 읽기·초안·확인 단계도 함께 볼 수 있어요.

AI 정리 카드

내가 현재 열람을 허용한 AI 일정 조율 흐름 하나를 읽기 전용으로 조사해요. 일정을 생성·수정·취소·수락·거절하거나 참석자를 추가하고 알림을 보내거나 권한을 바꾸지 마세요. 모든 도구 호출에 대해 읽는 필드, 쓰는 자원, 영향을 받는 계정, 발생 가능한 외부 알림, 필요한 scope, 행동별 승인 유무를 적어요. 각 행동을 ‘공통 빈 시간 비교’, ‘사용자만 보는 개인 임시 일정’, ‘참석자가 있는 일정 생성과 초대 발송’으로 나누고, 두 계층 이상을 한꺼번에 넘는 도구는 경계가 넓다고 표시해요. 이어서 불필요한 일정 내용을 읽지 않고 후보 시간 두 개, 시간대, 충돌 출처, 확인되지 않은 값을 돌려주는 제안 전용 최소 버전을 설계해요. 쓰기가 필요하다면 주최 계정, 캘린더, 참석자와 역할, 시작·종료, 시간대, 반복, 제목, 장소, 공개 범위, 알림 대상, 승인 만료, 중복 방지 ID를 포함한 실행 미리보기 사양을 따로 작성해요. 없는 값은 추측하지 말고 실행 전에 멈춰요.

네 컷으로 보는 저녁 초대 전 단체 확인

민아와 친구 세 명이 저녁 약속을 의논하고 AI가 공통 후보 시간을 찾아요. 민아는 단체 대화방에서 먼저 물어 모두의 답을 기다린 뒤 세 명이 동의하고 나서야 캘린더 초대를 보내요

  1. 민아와 친구 세 명이 단체 대화방에서 저녁 약속을 의논하고, 세 주간 일정에는 서로 다른 바쁜 시간이 보여요.
  2. AI는 세 일정을 맞춰 모두가 비는 한 시간을 후보로만 표시하고 아무에게도 초대를 보내지 않아요.
  3. 민아가 단체 대화방에 후보 시간을 먼저 물어요. 한 명은 동의했지만 두 명의 답은 아직 기다리는 중이에요.
  4. 친구 세 명이 모두 괜찮다고 답한 뒤에야 민아가 일정을 만들고 정식 저녁 초대를 보내요.

민아가 먼저 받는 것은 모두의 일정을 확정한 저녁 약속이 아니라 친구들에게 물어볼 후보예요. AI는 맡은 빈 시간 찾기를 끝내고, 누구의 동의가 왔는지와 일정 이름, 실제 발송 여부는 민아가 정해요. 단체 확인 한 번이 친구들의 캘린더와 주최자로서 민아의 권한을 함께 지켜 줘요.

광고

Share

이 미니 클래스 공유

이 글이 업무 병목을 푸는 데 도움이 되었다면, AI를 어떻게 쓸지 고민하는 사람에게도 공유해 주세요.

참고 자료