다른 누군가가 대신하기 전에 스스로 에이전트의 속도 제한(Rate-Limit)을 설정하세요
요약
자율 에이전트의 무한 루프로 인한 대량 스팸 발송 및 계정 정지 문제를 방지하기 위해, 플랫폼의 강제 제한 이전에 자체적인 속도 제한(Rate-limit)과 할당량(Quota)을 설정해야 합니다. 할당량을 단순한 제한이 아닌 시스템의 정상 동작을 정의하는 '단언(Assertion)'으로 활용할 것을 권장합니다.
핵심 포인트
- 에이전트의 무한 루프는 예상치 못한 대량 발송을 초래할 수 있음
- 플랫폼의 강제 제한은 최후의 방어선이며, 자체적인 엄격한 제한이 필요함
- 할당량(Quota)을 시스템의 기대치를 인코딩하는 서킷 브레이커로 활용할 것
- 에이전트의 역할(아키타입)에 따라 차별화된 정책 적용 권장
0.1%. 이것은 Nylas Agent Accounts에서 이메일 발송 계정이 검토 대상이 되는 불만율(complaint rate)입니다. 즉, 1,000건의 발송당 1건의 스팸 보고가 발생할 때입니다. 0.5%가 되면 발송이 즉시 중단됩니다. 바운스(bounces)의 경우, 검토 임계값은 5%이며 10%에서 중단이 시작됩니다. 이것들은 권장 사항이 아닙니다. 플랫폼에 의해 강제되는 사항이며, 중단은 타이머에 의해 자동으로 해제되지 않습니다 — 해결책에 대한 증거를 가지고 고객 지원팀에 문의해야 합니다.
제 입장은 이렇습니다: 저 수치들이 당신의 속도 제한(rate limit)이 되어서는 안 됩니다. 그것들은 당신이 직접 설정한 더 엄격한 제한 뒤에 위치하는 최후의 방어선이 되어야 합니다. 다른 누군가가 당신을 위해 대신 하기 전에, 스스로 에이전트의 속도 제한(rate-limit)을 설정하세요.
LLM 루프에는 자연스러운 정지 지점이 없습니다
전통적인 이메일 코드는 사람이나 크론 잡(cron job)이 명령할 때 발송합니다. 자율 에이전트(autonomous agent)는 모델이 결정할 때 발송하며, 피드백 루프(feedback loops) 내의 모델들은 이상한 결정을 내리곤 합니다. 답장이 웹훅(webhook)을 트리거하고, 그 웹훅이 다시 답장을 트리거하여, 선의의 버그가 점심시간이 되기 전에 수천 건의 발송으로 이어질 수 있습니다. 모델의 추론 과정 중 그 어디에도 "이번 시간 내에 벌써 400번째 메시지네, 이건 좀 이상해"라고 말하는 부분은 없습니다. 그러한 인식은 인프라(infrastructure)에 존재해야 합니다.
Agent Accounts(베타 버전)는 정책(policies)을 통해 인프라를 내장하고 있습니다. 정책은 일일 발송 할당량(daily send quotas), 저장 용량 제한(storage caps), 보관 기간(retention windows), 스팸 설정 등을 하나로 묶어 워크스페이스의 모든 계정에 적용합니다. 정책이 없으면 계정은 귀하의 결제 플랜 최대치로 작동하는데 — 무료 플랜의 경우 계정당 하루 200개의 메시지 — 이는 루프(loop)가 발생할 수 있는 실험에서 정확히 당신이 원하지 않는 상황입니다. 정책의 모든 제한은 선택 사항입니다. 하나를 생략하면 해당 플랜의 최대치로 기본 설정되며, 플랜에서 허용하는 것보다 더 많은 것을 요청하면 API가 이를 거부합니다.
할당량(Quotas)은 예상되는 동작에 대한 선언입니다
유용한 사고의 전환은 다음과 같습니다. 스스로 설정한 할당량(Quota)은 스로틀링(Throttling, 속도 제한)이 아니라 하나의 단언(Assertion)입니다. "이 지원 에이전트는 하루에 150회 이상의 발송이 필요하지 않아야 합니다. 만약 151번째 요청을 한다면, 상위 단계(Upstream)에서 무언가 잘못된 것입니다." 이는 서비스 메쉬(Service Mesh)의 서킷 브레이커(Circuit Breaker)와 동일한 논리입니다. 용량을 제한하는 것이 아니라, 기대치를 인코딩함으로써 위반 사항이 비용이 많이 드는 문제가 되기 전에 가시화되도록 하는 것입니다.
정책(Policies)을 사용하면 에이전트 아키타입(Archetype)별로 서로 다른 기대치를 인코딩할 수 있습니다. 프로토타입은 엄격한 할당량을 할당받고, 프로덕션용 영업 에이전트는 더 높은 할당량을 할당받습니다. 문서에서는 아키타입별로 별도의 워크스페이스(Workspace)를 사용할 것을 명시적으로 권장하는데, 이는 분류(Triage) 에이전트와 아웃리치(Outreach) 에이전트의 발송 프로필이 완전히 다르기 때문입니다.
아웃바운드(Outbound) 규칙은 볼륨(Volume)보다 한 단계 더 나아가 방향을 제약합니다. trigger: "outbound"가 포함된 규칙은 메시지가 제공자(Provider)에 도달하기 전에 평가되며, block 액션은 403 오류와 함께 발송을 거부합니다.
curl --request POST \
--url "https://api.us.nylas.com/v3/rules" \
--header "Authorization: Bearer <NYLAS_API_KEY>" \
...
recipient.* 필드는 BCC 및 SMTP 엔벨로프 수신자(SMTP envelope recipients)를 포함한 모든 수신자와 매칭되므로, 에이전트가 주소를 숨겨서 규칙을 피해 발송을 몰래 수행할 수 없습니다. 또한 outbound.type (compose 대 reply)을 매칭하여, 예를 들어 에이전트가 답장은 자유롭게 하되 완전히 새로운 스레드를 시작하는 것은 차단하도록 설정할 수도 있습니다.
플랫폼이 모니터링하는 것과 동일한 텔레메트리(Telemetry)를 확인하세요
실제로 무엇이 집계되고 있는지 아는 것도 도움이 됩니다. 반송률(Bounce rate)은 존재하지 않는 주소인 하드 바운스(Hard bounce)만을 최근의 대표 발송 볼륨으로 나눈 값만을 계산합니다. 사서함 용량 초과나 그레이리스팅(Greylisting)으로 인한 소프트 바운스(Soft bounce)는 이에 영향을 주지 않으며, 2% 미만이면 정상입니다. 불만율(Complaint rate)은 수신자가 **이 이메일을 스팸으로 표시(Mark this email as spam)**를 클릭하거나 메일을 스팸함으로 드래그하는 경우를 집계하며, 불만 피드백을 보내는 도메인에 대해서만 측정됩니다. 낮은 볼륨에서 0.1%라는 수치가 달성하기 매우 쉬운 이유는, 2,000건을 발송하는 한 주 동안 단 몇 명의 불쾌함을 느낀 수신자만 있어도 계정이 검토 대상이 되기 때문입니다.
에러 응답 또한 알아둘 가치가 있습니다. 평판 일시 중단(reputation pause)은 발송 시 400 에러로 나타나며, 계정당 또는 도메인당 속도 제한(rate limit)은 429를 반환합니다 (잠시 멈춘 후 재시도해야 함). 남용 제한(abuse restriction)은 send blocked by abuse restriction이라는 메시지와 함께 403을 반환합니다. 마지막 케이스는 단일 발신자 주소, 도메인 및 그 하위 도메인, 권한(grant), 또는 애플리케이션 전체로 범위를 지정할 수 있습니다. 애플리케이션 수준의 제한은 문제를 일으킨 특정 계정뿐만 아니라 해당 앱 아래의 모든 에이전트 계정(Agent Account)을 중단시킵니다. 만약 당신의 에이전트가 모든 발송 실패를 재시도 가능한 것으로 처리한다면, 일시 중단된 계정을 계속해서 두드리기만 할 뿐 아무것도 배우지 못할 것입니다.
서킷 브레이커(Circuit breakers)에는 증거가 필요합니다
두 가지 세부 사항이 규칙 계층(rule layer)을 믿고 맡길 수 있을 만큼 신뢰할 수 있게 만듭니다. 첫째, 평가는 실패 시 차단(fails closed) 방식으로 작동합니다. 만약 in_list 매칭 중 리스트 조회 실패와 같은 일시적인 인프라 오류로 인해 block 규칙을 평가할 수 없다면, Nylas는 메시지를 통과시키는 대신 차단합니다. 이 실패는 재시도 가능한 것으로 나타납니다. 즉, API 발송은 403 대신 503을 반환하며, 인바운드 SMTP는 451 tempfail로 응답하여 발신 서버가 메시지를 반송(bounce)하는 대신 재시도하도록 합니다. 부하가 걸렸을 때 조용히 스스로를 비활성화하는 안전 장치는 안전 장치가 아닙니다.
둘째, 모든 평가는 감사 기록(audit record)을 작성합니다. GET /v3/grants/{grant_id}/rule-evaluations를 호출하면 가장 최근 항목부터 어떤 규칙이 일치했는지, 어떤 조치가 적용되었는지, 그리고 고려된 정규화된 발신자 및 수신자 데이터를 확인할 수 있습니다. 규칙 매칭이 아니라 평가 오류로 인해 차단이 발생한 경우, 해당 기록에는 blocked_by_evaluation_error: true가 포함됩니다. 따라서 새벽 2시에 에이전트의 발송이 403을 반환하더라도, "왜 차단되었는가?"에 대한 답을 찾는 것은 고고학 프로젝트가 아니라 단 한 번의 API 호출로 해결됩니다. 관측 가능성(observability)이 없는 서킷 브레이커는 그저 미스터리한 장애일 뿐입니다.
반론: 제한은 정당한 급증(bursts)을 방해한다
정당한 반론은 실제 워크로드(workloads)는 급증(spike)한다는 점입니다. 장애 발생 시의 지원 에이전트(support agent)는 정상적인 양의 5배가 정당하게 필요할 수 있으며, 엄격한 할당량(hard quota)은 당신의 안전망을 가용성 장애(availability incident)로 변질시킵니다. 만약 그 할당량이 막다른 길(dead end)이라면, 그것은 사실입니다.
그러니 그것을 막다른 길로 만들지 마세요. 할당량에 도달하는 것을 에스컬레이션 경로(escalation path)로 만드세요: 사람에게 알림을 보내거나, 초과분을 대기열(queue)에 넣거나, 한도를 높이기 위한 승인을 요구하는 식입니다. 너무 타이트한 할당량의 실패 모드(failure mode)는 Slack 알림 하나와 한 시간 정도 지연된 이메일입니다. 반면 할당량이 없는 경우의 실패 모드는 10%의 반송률(bounce rate), 지원 티켓(support ticket)을 제출해야만 해제되는 플랫폼 수준의 일시 중단, 그리고 몇 주에 걸쳐 다시 구축해야 하는 발신자 평판(sender reputation)입니다. 이것들은 대칭적인 위험이 아닙니다.
또한 알아둘 가치가 있는 더 부드러운 조절 장치도 있습니다: 정책(policies)은 인바운드 필터링(inbound filtering)을 위해 spam_sensitivity를 0.1에서 5.0까지 노출합니다. 인바운드 위생(hygiene)은 아웃바운드 건강(outbound health)에 있어 중요합니다. 왜냐하면 스팸에 답장하는 에이전트가 불만 사항(complaints)을 생성하기 때문입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기