diff --git a/apps/docs/components/icons.tsx b/apps/docs/components/icons.tsx index 6614c9f6036..05daa6b336d 100644 --- a/apps/docs/components/icons.tsx +++ b/apps/docs/components/icons.tsx @@ -1,6 +1,33 @@ import type { SVGProps } from 'react' import { useId } from 'react' +export function AgentMailIcon(props: SVGProps) { + return ( + + + + + + + + ) +} + export function SearchIcon(props: SVGProps) { return ( > export const blockTypeToIconMap: Record = { a2a: A2AIcon, + agentmail: AgentMailIcon, ahrefs: AhrefsIcon, airtable: AirtableIcon, airweave: AirweaveIcon, diff --git a/apps/docs/content/docs/en/tools/agentmail.mdx b/apps/docs/content/docs/en/tools/agentmail.mdx new file mode 100644 index 00000000000..5d5a14c3934 --- /dev/null +++ b/apps/docs/content/docs/en/tools/agentmail.mdx @@ -0,0 +1,592 @@ +--- +title: AgentMail +description: Manage email inboxes, threads, and messages with AgentMail +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[AgentMail](https://agentmail.to/) is an API-first email platform built for agents and automation. AgentMail lets you create email inboxes on the fly, send and receive messages, reply to threads, manage drafts, and organize conversations with labels — all through a simple REST API designed for programmatic access. + +**Why AgentMail?** +- **Agent-Native Email:** Purpose-built for AI agents and automation — create inboxes, send messages, and manage threads without human-facing UI overhead. +- **Full Email Lifecycle:** Send new messages, reply to threads, forward emails, manage drafts, and schedule sends — all from a single API. +- **Thread & Conversation Management:** Organize emails into threads with full read, reply, forward, and label support for structured conversation tracking. +- **Draft Workflow:** Compose drafts, update them, schedule sends, and dispatch when ready — perfect for review-before-send workflows. +- **Label Organization:** Tag threads and messages with custom labels for filtering, routing, and downstream automation. + +**Using AgentMail in Sim** + +Sim's AgentMail integration connects your agentic workflows directly to AgentMail using an API key. With 20 operations spanning inboxes, threads, messages, and drafts, you can build powerful email automations without writing backend code. + +**Key benefits of using AgentMail in Sim:** +- **Dynamic inbox creation:** Spin up new inboxes on the fly for each agent, workflow, or customer — perfect for multi-tenant email handling. +- **Automated email processing:** List and read incoming messages, then trigger downstream actions based on content, sender, or labels. +- **Conversational email:** Reply to threads and forward messages to keep conversations flowing naturally within your automated workflows. +- **Draft and review workflows:** Create drafts, update them with AI-generated content, and send when approved — ideal for human-in-the-loop patterns. +- **Email organization:** Apply labels to threads and messages to categorize, filter, and route emails through your automation pipeline. + +Whether you're building an AI email assistant, automating customer support replies, processing incoming leads, or managing multi-agent email workflows, AgentMail in Sim gives you direct, secure access to the full AgentMail API — no middleware required. Simply configure your API key, select the operation you need, and let Sim handle the rest. +{/* MANUAL-CONTENT-END */} + + +## Usage Instructions + +Integrate AgentMail into your workflow. Create and manage email inboxes, send and receive messages, reply to threads, manage drafts, and organize threads with labels. Requires API Key. + + + +## Tools + +### `agentmail_create_draft` + +Create a new email draft in AgentMail + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | AgentMail API key | +| `inboxId` | string | Yes | ID of the inbox to create the draft in | +| `to` | string | No | Recipient email addresses \(comma-separated\) | +| `subject` | string | No | Draft subject line | +| `text` | string | No | Plain text draft body | +| `html` | string | No | HTML draft body | +| `cc` | string | No | CC recipient email addresses \(comma-separated\) | +| `bcc` | string | No | BCC recipient email addresses \(comma-separated\) | +| `inReplyTo` | string | No | ID of message being replied to | +| `sendAt` | string | No | ISO 8601 timestamp to schedule sending | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `draftId` | string | Unique identifier for the draft | +| `inboxId` | string | Inbox the draft belongs to | +| `subject` | string | Draft subject | +| `to` | array | Recipient email addresses | +| `cc` | array | CC email addresses | +| `bcc` | array | BCC email addresses | +| `text` | string | Plain text content | +| `html` | string | HTML content | +| `preview` | string | Draft preview text | +| `labels` | array | Labels assigned to the draft | +| `inReplyTo` | string | Message ID this draft replies to | +| `sendStatus` | string | Send status \(scheduled, sending, failed\) | +| `sendAt` | string | Scheduled send time | +| `createdAt` | string | Creation timestamp | +| `updatedAt` | string | Last updated timestamp | + +### `agentmail_create_inbox` + +Create a new email inbox with AgentMail + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | AgentMail API key | +| `username` | string | No | Username for the inbox email address | +| `domain` | string | No | Domain for the inbox email address | +| `displayName` | string | No | Display name for the inbox | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `inboxId` | string | Unique identifier for the inbox | +| `email` | string | Email address of the inbox | +| `displayName` | string | Display name of the inbox | +| `createdAt` | string | Creation timestamp | +| `updatedAt` | string | Last updated timestamp | + +### `agentmail_delete_draft` + +Delete an email draft in AgentMail + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | AgentMail API key | +| `inboxId` | string | Yes | ID of the inbox containing the draft | +| `draftId` | string | Yes | ID of the draft to delete | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `deleted` | boolean | Whether the draft was successfully deleted | + +### `agentmail_delete_inbox` + +Delete an email inbox in AgentMail + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | AgentMail API key | +| `inboxId` | string | Yes | ID of the inbox to delete | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `deleted` | boolean | Whether the inbox was successfully deleted | + +### `agentmail_delete_thread` + +Delete an email thread in AgentMail (moves to trash, or permanently deletes if already in trash) + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | AgentMail API key | +| `inboxId` | string | Yes | ID of the inbox containing the thread | +| `threadId` | string | Yes | ID of the thread to delete | +| `permanent` | boolean | No | Force permanent deletion instead of moving to trash | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `deleted` | boolean | Whether the thread was successfully deleted | + +### `agentmail_forward_message` + +Forward an email message to new recipients in AgentMail + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | AgentMail API key | +| `inboxId` | string | Yes | ID of the inbox containing the message | +| `messageId` | string | Yes | ID of the message to forward | +| `to` | string | Yes | Recipient email addresses \(comma-separated\) | +| `subject` | string | No | Override subject line | +| `text` | string | No | Additional plain text to prepend | +| `html` | string | No | Additional HTML to prepend | +| `cc` | string | No | CC recipient email addresses \(comma-separated\) | +| `bcc` | string | No | BCC recipient email addresses \(comma-separated\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `messageId` | string | ID of the forwarded message | +| `threadId` | string | ID of the thread | + +### `agentmail_get_draft` + +Get details of a specific email draft in AgentMail + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | AgentMail API key | +| `inboxId` | string | Yes | ID of the inbox the draft belongs to | +| `draftId` | string | Yes | ID of the draft to retrieve | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `draftId` | string | Unique identifier for the draft | +| `inboxId` | string | Inbox the draft belongs to | +| `subject` | string | Draft subject | +| `to` | array | Recipient email addresses | +| `cc` | array | CC email addresses | +| `bcc` | array | BCC email addresses | +| `text` | string | Plain text content | +| `html` | string | HTML content | +| `preview` | string | Draft preview text | +| `labels` | array | Labels assigned to the draft | +| `inReplyTo` | string | Message ID this draft replies to | +| `sendStatus` | string | Send status \(scheduled, sending, failed\) | +| `sendAt` | string | Scheduled send time | +| `createdAt` | string | Creation timestamp | +| `updatedAt` | string | Last updated timestamp | + +### `agentmail_get_inbox` + +Get details of a specific email inbox in AgentMail + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | AgentMail API key | +| `inboxId` | string | Yes | ID of the inbox to retrieve | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `inboxId` | string | Unique identifier for the inbox | +| `email` | string | Email address of the inbox | +| `displayName` | string | Display name of the inbox | +| `createdAt` | string | Creation timestamp | +| `updatedAt` | string | Last updated timestamp | + +### `agentmail_get_message` + +Get details of a specific email message in AgentMail + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | AgentMail API key | +| `inboxId` | string | Yes | ID of the inbox containing the message | +| `messageId` | string | Yes | ID of the message to retrieve | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `messageId` | string | Unique identifier for the message | +| `threadId` | string | ID of the thread this message belongs to | +| `from` | string | Sender email address | +| `to` | array | Recipient email addresses | +| `cc` | array | CC email addresses | +| `bcc` | array | BCC email addresses | +| `subject` | string | Message subject | +| `text` | string | Plain text content | +| `html` | string | HTML content | +| `createdAt` | string | Creation timestamp | + +### `agentmail_get_thread` + +Get details of a specific email thread including messages in AgentMail + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | AgentMail API key | +| `inboxId` | string | Yes | ID of the inbox containing the thread | +| `threadId` | string | Yes | ID of the thread to retrieve | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `threadId` | string | Unique identifier for the thread | +| `subject` | string | Thread subject | +| `senders` | array | List of sender email addresses | +| `recipients` | array | List of recipient email addresses | +| `messageCount` | number | Number of messages in the thread | +| `labels` | array | Labels assigned to the thread | +| `lastMessageAt` | string | Timestamp of last message | +| `createdAt` | string | Creation timestamp | +| `updatedAt` | string | Last updated timestamp | +| `messages` | array | Messages in the thread | +| ↳ `messageId` | string | Unique identifier for the message | +| ↳ `from` | string | Sender email address | +| ↳ `to` | array | Recipient email addresses | +| ↳ `cc` | array | CC email addresses | +| ↳ `bcc` | array | BCC email addresses | +| ↳ `subject` | string | Message subject | +| ↳ `text` | string | Plain text content | +| ↳ `html` | string | HTML content | +| ↳ `createdAt` | string | Creation timestamp | + +### `agentmail_list_drafts` + +List email drafts in an inbox in AgentMail + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | AgentMail API key | +| `inboxId` | string | Yes | ID of the inbox to list drafts from | +| `limit` | number | No | Maximum number of drafts to return | +| `pageToken` | string | No | Pagination token for next page of results | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `drafts` | array | List of drafts | +| ↳ `draftId` | string | Unique identifier for the draft | +| ↳ `inboxId` | string | Inbox the draft belongs to | +| ↳ `subject` | string | Draft subject | +| ↳ `to` | array | Recipient email addresses | +| ↳ `cc` | array | CC email addresses | +| ↳ `bcc` | array | BCC email addresses | +| ↳ `preview` | string | Draft preview text | +| ↳ `sendStatus` | string | Send status \(scheduled, sending, failed\) | +| ↳ `sendAt` | string | Scheduled send time | +| ↳ `createdAt` | string | Creation timestamp | +| ↳ `updatedAt` | string | Last updated timestamp | +| `count` | number | Total number of drafts | +| `nextPageToken` | string | Token for retrieving the next page | + +### `agentmail_list_inboxes` + +List all email inboxes in AgentMail + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | AgentMail API key | +| `limit` | number | No | Maximum number of inboxes to return | +| `pageToken` | string | No | Pagination token for next page of results | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `inboxes` | array | List of inboxes | +| ↳ `inboxId` | string | Unique identifier for the inbox | +| ↳ `email` | string | Email address of the inbox | +| ↳ `displayName` | string | Display name of the inbox | +| ↳ `createdAt` | string | Creation timestamp | +| ↳ `updatedAt` | string | Last updated timestamp | +| `count` | number | Total number of inboxes | +| `nextPageToken` | string | Token for retrieving the next page | + +### `agentmail_list_messages` + +List messages in an inbox in AgentMail + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | AgentMail API key | +| `inboxId` | string | Yes | ID of the inbox to list messages from | +| `limit` | number | No | Maximum number of messages to return | +| `pageToken` | string | No | Pagination token for next page of results | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `messages` | array | List of messages in the inbox | +| ↳ `messageId` | string | Unique identifier for the message | +| ↳ `from` | string | Sender email address | +| ↳ `to` | array | Recipient email addresses | +| ↳ `subject` | string | Message subject | +| ↳ `preview` | string | Message preview text | +| ↳ `createdAt` | string | Creation timestamp | +| `count` | number | Total number of messages | +| `nextPageToken` | string | Token for retrieving the next page | + +### `agentmail_list_threads` + +List email threads in AgentMail + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | AgentMail API key | +| `inboxId` | string | Yes | ID of the inbox to list threads from | +| `limit` | number | No | Maximum number of threads to return | +| `pageToken` | string | No | Pagination token for next page of results | +| `labels` | string | No | Comma-separated labels to filter threads by | +| `before` | string | No | Filter threads before this ISO 8601 timestamp | +| `after` | string | No | Filter threads after this ISO 8601 timestamp | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `threads` | array | List of email threads | +| ↳ `threadId` | string | Unique identifier for the thread | +| ↳ `subject` | string | Thread subject | +| ↳ `senders` | array | List of sender email addresses | +| ↳ `recipients` | array | List of recipient email addresses | +| ↳ `messageCount` | number | Number of messages in the thread | +| ↳ `lastMessageAt` | string | Timestamp of last message | +| ↳ `createdAt` | string | Creation timestamp | +| ↳ `updatedAt` | string | Last updated timestamp | +| `count` | number | Total number of threads | +| `nextPageToken` | string | Token for retrieving the next page | + +### `agentmail_reply_message` + +Reply to an existing email message in AgentMail + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | AgentMail API key | +| `inboxId` | string | Yes | ID of the inbox to reply from | +| `messageId` | string | Yes | ID of the message to reply to | +| `text` | string | No | Plain text reply body | +| `html` | string | No | HTML reply body | +| `to` | string | No | Override recipient email addresses \(comma-separated\) | +| `cc` | string | No | CC email addresses \(comma-separated\) | +| `bcc` | string | No | BCC email addresses \(comma-separated\) | +| `replyAll` | boolean | No | Reply to all recipients of the original message | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `messageId` | string | ID of the sent reply message | +| `threadId` | string | ID of the thread | + +### `agentmail_send_draft` + +Send an existing email draft in AgentMail + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | AgentMail API key | +| `inboxId` | string | Yes | ID of the inbox containing the draft | +| `draftId` | string | Yes | ID of the draft to send | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `messageId` | string | ID of the sent message | +| `threadId` | string | ID of the thread | + +### `agentmail_send_message` + +Send an email message from an AgentMail inbox + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | AgentMail API key | +| `inboxId` | string | Yes | ID of the inbox to send from | +| `to` | string | Yes | Recipient email address \(comma-separated for multiple\) | +| `subject` | string | Yes | Email subject line | +| `text` | string | No | Plain text email body | +| `html` | string | No | HTML email body | +| `cc` | string | No | CC recipient email addresses \(comma-separated\) | +| `bcc` | string | No | BCC recipient email addresses \(comma-separated\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `threadId` | string | ID of the created thread | +| `messageId` | string | ID of the sent message | +| `subject` | string | Email subject line | +| `to` | string | Recipient email address | + +### `agentmail_update_draft` + +Update an existing email draft in AgentMail + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | AgentMail API key | +| `inboxId` | string | Yes | ID of the inbox containing the draft | +| `draftId` | string | Yes | ID of the draft to update | +| `to` | string | No | Recipient email addresses \(comma-separated\) | +| `subject` | string | No | Draft subject line | +| `text` | string | No | Plain text draft body | +| `html` | string | No | HTML draft body | +| `cc` | string | No | CC recipient email addresses \(comma-separated\) | +| `bcc` | string | No | BCC recipient email addresses \(comma-separated\) | +| `sendAt` | string | No | ISO 8601 timestamp to schedule sending | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `draftId` | string | Unique identifier for the draft | +| `inboxId` | string | Inbox the draft belongs to | +| `subject` | string | Draft subject | +| `to` | array | Recipient email addresses | +| `cc` | array | CC email addresses | +| `bcc` | array | BCC email addresses | +| `text` | string | Plain text content | +| `html` | string | HTML content | +| `preview` | string | Draft preview text | +| `labels` | array | Labels assigned to the draft | +| `inReplyTo` | string | Message ID this draft replies to | +| `sendStatus` | string | Send status \(scheduled, sending, failed\) | +| `sendAt` | string | Scheduled send time | +| `createdAt` | string | Creation timestamp | +| `updatedAt` | string | Last updated timestamp | + +### `agentmail_update_inbox` + +Update the display name of an email inbox in AgentMail + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | AgentMail API key | +| `inboxId` | string | Yes | ID of the inbox to update | +| `displayName` | string | Yes | New display name for the inbox | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `inboxId` | string | Unique identifier for the inbox | +| `email` | string | Email address of the inbox | +| `displayName` | string | Display name of the inbox | +| `createdAt` | string | Creation timestamp | +| `updatedAt` | string | Last updated timestamp | + +### `agentmail_update_message` + +Add or remove labels on an email message in AgentMail + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | AgentMail API key | +| `inboxId` | string | Yes | ID of the inbox containing the message | +| `messageId` | string | Yes | ID of the message to update | +| `addLabels` | string | No | Comma-separated labels to add to the message | +| `removeLabels` | string | No | Comma-separated labels to remove from the message | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `messageId` | string | Unique identifier for the message | +| `labels` | array | Current labels on the message | + +### `agentmail_update_thread` + +Add or remove labels on an email thread in AgentMail + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | AgentMail API key | +| `inboxId` | string | Yes | ID of the inbox containing the thread | +| `threadId` | string | Yes | ID of the thread to update | +| `addLabels` | string | No | Comma-separated labels to add to the thread | +| `removeLabels` | string | No | Comma-separated labels to remove from the thread | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `threadId` | string | Unique identifier for the thread | +| `labels` | array | Current labels on the thread | + + diff --git a/apps/docs/content/docs/en/tools/meta.json b/apps/docs/content/docs/en/tools/meta.json index 20dd3a4bf9f..fa396399a4d 100644 --- a/apps/docs/content/docs/en/tools/meta.json +++ b/apps/docs/content/docs/en/tools/meta.json @@ -2,6 +2,7 @@ "pages": [ "index", "a2a", + "agentmail", "ahrefs", "airtable", "airweave", diff --git a/apps/docs/content/docs/en/tools/rippling.mdx b/apps/docs/content/docs/en/tools/rippling.mdx index 31945d94aca..88160e37d23 100644 --- a/apps/docs/content/docs/en/tools/rippling.mdx +++ b/apps/docs/content/docs/en/tools/rippling.mdx @@ -2201,7 +2201,7 @@ Create a new object category ### `rippling_update_object_category` -Update a object category +Update an object category #### Input @@ -2224,7 +2224,7 @@ Update a object category ### `rippling_delete_object_category` -Delete a object category +Delete an object category #### Input diff --git a/apps/sim/app/(landing)/integrations/data/icon-mapping.ts b/apps/sim/app/(landing)/integrations/data/icon-mapping.ts index 7b9b36c977a..910d0ae2ae7 100644 --- a/apps/sim/app/(landing)/integrations/data/icon-mapping.ts +++ b/apps/sim/app/(landing)/integrations/data/icon-mapping.ts @@ -5,6 +5,7 @@ import type { ComponentType, SVGProps } from 'react' import { A2AIcon, + AgentMailIcon, AhrefsIcon, AirtableIcon, AirweaveIcon, @@ -188,6 +189,7 @@ type IconComponent = ComponentType> export const blockTypeToIconMap: Record = { a2a: A2AIcon, + agentmail: AgentMailIcon, ahrefs: AhrefsIcon, airtable: AirtableIcon, airweave: AirweaveIcon, diff --git a/apps/sim/app/(landing)/integrations/data/integrations.json b/apps/sim/app/(landing)/integrations/data/integrations.json index ae89ed9506e..7b5822efe20 100644 --- a/apps/sim/app/(landing)/integrations/data/integrations.json +++ b/apps/sim/app/(landing)/integrations/data/integrations.json @@ -105,6 +105,109 @@ "integrationType": "developer-tools", "tags": ["agentic", "automation"] }, + { + "type": "agentmail", + "slug": "agentmail", + "name": "AgentMail", + "description": "Manage email inboxes, threads, and messages with AgentMail", + "longDescription": "Integrate AgentMail into your workflow. Create and manage email inboxes, send and receive messages, reply to threads, manage drafts, and organize threads with labels. Requires API Key.", + "bgColor": "#000000", + "iconName": "AgentMailIcon", + "docsUrl": "https://docs.sim.ai/tools/agentmail", + "operations": [ + { + "name": "Send Message", + "description": "Send an email message from an AgentMail inbox" + }, + { + "name": "Reply to Message", + "description": "Reply to an existing email message in AgentMail" + }, + { + "name": "Forward Message", + "description": "Forward an email message to new recipients in AgentMail" + }, + { + "name": "List Threads", + "description": "List email threads in AgentMail" + }, + { + "name": "Get Thread", + "description": "Get details of a specific email thread including messages in AgentMail" + }, + { + "name": "Update Thread Labels", + "description": "Add or remove labels on an email thread in AgentMail" + }, + { + "name": "Delete Thread", + "description": "Delete an email thread in AgentMail (moves to trash, or permanently deletes if already in trash)" + }, + { + "name": "List Messages", + "description": "List messages in an inbox in AgentMail" + }, + { + "name": "Get Message", + "description": "Get details of a specific email message in AgentMail" + }, + { + "name": "Update Message Labels", + "description": "Add or remove labels on an email message in AgentMail" + }, + { + "name": "Create Draft", + "description": "Create a new email draft in AgentMail" + }, + { + "name": "List Drafts", + "description": "List email drafts in an inbox in AgentMail" + }, + { + "name": "Get Draft", + "description": "Get details of a specific email draft in AgentMail" + }, + { + "name": "Update Draft", + "description": "Update an existing email draft in AgentMail" + }, + { + "name": "Delete Draft", + "description": "Delete an email draft in AgentMail" + }, + { + "name": "Send Draft", + "description": "Send an existing email draft in AgentMail" + }, + { + "name": "Create Inbox", + "description": "Create a new email inbox with AgentMail" + }, + { + "name": "List Inboxes", + "description": "List all email inboxes in AgentMail" + }, + { + "name": "Get Inbox", + "description": "Get details of a specific email inbox in AgentMail" + }, + { + "name": "Update Inbox", + "description": "Update the display name of an email inbox in AgentMail" + }, + { + "name": "Delete Inbox", + "description": "Delete an email inbox in AgentMail" + } + ], + "operationCount": 21, + "triggers": [], + "triggerCount": 0, + "authType": "api-key", + "category": "tools", + "integrationType": "email", + "tags": ["messaging"] + }, { "type": "ahrefs", "slug": "ahrefs", @@ -9625,11 +9728,11 @@ }, { "name": "Update Object Category", - "description": "Update a object category" + "description": "Update an object category" }, { "name": "Delete Object Category", - "description": "Delete a object category" + "description": "Delete an object category" }, { "name": "Get Report Run", diff --git a/apps/sim/blocks/blocks/agentmail.ts b/apps/sim/blocks/blocks/agentmail.ts new file mode 100644 index 00000000000..cecf84f3907 --- /dev/null +++ b/apps/sim/blocks/blocks/agentmail.ts @@ -0,0 +1,621 @@ +import { AgentMailIcon } from '@/components/icons' +import type { BlockConfig } from '@/blocks/types' +import { AuthMode, IntegrationType } from '@/blocks/types' + +export const AgentMailBlock: BlockConfig = { + type: 'agentmail', + name: 'AgentMail', + description: 'Manage email inboxes, threads, and messages with AgentMail', + longDescription: + 'Integrate AgentMail into your workflow. Create and manage email inboxes, send and receive messages, reply to threads, manage drafts, and organize threads with labels. Requires API Key.', + docsLink: 'https://docs.sim.ai/tools/agentmail', + category: 'tools', + integrationType: IntegrationType.Email, + tags: ['messaging'], + bgColor: '#000000', + icon: AgentMailIcon, + authMode: AuthMode.ApiKey, + + subBlocks: [ + { + id: 'operation', + title: 'Operation', + type: 'dropdown', + options: [ + { label: 'Send Message', id: 'send_message' }, + { label: 'Reply to Message', id: 'reply_message' }, + { label: 'Forward Message', id: 'forward_message' }, + { label: 'List Threads', id: 'list_threads' }, + { label: 'Get Thread', id: 'get_thread' }, + { label: 'Update Thread Labels', id: 'update_thread' }, + { label: 'Delete Thread', id: 'delete_thread' }, + { label: 'List Messages', id: 'list_messages' }, + { label: 'Get Message', id: 'get_message' }, + { label: 'Update Message Labels', id: 'update_message' }, + { label: 'Create Draft', id: 'create_draft' }, + { label: 'List Drafts', id: 'list_drafts' }, + { label: 'Get Draft', id: 'get_draft' }, + { label: 'Update Draft', id: 'update_draft' }, + { label: 'Delete Draft', id: 'delete_draft' }, + { label: 'Send Draft', id: 'send_draft' }, + { label: 'Create Inbox', id: 'create_inbox' }, + { label: 'List Inboxes', id: 'list_inboxes' }, + { label: 'Get Inbox', id: 'get_inbox' }, + { label: 'Update Inbox', id: 'update_inbox' }, + { label: 'Delete Inbox', id: 'delete_inbox' }, + ], + value: () => 'send_message', + }, + { + id: 'apiKey', + title: 'API Key', + type: 'short-input', + placeholder: 'Enter your AgentMail API key', + required: true, + password: true, + }, + + // Send Message fields + { + id: 'inboxId', + title: 'Inbox ID', + type: 'short-input', + placeholder: 'Inbox ID', + condition: { + field: 'operation', + value: [ + 'send_message', + 'reply_message', + 'forward_message', + 'list_threads', + 'get_thread', + 'update_thread', + 'delete_thread', + 'list_messages', + 'get_message', + 'update_message', + 'create_draft', + 'list_drafts', + 'get_draft', + 'update_draft', + 'delete_draft', + 'send_draft', + ], + }, + required: { + field: 'operation', + value: [ + 'send_message', + 'reply_message', + 'forward_message', + 'list_threads', + 'get_thread', + 'update_thread', + 'delete_thread', + 'list_messages', + 'get_message', + 'update_message', + 'create_draft', + 'list_drafts', + 'get_draft', + 'update_draft', + 'delete_draft', + 'send_draft', + ], + }, + }, + { + id: 'to', + title: 'To', + type: 'short-input', + placeholder: 'recipient@example.com', + condition: { + field: 'operation', + value: ['send_message', 'forward_message', 'create_draft', 'update_draft'], + }, + required: { field: 'operation', value: ['send_message', 'forward_message'] }, + }, + { + id: 'subject', + title: 'Subject', + type: 'short-input', + placeholder: 'Email subject', + condition: { + field: 'operation', + value: ['send_message', 'forward_message', 'create_draft', 'update_draft'], + }, + required: { field: 'operation', value: 'send_message' }, + wandConfig: { + enabled: true, + prompt: + 'Generate a compelling email subject line based on the description. Keep it concise. Return ONLY the subject line.', + placeholder: 'Describe the email topic...', + }, + }, + { + id: 'text', + title: 'Text', + type: 'long-input', + placeholder: 'Plain text email body', + condition: { + field: 'operation', + value: ['send_message', 'reply_message', 'forward_message', 'create_draft', 'update_draft'], + }, + wandConfig: { + enabled: true, + prompt: + 'Generate email content based on the description. Use clear formatting with short paragraphs. Return ONLY the email body.', + placeholder: 'Describe the email content...', + }, + }, + { + id: 'html', + title: 'HTML', + type: 'long-input', + placeholder: '

HTML email body

', + condition: { + field: 'operation', + value: ['send_message', 'reply_message', 'forward_message', 'create_draft', 'update_draft'], + }, + mode: 'advanced', + }, + { + id: 'cc', + title: 'CC', + type: 'short-input', + placeholder: 'cc@example.com', + condition: { + field: 'operation', + value: ['send_message', 'reply_message', 'forward_message', 'create_draft', 'update_draft'], + }, + mode: 'advanced', + }, + { + id: 'bcc', + title: 'BCC', + type: 'short-input', + placeholder: 'bcc@example.com', + condition: { + field: 'operation', + value: ['send_message', 'reply_message', 'forward_message', 'create_draft', 'update_draft'], + }, + mode: 'advanced', + }, + + // Reply to Message fields + { + id: 'replyMessageId', + title: 'Message ID to Reply To', + type: 'short-input', + placeholder: 'Message ID', + condition: { field: 'operation', value: 'reply_message' }, + required: { field: 'operation', value: 'reply_message' }, + }, + { + id: 'replyTo', + title: 'Override To', + type: 'short-input', + placeholder: 'Override recipient (optional)', + condition: { field: 'operation', value: 'reply_message' }, + mode: 'advanced', + }, + { + id: 'replyAll', + title: 'Reply All', + type: 'dropdown', + options: [ + { label: 'No', id: 'false' }, + { label: 'Yes', id: 'true' }, + ], + value: () => 'false', + condition: { field: 'operation', value: 'reply_message' }, + mode: 'advanced', + }, + + // Thread ID fields (shared across thread operations) + { + id: 'threadId', + title: 'Thread ID', + type: 'short-input', + placeholder: 'Thread ID', + condition: { + field: 'operation', + value: ['get_thread', 'update_thread', 'delete_thread'], + }, + required: { + field: 'operation', + value: ['get_thread', 'update_thread', 'delete_thread'], + }, + }, + + // Update Thread Labels fields + { + id: 'addLabels', + title: 'Add Labels', + type: 'short-input', + placeholder: 'important, follow-up', + condition: { field: 'operation', value: 'update_thread' }, + }, + { + id: 'removeLabels', + title: 'Remove Labels', + type: 'short-input', + placeholder: 'inbox, unread', + condition: { field: 'operation', value: 'update_thread' }, + }, + + // Delete Thread fields + { + id: 'permanent', + title: 'Permanent Delete', + type: 'dropdown', + options: [ + { label: 'No (move to trash)', id: 'false' }, + { label: 'Yes (permanent)', id: 'true' }, + ], + value: () => 'false', + condition: { field: 'operation', value: 'delete_thread' }, + mode: 'advanced', + }, + + // Forward Message fields + { + id: 'forwardMessageId', + title: 'Message ID to Forward', + type: 'short-input', + placeholder: 'Message ID', + condition: { field: 'operation', value: 'forward_message' }, + required: { field: 'operation', value: 'forward_message' }, + }, + + // Update Message Labels fields + { + id: 'updateMessageId', + title: 'Message ID', + type: 'short-input', + placeholder: 'Message ID', + condition: { field: 'operation', value: 'update_message' }, + required: { field: 'operation', value: 'update_message' }, + }, + { + id: 'msgAddLabels', + title: 'Add Labels', + type: 'short-input', + placeholder: 'important, follow-up', + condition: { field: 'operation', value: 'update_message' }, + }, + { + id: 'msgRemoveLabels', + title: 'Remove Labels', + type: 'short-input', + placeholder: 'inbox, unread', + condition: { field: 'operation', value: 'update_message' }, + }, + + // Get Message fields + { + id: 'messageId', + title: 'Message ID', + type: 'short-input', + placeholder: 'Message ID', + condition: { field: 'operation', value: 'get_message' }, + required: { field: 'operation', value: 'get_message' }, + }, + + // Draft ID fields (shared across draft operations) + { + id: 'draftId', + title: 'Draft ID', + type: 'short-input', + placeholder: 'Draft ID', + condition: { + field: 'operation', + value: ['get_draft', 'update_draft', 'delete_draft', 'send_draft'], + }, + required: { + field: 'operation', + value: ['get_draft', 'update_draft', 'delete_draft', 'send_draft'], + }, + }, + + // Create/Update Draft fields + { + id: 'draftInReplyTo', + title: 'In Reply To', + type: 'short-input', + placeholder: 'Message ID this draft replies to', + condition: { field: 'operation', value: 'create_draft' }, + mode: 'advanced', + }, + { + id: 'sendAt', + title: 'Schedule Send', + type: 'short-input', + placeholder: 'ISO 8601 timestamp to schedule sending', + condition: { field: 'operation', value: ['create_draft', 'update_draft'] }, + mode: 'advanced', + wandConfig: { + enabled: true, + generationType: 'timestamp', + prompt: 'Generate an ISO 8601 timestamp. Return ONLY the timestamp string.', + placeholder: 'Describe when to send (e.g., "tomorrow at 9am")...', + }, + }, + + // Create Inbox fields + { + id: 'username', + title: 'Username', + type: 'short-input', + placeholder: 'Optional username for email address', + condition: { field: 'operation', value: 'create_inbox' }, + }, + { + id: 'domain', + title: 'Domain', + type: 'short-input', + placeholder: 'Optional domain for email address', + condition: { field: 'operation', value: 'create_inbox' }, + mode: 'advanced', + }, + { + id: 'displayName', + title: 'Display Name', + type: 'short-input', + placeholder: 'Inbox display name', + condition: { field: 'operation', value: ['create_inbox', 'update_inbox'] }, + required: { field: 'operation', value: 'update_inbox' }, + }, + + // Inbox ID for get/update/delete inbox + { + id: 'inboxIdParam', + title: 'Inbox ID', + type: 'short-input', + placeholder: 'Inbox ID', + condition: { + field: 'operation', + value: ['get_inbox', 'update_inbox', 'delete_inbox'], + }, + required: { + field: 'operation', + value: ['get_inbox', 'update_inbox', 'delete_inbox'], + }, + }, + + // Pagination fields (advanced) + { + id: 'limit', + title: 'Limit', + type: 'short-input', + placeholder: 'Max results to return', + condition: { + field: 'operation', + value: ['list_inboxes', 'list_threads', 'list_messages', 'list_drafts'], + }, + mode: 'advanced', + }, + { + id: 'pageToken', + title: 'Page Token', + type: 'short-input', + placeholder: 'Pagination token', + condition: { + field: 'operation', + value: ['list_inboxes', 'list_threads', 'list_messages', 'list_drafts'], + }, + mode: 'advanced', + }, + + // List Threads filters (advanced) + { + id: 'labels', + title: 'Labels Filter', + type: 'short-input', + placeholder: 'Filter by labels (comma-separated)', + condition: { field: 'operation', value: 'list_threads' }, + mode: 'advanced', + }, + { + id: 'before', + title: 'Before', + type: 'short-input', + placeholder: 'Filter threads before this date', + condition: { field: 'operation', value: 'list_threads' }, + mode: 'advanced', + wandConfig: { + enabled: true, + generationType: 'timestamp', + prompt: 'Generate an ISO 8601 timestamp. Return ONLY the timestamp string.', + placeholder: 'Describe the date (e.g., "yesterday")...', + }, + }, + { + id: 'after', + title: 'After', + type: 'short-input', + placeholder: 'Filter threads after this date', + condition: { field: 'operation', value: 'list_threads' }, + mode: 'advanced', + wandConfig: { + enabled: true, + generationType: 'timestamp', + prompt: 'Generate an ISO 8601 timestamp. Return ONLY the timestamp string.', + placeholder: 'Describe the date (e.g., "last week")...', + }, + }, + ], + + tools: { + access: [ + 'agentmail_create_draft', + 'agentmail_create_inbox', + 'agentmail_delete_draft', + 'agentmail_delete_inbox', + 'agentmail_delete_thread', + 'agentmail_forward_message', + 'agentmail_get_draft', + 'agentmail_get_inbox', + 'agentmail_get_message', + 'agentmail_get_thread', + 'agentmail_list_drafts', + 'agentmail_list_inboxes', + 'agentmail_list_messages', + 'agentmail_list_threads', + 'agentmail_reply_message', + 'agentmail_send_draft', + 'agentmail_send_message', + 'agentmail_update_draft', + 'agentmail_update_inbox', + 'agentmail_update_message', + 'agentmail_update_thread', + ], + config: { + tool: (params) => `agentmail_${params.operation || 'send_message'}`, + params: (params) => { + const { + operation, + inboxIdParam, + permanent, + replyMessageId, + replyTo, + replyAll, + forwardMessageId, + updateMessageId, + msgAddLabels, + msgRemoveLabels, + addLabels, + removeLabels, + draftInReplyTo, + ...rest + } = params + + if (['get_inbox', 'update_inbox', 'delete_inbox'].includes(operation) && inboxIdParam) { + rest.inboxId = inboxIdParam + } + + if (operation === 'delete_thread' && permanent !== undefined) { + rest.permanent = permanent === 'true' + } + + if (operation === 'reply_message' && replyAll !== undefined) { + rest.replyAll = replyAll === 'true' + } + + if (operation === 'reply_message' && replyMessageId) { + rest.messageId = replyMessageId + } + + if (operation === 'reply_message' && replyTo) { + rest.to = replyTo + } else if (operation === 'reply_message') { + rest.to = undefined + } + + if (operation === 'forward_message' && forwardMessageId) { + rest.messageId = forwardMessageId + } + + if (operation === 'update_message' && updateMessageId) { + rest.messageId = updateMessageId + } + + if (operation === 'update_message' && msgAddLabels) { + rest.addLabels = msgAddLabels + } + + if (operation === 'update_message' && msgRemoveLabels) { + rest.removeLabels = msgRemoveLabels + } + + if (operation === 'update_thread' && addLabels) { + rest.addLabels = addLabels + } + + if (operation === 'update_thread' && removeLabels) { + rest.removeLabels = removeLabels + } + + if (operation === 'create_draft' && draftInReplyTo) { + rest.inReplyTo = draftInReplyTo + } + + if (rest.limit) { + rest.limit = Number(rest.limit) + } + + return rest + }, + }, + }, + + inputs: { + operation: { type: 'string', description: 'Operation to perform' }, + apiKey: { type: 'string', description: 'AgentMail API key' }, + inboxId: { type: 'string', description: 'Inbox ID' }, + inboxIdParam: { + type: 'string', + description: 'Inbox ID for get/update/delete inbox operations', + }, + to: { type: 'string', description: 'Recipient email address' }, + subject: { type: 'string', description: 'Email subject' }, + text: { type: 'string', description: 'Plain text email body' }, + html: { type: 'string', description: 'HTML email body' }, + cc: { type: 'string', description: 'CC email addresses' }, + bcc: { type: 'string', description: 'BCC email addresses' }, + replyMessageId: { type: 'string', description: 'Message ID to reply to' }, + replyTo: { type: 'string', description: 'Override recipient for reply' }, + replyAll: { type: 'string', description: 'Reply to all recipients' }, + forwardMessageId: { type: 'string', description: 'Message ID to forward' }, + updateMessageId: { type: 'string', description: 'Message ID to update labels on' }, + msgAddLabels: { type: 'string', description: 'Labels to add to message' }, + msgRemoveLabels: { type: 'string', description: 'Labels to remove from message' }, + threadId: { type: 'string', description: 'Thread ID' }, + addLabels: { type: 'string', description: 'Labels to add to thread (comma-separated)' }, + removeLabels: { type: 'string', description: 'Labels to remove from thread (comma-separated)' }, + permanent: { type: 'string', description: 'Whether to permanently delete' }, + messageId: { type: 'string', description: 'Message ID' }, + draftId: { type: 'string', description: 'Draft ID' }, + draftInReplyTo: { type: 'string', description: 'Message ID this draft replies to' }, + sendAt: { type: 'string', description: 'ISO 8601 timestamp to schedule sending' }, + username: { type: 'string', description: 'Username for new inbox' }, + domain: { type: 'string', description: 'Domain for new inbox' }, + displayName: { type: 'string', description: 'Display name for inbox' }, + limit: { type: 'string', description: 'Max results to return' }, + pageToken: { type: 'string', description: 'Pagination token' }, + labels: { type: 'string', description: 'Labels filter for threads' }, + before: { type: 'string', description: 'Filter threads before this date' }, + after: { type: 'string', description: 'Filter threads after this date' }, + }, + + outputs: { + inboxId: { type: 'string', description: 'Inbox ID' }, + email: { type: 'string', description: 'Inbox email address' }, + displayName: { type: 'string', description: 'Inbox display name' }, + threadId: { type: 'string', description: 'Thread ID' }, + messageId: { type: 'string', description: 'Message ID' }, + draftId: { type: 'string', description: 'Draft ID' }, + subject: { type: 'string', description: 'Email subject' }, + to: { type: 'string', description: 'Recipient email address' }, + from: { type: 'string', description: 'Sender email address' }, + text: { type: 'string', description: 'Plain text content' }, + html: { type: 'string', description: 'HTML content' }, + preview: { type: 'string', description: 'Message or draft preview text' }, + senders: { type: 'json', description: 'List of sender email addresses' }, + recipients: { type: 'json', description: 'List of recipient email addresses' }, + labels: { type: 'json', description: 'Thread or draft labels' }, + messages: { type: 'json', description: 'List of messages' }, + threads: { type: 'json', description: 'List of threads' }, + inboxes: { type: 'json', description: 'List of inboxes' }, + drafts: { type: 'json', description: 'List of drafts' }, + messageCount: { type: 'number', description: 'Number of messages in thread' }, + count: { type: 'number', description: 'Total number of results' }, + nextPageToken: { type: 'string', description: 'Token for next page of results' }, + deleted: { type: 'boolean', description: 'Whether the resource was deleted' }, + sendStatus: { type: 'string', description: 'Draft send status' }, + sendAt: { type: 'string', description: 'Scheduled send time' }, + inReplyTo: { type: 'string', description: 'Message ID this draft replies to' }, + createdAt: { type: 'string', description: 'Creation timestamp' }, + updatedAt: { type: 'string', description: 'Last updated timestamp' }, + }, +} diff --git a/apps/sim/blocks/registry.ts b/apps/sim/blocks/registry.ts index 574fdd000eb..93e7c808eab 100644 --- a/apps/sim/blocks/registry.ts +++ b/apps/sim/blocks/registry.ts @@ -1,5 +1,6 @@ import { A2ABlock } from '@/blocks/blocks/a2a' import { AgentBlock } from '@/blocks/blocks/agent' +import { AgentMailBlock } from '@/blocks/blocks/agentmail' import { AhrefsBlock } from '@/blocks/blocks/ahrefs' import { AirtableBlock } from '@/blocks/blocks/airtable' import { AirweaveBlock } from '@/blocks/blocks/airweave' @@ -216,6 +217,7 @@ import type { BlockConfig } from '@/blocks/types' export const registry: Record = { a2a: A2ABlock, agent: AgentBlock, + agentmail: AgentMailBlock, ahrefs: AhrefsBlock, airtable: AirtableBlock, airweave: AirweaveBlock, diff --git a/apps/sim/components/icons.tsx b/apps/sim/components/icons.tsx index 6614c9f6036..05daa6b336d 100644 --- a/apps/sim/components/icons.tsx +++ b/apps/sim/components/icons.tsx @@ -1,6 +1,33 @@ import type { SVGProps } from 'react' import { useId } from 'react' +export function AgentMailIcon(props: SVGProps) { + return ( + + + + + + + + ) +} + export function SearchIcon(props: SVGProps) { return ( = { + id: 'agentmail_create_draft', + name: 'Create Draft', + description: 'Create a new email draft in AgentMail', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'AgentMail API key', + }, + inboxId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the inbox to create the draft in', + }, + to: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Recipient email addresses (comma-separated)', + }, + subject: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Draft subject line', + }, + text: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Plain text draft body', + }, + html: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'HTML draft body', + }, + cc: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'CC recipient email addresses (comma-separated)', + }, + bcc: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'BCC recipient email addresses (comma-separated)', + }, + inReplyTo: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'ID of message being replied to', + }, + sendAt: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'ISO 8601 timestamp to schedule sending', + }, + }, + + request: { + url: (params) => `https://api.agentmail.to/v0/inboxes/${params.inboxId.trim()}/drafts`, + method: 'POST', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => { + const body: Record = {} + if (params.to) body.to = params.to.split(',').map((e) => e.trim()) + if (params.subject) body.subject = params.subject + if (params.text) body.text = params.text + if (params.html) body.html = params.html + if (params.cc) body.cc = params.cc.split(',').map((e) => e.trim()) + if (params.bcc) body.bcc = params.bcc.split(',').map((e) => e.trim()) + if (params.inReplyTo) body.in_reply_to = params.inReplyTo + if (params.sendAt) body.send_at = params.sendAt + return body + }, + }, + + transformResponse: async (response): Promise => { + const data = await response.json() + + if (!response.ok) { + return { + success: false, + error: data.message ?? 'Failed to create draft', + output: { + draftId: '', + inboxId: '', + subject: null, + to: [], + cc: [], + bcc: [], + text: null, + html: null, + preview: null, + labels: [], + inReplyTo: null, + sendStatus: null, + sendAt: null, + createdAt: '', + updatedAt: '', + }, + } + } + + return { + success: true, + output: { + draftId: data.draft_id ?? '', + inboxId: data.inbox_id ?? '', + subject: data.subject ?? null, + to: data.to ?? [], + cc: data.cc ?? [], + bcc: data.bcc ?? [], + text: data.text ?? null, + html: data.html ?? null, + preview: data.preview ?? null, + labels: data.labels ?? [], + inReplyTo: data.in_reply_to ?? null, + sendStatus: data.send_status ?? null, + sendAt: data.send_at ?? null, + createdAt: data.created_at ?? '', + updatedAt: data.updated_at ?? '', + }, + } + }, + + outputs: { + draftId: { type: 'string', description: 'Unique identifier for the draft' }, + inboxId: { type: 'string', description: 'Inbox the draft belongs to' }, + subject: { type: 'string', description: 'Draft subject', optional: true }, + to: { type: 'array', description: 'Recipient email addresses' }, + cc: { type: 'array', description: 'CC email addresses' }, + bcc: { type: 'array', description: 'BCC email addresses' }, + text: { type: 'string', description: 'Plain text content', optional: true }, + html: { type: 'string', description: 'HTML content', optional: true }, + preview: { type: 'string', description: 'Draft preview text', optional: true }, + labels: { type: 'array', description: 'Labels assigned to the draft' }, + inReplyTo: { type: 'string', description: 'Message ID this draft replies to', optional: true }, + sendStatus: { + type: 'string', + description: 'Send status (scheduled, sending, failed)', + optional: true, + }, + sendAt: { type: 'string', description: 'Scheduled send time', optional: true }, + createdAt: { type: 'string', description: 'Creation timestamp' }, + updatedAt: { type: 'string', description: 'Last updated timestamp' }, + }, +} diff --git a/apps/sim/tools/agentmail/create_inbox.ts b/apps/sim/tools/agentmail/create_inbox.ts new file mode 100644 index 00000000000..4ece2d3d80f --- /dev/null +++ b/apps/sim/tools/agentmail/create_inbox.ts @@ -0,0 +1,87 @@ +import type { CreateInboxParams, CreateInboxResult } from '@/tools/agentmail/types' +import type { ToolConfig } from '@/tools/types' + +export const agentmailCreateInboxTool: ToolConfig = { + id: 'agentmail_create_inbox', + name: 'Create Inbox', + description: 'Create a new email inbox with AgentMail', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'AgentMail API key', + }, + username: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Username for the inbox email address', + }, + domain: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Domain for the inbox email address', + }, + displayName: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Display name for the inbox', + }, + }, + + request: { + url: 'https://api.agentmail.to/v0/inboxes', + method: 'POST', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => ({ + ...(params.username && { username: params.username }), + ...(params.domain && { domain: params.domain }), + ...(params.displayName && { display_name: params.displayName }), + }), + }, + + transformResponse: async (response): Promise => { + const data = await response.json() + + if (!response.ok) { + return { + success: false, + error: data.message ?? 'Failed to create inbox', + output: { + inboxId: '', + email: '', + displayName: null, + createdAt: '', + updatedAt: '', + }, + } + } + + return { + success: true, + output: { + inboxId: data.inbox_id ?? '', + email: data.email ?? '', + displayName: data.display_name ?? null, + createdAt: data.created_at ?? '', + updatedAt: data.updated_at ?? '', + }, + } + }, + + outputs: { + inboxId: { type: 'string', description: 'Unique identifier for the inbox' }, + email: { type: 'string', description: 'Email address of the inbox' }, + displayName: { type: 'string', description: 'Display name of the inbox', optional: true }, + createdAt: { type: 'string', description: 'Creation timestamp' }, + updatedAt: { type: 'string', description: 'Last updated timestamp' }, + }, +} diff --git a/apps/sim/tools/agentmail/delete_draft.ts b/apps/sim/tools/agentmail/delete_draft.ts new file mode 100644 index 00000000000..4ff9b80d8d7 --- /dev/null +++ b/apps/sim/tools/agentmail/delete_draft.ts @@ -0,0 +1,59 @@ +import type { DeleteDraftParams, DeleteDraftResult } from '@/tools/agentmail/types' +import type { ToolConfig } from '@/tools/types' + +export const agentmailDeleteDraftTool: ToolConfig = { + id: 'agentmail_delete_draft', + name: 'Delete Draft', + description: 'Delete an email draft in AgentMail', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'AgentMail API key', + }, + inboxId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the inbox containing the draft', + }, + draftId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the draft to delete', + }, + }, + + request: { + url: (params) => + `https://api.agentmail.to/v0/inboxes/${params.inboxId.trim()}/drafts/${params.draftId.trim()}`, + method: 'DELETE', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response): Promise => { + if (!response.ok) { + const data = await response.json() + return { + success: false, + error: data.message ?? 'Failed to delete draft', + output: { deleted: false }, + } + } + + return { + success: true, + output: { deleted: true }, + } + }, + + outputs: { + deleted: { type: 'boolean', description: 'Whether the draft was successfully deleted' }, + }, +} diff --git a/apps/sim/tools/agentmail/delete_inbox.ts b/apps/sim/tools/agentmail/delete_inbox.ts new file mode 100644 index 00000000000..925aceb546d --- /dev/null +++ b/apps/sim/tools/agentmail/delete_inbox.ts @@ -0,0 +1,52 @@ +import type { DeleteInboxParams, DeleteInboxResult } from '@/tools/agentmail/types' +import type { ToolConfig } from '@/tools/types' + +export const agentmailDeleteInboxTool: ToolConfig = { + id: 'agentmail_delete_inbox', + name: 'Delete Inbox', + description: 'Delete an email inbox in AgentMail', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'AgentMail API key', + }, + inboxId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the inbox to delete', + }, + }, + + request: { + url: (params) => `https://api.agentmail.to/v0/inboxes/${params.inboxId.trim()}`, + method: 'DELETE', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response): Promise => { + if (!response.ok) { + const data = await response.json() + return { + success: false, + error: data.message ?? 'Failed to delete inbox', + output: { deleted: false }, + } + } + + return { + success: true, + output: { deleted: true }, + } + }, + + outputs: { + deleted: { type: 'boolean', description: 'Whether the inbox was successfully deleted' }, + }, +} diff --git a/apps/sim/tools/agentmail/delete_thread.ts b/apps/sim/tools/agentmail/delete_thread.ts new file mode 100644 index 00000000000..8a2d0165471 --- /dev/null +++ b/apps/sim/tools/agentmail/delete_thread.ts @@ -0,0 +1,70 @@ +import type { DeleteThreadParams, DeleteThreadResult } from '@/tools/agentmail/types' +import type { ToolConfig } from '@/tools/types' + +export const agentmailDeleteThreadTool: ToolConfig = { + id: 'agentmail_delete_thread', + name: 'Delete Thread', + description: + 'Delete an email thread in AgentMail (moves to trash, or permanently deletes if already in trash)', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'AgentMail API key', + }, + inboxId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the inbox containing the thread', + }, + threadId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the thread to delete', + }, + permanent: { + type: 'boolean', + required: false, + visibility: 'user-or-llm', + description: 'Force permanent deletion instead of moving to trash', + }, + }, + + request: { + url: (params) => { + const query = new URLSearchParams() + if (params.permanent) query.set('permanent', 'true') + const qs = query.toString() + return `https://api.agentmail.to/v0/inboxes/${params.inboxId.trim()}/threads/${params.threadId.trim()}${qs ? `?${qs}` : ''}` + }, + method: 'DELETE', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response): Promise => { + if (!response.ok) { + const data = await response.json() + return { + success: false, + error: data.message ?? 'Failed to delete thread', + output: { deleted: false }, + } + } + + return { + success: true, + output: { deleted: true }, + } + }, + + outputs: { + deleted: { type: 'boolean', description: 'Whether the thread was successfully deleted' }, + }, +} diff --git a/apps/sim/tools/agentmail/forward_message.ts b/apps/sim/tools/agentmail/forward_message.ts new file mode 100644 index 00000000000..03e9d827ea0 --- /dev/null +++ b/apps/sim/tools/agentmail/forward_message.ts @@ -0,0 +1,112 @@ +import type { ForwardMessageParams, ForwardMessageResult } from '@/tools/agentmail/types' +import type { ToolConfig } from '@/tools/types' + +export const agentmailForwardMessageTool: ToolConfig = { + id: 'agentmail_forward_message', + name: 'Forward Message', + description: 'Forward an email message to new recipients in AgentMail', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'AgentMail API key', + }, + inboxId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the inbox containing the message', + }, + messageId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the message to forward', + }, + to: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Recipient email addresses (comma-separated)', + }, + subject: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Override subject line', + }, + text: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Additional plain text to prepend', + }, + html: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Additional HTML to prepend', + }, + cc: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'CC recipient email addresses (comma-separated)', + }, + bcc: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'BCC recipient email addresses (comma-separated)', + }, + }, + + request: { + url: (params) => + `https://api.agentmail.to/v0/inboxes/${params.inboxId.trim()}/messages/${params.messageId.trim()}/forward`, + method: 'POST', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => { + const body: Record = { + to: params.to.split(',').map((e) => e.trim()), + } + if (params.subject) body.subject = params.subject + if (params.text) body.text = params.text + if (params.html) body.html = params.html + if (params.cc) body.cc = params.cc.split(',').map((e) => e.trim()) + if (params.bcc) body.bcc = params.bcc.split(',').map((e) => e.trim()) + return body + }, + }, + + transformResponse: async (response): Promise => { + const data = await response.json() + + if (!response.ok) { + return { + success: false, + error: data.message ?? 'Failed to forward message', + output: { messageId: '', threadId: '' }, + } + } + + return { + success: true, + output: { + messageId: data.message_id ?? '', + threadId: data.thread_id ?? '', + }, + } + }, + + outputs: { + messageId: { type: 'string', description: 'ID of the forwarded message' }, + threadId: { type: 'string', description: 'ID of the thread' }, + }, +} diff --git a/apps/sim/tools/agentmail/get_draft.ts b/apps/sim/tools/agentmail/get_draft.ts new file mode 100644 index 00000000000..011845595bc --- /dev/null +++ b/apps/sim/tools/agentmail/get_draft.ts @@ -0,0 +1,110 @@ +import type { GetDraftParams, GetDraftResult } from '@/tools/agentmail/types' +import type { ToolConfig } from '@/tools/types' + +export const agentmailGetDraftTool: ToolConfig = { + id: 'agentmail_get_draft', + name: 'Get Draft', + description: 'Get details of a specific email draft in AgentMail', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'AgentMail API key', + }, + inboxId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the inbox the draft belongs to', + }, + draftId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the draft to retrieve', + }, + }, + + request: { + url: (params) => + `https://api.agentmail.to/v0/inboxes/${params.inboxId.trim()}/drafts/${params.draftId.trim()}`, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response): Promise => { + const data = await response.json() + + if (!response.ok) { + return { + success: false, + error: data.message ?? 'Failed to get draft', + output: { + draftId: '', + inboxId: '', + subject: null, + to: [], + cc: [], + bcc: [], + text: null, + html: null, + preview: null, + labels: [], + inReplyTo: null, + sendStatus: null, + sendAt: null, + createdAt: '', + updatedAt: '', + }, + } + } + + return { + success: true, + output: { + draftId: data.draft_id ?? '', + inboxId: data.inbox_id ?? '', + subject: data.subject ?? null, + to: data.to ?? [], + cc: data.cc ?? [], + bcc: data.bcc ?? [], + text: data.text ?? null, + html: data.html ?? null, + preview: data.preview ?? null, + labels: data.labels ?? [], + inReplyTo: data.in_reply_to ?? null, + sendStatus: data.send_status ?? null, + sendAt: data.send_at ?? null, + createdAt: data.created_at ?? '', + updatedAt: data.updated_at ?? '', + }, + } + }, + + outputs: { + draftId: { type: 'string', description: 'Unique identifier for the draft' }, + inboxId: { type: 'string', description: 'Inbox the draft belongs to' }, + subject: { type: 'string', description: 'Draft subject', optional: true }, + to: { type: 'array', description: 'Recipient email addresses' }, + cc: { type: 'array', description: 'CC email addresses' }, + bcc: { type: 'array', description: 'BCC email addresses' }, + text: { type: 'string', description: 'Plain text content', optional: true }, + html: { type: 'string', description: 'HTML content', optional: true }, + preview: { type: 'string', description: 'Draft preview text', optional: true }, + labels: { type: 'array', description: 'Labels assigned to the draft' }, + inReplyTo: { type: 'string', description: 'Message ID this draft replies to', optional: true }, + sendStatus: { + type: 'string', + description: 'Send status (scheduled, sending, failed)', + optional: true, + }, + sendAt: { type: 'string', description: 'Scheduled send time', optional: true }, + createdAt: { type: 'string', description: 'Creation timestamp' }, + updatedAt: { type: 'string', description: 'Last updated timestamp' }, + }, +} diff --git a/apps/sim/tools/agentmail/get_inbox.ts b/apps/sim/tools/agentmail/get_inbox.ts new file mode 100644 index 00000000000..1ba7aea1385 --- /dev/null +++ b/apps/sim/tools/agentmail/get_inbox.ts @@ -0,0 +1,69 @@ +import type { GetInboxParams, GetInboxResult } from '@/tools/agentmail/types' +import type { ToolConfig } from '@/tools/types' + +export const agentmailGetInboxTool: ToolConfig = { + id: 'agentmail_get_inbox', + name: 'Get Inbox', + description: 'Get details of a specific email inbox in AgentMail', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'AgentMail API key', + }, + inboxId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the inbox to retrieve', + }, + }, + + request: { + url: (params) => `https://api.agentmail.to/v0/inboxes/${params.inboxId.trim()}`, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response): Promise => { + const data = await response.json() + + if (!response.ok) { + return { + success: false, + error: data.message ?? 'Failed to get inbox', + output: { + inboxId: '', + email: '', + displayName: null, + createdAt: '', + updatedAt: '', + }, + } + } + + return { + success: true, + output: { + inboxId: data.inbox_id ?? '', + email: data.email ?? '', + displayName: data.display_name ?? null, + createdAt: data.created_at ?? '', + updatedAt: data.updated_at ?? '', + }, + } + }, + + outputs: { + inboxId: { type: 'string', description: 'Unique identifier for the inbox' }, + email: { type: 'string', description: 'Email address of the inbox' }, + displayName: { type: 'string', description: 'Display name of the inbox', optional: true }, + createdAt: { type: 'string', description: 'Creation timestamp' }, + updatedAt: { type: 'string', description: 'Last updated timestamp' }, + }, +} diff --git a/apps/sim/tools/agentmail/get_message.ts b/apps/sim/tools/agentmail/get_message.ts new file mode 100644 index 00000000000..4db694244ff --- /dev/null +++ b/apps/sim/tools/agentmail/get_message.ts @@ -0,0 +1,91 @@ +import type { GetMessageParams, GetMessageResult } from '@/tools/agentmail/types' +import type { ToolConfig } from '@/tools/types' + +export const agentmailGetMessageTool: ToolConfig = { + id: 'agentmail_get_message', + name: 'Get Message', + description: 'Get details of a specific email message in AgentMail', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'AgentMail API key', + }, + inboxId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the inbox containing the message', + }, + messageId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the message to retrieve', + }, + }, + + request: { + url: (params) => + `https://api.agentmail.to/v0/inboxes/${params.inboxId.trim()}/messages/${params.messageId.trim()}`, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response): Promise => { + const data = await response.json() + + if (!response.ok) { + return { + success: false, + error: data.message ?? 'Failed to get message', + output: { + messageId: '', + threadId: '', + from: null, + to: [], + cc: [], + bcc: [], + subject: null, + text: null, + html: null, + createdAt: '', + }, + } + } + + return { + success: true, + output: { + messageId: data.message_id ?? '', + threadId: data.thread_id ?? '', + from: data.from ?? null, + to: data.to ?? [], + cc: data.cc ?? [], + bcc: data.bcc ?? [], + subject: data.subject ?? null, + text: data.text ?? null, + html: data.html ?? null, + createdAt: data.created_at ?? '', + }, + } + }, + + outputs: { + messageId: { type: 'string', description: 'Unique identifier for the message' }, + threadId: { type: 'string', description: 'ID of the thread this message belongs to' }, + from: { type: 'string', description: 'Sender email address', optional: true }, + to: { type: 'array', description: 'Recipient email addresses' }, + cc: { type: 'array', description: 'CC email addresses' }, + bcc: { type: 'array', description: 'BCC email addresses' }, + subject: { type: 'string', description: 'Message subject', optional: true }, + text: { type: 'string', description: 'Plain text content', optional: true }, + html: { type: 'string', description: 'HTML content', optional: true }, + createdAt: { type: 'string', description: 'Creation timestamp' }, + }, +} diff --git a/apps/sim/tools/agentmail/get_thread.ts b/apps/sim/tools/agentmail/get_thread.ts new file mode 100644 index 00000000000..bb41ff6d4ec --- /dev/null +++ b/apps/sim/tools/agentmail/get_thread.ts @@ -0,0 +1,118 @@ +import type { GetThreadParams, GetThreadResult } from '@/tools/agentmail/types' +import type { ToolConfig } from '@/tools/types' + +export const agentmailGetThreadTool: ToolConfig = { + id: 'agentmail_get_thread', + name: 'Get Thread', + description: 'Get details of a specific email thread including messages in AgentMail', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'AgentMail API key', + }, + inboxId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the inbox containing the thread', + }, + threadId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the thread to retrieve', + }, + }, + + request: { + url: (params) => + `https://api.agentmail.to/v0/inboxes/${params.inboxId.trim()}/threads/${params.threadId.trim()}`, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response): Promise => { + const data = await response.json() + + if (!response.ok) { + return { + success: false, + error: data.message ?? 'Failed to get thread', + output: { + threadId: '', + subject: null, + senders: [], + recipients: [], + messageCount: 0, + labels: [], + lastMessageAt: null, + createdAt: '', + updatedAt: '', + messages: [], + }, + } + } + + return { + success: true, + output: { + threadId: data.thread_id ?? '', + subject: data.subject ?? null, + senders: data.senders ?? [], + recipients: data.recipients ?? [], + messageCount: data.message_count ?? 0, + labels: data.labels ?? [], + lastMessageAt: data.timestamp ?? null, + createdAt: data.created_at ?? '', + updatedAt: data.updated_at ?? '', + messages: (data.messages ?? []).map((msg: Record) => ({ + messageId: msg.message_id ?? '', + from: (msg.from as string) ?? null, + to: (msg.to as string[]) ?? [], + cc: (msg.cc as string[]) ?? [], + bcc: (msg.bcc as string[]) ?? [], + subject: (msg.subject as string) ?? null, + text: (msg.text as string) ?? null, + html: (msg.html as string) ?? null, + createdAt: (msg.created_at as string) ?? '', + })), + }, + } + }, + + outputs: { + threadId: { type: 'string', description: 'Unique identifier for the thread' }, + subject: { type: 'string', description: 'Thread subject', optional: true }, + senders: { type: 'array', description: 'List of sender email addresses' }, + recipients: { type: 'array', description: 'List of recipient email addresses' }, + messageCount: { type: 'number', description: 'Number of messages in the thread' }, + labels: { type: 'array', description: 'Labels assigned to the thread' }, + lastMessageAt: { type: 'string', description: 'Timestamp of last message', optional: true }, + createdAt: { type: 'string', description: 'Creation timestamp' }, + updatedAt: { type: 'string', description: 'Last updated timestamp' }, + messages: { + type: 'array', + description: 'Messages in the thread', + items: { + type: 'object', + properties: { + messageId: { type: 'string', description: 'Unique identifier for the message' }, + from: { type: 'string', description: 'Sender email address', optional: true }, + to: { type: 'array', description: 'Recipient email addresses' }, + cc: { type: 'array', description: 'CC email addresses' }, + bcc: { type: 'array', description: 'BCC email addresses' }, + subject: { type: 'string', description: 'Message subject', optional: true }, + text: { type: 'string', description: 'Plain text content', optional: true }, + html: { type: 'string', description: 'HTML content', optional: true }, + createdAt: { type: 'string', description: 'Creation timestamp' }, + }, + }, + }, + }, +} diff --git a/apps/sim/tools/agentmail/index.ts b/apps/sim/tools/agentmail/index.ts new file mode 100644 index 00000000000..c1342b0d13c --- /dev/null +++ b/apps/sim/tools/agentmail/index.ts @@ -0,0 +1,65 @@ +export { agentmailCreateDraftTool } from '@/tools/agentmail/create_draft' +export { agentmailCreateInboxTool } from '@/tools/agentmail/create_inbox' +export { agentmailDeleteDraftTool } from '@/tools/agentmail/delete_draft' +export { agentmailDeleteInboxTool } from '@/tools/agentmail/delete_inbox' +export { agentmailDeleteThreadTool } from '@/tools/agentmail/delete_thread' +export { agentmailForwardMessageTool } from '@/tools/agentmail/forward_message' +export { agentmailGetDraftTool } from '@/tools/agentmail/get_draft' +export { agentmailGetInboxTool } from '@/tools/agentmail/get_inbox' +export { agentmailGetMessageTool } from '@/tools/agentmail/get_message' +export { agentmailGetThreadTool } from '@/tools/agentmail/get_thread' +export { agentmailListDraftsTool } from '@/tools/agentmail/list_drafts' +export { agentmailListInboxesTool } from '@/tools/agentmail/list_inboxes' +export { agentmailListMessagesTool } from '@/tools/agentmail/list_messages' +export { agentmailListThreadsTool } from '@/tools/agentmail/list_threads' +export { agentmailReplyMessageTool } from '@/tools/agentmail/reply_message' +export { agentmailSendDraftTool } from '@/tools/agentmail/send_draft' +export { agentmailSendMessageTool } from '@/tools/agentmail/send_message' +export type { + CreateDraftParams, + CreateDraftResult, + CreateInboxParams, + CreateInboxResult, + DeleteDraftParams, + DeleteDraftResult, + DeleteInboxParams, + DeleteInboxResult, + DeleteThreadParams, + DeleteThreadResult, + ForwardMessageParams, + ForwardMessageResult, + GetDraftParams, + GetDraftResult, + GetInboxParams, + GetInboxResult, + GetMessageParams, + GetMessageResult, + GetThreadParams, + GetThreadResult, + ListDraftsParams, + ListDraftsResult, + ListInboxesParams, + ListInboxesResult, + ListMessagesParams, + ListMessagesResult, + ListThreadsParams, + ListThreadsResult, + ReplyMessageParams, + ReplyMessageResult, + SendDraftParams, + SendDraftResult, + SendMessageParams, + SendMessageResult, + UpdateDraftParams, + UpdateDraftResult, + UpdateInboxParams, + UpdateInboxResult, + UpdateMessageParams, + UpdateMessageResult, + UpdateThreadParams, + UpdateThreadResult, +} from '@/tools/agentmail/types' +export { agentmailUpdateDraftTool } from '@/tools/agentmail/update_draft' +export { agentmailUpdateInboxTool } from '@/tools/agentmail/update_inbox' +export { agentmailUpdateMessageTool } from '@/tools/agentmail/update_message' +export { agentmailUpdateThreadTool } from '@/tools/agentmail/update_thread' diff --git a/apps/sim/tools/agentmail/list_drafts.ts b/apps/sim/tools/agentmail/list_drafts.ts new file mode 100644 index 00000000000..c8d64b79075 --- /dev/null +++ b/apps/sim/tools/agentmail/list_drafts.ts @@ -0,0 +1,116 @@ +import type { ListDraftsParams, ListDraftsResult } from '@/tools/agentmail/types' +import type { ToolConfig } from '@/tools/types' + +export const agentmailListDraftsTool: ToolConfig = { + id: 'agentmail_list_drafts', + name: 'List Drafts', + description: 'List email drafts in an inbox in AgentMail', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'AgentMail API key', + }, + inboxId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the inbox to list drafts from', + }, + limit: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Maximum number of drafts to return', + }, + pageToken: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Pagination token for next page of results', + }, + }, + + request: { + url: (params) => { + const query = new URLSearchParams() + if (params.limit) query.set('limit', String(params.limit)) + if (params.pageToken) query.set('page_token', params.pageToken) + const qs = query.toString() + return `https://api.agentmail.to/v0/inboxes/${params.inboxId.trim()}/drafts${qs ? `?${qs}` : ''}` + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response): Promise => { + const data = await response.json() + + if (!response.ok) { + return { + success: false, + error: data.message ?? 'Failed to list drafts', + output: { drafts: [], count: 0, nextPageToken: null }, + } + } + + return { + success: true, + output: { + drafts: (data.drafts ?? []).map((draft: Record) => ({ + draftId: draft.draft_id ?? '', + inboxId: draft.inbox_id ?? '', + subject: (draft.subject as string) ?? null, + to: (draft.to as string[]) ?? [], + cc: (draft.cc as string[]) ?? [], + bcc: (draft.bcc as string[]) ?? [], + preview: (draft.preview as string) ?? null, + sendStatus: (draft.send_status as string) ?? null, + sendAt: (draft.send_at as string) ?? null, + createdAt: (draft.created_at as string) ?? '', + updatedAt: (draft.updated_at as string) ?? '', + })), + count: data.count ?? 0, + nextPageToken: data.next_page_token ?? null, + }, + } + }, + + outputs: { + drafts: { + type: 'array', + description: 'List of drafts', + items: { + type: 'object', + properties: { + draftId: { type: 'string', description: 'Unique identifier for the draft' }, + inboxId: { type: 'string', description: 'Inbox the draft belongs to' }, + subject: { type: 'string', description: 'Draft subject', optional: true }, + to: { type: 'array', description: 'Recipient email addresses' }, + cc: { type: 'array', description: 'CC email addresses' }, + bcc: { type: 'array', description: 'BCC email addresses' }, + preview: { type: 'string', description: 'Draft preview text', optional: true }, + sendStatus: { + type: 'string', + description: 'Send status (scheduled, sending, failed)', + optional: true, + }, + sendAt: { type: 'string', description: 'Scheduled send time', optional: true }, + createdAt: { type: 'string', description: 'Creation timestamp' }, + updatedAt: { type: 'string', description: 'Last updated timestamp' }, + }, + }, + }, + count: { type: 'number', description: 'Total number of drafts' }, + nextPageToken: { + type: 'string', + description: 'Token for retrieving the next page', + optional: true, + }, + }, +} diff --git a/apps/sim/tools/agentmail/list_inboxes.ts b/apps/sim/tools/agentmail/list_inboxes.ts new file mode 100644 index 00000000000..d05b9eacb10 --- /dev/null +++ b/apps/sim/tools/agentmail/list_inboxes.ts @@ -0,0 +1,98 @@ +import type { ListInboxesParams, ListInboxesResult } from '@/tools/agentmail/types' +import type { ToolConfig } from '@/tools/types' + +export const agentmailListInboxesTool: ToolConfig = { + id: 'agentmail_list_inboxes', + name: 'List Inboxes', + description: 'List all email inboxes in AgentMail', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'AgentMail API key', + }, + limit: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Maximum number of inboxes to return', + }, + pageToken: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Pagination token for next page of results', + }, + }, + + request: { + url: (params) => { + const query = new URLSearchParams() + if (params.limit) query.set('limit', String(params.limit)) + if (params.pageToken) query.set('page_token', params.pageToken) + const qs = query.toString() + return `https://api.agentmail.to/v0/inboxes${qs ? `?${qs}` : ''}` + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response): Promise => { + const data = await response.json() + + if (!response.ok) { + return { + success: false, + error: data.message ?? 'Failed to list inboxes', + output: { inboxes: [], count: 0, nextPageToken: null }, + } + } + + return { + success: true, + output: { + inboxes: (data.inboxes ?? []).map((inbox: Record) => ({ + inboxId: inbox.inbox_id ?? '', + email: inbox.email ?? '', + displayName: inbox.display_name ?? null, + createdAt: inbox.created_at ?? '', + updatedAt: inbox.updated_at ?? '', + })), + count: data.count ?? 0, + nextPageToken: data.next_page_token ?? null, + }, + } + }, + + outputs: { + inboxes: { + type: 'array', + description: 'List of inboxes', + items: { + type: 'object', + properties: { + inboxId: { type: 'string', description: 'Unique identifier for the inbox' }, + email: { type: 'string', description: 'Email address of the inbox' }, + displayName: { + type: 'string', + description: 'Display name of the inbox', + optional: true, + }, + createdAt: { type: 'string', description: 'Creation timestamp' }, + updatedAt: { type: 'string', description: 'Last updated timestamp' }, + }, + }, + }, + count: { type: 'number', description: 'Total number of inboxes' }, + nextPageToken: { + type: 'string', + description: 'Token for retrieving the next page', + optional: true, + }, + }, +} diff --git a/apps/sim/tools/agentmail/list_messages.ts b/apps/sim/tools/agentmail/list_messages.ts new file mode 100644 index 00000000000..056e5291bb0 --- /dev/null +++ b/apps/sim/tools/agentmail/list_messages.ts @@ -0,0 +1,102 @@ +import type { ListMessagesParams, ListMessagesResult } from '@/tools/agentmail/types' +import type { ToolConfig } from '@/tools/types' + +export const agentmailListMessagesTool: ToolConfig = { + id: 'agentmail_list_messages', + name: 'List Messages', + description: 'List messages in an inbox in AgentMail', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'AgentMail API key', + }, + inboxId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the inbox to list messages from', + }, + limit: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Maximum number of messages to return', + }, + pageToken: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Pagination token for next page of results', + }, + }, + + request: { + url: (params) => { + const query = new URLSearchParams() + if (params.limit) query.set('limit', String(params.limit)) + if (params.pageToken) query.set('page_token', params.pageToken) + const qs = query.toString() + return `https://api.agentmail.to/v0/inboxes/${params.inboxId.trim()}/messages${qs ? `?${qs}` : ''}` + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response): Promise => { + const data = await response.json() + + if (!response.ok) { + return { + success: false, + error: data.message ?? 'Failed to list messages', + output: { messages: [], count: 0, nextPageToken: null }, + } + } + + return { + success: true, + output: { + messages: (data.messages ?? []).map((msg: Record) => ({ + messageId: msg.message_id ?? '', + from: (msg.from as string) ?? null, + to: (msg.to as string[]) ?? [], + subject: (msg.subject as string) ?? null, + preview: (msg.preview as string) ?? null, + createdAt: (msg.created_at as string) ?? '', + })), + count: data.count ?? 0, + nextPageToken: data.next_page_token ?? null, + }, + } + }, + + outputs: { + messages: { + type: 'array', + description: 'List of messages in the inbox', + items: { + type: 'object', + properties: { + messageId: { type: 'string', description: 'Unique identifier for the message' }, + from: { type: 'string', description: 'Sender email address', optional: true }, + to: { type: 'array', description: 'Recipient email addresses' }, + subject: { type: 'string', description: 'Message subject', optional: true }, + preview: { type: 'string', description: 'Message preview text', optional: true }, + createdAt: { type: 'string', description: 'Creation timestamp' }, + }, + }, + }, + count: { type: 'number', description: 'Total number of messages' }, + nextPageToken: { + type: 'string', + description: 'Token for retrieving the next page', + optional: true, + }, + }, +} diff --git a/apps/sim/tools/agentmail/list_threads.ts b/apps/sim/tools/agentmail/list_threads.ts new file mode 100644 index 00000000000..111c2336dba --- /dev/null +++ b/apps/sim/tools/agentmail/list_threads.ts @@ -0,0 +1,135 @@ +import type { ListThreadsParams, ListThreadsResult } from '@/tools/agentmail/types' +import type { ToolConfig } from '@/tools/types' + +export const agentmailListThreadsTool: ToolConfig = { + id: 'agentmail_list_threads', + name: 'List Threads', + description: 'List email threads in AgentMail', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'AgentMail API key', + }, + inboxId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the inbox to list threads from', + }, + limit: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Maximum number of threads to return', + }, + pageToken: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Pagination token for next page of results', + }, + labels: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Comma-separated labels to filter threads by', + }, + before: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Filter threads before this ISO 8601 timestamp', + }, + after: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Filter threads after this ISO 8601 timestamp', + }, + }, + + request: { + url: (params) => { + const query = new URLSearchParams() + if (params.limit) query.set('limit', String(params.limit)) + if (params.pageToken) query.set('page_token', params.pageToken) + if (params.labels) { + for (const label of params.labels.split(',')) { + query.append('labels', label.trim()) + } + } + if (params.before) query.set('before', params.before) + if (params.after) query.set('after', params.after) + const qs = query.toString() + return `https://api.agentmail.to/v0/inboxes/${params.inboxId.trim()}/threads${qs ? `?${qs}` : ''}` + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response): Promise => { + const data = await response.json() + + if (!response.ok) { + return { + success: false, + error: data.message ?? 'Failed to list threads', + output: { threads: [], count: 0, nextPageToken: null }, + } + } + + return { + success: true, + output: { + threads: (data.threads ?? []).map((thread: Record) => ({ + threadId: thread.thread_id ?? '', + subject: (thread.subject as string) ?? null, + senders: (thread.senders as string[]) ?? [], + recipients: (thread.recipients as string[]) ?? [], + messageCount: (thread.message_count as number) ?? 0, + lastMessageAt: (thread.timestamp as string) ?? null, + createdAt: (thread.created_at as string) ?? '', + updatedAt: (thread.updated_at as string) ?? '', + })), + count: data.count ?? 0, + nextPageToken: data.next_page_token ?? null, + }, + } + }, + + outputs: { + threads: { + type: 'array', + description: 'List of email threads', + items: { + type: 'object', + properties: { + threadId: { type: 'string', description: 'Unique identifier for the thread' }, + subject: { type: 'string', description: 'Thread subject', optional: true }, + senders: { type: 'array', description: 'List of sender email addresses' }, + recipients: { type: 'array', description: 'List of recipient email addresses' }, + messageCount: { type: 'number', description: 'Number of messages in the thread' }, + lastMessageAt: { + type: 'string', + description: 'Timestamp of last message', + optional: true, + }, + createdAt: { type: 'string', description: 'Creation timestamp' }, + updatedAt: { type: 'string', description: 'Last updated timestamp' }, + }, + }, + }, + count: { type: 'number', description: 'Total number of threads' }, + nextPageToken: { + type: 'string', + description: 'Token for retrieving the next page', + optional: true, + }, + }, +} diff --git a/apps/sim/tools/agentmail/reply_message.ts b/apps/sim/tools/agentmail/reply_message.ts new file mode 100644 index 00000000000..719daf8faaa --- /dev/null +++ b/apps/sim/tools/agentmail/reply_message.ts @@ -0,0 +1,115 @@ +import type { ReplyMessageParams, ReplyMessageResult } from '@/tools/agentmail/types' +import type { ToolConfig } from '@/tools/types' + +export const agentmailReplyMessageTool: ToolConfig = { + id: 'agentmail_reply_message', + name: 'Reply to Message', + description: 'Reply to an existing email message in AgentMail', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'AgentMail API key', + }, + inboxId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the inbox to reply from', + }, + messageId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the message to reply to', + }, + text: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Plain text reply body', + }, + html: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'HTML reply body', + }, + to: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Override recipient email addresses (comma-separated)', + }, + cc: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'CC email addresses (comma-separated)', + }, + bcc: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'BCC email addresses (comma-separated)', + }, + replyAll: { + type: 'boolean', + required: false, + visibility: 'user-or-llm', + description: 'Reply to all recipients of the original message', + }, + }, + + request: { + url: (params) => { + const endpoint = params.replyAll ? 'reply-all' : 'reply' + return `https://api.agentmail.to/v0/inboxes/${params.inboxId.trim()}/messages/${params.messageId.trim()}/${endpoint}` + }, + method: 'POST', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => { + const body: Record = {} + if (params.text) body.text = params.text + if (params.html) body.html = params.html + // /reply-all endpoint auto-determines recipients; only /reply accepts to/cc/bcc + if (!params.replyAll) { + if (params.to) body.to = params.to.split(',').map((e) => e.trim()) + if (params.cc) body.cc = params.cc.split(',').map((e) => e.trim()) + if (params.bcc) body.bcc = params.bcc.split(',').map((e) => e.trim()) + } + return body + }, + }, + + transformResponse: async (response): Promise => { + const data = await response.json() + + if (!response.ok) { + return { + success: false, + error: data.message ?? 'Failed to reply to message', + output: { messageId: '', threadId: '' }, + } + } + + return { + success: true, + output: { + messageId: data.message_id ?? '', + threadId: data.thread_id ?? '', + }, + } + }, + + outputs: { + messageId: { type: 'string', description: 'ID of the sent reply message' }, + threadId: { type: 'string', description: 'ID of the thread' }, + }, +} diff --git a/apps/sim/tools/agentmail/send_draft.ts b/apps/sim/tools/agentmail/send_draft.ts new file mode 100644 index 00000000000..4352df776b2 --- /dev/null +++ b/apps/sim/tools/agentmail/send_draft.ts @@ -0,0 +1,66 @@ +import type { SendDraftParams, SendDraftResult } from '@/tools/agentmail/types' +import type { ToolConfig } from '@/tools/types' + +export const agentmailSendDraftTool: ToolConfig = { + id: 'agentmail_send_draft', + name: 'Send Draft', + description: 'Send an existing email draft in AgentMail', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'AgentMail API key', + }, + inboxId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the inbox containing the draft', + }, + draftId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the draft to send', + }, + }, + + request: { + url: (params) => + `https://api.agentmail.to/v0/inboxes/${params.inboxId.trim()}/drafts/${params.draftId.trim()}/send`, + method: 'POST', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: () => ({}), + }, + + transformResponse: async (response): Promise => { + const data = await response.json() + + if (!response.ok) { + return { + success: false, + error: data.message ?? 'Failed to send draft', + output: { messageId: '', threadId: '' }, + } + } + + return { + success: true, + output: { + messageId: data.message_id ?? '', + threadId: data.thread_id ?? '', + }, + } + }, + + outputs: { + messageId: { type: 'string', description: 'ID of the sent message' }, + threadId: { type: 'string', description: 'ID of the thread' }, + }, +} diff --git a/apps/sim/tools/agentmail/send_message.ts b/apps/sim/tools/agentmail/send_message.ts new file mode 100644 index 00000000000..94d692e2988 --- /dev/null +++ b/apps/sim/tools/agentmail/send_message.ts @@ -0,0 +1,114 @@ +import type { SendMessageParams, SendMessageResult } from '@/tools/agentmail/types' +import type { ToolConfig } from '@/tools/types' + +export const agentmailSendMessageTool: ToolConfig = { + id: 'agentmail_send_message', + name: 'Send Message', + description: 'Send an email message from an AgentMail inbox', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'AgentMail API key', + }, + inboxId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the inbox to send from', + }, + to: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Recipient email address (comma-separated for multiple)', + }, + subject: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Email subject line', + }, + text: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Plain text email body', + }, + html: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'HTML email body', + }, + cc: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'CC recipient email addresses (comma-separated)', + }, + bcc: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'BCC recipient email addresses (comma-separated)', + }, + }, + + request: { + url: (params) => `https://api.agentmail.to/v0/inboxes/${params.inboxId.trim()}/messages/send`, + method: 'POST', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => { + const body: Record = { + to: params.to.split(',').map((e) => e.trim()), + subject: params.subject, + } + if (params.text) body.text = params.text + if (params.html) body.html = params.html + if (params.cc) body.cc = params.cc.split(',').map((e) => e.trim()) + if (params.bcc) body.bcc = params.bcc.split(',').map((e) => e.trim()) + return body + }, + }, + + transformResponse: async (response, params): Promise => { + const data = await response.json() + + if (!response.ok) { + return { + success: false, + error: data.message ?? 'Failed to send message', + output: { + threadId: '', + messageId: '', + subject: '', + to: '', + }, + } + } + + return { + success: true, + output: { + threadId: data.thread_id ?? '', + messageId: data.message_id ?? '', + subject: params?.subject ?? '', + to: params?.to ?? '', + }, + } + }, + + outputs: { + threadId: { type: 'string', description: 'ID of the created thread' }, + messageId: { type: 'string', description: 'ID of the sent message' }, + subject: { type: 'string', description: 'Email subject line' }, + to: { type: 'string', description: 'Recipient email address' }, + }, +} diff --git a/apps/sim/tools/agentmail/types.ts b/apps/sim/tools/agentmail/types.ts new file mode 100644 index 00000000000..08c62bb1e5c --- /dev/null +++ b/apps/sim/tools/agentmail/types.ts @@ -0,0 +1,447 @@ +import type { ToolResponse } from '@/tools/types' + +/** Create Inbox */ +export interface CreateInboxParams { + apiKey: string + username?: string + domain?: string + displayName?: string +} + +export interface CreateInboxResult extends ToolResponse { + output: { + inboxId: string + email: string + displayName: string | null + createdAt: string + updatedAt: string + } +} + +/** List Inboxes */ +export interface ListInboxesParams { + apiKey: string + limit?: number + pageToken?: string +} + +export interface ListInboxesResult extends ToolResponse { + output: { + inboxes: Array<{ + inboxId: string + email: string + displayName: string | null + createdAt: string + updatedAt: string + }> + count: number + nextPageToken: string | null + } +} + +/** Get Inbox */ +export interface GetInboxParams { + apiKey: string + inboxId: string +} + +export interface GetInboxResult extends ToolResponse { + output: { + inboxId: string + email: string + displayName: string | null + createdAt: string + updatedAt: string + } +} + +/** Update Inbox */ +export interface UpdateInboxParams { + apiKey: string + inboxId: string + displayName: string +} + +export interface UpdateInboxResult extends ToolResponse { + output: { + inboxId: string + email: string + displayName: string | null + createdAt: string + updatedAt: string + } +} + +/** Delete Inbox */ +export interface DeleteInboxParams { + apiKey: string + inboxId: string +} + +export interface DeleteInboxResult extends ToolResponse { + output: { + deleted: boolean + } +} + +/** Send Message (Create Thread) */ +export interface SendMessageParams { + apiKey: string + inboxId: string + to: string + subject: string + text?: string + html?: string + cc?: string + bcc?: string +} + +export interface SendMessageResult extends ToolResponse { + output: { + threadId: string + messageId: string + subject: string + to: string + } +} + +/** Reply to Message */ +export interface ReplyMessageParams { + apiKey: string + inboxId: string + messageId: string + text?: string + html?: string + to?: string + cc?: string + bcc?: string + replyAll?: boolean +} + +export interface ReplyMessageResult extends ToolResponse { + output: { + messageId: string + threadId: string + } +} + +/** Forward Message */ +export interface ForwardMessageParams { + apiKey: string + inboxId: string + messageId: string + to: string + subject?: string + text?: string + html?: string + cc?: string + bcc?: string +} + +export interface ForwardMessageResult extends ToolResponse { + output: { + messageId: string + threadId: string + } +} + +/** Update Message Labels */ +export interface UpdateMessageParams { + apiKey: string + inboxId: string + messageId: string + addLabels?: string + removeLabels?: string +} + +export interface UpdateMessageResult extends ToolResponse { + output: { + messageId: string + labels: string[] + } +} + +/** Create Draft */ +export interface CreateDraftParams { + apiKey: string + inboxId: string + to?: string + subject?: string + text?: string + html?: string + cc?: string + bcc?: string + inReplyTo?: string + sendAt?: string +} + +export interface CreateDraftResult extends ToolResponse { + output: { + draftId: string + inboxId: string + subject: string | null + to: string[] + cc: string[] + bcc: string[] + text: string | null + html: string | null + preview: string | null + labels: string[] + inReplyTo: string | null + sendStatus: string | null + sendAt: string | null + createdAt: string + updatedAt: string + } +} + +/** Update Draft */ +export interface UpdateDraftParams { + apiKey: string + inboxId: string + draftId: string + to?: string + subject?: string + text?: string + html?: string + cc?: string + bcc?: string + sendAt?: string +} + +export interface UpdateDraftResult extends ToolResponse { + output: { + draftId: string + inboxId: string + subject: string | null + to: string[] + cc: string[] + bcc: string[] + text: string | null + html: string | null + preview: string | null + labels: string[] + inReplyTo: string | null + sendStatus: string | null + sendAt: string | null + createdAt: string + updatedAt: string + } +} + +/** Delete Draft */ +export interface DeleteDraftParams { + apiKey: string + inboxId: string + draftId: string +} + +export interface DeleteDraftResult extends ToolResponse { + output: { + deleted: boolean + } +} + +/** Send Draft */ +export interface SendDraftParams { + apiKey: string + inboxId: string + draftId: string +} + +export interface SendDraftResult extends ToolResponse { + output: { + messageId: string + threadId: string + } +} + +/** List Drafts */ +export interface ListDraftsParams { + apiKey: string + inboxId: string + limit?: number + pageToken?: string +} + +export interface ListDraftsResult extends ToolResponse { + output: { + drafts: Array<{ + draftId: string + inboxId: string + subject: string | null + to: string[] + cc: string[] + bcc: string[] + preview: string | null + sendStatus: string | null + sendAt: string | null + createdAt: string + updatedAt: string + }> + count: number + nextPageToken: string | null + } +} + +/** Get Draft */ +export interface GetDraftParams { + apiKey: string + inboxId: string + draftId: string +} + +export interface GetDraftResult extends ToolResponse { + output: { + draftId: string + inboxId: string + subject: string | null + to: string[] + cc: string[] + bcc: string[] + text: string | null + html: string | null + preview: string | null + labels: string[] + inReplyTo: string | null + sendStatus: string | null + sendAt: string | null + createdAt: string + updatedAt: string + } +} + +/** List Threads */ +export interface ListThreadsParams { + apiKey: string + inboxId: string + limit?: number + pageToken?: string + labels?: string + before?: string + after?: string +} + +export interface ListThreadsResult extends ToolResponse { + output: { + threads: Array<{ + threadId: string + subject: string | null + senders: string[] + recipients: string[] + messageCount: number + lastMessageAt: string | null + createdAt: string + updatedAt: string + }> + count: number + nextPageToken: string | null + } +} + +/** Get Thread */ +export interface GetThreadParams { + apiKey: string + inboxId: string + threadId: string +} + +export interface GetThreadResult extends ToolResponse { + output: { + threadId: string + subject: string | null + senders: string[] + recipients: string[] + messageCount: number + labels: string[] + lastMessageAt: string | null + createdAt: string + updatedAt: string + messages: Array<{ + messageId: string + from: string | null + to: string[] + cc: string[] + bcc: string[] + subject: string | null + text: string | null + html: string | null + createdAt: string + }> + } +} + +/** Update Thread Labels */ +export interface UpdateThreadParams { + apiKey: string + inboxId: string + threadId: string + addLabels?: string + removeLabels?: string +} + +export interface UpdateThreadResult extends ToolResponse { + output: { + threadId: string + labels: string[] + } +} + +/** Delete Thread */ +export interface DeleteThreadParams { + apiKey: string + inboxId: string + threadId: string + permanent?: boolean +} + +export interface DeleteThreadResult extends ToolResponse { + output: { + deleted: boolean + } +} + +/** List Messages */ +export interface ListMessagesParams { + apiKey: string + inboxId: string + limit?: number + pageToken?: string +} + +export interface ListMessagesResult extends ToolResponse { + output: { + messages: Array<{ + messageId: string + from: string | null + to: string[] + subject: string | null + preview: string | null + createdAt: string + }> + count: number + nextPageToken: string | null + } +} + +/** Get Message */ +export interface GetMessageParams { + apiKey: string + inboxId: string + messageId: string +} + +export interface GetMessageResult extends ToolResponse { + output: { + messageId: string + threadId: string + from: string | null + to: string[] + cc: string[] + bcc: string[] + subject: string | null + text: string | null + html: string | null + createdAt: string + } +} diff --git a/apps/sim/tools/agentmail/update_draft.ts b/apps/sim/tools/agentmail/update_draft.ts new file mode 100644 index 00000000000..c2d68989954 --- /dev/null +++ b/apps/sim/tools/agentmail/update_draft.ts @@ -0,0 +1,164 @@ +import type { UpdateDraftParams, UpdateDraftResult } from '@/tools/agentmail/types' +import type { ToolConfig } from '@/tools/types' + +export const agentmailUpdateDraftTool: ToolConfig = { + id: 'agentmail_update_draft', + name: 'Update Draft', + description: 'Update an existing email draft in AgentMail', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'AgentMail API key', + }, + inboxId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the inbox containing the draft', + }, + draftId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the draft to update', + }, + to: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Recipient email addresses (comma-separated)', + }, + subject: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Draft subject line', + }, + text: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Plain text draft body', + }, + html: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'HTML draft body', + }, + cc: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'CC recipient email addresses (comma-separated)', + }, + bcc: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'BCC recipient email addresses (comma-separated)', + }, + sendAt: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'ISO 8601 timestamp to schedule sending', + }, + }, + + request: { + url: (params) => + `https://api.agentmail.to/v0/inboxes/${params.inboxId.trim()}/drafts/${params.draftId.trim()}`, + method: 'PATCH', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => { + const body: Record = {} + if (params.to) body.to = params.to.split(',').map((e) => e.trim()) + if (params.subject) body.subject = params.subject + if (params.text) body.text = params.text + if (params.html) body.html = params.html + if (params.cc) body.cc = params.cc.split(',').map((e) => e.trim()) + if (params.bcc) body.bcc = params.bcc.split(',').map((e) => e.trim()) + if (params.sendAt) body.send_at = params.sendAt + return body + }, + }, + + transformResponse: async (response): Promise => { + const data = await response.json() + + if (!response.ok) { + return { + success: false, + error: data.message ?? 'Failed to update draft', + output: { + draftId: '', + inboxId: '', + subject: null, + to: [], + cc: [], + bcc: [], + text: null, + html: null, + preview: null, + labels: [], + inReplyTo: null, + sendStatus: null, + sendAt: null, + createdAt: '', + updatedAt: '', + }, + } + } + + return { + success: true, + output: { + draftId: data.draft_id ?? '', + inboxId: data.inbox_id ?? '', + subject: data.subject ?? null, + to: data.to ?? [], + cc: data.cc ?? [], + bcc: data.bcc ?? [], + text: data.text ?? null, + html: data.html ?? null, + preview: data.preview ?? null, + labels: data.labels ?? [], + inReplyTo: data.in_reply_to ?? null, + sendStatus: data.send_status ?? null, + sendAt: data.send_at ?? null, + createdAt: data.created_at ?? '', + updatedAt: data.updated_at ?? '', + }, + } + }, + + outputs: { + draftId: { type: 'string', description: 'Unique identifier for the draft' }, + inboxId: { type: 'string', description: 'Inbox the draft belongs to' }, + subject: { type: 'string', description: 'Draft subject', optional: true }, + to: { type: 'array', description: 'Recipient email addresses' }, + cc: { type: 'array', description: 'CC email addresses' }, + bcc: { type: 'array', description: 'BCC email addresses' }, + text: { type: 'string', description: 'Plain text content', optional: true }, + html: { type: 'string', description: 'HTML content', optional: true }, + preview: { type: 'string', description: 'Draft preview text', optional: true }, + labels: { type: 'array', description: 'Labels assigned to the draft' }, + inReplyTo: { type: 'string', description: 'Message ID this draft replies to', optional: true }, + sendStatus: { + type: 'string', + description: 'Send status (scheduled, sending, failed)', + optional: true, + }, + sendAt: { type: 'string', description: 'Scheduled send time', optional: true }, + createdAt: { type: 'string', description: 'Creation timestamp' }, + updatedAt: { type: 'string', description: 'Last updated timestamp' }, + }, +} diff --git a/apps/sim/tools/agentmail/update_inbox.ts b/apps/sim/tools/agentmail/update_inbox.ts new file mode 100644 index 00000000000..b05cb180b41 --- /dev/null +++ b/apps/sim/tools/agentmail/update_inbox.ts @@ -0,0 +1,79 @@ +import type { UpdateInboxParams, UpdateInboxResult } from '@/tools/agentmail/types' +import type { ToolConfig } from '@/tools/types' + +export const agentmailUpdateInboxTool: ToolConfig = { + id: 'agentmail_update_inbox', + name: 'Update Inbox', + description: 'Update the display name of an email inbox in AgentMail', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'AgentMail API key', + }, + inboxId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the inbox to update', + }, + displayName: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'New display name for the inbox', + }, + }, + + request: { + url: (params) => `https://api.agentmail.to/v0/inboxes/${params.inboxId.trim()}`, + method: 'PATCH', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => ({ + display_name: params.displayName, + }), + }, + + transformResponse: async (response): Promise => { + const data = await response.json() + + if (!response.ok) { + return { + success: false, + error: data.message ?? 'Failed to update inbox', + output: { + inboxId: '', + email: '', + displayName: null, + createdAt: '', + updatedAt: '', + }, + } + } + + return { + success: true, + output: { + inboxId: data.inbox_id ?? '', + email: data.email ?? '', + displayName: data.display_name ?? null, + createdAt: data.created_at ?? '', + updatedAt: data.updated_at ?? '', + }, + } + }, + + outputs: { + inboxId: { type: 'string', description: 'Unique identifier for the inbox' }, + email: { type: 'string', description: 'Email address of the inbox' }, + displayName: { type: 'string', description: 'Display name of the inbox', optional: true }, + createdAt: { type: 'string', description: 'Creation timestamp' }, + updatedAt: { type: 'string', description: 'Last updated timestamp' }, + }, +} diff --git a/apps/sim/tools/agentmail/update_message.ts b/apps/sim/tools/agentmail/update_message.ts new file mode 100644 index 00000000000..d22c524f799 --- /dev/null +++ b/apps/sim/tools/agentmail/update_message.ts @@ -0,0 +1,87 @@ +import type { UpdateMessageParams, UpdateMessageResult } from '@/tools/agentmail/types' +import type { ToolConfig } from '@/tools/types' + +export const agentmailUpdateMessageTool: ToolConfig = { + id: 'agentmail_update_message', + name: 'Update Message', + description: 'Add or remove labels on an email message in AgentMail', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'AgentMail API key', + }, + inboxId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the inbox containing the message', + }, + messageId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the message to update', + }, + addLabels: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Comma-separated labels to add to the message', + }, + removeLabels: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Comma-separated labels to remove from the message', + }, + }, + + request: { + url: (params) => + `https://api.agentmail.to/v0/inboxes/${params.inboxId.trim()}/messages/${params.messageId.trim()}`, + method: 'PATCH', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => { + const body: Record = {} + if (params.addLabels) { + body.add_labels = params.addLabels.split(',').map((l) => l.trim()) + } + if (params.removeLabels) { + body.remove_labels = params.removeLabels.split(',').map((l) => l.trim()) + } + return body + }, + }, + + transformResponse: async (response): Promise => { + const data = await response.json() + + if (!response.ok) { + return { + success: false, + error: data.message ?? 'Failed to update message', + output: { messageId: '', labels: [] }, + } + } + + return { + success: true, + output: { + messageId: data.message_id ?? '', + labels: data.labels ?? [], + }, + } + }, + + outputs: { + messageId: { type: 'string', description: 'Unique identifier for the message' }, + labels: { type: 'array', description: 'Current labels on the message' }, + }, +} diff --git a/apps/sim/tools/agentmail/update_thread.ts b/apps/sim/tools/agentmail/update_thread.ts new file mode 100644 index 00000000000..1e86139e69f --- /dev/null +++ b/apps/sim/tools/agentmail/update_thread.ts @@ -0,0 +1,85 @@ +import type { UpdateThreadParams, UpdateThreadResult } from '@/tools/agentmail/types' +import type { ToolConfig } from '@/tools/types' + +export const agentmailUpdateThreadTool: ToolConfig = { + id: 'agentmail_update_thread', + name: 'Update Thread Labels', + description: 'Add or remove labels on an email thread in AgentMail', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'AgentMail API key', + }, + inboxId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the inbox containing the thread', + }, + threadId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'ID of the thread to update', + }, + addLabels: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Comma-separated labels to add to the thread', + }, + removeLabels: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Comma-separated labels to remove from the thread', + }, + }, + + request: { + url: (params) => + `https://api.agentmail.to/v0/inboxes/${params.inboxId.trim()}/threads/${params.threadId.trim()}`, + method: 'PATCH', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => ({ + ...(params.addLabels && { + add_labels: params.addLabels.split(',').map((l) => l.trim()), + }), + ...(params.removeLabels && { + remove_labels: params.removeLabels.split(',').map((l) => l.trim()), + }), + }), + }, + + transformResponse: async (response): Promise => { + const data = await response.json() + + if (!response.ok) { + return { + success: false, + error: data.message ?? 'Failed to update thread', + output: { threadId: '', labels: [] }, + } + } + + return { + success: true, + output: { + threadId: data.thread_id ?? '', + labels: data.labels ?? [], + }, + } + }, + + outputs: { + threadId: { type: 'string', description: 'Unique identifier for the thread' }, + labels: { type: 'array', description: 'Current labels on the thread' }, + }, +} diff --git a/apps/sim/tools/registry.ts b/apps/sim/tools/registry.ts index 09da0ce4bf5..aaaa0a88ea7 100644 --- a/apps/sim/tools/registry.ts +++ b/apps/sim/tools/registry.ts @@ -8,6 +8,29 @@ import { a2aSendMessageTool, a2aSetPushNotificationTool, } from '@/tools/a2a' +import { + agentmailCreateDraftTool, + agentmailCreateInboxTool, + agentmailDeleteDraftTool, + agentmailDeleteInboxTool, + agentmailDeleteThreadTool, + agentmailForwardMessageTool, + agentmailGetDraftTool, + agentmailGetInboxTool, + agentmailGetMessageTool, + agentmailGetThreadTool, + agentmailListDraftsTool, + agentmailListInboxesTool, + agentmailListMessagesTool, + agentmailListThreadsTool, + agentmailReplyMessageTool, + agentmailSendDraftTool, + agentmailSendMessageTool, + agentmailUpdateDraftTool, + agentmailUpdateInboxTool, + agentmailUpdateMessageTool, + agentmailUpdateThreadTool, +} from '@/tools/agentmail' import { ahrefsBacklinksStatsTool, ahrefsBacklinksTool, @@ -2664,6 +2687,27 @@ export const tools: Record = { a2a_resubscribe: a2aResubscribeTool, a2a_send_message: a2aSendMessageTool, a2a_set_push_notification: a2aSetPushNotificationTool, + agentmail_create_draft: agentmailCreateDraftTool, + agentmail_create_inbox: agentmailCreateInboxTool, + agentmail_delete_draft: agentmailDeleteDraftTool, + agentmail_delete_inbox: agentmailDeleteInboxTool, + agentmail_delete_thread: agentmailDeleteThreadTool, + agentmail_forward_message: agentmailForwardMessageTool, + agentmail_get_draft: agentmailGetDraftTool, + agentmail_get_inbox: agentmailGetInboxTool, + agentmail_get_message: agentmailGetMessageTool, + agentmail_get_thread: agentmailGetThreadTool, + agentmail_list_drafts: agentmailListDraftsTool, + agentmail_list_inboxes: agentmailListInboxesTool, + agentmail_list_messages: agentmailListMessagesTool, + agentmail_list_threads: agentmailListThreadsTool, + agentmail_reply_message: agentmailReplyMessageTool, + agentmail_send_draft: agentmailSendDraftTool, + agentmail_send_message: agentmailSendMessageTool, + agentmail_update_draft: agentmailUpdateDraftTool, + agentmail_update_inbox: agentmailUpdateInboxTool, + agentmail_update_message: agentmailUpdateMessageTool, + agentmail_update_thread: agentmailUpdateThreadTool, airweave_search: airweaveSearchTool, amplitude_send_event: amplitudeSendEventTool, amplitude_identify_user: amplitudeIdentifyUserTool,