가족용 캘린더 봇이 모든 것을 처리해야 한다고 생각했지만, AI는 의사결정보다 정보 수집(Intake)에 훨씬 뛰어나다는 것을 깨달았습니다
요약
AI 에이전트 설계 시 자율적 의사결정보다 비정형 데이터를 구조화된 정보로 변환하는 '정보 수집(Intake)' 역할에 집중할 것을 제안합니다. LLM은 난잡한 인간의 입력을 추출하는 데 사용하고, 일정 생성 및 중복 방지와 같은 실행 로직은 결정론적 코드로 처리해야 합니다.
핵심 포인트
- AI는 의사결정보다 비정형 데이터의 구조화(Intake)에 더 효과적임
- LLM은 데이터 추출 및 추론에, 일반 코드는 결정론적 로직 수행에 분리 사용
- 에이전트 설계 시 부수 효과(Side effects)보다 정보 수집 패턴을 우선 고려
- Google Calendar API와 같은 실행 단계는 안정적인 코드로 제어해야 함
r/openclaw의 가족용 Gmail/캘린더 어시스턴트 구축에 관한 스레드를 읽고 깊이 빠져들게 되었습니다.
한 문장이 전체 유스케이스(use case)를 포착했습니다:
“이메일(또는 나중에 텔레그램 메시지)을 수신하고, 적절할 때 자신의 캘린더에 일정 항목을 생성하며, 요청자(및 기타 관련자)에게 알림이 포함된 초대장을 보내기를 원합니다.”
이것은 정말 좋은 자동화 대상입니다.
“자율적인 가계 에이전트(autonomous household agent)를 구축하는 것”이 아닙니다.
단지: 엉망인 요청을 받아서, 유효한 이벤트로 변환하고, 적절한 사람들을 초대하며, 혼란을 야기하지 않는 것입니다.
그때 스레드의 누군가가 가능한 가장 좋은 질문을 던졌습니다:
“결국 당신이 그냥 초대만 받는 것이라면, 그게 무슨 이득인가요?”
그 질문은 많은 잘못된 아키텍처(architecture)를 무너뜨립니다.
왜냐하면 최종 결과물이 캘린더 초대라면, 어려운 부분은 Google Calendar가 아니기 때문입니다. 어려운 부분은 Google Calendar에 입력되기 전의 엉망인 인간의 입력값입니다.
그 지점이 바로 GPT-5, Claude Opus 4.6 또는 다른 강력한 모델이 도움이 되는 곳입니다.
그 이후의 모든 과정은 결정론적(deterministic)이어야 합니다.
패턴: 부수 효과(side effects)가 아닌 정보 수집(intake)에 AI를 사용하라
만약 여러분이 n8n, OpenClaw, Make, Zapier 또는 자체 Node/Python 서비스로 이를 구축하고 있다면, 깔끔한 분리는 다음과 같습니다:
- LLM을 사용하여 엉망인 텍스트에서 구조화된 필드(structured fields)를 추출합니다.
- 일반적인 코드를 사용하여 이벤트를 생성할지 여부를 결정합니다.
- Google Calendar API를 사용하여 부수 효과(side effect)를 수행합니다.
이것은 “AI 캘린더 에이전트”라는 말보다 덜 흥미롭게 들릴 수 있습니다.
하지만 이것이 치과 예약 일정을 무작위로 중복 생성하지 않는 설계입니다.
Google Calendar는 쉬운 부분입니다
Google Calendar API는 가장 좋은 의미에서 지루합니다.
events.insert는 깊은 추론을 요구하지 않습니다. 유효한 필드를 원할 뿐입니다.
최소한, 정말로 필요한 것은 사용 가능한 start와 end입니다. 그 이후에는 다음과 같은 것들을 추가할 수 있습니다:
attendees(참석자)reminders(알림)recurrence(반복)location(장소)conferenceData(회의 데이터)- 커스텀 이벤트 ID
extendedProperties(확장 속성)
어려운 부분은 인간으로부터 받는 입력값입니다.
예시:
- “다음 주 목요일 3시에 Sam의 치과 예약 잡아주고, 1시간 전에 알림 설정한 다음 나랑 아빠 초대해줘.”
- “다음 한 달 동안 매주 화요일 6시에 축구 연습 예약해줘.”
- “내 오후 2시 일정 끝난 뒤에 Priya랑 점심 식사, 교통 체증이 있으면 3시 30분쯤으로.”
인간은 스키마 (Schema)를 작성하는 데 서툽니다.
LLM (대규모 언어 모델)은 그 난잡한 정보를 구조화된 데이터로 바꾸는 데 매우 능숙합니다.
모델이 도움을 주는 부분
다음 작업에는 GPT-5, Claude 또는 Grok을 사용하세요:
summary(요약) 추출start(시작) 및end(종료) 시간 추론- 참석자 식별
- 반복 의도 파악
- 신뢰도 점수 (Confidence score) 할당
- 후속 질문을 던질 시점 결정
코드가 주도권을 가져야 하는 부분
다음 작업에는 결정론적 로직 (Deterministic logic)을 사용하세요:
- 중복 방지
- 알림 기본값 설정
- 초대 정책
- 충돌 확인
- RRULE (반복 규칙) 포맷팅
- 재시도 (Retries)
- 멱등성 (Idempotency)
- 불완전한 요청 거부
이러한 역할 분담이 설계의 핵심입니다.
3가지 접근 방식 순위
에이전트 (Agent)를 프로덕션 API에 직접 연결하기 전에, 더 많은 사람들이 수행했으면 하는 비교 분석입니다:
| 접근 방식 | 실제로 일어나는 일 |
|---|---|
| LLM 추출 + 결정론적 캘린더 로직 | 가장 권장되는 기본 방식. 유연한 입력 처리, 신뢰할 수 있는 부수 효과 (Side effects), 검증 및 디버깅 용이. |
| ... |
만약 이 포스트에서 단 한 가지만 기억해야 한다면, 바로 저 표입니다.
내가 완전한 에이전트 방식의 캘린더 봇을 신뢰하지 않는 이유
나는 에이전트 반대론자가 아닙니다.
나는 작업 범위가 명확함에도 불구하고 부수 효과 (Side effects)를 동반하는 에이전트 방식에 반대하는 것입니다.
캘린더 봇은 “창의적인 탐색 (Creative exploration)”을 원하는 곳이 아닙니다.
당신이 원하는 것은 제한된 해석 (Bounded interpretation)입니다.
모델은 다음과 같은 질문에 답해야 합니다:
- 사용자가 의도한 날짜가 언제인가?
- 이것이 반복되는 일정인가?
- 누구를 초대해야 하는가?
- 진행하기에 충분한 신뢰도가 확보되었는가?
모델이 전체 워크플로우 (Workflow)를 즉흥적으로 수행한 뒤 실제 캘린더를 직접 수정하게 해서는 안 됩니다.
그렇게 하면, 가장 짜증 나는 방식으로 실패하기 직전까지는 신뢰할 수 있는 것처럼 느껴지다가 결국 망가져 버리는 시스템을 만들게 됩니다.
n8n 또는 커스텀 코드를 위한 실무적인 아키텍처 (Architecture)
만약 제가 오늘 이 시스템을 구축한다면, 이를 구조화된 정보 수집 (Structured Intake)과 결정론적 실행 (Deterministic Execution)의 결합으로 다룰 것입니다.
흐름 (Flow)
- 전용 Gmail 라벨 또는 Telegram 봇 수신함을 모니터링합니다.
- 메시지 텍스트를 가져옵니다.
- 엄격한 스키마 (Schema)를 가진 LLM (대규모 언어 모델)으로 전송합니다.
- 필수 필드를 검증합니다.
- 신뢰도 (Confidence)가 낮으면 추가 질문을 던집니다.
- 유효하다면 Google Calendar API를 통해 이벤트를 생성합니다.
- 중복 제거 (Dedupe) 및 추후 업데이트를 위해 메타데이터를 저장합니다.
이 아키텍처 (Architecture)는 다음 환경에서 작동합니다:
- n8n
- OpenClaw
- Make
- Zapier
- 순수 Node.js
- 순수 Python
"유효한 JSON을 반환해 주세요"가 아닌 구조화된 출력 (Structured Outputs)을 사용하세요
이 부분은 여러분이 몇 달 동안 재시도 로직 (Retry glue)을 작성하며 고생하는 것을 막아주는 핵심입니다.
만약 OpenAI 호환 API를 사용하고 있다면, 구조화된 출력 (Structured Outputs) 또는 스키마 제약 응답 (Schema-constrained responses)을 사용하세요.
최소한의 Node.js 예시:
import OpenAI from "openai";
import { z } from "zod";
import { zodResponseFormat } from "openai/helpers/zod";
...
이것이 여기서 AI가 주는 유용한 부분입니다.
"내 캘린더를 실행해 줘"가 아닙니다.
그저 "내 코드가 신뢰할 수 있는 형태로 의도 (Intent)를 추출해 줘"인 것입니다.
n8n을 사용한다면, 이 방식이 깔끔하게 매핑됩니다
n8n의 Information Extractor 노드는 이 패턴에 매우 잘 맞습니다.
원하는 필드를 정의하고, 설명이나 스키마를 제공하면 모델이 구조를 채우도록 합니다.
그러면 나머지 워크플로 (Workflow)는 평소와 같이 유지됩니다.
예시 구조:
{
"summary": "Sam dentist appointment",
"start": "2026-05-28T15:00:00-04:00",
...
그 이후부터는 단순한 워크플로 로직일 뿐입니다.
Gmail 수집 (Intake): 범위를 좁게 유지하세요
가족용 봇이 여러분의 메일함 전체에 접근할 필요는 없습니다.
전용 라벨이나 수신 경로를 사용하세요.
이렇게 하면 두 가지 합리적인 운영 모드를 가질 수 있습니다:
messages.list를 이용한 폴링 (Polling)users.watch를 이용한 푸시 알림 (Push notifications)
예시 watch 요청:
POST https://gmail.googleapis.com/gmail/v1/users/me/watch
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
...
이 설계는 사람들이 생각하는 것보다 훨씬 중요합니다.
봇이 좁은 경로만 읽는다면, 장애 발생 모드 (Failure modes)가 훨씬 줄어듭니다.
그다음 일반적인 코드로 이벤트를 생성하세요
googleapis를 사용하는 간소화된 Node.js 예제는 다음과 같습니다:
npm install googleapis
import { google } from "googleapis";
const auth = new google.auth2.OAuth2(
...
이는 에이전트에게 광범위한 Google Calendar 접근 권한을 부여하고 결과가 좋기를 바라는 것보다 훨씬 안전합니다.
매우 중요한 세 가지 구현 세부 사항
이 부분들은 시스템을 신뢰할 수 있게 만드는 지루한 작업들입니다.
1. 자체 이벤트 ID 사용하기
이벤트를 삽입할 때 커스텀 이벤트 ID를 설정하세요.
이를 통해 멱등성 (Idempotency)을 확보할 수 있습니다.
워크플로 (Workflow)가 재시도되더라도 중복된 이벤트를 생성하지 않게 됩니다.
2. extendedProperties에 메타데이터 저장하기
이 방법은 과소평가되어 있습니다.
다음과 같은 정보들을 저장하세요:
- 원본 Gmail 메시지 ID
- 소스 채널 (
gmail,telegram) - 추출 신뢰도 (Extraction confidence)
- 내부 워크플로 실행 ID
이렇게 하면 향후 데이터 대조 (Reconciliation) 및 디버깅 (Debugging)이 훨씬 쉬워집니다.
3. 업데이트 시 etag 준수하기
사람들은 캘린더 항목을 수동으로 편집합니다.
앞으로도 항상 그럴 것입니다.
나중에 워크플로가 이벤트를 업데이트할 경우, etag / If-Match 의미론 (Semantics)을 사용하여 사람의 변경 사항을 맹목적으로 덮어쓰지 않도록 하세요.
그래야만 이벤트를 계속해서 잘못된 버전으로 "수정"하며 가정 내의 골칫거리가 되는 상황을 피할 수 있습니다.
Telegram이 실제로 더 나은 정보 수집 (Intake) 레이어일 수 있습니다
이메일은 지저분합니다.
이러한 정확한 사용 사례에는 Telegram이 종종 더 깔끔합니다.
메시지가 더 짧고, 더 직접적이며, 서명, 인용된 스레드, 전달된 스팸 등으로 인해 오염되는 일이 적습니다.
예시:
“다음 한 달 동안 매주 화요일 6시에 축구 연습 예약해줘”
이는 LLM 입력값으로서 거의 이상적입니다.
흐름은 동일합니다:
- 메시지 수신
- 필드 추출
- 반복 의도 (Recurrence intent)를 실제 RRULE로 변환
- 이벤트 생성
- 중요한 정보가 누락된 경우에만 후속 질문 수행
다시 말하지만, 모델은 해석(Interpret)할 뿐입니다.
결정(Decide)하는 것은 당신의 코드입니다.
디자인을 증명하기에는 작은 CLI 프로토타입만으로도 충분합니다
이 패턴을 검증하기 위해 완전한 에이전트 프레임워크 (Agent framework)가 필요하지는 않습니다.
단일 스크립트로 프로토타입을 만들 수 있습니다.
npm install openai zod googleapis dotenv
OPENAI_API_KEY=your_key
OPENAI_BASE_URL=https://api.openai.com/v1
GOOGLE_CLIENT_ID=your_client_id
...
그런 다음 테스트 문자열을 입력하여 쓰기(write) 기능을 활성화하기 전에 추출된 의도(intent)를 검사하십시오.
이 방식은 처음부터 "다중 에이전트 자율 가족 비서(multi-agent autonomous family assistant)"로 시작하는 것보다 프로덕션 수준의 신뢰성에 훨씬 더 가깝게 다가갈 수 있게 해줍니다.
이 패턴은 매우 잘 일반화됩니다
제가 이 아키텍처(architecture)를 좋아하는 이유는 가족용 캘린더 봇이 진지한 운영(ops) 워크플로우의 친근한 버전일 뿐이기 때문입니다.
동일한 패턴이 다음 작업에도 적용됩니다:
- 고객 지원 분류 (support triage)
- 채용 조율 (recruiting coordination)
- 인바운드 일정 예약 (inbound scheduling)
- CRM 업데이트
- 내부 요청 큐 (internal request queues)
- 리드 자격 검증 (lead qualification)
인간은 무질서한 텍스트를 보냅니다.
AI는 구조를 추출합니다.
코드는 부수 효과(side effect)를 수행합니다.
이것이 반복 가능한 패턴입니다.
한 가지 더 실질적인 점: 모든 것을 에이전트화하면 비용이 빠르게 이상해집니다
이것이 제가 좁은 범위의 워크플로우를 방대한 에이전트 시스템으로 전환하는 것에 회의적인 이유이기도 합니다.
만약 작업이 주로 추출(extraction)과 결정론적인 API 호출(deterministic API call)로 이루어져 있다면, 에이전트 루프(agent loops)에 엄청난 양의 토큰을 소모하는 것은 잘못된 거래입니다.
이는 n8n, Make, Zapier, OpenClaw 또는 커스텀 워커(custom workers)에서 하루 종일 자동화를 실행하는 팀들에게 특히 해당됩니다.
모델은 기본적으로 모든 곳에 적용하는 것이 아니라, 레버리지(leverage)를 더할 수 있는 곳에 사용해야 합니다.
이것이 Standard Compute와 같은 제품이 이 카테고리에서 흥미로운 이유 중 하나입니다. 모든 자동화 실행을 토큰 예산 비상사태처럼 취급하지 않고도 워크플로우 내에서 유용한 LLM 단계를 유지할 수 있기 때문입니다. 고정 월정액 요금제는 워크플로우가 급증할 때마다 토큰당 비용을 주시하는 것보다, 항상 켜져 있는 에이전트 및 자동화에 훨씬 더 적합합니다.
저의 기본 권장 사항
캘린더 비서를 구축하고 있다면, 다음과 같이 하십시오:
- 추출(extraction)을 위한 LLM
- 구조화를 위한 스키마 (schema)
- 검증을 위한 코드
- 부수 효과(side effects)를 위한 Google Calendar API
- 멱등성(idempotency)을 위한 커스텀 ID
- 감사 가능성(auditability)을 위한 메타데이터
- 신뢰도가 낮을 때의 후속 질문
매우 구체적인 이유가 없다면, 완전히 에이전트 중심적인(agentic) 봇으로 시작하지 마십시오.
재미있는 점은 이 시스템의 가장 이상적인 버전이 AI 마법이라기보다는 훌륭한 배관(plumbing)처럼 느껴진다는 것입니다.
이는 찬사입니다.
왜냐하면 진정한 승리는 AI가 "당신의 가족 캘린더를 운영하는 것"에 있지 않기 때문입니다.
진정한 승리는 AI가 엉망인 정보 수집(intake) 계층을 정리하고, 나머지 부분을 신뢰할 수 있는 로직(logic)에 넘겨주는 데 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기