From 87d4d639236dac50c07e5ee12ac1717fddc934df Mon Sep 17 00:00:00 2001 From: Haakam Aujla Date: Wed, 9 Apr 2025 19:07:57 -0400 Subject: [PATCH 1/4] Init AgentMail tool --- agentstack/_tools/agentmail/__init__.py | 53 +++++++++++++++++++++++++ agentstack/_tools/agentmail/config.json | 13 ++++++ 2 files changed, 66 insertions(+) create mode 100644 agentstack/_tools/agentmail/__init__.py create mode 100644 agentstack/_tools/agentmail/config.json diff --git a/agentstack/_tools/agentmail/__init__.py b/agentstack/_tools/agentmail/__init__.py new file mode 100644 index 0000000..adeb3c0 --- /dev/null +++ b/agentstack/_tools/agentmail/__init__.py @@ -0,0 +1,53 @@ +from agentmail import AgentMail +from typing import Optional + + +client = AgentMail() + + +def list_inboxes(limit: Optional[int] = None, last_key: Optional[str] = None): + """ + List all inboxes. + + Args: + limit: The maximum number of inboxes to return. + last_key: The last key returned from the previous page. + + Returns: + A list of inboxes. + """ + return client.inboxes.list(limit=limit, last_key=last_key) + + +def get_inbox(inbox_id: str): + """ + Get an inbox by ID. + + Args: + inbox_id: The ID of the inbox to get. + + Returns: + An inbox. + """ + return client.inboxes.get(inbox_id) + + +def create_inbox( + username: Optional[str] = None, + domain: Optional[str] = None, + display_name: Optional[str] = None, +): + """ + Create an inbox. + + Args: + username: The username of the inbox. + domain: The domain of the inbox. + display_name: The display name of the inbox. + + Returns: + An inbox. + """ + return client.inboxes.create( + username=username, domain=domain, display_name=display_name + ) diff --git a/agentstack/_tools/agentmail/config.json b/agentstack/_tools/agentmail/config.json new file mode 100644 index 0000000..e4e2a8c --- /dev/null +++ b/agentstack/_tools/agentmail/config.json @@ -0,0 +1,13 @@ +{ + "name": "agentmail", + "category": "email", + "tools": ["list_inboxes", "get_inbox", "create_inbox"], + "url": "https://agentmail.to", + "cta": "Get your AgentMail API key at https://agentmail.to", + "env": { + "AGENTMAIL_API_KEY": null + }, + "dependencies": [ + "agentmail>=0.0.19" + ] +} \ No newline at end of file From b0832da9e92c5aeee16b9a30df9f03b0ab2b5cd5 Mon Sep 17 00:00:00 2001 From: Haakam Aujla Date: Fri, 11 Apr 2025 18:36:50 -0400 Subject: [PATCH 2/4] Complete tools --- agentstack/_tools/agentmail/__init__.py | 135 +++++++++++++++++++++++- agentstack/_tools/agentmail/config.json | 2 +- 2 files changed, 134 insertions(+), 3 deletions(-) diff --git a/agentstack/_tools/agentmail/__init__.py b/agentstack/_tools/agentmail/__init__.py index adeb3c0..a306d69 100644 --- a/agentstack/_tools/agentmail/__init__.py +++ b/agentstack/_tools/agentmail/__init__.py @@ -1,5 +1,5 @@ from agentmail import AgentMail -from typing import Optional +from typing import Optional, List client = AgentMail() @@ -7,7 +7,7 @@ def list_inboxes(limit: Optional[int] = None, last_key: Optional[str] = None): """ - List all inboxes. + List inboxes. Args: limit: The maximum number of inboxes to return. @@ -51,3 +51,134 @@ def create_inbox( return client.inboxes.create( username=username, domain=domain, display_name=display_name ) + + +def list_threads( + inbox_id: str, limit: Optional[int] = None, last_key: Optional[str] = None +): + """ + List threads in an inbox. + + Args: + inbox_id: The ID of the inbox to list threads for. + limit: The maximum number of threads to return. + last_key: The last key returned from the previous page. + + Returns: + A list of threads. + """ + return client.threads.list(inbox_id=inbox_id, limit=limit, last_key=last_key) + + +def get_thread(inbox_id: str, thread_id: str): + """ + Get a thread by ID. + + Args: + inbox_id: The ID of the inbox to get the thread for. + thread_id: The ID of the thread to get. + + Returns: + A thread. + """ + return client.threads.get(inbox_id=inbox_id, thread_id=thread_id) + + +def list_messages( + inbox_id: str, limit: Optional[int] = None, last_key: Optional[str] = None +): + """ + List messages in an inbox. + + Args: + inbox_id: The ID of the inbox to list messages for. + limit: The maximum number of messages to return. + last_key: The last key returned from the previous page. + + Returns: + A list of messages. + """ + return client.messages.list(inbox_id=inbox_id, limit=limit, last_key=last_key) + + +def get_message(inbox_id: str, message_id: str): + """ + Get a message by ID. + + Args: + inbox_id: The ID of the inbox to get the message for. + message_id: The ID of the message to get. + + Returns: + A message. + """ + return client.messages.get(inbox_id=inbox_id, message_id=message_id) + + +def get_attachment(inbox_id: str, message_id: str, attachment_id: str): + """ + Get an attachment by message ID and attachment ID. + + Args: + inbox_id: The ID of the inbox to get the attachment for. + message_id: The ID of the message to get the attachment for. + attachment_id: The ID of the attachment to get. + + Returns: + An attachment. + """ + return client.attachments.get( + inbox_id=inbox_id, message_id=message_id, attachment_id=attachment_id + ) + + +def send_message( + inbox_id: str, + to: List[str], + cc: Optional[List[str]] = None, + bcc: Optional[List[str]] = None, + subject: Optional[str] = None, + text: Optional[str] = None, + html: Optional[str] = None, +): + """ + Send a message. + + Args: + inbox_id: The ID of the inbox to send the message from. + to: The list of recipients. + cc: The list of CC recipients. + bcc: The list of BCC recipients. + subject: The subject of the message. + text: The plain text body of the message. + html: The HTML body of the message. + + Returns: + A message. + """ + return client.messages.send( + inbox_id=inbox_id, to=to, cc=cc, bcc=bcc, subject=subject, text=text, html=html + ) + + +def reply_to_message( + inbox_id: str, + message_id: str, + text: Optional[str] = None, + html: Optional[str] = None, +): + """ + Reply to a message. + + Args: + inbox_id: The ID of the inbox to reply to the message in. + message_id: The ID of the message to reply to. + text: The plain text body of the reply. + html: The HTML body of the reply. + + Returns: + A message. + """ + return client.messages.reply( + inbox_id=inbox_id, message_id=message_id, text=text, html=html + ) diff --git a/agentstack/_tools/agentmail/config.json b/agentstack/_tools/agentmail/config.json index e4e2a8c..71c981b 100644 --- a/agentstack/_tools/agentmail/config.json +++ b/agentstack/_tools/agentmail/config.json @@ -1,7 +1,7 @@ { "name": "agentmail", "category": "email", - "tools": ["list_inboxes", "get_inbox", "create_inbox"], + "tools": ["list_inboxes", "get_inbox", "create_inbox", "list_threads", "get_thread", "list_messages", "get_message", "get_attachment", "send_message", "reply_to_message"], "url": "https://agentmail.to", "cta": "Get your AgentMail API key at https://agentmail.to", "env": { From c3f3a7471e2cef631f50b30e7066acd117d67719 Mon Sep 17 00:00:00 2001 From: Haakam Aujla Date: Fri, 11 Apr 2025 19:03:57 -0400 Subject: [PATCH 3/4] Update docs --- docs/tools/community.mdx | 27 +++++++++++++--------- docs/tools/tool/agentmail.mdx | 42 +++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 10 deletions(-) create mode 100644 docs/tools/tool/agentmail.mdx diff --git a/docs/tools/community.mdx b/docs/tools/community.mdx index ae703bb..c083f5b 100644 --- a/docs/tools/community.mdx +++ b/docs/tools/community.mdx @@ -1,17 +1,24 @@ --- -title: 'Community Tools' -description: 'AgentStack tools from community contributors' +title: Community Tools +description: AgentStack tools from community contributors --- +## Email + +- [AgentMail](/tools/tool/agentmail) + ## Web Retrieval + - [AgentQL](/tools/tool/agentql) ## Browsing -[//]: # (- [Browserbase](/tools/tool/browserbase)) +[//]: # "- [Browserbase](/tools/tool/browserbase)" + - [Firecrawl](/tools/tool/firecrawl) ## Search + - [Perplexity](/tools/tool/perplexity) ## Memory / State @@ -19,7 +26,8 @@ description: 'AgentStack tools from community contributors' - [Mem0](/tools/tool/mem0) ## Database Tools -- [Neon](/tools/tool/neon) + +- [Neon](/tools/tool/neon) ## Code Execution @@ -30,17 +38,16 @@ description: 'AgentStack tools from community contributors' - [Composio](/tools/tool/composio) ## Network Protocols + - [Agent Connect](/tools/tool/agent-connect) ## Application Specific + - [Stripe](/tools/tool/stripe) - [Payman](/tools/tool/payman) + - + Default tools in AgentStack - \ No newline at end of file + diff --git a/docs/tools/tool/agentmail.mdx b/docs/tools/tool/agentmail.mdx new file mode 100644 index 0000000..fa5f3a9 --- /dev/null +++ b/docs/tools/tool/agentmail.mdx @@ -0,0 +1,42 @@ +--- +title: AgentMail +description: Email for agents +icon: email +--- + +[AgentMail](https://agentmail.to) is an API-first email provider designed to give agents their own inboxes for sending, receiving, and managing email. + +## Tools + +- List inboxes +- Get inbox +- Create inbox +- List threads +- Get thread +- List messages +- Get message +- Get attachment +- Send message +- Reply to message + +## Installation + +Add the AgentMail tool to your project + +```sh +agentstack tools add agentmail +``` + +Get your [AgentMail API key](https://agentmail.to) and set the environment variable + +```env +AGENTMAIL_API_KEY=your-agentmail-api-key +``` + +## Usage + +Use the AgentMail API to create an inbox for your agent. Then prompt your agent to handle any email related tasks. + +## Examples + +Coming soon... From 062b38c198ec4faa1d708c1613c40b640ff7dfce Mon Sep 17 00:00:00 2001 From: Haakam Aujla Date: Fri, 11 Apr 2025 19:17:35 -0400 Subject: [PATCH 4/4] Fix --- agentstack/_tools/agentmail/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agentstack/_tools/agentmail/__init__.py b/agentstack/_tools/agentmail/__init__.py index a306d69..142abc1 100644 --- a/agentstack/_tools/agentmail/__init__.py +++ b/agentstack/_tools/agentmail/__init__.py @@ -127,7 +127,7 @@ def get_attachment(inbox_id: str, message_id: str, attachment_id: str): Returns: An attachment. """ - return client.attachments.get( + return client.messages.get_attachment( inbox_id=inbox_id, message_id=message_id, attachment_id=attachment_id )