Skip to content

Add AgentMail tool #348

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
184 changes: 184 additions & 0 deletions agentstack/_tools/agentmail/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
from agentmail import AgentMail
from typing import Optional, List


client = AgentMail()


def list_inboxes(limit: Optional[int] = None, last_key: Optional[str] = None):
"""
List 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
)


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.messages.get_attachment(
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
)
13 changes: 13 additions & 0 deletions agentstack/_tools/agentmail/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "agentmail",
"category": "email",
"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": {
"AGENTMAIL_API_KEY": null
},
"dependencies": [
"agentmail>=0.0.19"
]
}
27 changes: 17 additions & 10 deletions docs/tools/community.mdx
Original file line number Diff line number Diff line change
@@ -1,25 +1,33 @@
---
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

- [Mem0](/tools/tool/mem0)

## Database Tools
- [Neon](/tools/tool/neon)

- [Neon](/tools/tool/neon)

## Code Execution

Expand All @@ -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)

<CardGroup cols={1}>
<Card
title="Core Tools"
icon="hammer"
href="/tools/core"
>
<Card title="Core Tools" icon="hammer" href="/tools/core">
Default tools in AgentStack
</Card>
</CardGroup>
</CardGroup>
42 changes: 42 additions & 0 deletions docs/tools/tool/agentmail.mdx
Original file line number Diff line number Diff line change
@@ -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...