refactor(blocks): use AsyncAgentMail client in all agent mail blocks

Replace synchronous AgentMail client with AsyncAgentMail to avoid
blocking the event loop during HTTP calls in async run() methods.
This commit is contained in:
abhi1992002
2026-03-16 21:50:23 +05:30
parent c3855c0910
commit cf1ba67d86
7 changed files with 60 additions and 58 deletions

View File

@@ -11,7 +11,7 @@ then use these blocks to retrieve the file content as base64.
import base64
from agentmail import AgentMail
from agentmail import AsyncAgentMail
from backend.sdk import (
APIKeyCredentials,
@@ -27,8 +27,8 @@ from backend.sdk import (
from ._config import agent_mail
def _client(credentials: APIKeyCredentials) -> AgentMail:
return AgentMail(api_key=credentials.api_key.get_secret_value())
def _client(credentials: APIKeyCredentials) -> AsyncAgentMail:
return AsyncAgentMail(api_key=credentials.api_key.get_secret_value())
class AgentMailGetMessageAttachmentBlock(Block):
@@ -77,7 +77,7 @@ class AgentMailGetMessageAttachmentBlock(Block):
) -> BlockOutput:
try:
client = _client(credentials)
data = client.inboxes.messages.get_attachment(
data = await client.inboxes.messages.get_attachment(
inbox_id=input_data.inbox_id,
message_id=input_data.message_id,
attachment_id=input_data.attachment_id,
@@ -141,7 +141,7 @@ class AgentMailGetThreadAttachmentBlock(Block):
) -> BlockOutput:
try:
client = _client(credentials)
data = client.inboxes.threads.get_attachment(
data = await client.inboxes.threads.get_attachment(
inbox_id=input_data.inbox_id,
thread_id=input_data.thread_id,
attachment_id=input_data.attachment_id,

View File

@@ -8,7 +8,7 @@ and complex multi-step email composition workflows.
from typing import Optional
from agentmail import AgentMail
from agentmail import AsyncAgentMail
from backend.sdk import (
APIKeyCredentials,
@@ -24,8 +24,8 @@ from backend.sdk import (
from ._config import agent_mail
def _client(credentials: APIKeyCredentials) -> AgentMail:
return AgentMail(api_key=credentials.api_key.get_secret_value())
def _client(credentials: APIKeyCredentials) -> AsyncAgentMail:
return AsyncAgentMail(api_key=credentials.api_key.get_secret_value())
class AgentMailCreateDraftBlock(Block):
@@ -116,7 +116,7 @@ class AgentMailCreateDraftBlock(Block):
if input_data.send_at:
params["send_at"] = input_data.send_at
draft = client.inboxes.drafts.create(input_data.inbox_id, **params)
draft = await client.inboxes.drafts.create(input_data.inbox_id, **params)
result = draft.__dict__ if hasattr(draft, "__dict__") else {}
yield "draft_id", draft.draft_id
@@ -167,7 +167,7 @@ class AgentMailGetDraftBlock(Block):
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
) -> BlockOutput:
client = _client(credentials)
draft = client.inboxes.drafts.get(
draft = await client.inboxes.drafts.get(
inbox_id=input_data.inbox_id,
draft_id=input_data.draft_id,
)
@@ -241,7 +241,7 @@ class AgentMailListDraftsBlock(Block):
if input_data.labels:
params["labels"] = input_data.labels
response = client.inboxes.drafts.list(input_data.inbox_id, **params)
response = await client.inboxes.drafts.list(input_data.inbox_id, **params)
drafts = [
d.__dict__ if hasattr(d, "__dict__") else d
for d in getattr(response, "drafts", [])
@@ -325,7 +325,7 @@ class AgentMailUpdateDraftBlock(Block):
if input_data.send_at is not None:
params["send_at"] = input_data.send_at
draft = client.inboxes.drafts.update(
draft = await client.inboxes.drafts.update(
inbox_id=input_data.inbox_id,
draft_id=input_data.draft_id,
**params,
@@ -379,7 +379,7 @@ class AgentMailSendDraftBlock(Block):
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
) -> BlockOutput:
client = _client(credentials)
msg = client.inboxes.drafts.send(
msg = await client.inboxes.drafts.send(
inbox_id=input_data.inbox_id,
draft_id=input_data.draft_id,
)
@@ -429,7 +429,7 @@ class AgentMailDeleteDraftBlock(Block):
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
) -> BlockOutput:
client = _client(credentials)
client.inboxes.drafts.delete(
await client.inboxes.drafts.delete(
inbox_id=input_data.inbox_id,
draft_id=input_data.draft_id,
)
@@ -488,7 +488,7 @@ class AgentMailListOrgDraftsBlock(Block):
if input_data.page_token:
params["page_token"] = input_data.page_token
response = client.drafts.list(**params)
response = await client.drafts.list(**params)
drafts = [
d.__dict__ if hasattr(d, "__dict__") else d
for d in getattr(response, "drafts", [])

View File

@@ -6,7 +6,7 @@ a unique email address and can send, receive, and manage emails via the
AgentMail API. You can create thousands of inboxes on demand.
"""
from agentmail import AgentMail
from agentmail import AsyncAgentMail
from agentmail.inboxes.types import CreateInboxRequest
from backend.sdk import (
@@ -23,8 +23,8 @@ from backend.sdk import (
from ._config import agent_mail
def _client(credentials: APIKeyCredentials) -> AgentMail:
return AgentMail(api_key=credentials.api_key.get_secret_value())
def _client(credentials: APIKeyCredentials) -> AsyncAgentMail:
return AsyncAgentMail(api_key=credentials.api_key.get_secret_value())
class AgentMailCreateInboxBlock(Block):
@@ -89,7 +89,7 @@ class AgentMailCreateInboxBlock(Block):
if input_data.display_name:
params["display_name"] = input_data.display_name
inbox = client.inboxes.create(request=CreateInboxRequest(**params))
inbox = await client.inboxes.create(request=CreateInboxRequest(**params))
result = inbox.__dict__ if hasattr(inbox, "__dict__") else {}
yield "inbox_id", inbox.inbox_id
@@ -137,7 +137,7 @@ class AgentMailGetInboxBlock(Block):
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
) -> BlockOutput:
client = _client(credentials)
inbox = client.inboxes.get(inbox_id=input_data.inbox_id)
inbox = await client.inboxes.get(inbox_id=input_data.inbox_id)
result = inbox.__dict__ if hasattr(inbox, "__dict__") else {}
yield "inbox_id", inbox.inbox_id
@@ -199,7 +199,7 @@ class AgentMailListInboxesBlock(Block):
if input_data.page_token:
params["page_token"] = input_data.page_token
response = client.inboxes.list(**params)
response = await client.inboxes.list(**params)
inboxes = [
inbox.__dict__ if hasattr(inbox, "__dict__") else inbox
for inbox in getattr(response, "inboxes", [])
@@ -251,7 +251,7 @@ class AgentMailUpdateInboxBlock(Block):
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
) -> BlockOutput:
client = _client(credentials)
inbox = client.inboxes.update(
inbox = await client.inboxes.update(
inbox_id=input_data.inbox_id,
display_name=input_data.display_name,
)
@@ -298,5 +298,5 @@ class AgentMailDeleteInboxBlock(Block):
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
) -> BlockOutput:
client = _client(credentials)
client.inboxes.delete(inbox_id=input_data.inbox_id)
await client.inboxes.delete(inbox_id=input_data.inbox_id)
yield "success", True

View File

@@ -13,7 +13,7 @@ direction (send/receive) and type (allow/block).
from enum import Enum
from agentmail import AgentMail
from agentmail import AsyncAgentMail
from backend.sdk import (
APIKeyCredentials,
@@ -29,8 +29,8 @@ from backend.sdk import (
from ._config import agent_mail
def _client(credentials: APIKeyCredentials) -> AgentMail:
return AgentMail(api_key=credentials.api_key.get_secret_value())
def _client(credentials: APIKeyCredentials) -> AsyncAgentMail:
return AsyncAgentMail(api_key=credentials.api_key.get_secret_value())
class ListDirection(str, Enum):
@@ -101,7 +101,7 @@ class AgentMailListEntriesBlock(Block):
if input_data.page_token:
params["page_token"] = input_data.page_token
response = client.lists.list(
response = await client.lists.list(
input_data.direction.value, input_data.list_type.value, **params
)
entries = [
@@ -169,7 +169,7 @@ class AgentMailCreateListEntryBlock(Block):
if input_data.reason and input_data.list_type == ListType.BLOCK:
params["reason"] = input_data.reason
result = client.lists.create(
result = await client.lists.create(
input_data.direction.value, input_data.list_type.value, **params
)
result_dict = result.__dict__ if hasattr(result, "__dict__") else {}
@@ -218,7 +218,7 @@ class AgentMailGetListEntryBlock(Block):
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
) -> BlockOutput:
client = _client(credentials)
result = client.lists.get(
result = await client.lists.get(
input_data.direction.value,
input_data.list_type.value,
entry=input_data.entry,
@@ -270,7 +270,7 @@ class AgentMailDeleteListEntryBlock(Block):
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
) -> BlockOutput:
client = _client(credentials)
client.lists.delete(
await client.lists.delete(
input_data.direction.value,
input_data.list_type.value,
entry=input_data.entry,

View File

@@ -6,7 +6,7 @@ A Message is an individual email within a Thread. Agents can send new messages
labels for state tracking (e.g. read/unread, campaign tags).
"""
from agentmail import AgentMail
from agentmail import AsyncAgentMail
from backend.sdk import (
APIKeyCredentials,
@@ -22,8 +22,8 @@ from backend.sdk import (
from ._config import agent_mail
def _client(credentials: APIKeyCredentials) -> AgentMail:
return AgentMail(api_key=credentials.api_key.get_secret_value())
def _client(credentials: APIKeyCredentials) -> AsyncAgentMail:
return AsyncAgentMail(api_key=credentials.api_key.get_secret_value())
class AgentMailSendMessageBlock(Block):
@@ -116,7 +116,7 @@ class AgentMailSendMessageBlock(Block):
if input_data.labels:
params["labels"] = input_data.labels
msg = client.inboxes.messages.send(input_data.inbox_id, **params)
msg = await client.inboxes.messages.send(input_data.inbox_id, **params)
result = msg.__dict__ if hasattr(msg, "__dict__") else {}
yield "message_id", msg.message_id
@@ -186,7 +186,7 @@ class AgentMailListMessagesBlock(Block):
if input_data.labels:
params["labels"] = input_data.labels
response = client.inboxes.messages.list(input_data.inbox_id, **params)
response = await client.inboxes.messages.list(input_data.inbox_id, **params)
messages = [
m.__dict__ if hasattr(m, "__dict__") else m
for m in getattr(response, "messages", [])
@@ -249,7 +249,7 @@ class AgentMailGetMessageBlock(Block):
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
) -> BlockOutput:
client = _client(credentials)
msg = client.inboxes.messages.get(
msg = await client.inboxes.messages.get(
inbox_id=input_data.inbox_id,
message_id=input_data.message_id,
)
@@ -317,7 +317,7 @@ class AgentMailReplyToMessageBlock(Block):
if input_data.html:
params["html"] = input_data.html
reply = client.inboxes.messages.reply(
reply = await client.inboxes.messages.reply(
inbox_id=input_data.inbox_id,
message_id=input_data.message_id,
**params,
@@ -417,7 +417,7 @@ class AgentMailForwardMessageBlock(Block):
if input_data.html:
params["html"] = input_data.html
fwd = client.inboxes.messages.forward(
fwd = await client.inboxes.messages.forward(
inbox_id=input_data.inbox_id,
message_id=input_data.message_id,
**params,
@@ -481,7 +481,7 @@ class AgentMailUpdateMessageBlock(Block):
if input_data.remove_labels:
params["remove_labels"] = input_data.remove_labels
msg = client.inboxes.messages.update(
msg = await client.inboxes.messages.update(
inbox_id=input_data.inbox_id,
message_id=input_data.message_id,
**params,

View File

@@ -7,7 +7,7 @@ Use pods when building SaaS platforms, agency tools, or AI agent fleets that
serve multiple customers.
"""
from agentmail import AgentMail
from agentmail import AsyncAgentMail
from backend.sdk import (
APIKeyCredentials,
@@ -23,8 +23,8 @@ from backend.sdk import (
from ._config import agent_mail
def _client(credentials: APIKeyCredentials) -> AgentMail:
return AgentMail(api_key=credentials.api_key.get_secret_value())
def _client(credentials: APIKeyCredentials) -> AsyncAgentMail:
return AsyncAgentMail(api_key=credentials.api_key.get_secret_value())
class AgentMailCreatePodBlock(Block):
@@ -67,7 +67,7 @@ class AgentMailCreatePodBlock(Block):
if input_data.client_id:
params["client_id"] = input_data.client_id
pod = client.pods.create(**params)
pod = await client.pods.create(**params)
result = pod.__dict__ if hasattr(pod, "__dict__") else {}
yield "pod_id", pod.pod_id
@@ -106,7 +106,7 @@ class AgentMailGetPodBlock(Block):
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
) -> BlockOutput:
client = _client(credentials)
pod = client.pods.get(pod_id=input_data.pod_id)
pod = await client.pods.get(pod_id=input_data.pod_id)
result = pod.__dict__ if hasattr(pod, "__dict__") else {}
yield "pod_id", pod.pod_id
@@ -164,7 +164,7 @@ class AgentMailListPodsBlock(Block):
if input_data.page_token:
params["page_token"] = input_data.page_token
response = client.pods.list(**params)
response = await client.pods.list(**params)
pods = [
p.__dict__ if hasattr(p, "__dict__") else p
for p in getattr(response, "pods", [])
@@ -213,7 +213,7 @@ class AgentMailDeletePodBlock(Block):
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
) -> BlockOutput:
client = _client(credentials)
client.pods.delete(pod_id=input_data.pod_id)
await client.pods.delete(pod_id=input_data.pod_id)
yield "success", True
@@ -269,7 +269,7 @@ class AgentMailListPodInboxesBlock(Block):
if input_data.page_token:
params["page_token"] = input_data.page_token
response = client.pods.inboxes.list(pod_id=input_data.pod_id, **params)
response = await client.pods.inboxes.list(pod_id=input_data.pod_id, **params)
inboxes = [
i.__dict__ if hasattr(i, "__dict__") else i
for i in getattr(response, "inboxes", [])
@@ -342,7 +342,7 @@ class AgentMailListPodThreadsBlock(Block):
if input_data.labels:
params["labels"] = input_data.labels
response = client.pods.threads.list(pod_id=input_data.pod_id, **params)
response = await client.pods.threads.list(pod_id=input_data.pod_id, **params)
threads = [
t.__dict__ if hasattr(t, "__dict__") else t
for t in getattr(response, "threads", [])
@@ -407,7 +407,7 @@ class AgentMailListPodDraftsBlock(Block):
if input_data.page_token:
params["page_token"] = input_data.page_token
response = client.pods.drafts.list(pod_id=input_data.pod_id, **params)
response = await client.pods.drafts.list(pod_id=input_data.pod_id, **params)
drafts = [
d.__dict__ if hasattr(d, "__dict__") else d
for d in getattr(response, "drafts", [])
@@ -478,7 +478,7 @@ class AgentMailCreatePodInboxBlock(Block):
if input_data.display_name:
params["display_name"] = input_data.display_name
inbox = client.pods.inboxes.create(pod_id=input_data.pod_id, **params)
inbox = await client.pods.inboxes.create(pod_id=input_data.pod_id, **params)
result = inbox.__dict__ if hasattr(inbox, "__dict__") else {}
yield "inbox_id", inbox.inbox_id

View File

@@ -6,7 +6,7 @@ created automatically when a new message is sent and grow as replies are added.
Threads can be queried per-inbox or across the entire organization.
"""
from agentmail import AgentMail
from agentmail import AsyncAgentMail
from backend.sdk import (
APIKeyCredentials,
@@ -22,8 +22,8 @@ from backend.sdk import (
from ._config import agent_mail
def _client(credentials: APIKeyCredentials) -> AgentMail:
return AgentMail(api_key=credentials.api_key.get_secret_value())
def _client(credentials: APIKeyCredentials) -> AsyncAgentMail:
return AsyncAgentMail(api_key=credentials.api_key.get_secret_value())
class AgentMailListInboxThreadsBlock(Block):
@@ -87,7 +87,9 @@ class AgentMailListInboxThreadsBlock(Block):
if input_data.labels:
params["labels"] = input_data.labels
response = client.inboxes.threads.list(inbox_id=input_data.inbox_id, **params)
response = await client.inboxes.threads.list(
inbox_id=input_data.inbox_id, **params
)
threads = [
t.__dict__ if hasattr(t, "__dict__") else t
for t in getattr(response, "threads", [])
@@ -141,7 +143,7 @@ class AgentMailGetInboxThreadBlock(Block):
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
) -> BlockOutput:
client = _client(credentials)
thread = client.inboxes.threads.get(
thread = await client.inboxes.threads.get(
inbox_id=input_data.inbox_id,
thread_id=input_data.thread_id,
)
@@ -195,7 +197,7 @@ class AgentMailDeleteInboxThreadBlock(Block):
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
) -> BlockOutput:
client = _client(credentials)
client.inboxes.threads.delete(
await client.inboxes.threads.delete(
inbox_id=input_data.inbox_id,
thread_id=input_data.thread_id,
)
@@ -261,7 +263,7 @@ class AgentMailListOrgThreadsBlock(Block):
if input_data.labels:
params["labels"] = input_data.labels
response = client.threads.list(**params)
response = await client.threads.list(**params)
threads = [
t.__dict__ if hasattr(t, "__dict__") else t
for t in getattr(response, "threads", [])
@@ -313,7 +315,7 @@ class AgentMailGetOrgThreadBlock(Block):
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
) -> BlockOutput:
client = _client(credentials)
thread = client.threads.get(thread_id=input_data.thread_id)
thread = await client.threads.get(thread_id=input_data.thread_id)
messages = [
m.__dict__ if hasattr(m, "__dict__") else m
for m in getattr(thread, "messages", [])