Claude를 위한 이메일 도구: 에이전트 메일박스를 사용한 도구 활용
요약
Claude가 Nylas Agent Account를 통해 실제 이메일 환경을 운영할 수 있는 도구 활용 방법을 소개합니다. 복잡한 OAuth 구현 대신 CLI 쉘아웃 방식을 사용하여 간결한 코드로 에이전트 전용 메일박스를 구축하는 가이드를 제공합니다.
핵심 포인트
- Nylas Agent Account를 활용해 에이전트 전용 호스팅 메일박스 구축 가능
- OAuth 구현의 복잡성을 줄이기 위해 CLI 서브프로세스 도구 방식 채택
- 모델이 스스로 검색과 읽기 단계를 결정하는 도구 활용(Tool Use)의 이점
- send_email 도구 사용 시 설명(description)을 통한 가드레일 설정 권장
Claude는 세 가지 도구 정의와 약 40줄의 접착 코드(glue code)만으로 실제 메일박스를 운영할 수 있습니다.
tools = [
{
"name": "read_emails",
...
흥미로운 부분은 스키마가 아니라 그것들을 뒷받침하는 방식입니다. 이 도구들을 OAuth를 통해 인간의 Gmail에 연결하는 대신, 에이전트가 완전히 소유하는 호스팅 메일박스인 Nylas Agent Account에 연결할 수 있습니다. 이는 등록된 도메인에서 단 하나의 명령어로 생성됩니다:
nylas agent account create agent@yourdomain.com
Agent Accounts는 베타 버전이지만, 다른 모든 권한(grant)처럼 작동하므로 동일한 CLI 명령어와 API 엔드포인트가 변경 없이 작동합니다.
순수 OAuth 대신 서브프로세스 도구를 사용하는 이유
Gmail OAuth를 직접 구현하려면 에이전트가 유용한 작업을 수행하기 전에 약 300줄의 토큰 플러밍(token plumbing) 코드를 작성해야 합니다. 여기에 Microsoft Graph까지 추가하면 600줄에 달합니다. IMAP 폴백(fallback)을 추가하면 1,000줄을 넘어섭니다. 도구를 사용한 LLM 에이전트 레시피는 다른 경로를 따릅니다: nylas CLI로 쉘아웃(shell out)하여 인증, 새로고침, 제공업체별 차이점 처리를 맡기게 합니다. 구현은 간결합니다:
import json, subprocess
def _run(cmd: list[str]) -> str:
...
두 개의 플래그가 보이는 것보다 더 중요합니다. --yes는 상호작용적인
루프에 실제 작업을 부여하면 코드보다 실행 추적(trace)이 더 흥미로워집니다. "계약에 대해 답장한 사람이 있나요?"라는 질문에 대한 전형적인 실행 과정은 다음과 같습니다:
- Claude가
tool_use블록을 생성합니다:search_emails를{"query": "contract"}와 함께 호출합니다. - CLI가 5개의 검색 결과를 JSON 형식으로 반환합니다. Claude는 그중 하나가 어제의 답장임을 인지하지만, 스니펫(snippet)이 잘려 있습니다.
- Claude는 전체 문맥(context)이 포함된 최근 메시지를 가져오기 위해
{"limit": 10}과 함께read_emails를 호출합니다. - 두 결과가 대화에 포함되면,
stop_reason이end_turn으로 반환되고 Claude는 누가, 언제, 무엇을 말했는지 평문(plain text)으로 답변합니다.
이 시퀀스의 어떤 단계도 스크립트로 작성되지 않았습니다. 모델은 읽기 전에 검색하기로 결정했고, 두 번의 도구 호출이면 충분하다고 판단했습니다. 이것이 하드코딩된 파이프라인(pipeline) 대신 도구 활용(tool use)을 사용하는 핵심적인 매력이며, 동시에 아래에서 설명할 가드레일(guardrails)이 중요한 이유입니다.
전송 도구 보호하기
read_emails와 search_emails는 무해합니다. 하지만 send_email은 그렇지 않으므로 세 가지 단계의 제약이 필요합니다:
- 설명(description)에 가드레일을 포함하세요. 이 쿡북(cookbook)의 전송 도구 스키마(schema)에는 다음과 같이 적혀 있습니다: "호출하기 전에 수신자, 제목, 본문을 사용자와 확인하십시오." Claude는 도구 설명을 지침(instruction)으로 취급하므로, 이 한 줄은 대화형 사용 시 의도치 않은 전송을 의미 있게 줄여줍니다.
- 타임아웃(timeout)을 유지하세요. 모든
subprocess.run호출에 적용된timeout=30은 단순한 장식이 아닙니다. 그렇지 않으면 프롬프트(prompt)를 기다리거나 네트워크가 느린 CLI 명령이 루프를 영원히 중단(hang)시킬 수 있습니다. 이는--yes플래그가 방지하고자 하는 실패 모드이며, 두 번째로 포착된 문제입니다. - 자격 증명(credential)의 범위를 제한하세요. CLI는 활성화된 권한에 따라 동작합니다. 멀티 테넌트(multi-tenant) 에이전트의 경우, 테넌트별로 CLI 프로세스를 실행하거나
--api-key를 명시적으로 전달하여 한 테넌트의 루프가 다른 테넌트의 메일박스에 절대 접근할 수 없도록 해야 합니다.
문맥(context) 제어하기
nylas email list --limit 100 명령은 컨텍스트 윈도우 (context window)를 다 잡아먹을 정도로 방대한 JSON 벽을 생성합니다. Cookbook의 조언은 다음과 같습니다: 스키마 자체에서 limit 값을 공격적으로 제한하십시오. 기본값인 10은 의도된 것이며, 목록 호출 시 5는 합리적인 최솟값입니다. 에러 문자열도 그대로 통과시키십시오. 서브프로세스 (Subprocess) 실패는 stderr 텍스트로 반환되는데, 모델은 "grant expired"와 "rate limited" 중 무엇을 어떻게 처리할지 결정하는 데 놀라울 정도로 능숙합니다.
운영 측면에서 한 가지 더 주의할 점이 있습니다: CLI는 nylas auth list에서 현재 활성화된 권한 (grant)에 따라 동작합니다. 에이전트 계정 (Agent Account)은 Provider: Nylas와 함께 목록에 표시되므로, 계정을 생성한 후 루프를 시작하기 전에 해당 계정으로 전환해야 합니다. 그렇지 않으면 에이전트가 당신의 개인 주소로 즐겁게 메일을 보낼 것입니다.
에이전트가 메일박스를 소유해야 하는 이유
이러한 도구들에 에이전트 자신의 주소를 연결하면 보안 측면의 이야기가 달라집니다. 답장은 당신의 애플리케이션이 제어하는 편지함으로 들어옵니다. 기계가 작성한 메일로 보낸 편지함이 가득 차는 사람도 없고, 그 사람이 퇴사할 때 깨져버리는 OAuth 동의 (OAuth consent) 문제도 없습니다. 메일박스는 일반 계정처럼 메일을 보내고, 받고, 스레드 (thread)를 형성합니다.
서브프로세스(Subprocess), MCP, 또는 SDK?
Claude를 이 메일박스에 연결하는 방법에는 세 가지가 있으며, 각각 다른 런타임 (runtime)에 적합합니다:
| 경로 | 최적의 용도 | 요구 사항 |
|---|---|---|
| 서브프로세스 (Subprocess) + CLI (본 포스트) | 당신이 완전히 제어하는 커스텀 Python 루프 | 3개의 래퍼 (wrapper) 함수, 약 40줄 |
| ... |
SDK 경로는 CLI의 편리함을 명시성 (explicitness)과 맞바꿉니다. 모든 호출은 grant_id를 포함하며, 에러는 error.type 필드(unauthorized, rate_limit_error, invalid_request_error)가 포함된 구조화된 JSON으로 반환되며, 로컬 CLI 상태에 의존하는 것이 아무것도 없습니다. 자율 에이전트 퀵스타트 (autonomous agents quickstart)에서는 CLI와 MCP 경로를 다루며, 코딩 에이전트 가이드 (coding agents guide)에서는 API를 직접 호출하고 싶은 경우를 위한 SDK 경로를 다룹니다.
여러 단계의 과정이 필요한 작업(예: "최신 인보이스 이메일을 찾아 요약본을 회계 부서로 전달해줘")을 루프(loop)에 입력해 보고, Claude가 어떤 도구들을 체인(chain)으로 연결하는지 관찰해 보세요. 이 세 가지 도구 외에 가장 먼저 추가하고 싶은 도구는 무엇인가요?
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기