에이전트 간 이메일 통신

발행: (2026년 6월 14일 PM 12:38 GMT+9)
8 분 소요
원문: Dev.to

출처: Dev.to

귀하의 구매 에이전트는 하드웨어 주문을 위해 세 개의 견적이 필요합니다. 반대쪽 공급업체는 가격을 자동으로 답변하는 영업 에이전트를 운영하고 있습니다. 두 팀은 서로 대화한 적이 없습니다. 공유된 API 계약도, 동의된 프로토콜도, 통합 프로젝트도 없습니다. 구매 에이전트는 단순히… 이메일을 보냅니다. 영업 에이전트가 회신합니다. 협상이 진행됩니다.

이것이 가능한 이유는 두 에이전트 모두 가장 AI 에이전트에게 없는 것 — 실제 이메일 주소 — 를 가지고 있기 때문입니다.

The interop problem nobody’­s protocol has solved

산업계는 에이전트‑대‑에이전트 프로토콜을 설계하는 데 바쁘다 — 기능 탐색용 스키마, 메시지 엔벨로프, 신뢰 핸쉐이션. 모두 동일한 부트스트랩 문제를 공유한다: 양쪽 모두가 같은 사양을 채택해야 하고, 사양은 원하는 상대방이 모두 구현했을 때만 유용하다.

이메일은 그 문제를 수십 년 전부터 회피해 왔다. 이는 퍼더레이션된 (anyone can run a mailbox on any domain), 자체 신원(주소), 자체 대화 상태(스레딩) 구조를 가지고 있으며, 지구상의 모든 조직이 이미 수신 전달을 받아들인다. SMTP를 구사하는 에이전트는 사전에 누구와도 합의하지 않고任何对方 — 사람이나 기계 — 와 통신할 수 있다.

What each agent needs: a first-­class identity

Agent Accounts — Nylas의 베타 기능 — 에이전트에게 정확히 그 기능을 제공한다. 각 계정은 procurement-agent@yourcompany.com과 같은 호스팅된 메일박스로, SMTP를 통해 상호작용하는 누구에게나 인간 운영 계정과 구별되지 않는다. 내부적으로는 단순히 또 다른 위탁(grant)이며, grant_id가 Messages, Drafts, Threads, Folders, Attachments 및 Webhooks 엔드포인트와 함께 작동한다.

그 “인간 계정과 구별할 수 없음”이라는 표현은 소리보다 더 중요하다. 이는 에이전트‑대‑에이전트와 에이전트‑대‑사람이 동일한 코드 경로를 사용한다는 의미다.采购 에이전트는 sales@vendor.example이 사람인지, 봇인지, 아니면 질문을 어려운 사람에게 인간에게 전달하는 사람인지 여부와는 무관하게 신경 쓰지 않는다. 협상은 어느 쪽에서도 원활히 인간 처리로 전환되며, 이는 맞춤형 에이전트 프로토콜이 주장할 수 없는 것이다.

The mechanics of a negotiation

에이전트 A는 단순히 send로 대화를 시작한다:

curl --request POST \
   --url "https://api.us.nylas.com/v3/grants/$AGENT_A_GRANT_ID/messages/send" \
   --header "Authorization: Bearer $NYLAS_API_KEY" \
   --header "Content-Type: application/json" \
   --data '{ 
     "to": [{ "email": "sales-agent@vendor.example" }], 
     "subject": "Quote request: 40 units, SKU TR-200", 
     "body": "Requesting a quote for 40 units of TR-200, delivery by end of quarter." 
   }'

On the vendor’­s side, the inbound message fires a standard message.created webhook — identical in shape to the same event for any other grant. Their agent reads it, reasons, and replies in-­thread by passing reply_to_message_id on its own send. The platform populates the In-Reply-To and References headers automatically, so both mailboxes index the exchange as one conversation.

That threading is the quiet superpower here. Each agent reconstructs the full negotiation state by fetching the thread — every offer, counter‑offer, and constraint is durable, ordered, and inspectable. No session store, no shared database, no conversation‑state service. The thread is the state, and it’­s replicated on both sides by the protocol itself.

Telling agents apart from humans in your handler

If your application also handles webhooks for connected human accounts, you’­ll want to know which deliveries belong to agent mailboxes. The payload shape gives you nothing to branch on — by design, message.created for an Agent Account is identical to message.created for a Gmail or Outlook grant.

async function handleMessageCreated(payload) { 
  const grantId = payload.data.grant_id; 
  const grant = await getGrant(grantId); // cache this lookup 

  if (grant.provider === "nylas") { 
    return agentLoop.enqueue(payload); // agent mailbox — route to the negotiation loop 
   } 
  return humanInboxHandlers.dispatch(payload); // connected human account 
}

One handler, one branch, and the rest of your webhook infrastructure — verification, retries, queueing — stays shared between humans and agents.

Guard the loop before the model sees anything

An agent that replies to whatever lands in its inbox will reply to spam, phishing, and cold outreach from other people’­s runaway agents. Inbound rules let you reject that traffic at the SMTP stage, before the message is stored and before message.created ever fires — your negotiation loop never sees it.

Rules match on sender fields (from.address, from.domain, from.tld) and run actions like block, mark_as_spam, or assign_to_folder. For values that change over time, point a rule at a list through the in_list operator: a typed collection of domains or addresses that anyone can update without touching the rule. A practical setup for a procurement agent is an address list of known vendor counterparts, a rule that routes their mail to a negotiations folder, and a block rule in front of everything from domains you’­ve flagged. The agent then reasons only over mail that survived the filter.

Structured data rides along fine

Email bodies are free text, which suits LLM agents — the model parses the counterpart’­s prose directly. But nothing stops you from embedding structure: a JSON block in the body, an attachment with the formal quote, a machine‑readable footer. The pattern that works well is 읽기 쉬운 텍스트와 구조화된 페이로드를 이어붙이는 방식이며, 동일한 메시지가 인간 검토자와 파싱 에이전트 모두에게 동일하게 작동한다. 상대방이 사람이라면 JSON을 무시한다. 에이전트라면 본문을 건너뛴다.

The honest caveats

Email’­s latency is seconds, not milliseconds — webhook delivery typically lands shortly after the SMTP handoff, but this’­s not a channel for tight request/response loops. It’­s a channel for negotiations, confirmations, and workflows that span hours or days, where durability beats speed.

There are quotas to respect too. The cap is 200 messages per account per day on the free plan (paid plans drop the daily cap by default), and outbound messages are capped at 40 MB total. A runaway agent loop — two bots politely thanking each other forever — will burn through a daily quota fast, so build a turn limit or a “no new information” detector into your reply logic.

And identity cuts both ways: because your agent has a real address on your real domain, its behavior affects your domain’­s sender reputation. One application can manage accounts across unlimited registered domains, which is why putting agents on a dedicated subdomain is the standard recommendation.

Try the two‑mailbox experiment

The fastest way to feel this pattern is to provision two accounts in the same application — the quickstart takes under 5 minutes per mailbox — wire each to a different LLM with a different objective (“buy below $50/unit” vs. “sell above $45/unit”), and let them email each other. Watch the thread in the mailbox as they converge.

Then ask yourself: what cross‑organization workflow are you currently exposing a REST API for that could just be… an email address?

0 조회
Back to Blog

관련 글

더 보기 »

넷라 보안

🔱 Building Netra Security: Creating a Python-Based Static Application Security Testing SAST Tool As a cybersecurity student, I've always been curious about how...