Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions apps/docs/components/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,35 @@ export const S3Icon = (props: SVGProps<SVGSVGElement>) => (
</svg>
)

export function SQSIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg
{...props}
viewBox='0 0 80 80'
version='1.1'
xmlns='http://www.w3.org/2000/svg'
xmlnsXlink='http://www.w3.org/1999/xlink'
>
<g
id='Icon-Architecture/64/Arch_Amazon-Simple-Queue-Service_64'
stroke='none'
strokeWidth='1'
fill='none'
fillRule='evenodd'
transform='translate(40, 40) scale(1.5) translate(-40, -40)'
>
<g id='Icon-Architecture-BG/64/Application-Integration' fill='currentColor'>
<path
d='M28.7169966,43.6876756 L31.7189265,40.721826 C31.9070474,40.5359011 32.0131156,40.2833614 32.0141233,40.019885 C32.0151169,39.7564086 31.9100493,39.5028747 31.722929,39.3159556 L28.7209992,36.3163014 L27.3020871,37.7181948 L28.5899149,39.0057494 L24.0089701,39.0057494 L24.0089701,40.9942506 L28.6059252,40.9942506 L27.3060896,42.2778282 L28.7169966,43.6876756 Z M51.627725,43.7781524 L55.630298,40.793412 C55.8804589,40.6054986 56.0295547,40.3112004 56.0295547,39.9990057 C56.0295547,39.6858168 55.8804589,39.3905244 55.6292974,39.202611 L51.6267243,36.2218476 L50.4259524,37.8126486 L52.0269816,39.0057494 L48.0244085,39.0057494 L48.0244085,40.9942506 L52.025981,40.9942506 L50.4249518,42.1873514 L51.627725,43.7781524 Z M35.2081695,40 C35.2081695,42.1107941 34.8429347,44.1012839 34.160496,45.8332685 C35.9606533,45.14127 37.9909585,44.7952708 40.0192624,44.7952708 C42.0475663,44.7952708 44.0778715,45.14127 45.8770281,45.8332685 C45.19559,44.1012839 44.8303552,42.1107941 44.8303552,40 C44.8303552,37.8892059 45.19559,35.8997104 45.8770281,34.1667315 C42.2777142,35.5497341 37.7608105,35.5497341 34.160496,34.1667315 C34.8429347,35.8997104 35.2081695,37.8892059 35.2081695,40 L35.2081695,40 Z M30.3060182,49.6511909 C30.1108927,49.4573121 30.0128297,49.2027839 30.0128297,48.9482557 C30.0128297,48.6937276 30.1108927,48.4391994 30.3060182,48.2453205 C32.1221857,46.4407556 33.206883,43.3575844 33.206883,40 C33.206883,36.6424156 32.1221857,33.5592444 30.3060182,31.7546795 C30.1108927,31.5608006 30.0128297,31.3062724 30.0128297,31.0517443 C30.0128297,30.7972161 30.1108927,30.5426879 30.3060182,30.3488091 C30.6972697,29.9600571 31.3296762,29.9600571 31.7209277,30.3488091 C35.5984204,34.2015303 44.4401044,34.2015303 48.317597,30.3488091 C48.7088485,29.9600571 49.3412551,29.9600571 49.7325066,30.3488091 C49.927632,30.5426879 50.0256951,30.7972161 50.0256951,31.0517443 C50.0256951,31.3062724 49.927632,31.5608006 49.7325066,31.7546795 C47.9163391,33.5592444 46.8316418,36.6424156 46.8316418,40 C46.8316418,43.3575844 47.9163391,46.4407556 49.7325066,48.2453205 C49.927632,48.4391994 50.0256951,48.6937276 50.0256951,48.9482557 C50.0256951,49.2027839 49.927632,49.4573121 49.7325066,49.6511909 C49.5373812,49.8450698 49.2812165,49.9425064 49.0250518,49.9425064 C48.7688871,49.9425064 48.5127225,49.8450698 48.317597,49.6511909 C44.4401044,45.7984697 35.5984204,45.7984697 31.7209277,49.6511909 C31.3296762,50.0399429 30.6972697,50.0399429 30.3060182,49.6511909 L30.3060182,49.6511909 Z M66.0009649,40.0049713 C66.0009649,39.0783297 65.6377314,38.2073661 64.9783075,37.5521549 C64.2978701,36.8750702 63.403295,36.5380193 62.5097205,36.5380193 C61.6161461,36.5380193 60.721571,36.8750702 60.0411336,37.5521549 C58.6792581,38.9043358 58.6792581,41.1046125 60.0411336,42.4577876 C61.4020084,43.8099684 63.6154313,43.8109627 64.9783075,42.4577876 C65.6377314,41.8025764 66.0009649,40.9316128 66.0009649,40.0049713 L66.0009649,40.0049713 Z M66.3932171,43.863658 C65.3225288,44.9275062 63.916625,45.4594303 62.5097205,45.4594303 C61.1028161,45.4594303 59.6969123,44.9275062 58.626224,43.863658 C56.4838468,41.7359616 56.4838468,38.2739809 58.626224,36.1462845 C60.7686012,34.0165997 64.2528411,34.0185882 66.3932171,36.1462845 C68.5355943,38.2739809 68.5355943,41.7359616 66.3932171,43.863658 L66.3932171,43.863658 Z M20.9800229,40.027839 C20.9800229,39.1011974 20.6167894,38.2302339 19.9573654,37.5750227 C19.2979415,36.9198115 18.421378,36.5588985 17.4887785,36.5588985 C16.5571796,36.5588985 15.6806161,36.9198115 15.0201916,37.5750227 C14.3607676,38.2302339 13.9985348,39.1011974 13.9985348,40.027839 C13.9985348,40.9534864 14.3607676,41.8244499 15.0201916,42.4806553 C16.34004,43.7900834 18.6385176,43.7900834 19.9573654,42.4806553 C20.6167894,41.8244499 20.9800229,40.9534864 20.9800229,40.027839 L20.9800229,40.027839 Z M21.372275,43.8865257 C20.3015867,44.9503739 18.8956829,45.482298 17.4887785,45.482298 C16.0828747,45.482298 14.6769709,44.9503739 13.605282,43.8865257 C11.464906,41.7588294 11.464906,38.2968487 13.605282,36.1691523 C15.7476592,34.0414559 19.2308984,34.0414559 21.372275,36.1691523 C23.5136516,38.2968487 23.5136516,41.7588294 21.372275,43.8865257 L21.372275,43.8865257 Z M54.8958259,54.856093 C50.901258,58.8261358 45.5888428,61.0114987 39.9392109,61.0114987 C34.2875777,61.0114987 28.9761632,58.8261358 24.9815953,54.856093 C22.241834,52.134829 20.7338646,48.8826352 19.9513616,46.6346345 L18.0601458,47.2848744 C18.9116932,49.730731 20.5577514,53.273246 23.5666857,56.2619634 C27.9394968,60.607833 33.7532342,63 39.9392109,63 C46.124187,63 51.9379244,60.607833 56.3107355,56.2619634 C58.8373597,53.7534691 60.8496533,50.563913 61.9793796,47.2818917 L60.0861625,46.6376173 C59.0534987,49.6382657 57.2103138,52.5573856 54.8958259,54.856093 L54.8958259,54.856093 Z M19.9503609,33.3663597 L18.0611465,32.7141313 C19.2719248,29.2501621 21.229183,26.0606061 23.5726896,23.7330653 C27.9434994,19.3911728 33.7552355,17 39.9392109,17 C46.1231863,17 51.9349225,19.3911728 56.3047316,23.7330653 C58.7713173,26.1838931 60.8396469,29.4569662 61.9773783,32.7141313 L60.0881638,33.3663597 C59.0444929,30.3836078 57.1502752,27.3849479 54.889822,25.1389357 C50.898256,21.1718757 45.5878422,18.9885013 39.9392109,18.9885013 C34.289579,18.9885013 28.9801658,21.1718757 24.9875992,25.1389357 C22.8542277,27.2596723 21.0650775,30.181775 19.9503609,33.3663597 L19.9503609,33.3663597 Z'
id='AWS-Simple-Queue-Service_Icon_64_Squid'
fill='currentColor'
/>
</g>
</g>
</svg>
)
}

export function GoogleIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg {...props} xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48' width='24' height='24'>
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/components/ui/icon-mapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ import {
ShopifyIcon,
SlackIcon,
SmtpIcon,
SQSIcon,
SshIcon,
STTIcon,
StagehandIcon,
Expand Down Expand Up @@ -215,6 +216,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
elevenlabs: ElevenLabsIcon,
elasticsearch: ElasticsearchIcon,
dynamodb: DynamoDBIcon,
sqs: SQSIcon,
duckduckgo: DuckDuckGoIcon,
dropbox: DropboxIcon,
discord: DiscordIcon,
Expand Down
1 change: 1 addition & 0 deletions apps/docs/content/docs/en/tools/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
"shopify",
"slack",
"smtp",
"sqs",
"ssh",
"stagehand",
"stagehand_agent",
Expand Down
63 changes: 63 additions & 0 deletions apps/docs/content/docs/en/tools/sqs.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
title: Amazon SQS
description: Connect to Amazon SQS
---

import { BlockInfoCard } from "@/components/ui/block-info-card";

<BlockInfoCard
type="sqs"
color="linear-gradient(45deg, #2E27AD 0%, #527FFF 100%)"
/>

{/* MANUAL-CONTENT-START:intro */}
[Amazon Simple Queue Service (SQS)](https://aws.amazon.com/sqs/) is a fully managed message queuing service that enables you to decouple and scale microservices, distributed systems, and serverless applications. SQS eliminates the complexity and overhead associated with managing and operating message-oriented middleware, and empowers developers to focus on differentiating work.

With Amazon SQS, you can:

- **Send messages**: Publish messages to queues for asynchronous processing
- **Decouple applications**: Enable loose coupling between components of your system
- **Scale workloads**: Handle variable workloads without provisioning infrastructure
- **Ensure reliability**: Built-in redundancy and high availability
- **Support FIFO queues**: Maintain strict message ordering and exactly-once processing

In Sim, the SQS integration enables your agents to send messages to Amazon SQS queues securely and programmatically. Supported operations include:

- **Send Message**: Send messages to SQS queues with optional message group ID and deduplication ID for FIFO queues

This integration allows your agents to automate message sending workflows without manual intervention. By connecting Sim with Amazon SQS, you can build agents that publish messages to queues within your workflows—all without handling queue infrastructure or connections.
{/* MANUAL-CONTENT-END */}

## Usage Instructions

Integrate Amazon SQS into the workflow. Can send messages to SQS queues.

## Tools

### `sqs_send`

Send a message to an Amazon SQS queue

#### Input

| Parameter | Type | Required | Description |
| ------------------------ | ------ | -------- | ----------------------------------------------------------------------------- |
| `region` | string | Yes | AWS region \(e.g., us-east-1\) |
| `accessKeyId` | string | Yes | AWS access key ID |
| `secretAccessKey` | string | Yes | AWS secret access key |
| `queueUrl` | string | Yes | Queue URL \(e.g., https://sqs.us-east-1.amazonaws.com/123456789012/my-queue\) |
| `data` | object | Yes | Message body to send as JSON object |
| `messageGroupId` | string | No | Message group ID \(optional\) |
| `messageDeduplicationId` | string | No | Message deduplication ID for FIFO queues \(optional\) |

#### Output

| Parameter | Type | Description |
| --------- | ------ | --------------------------------------------------------- |
| `message` | string | Success or error message describing the operation outcome |
| `id` | string | Message ID |

## Notes

- Category: `tools`
- Type: `sqs`
70 changes: 70 additions & 0 deletions apps/sim/app/api/tools/sqs/send/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { randomUUID } from 'crypto'
import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'
import { createLogger } from '@/lib/logs/console/logger'
import { createSqsClient, sendMessage } from '../utils'

const logger = createLogger('SQSSendMessageAPI')

const SendMessageSchema = z.object({
region: z.string().min(1, 'AWS region is required'),
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
queueUrl: z.string().min(1, 'Queue URL is required'),
messageGroupId: z.string().nullish(),
messageDeduplicationId: z.string().nullish(),
data: z.record(z.unknown()).refine((obj) => Object.keys(obj).length > 0, {
message: 'Data object must have at least one field',
}),
})

export async function POST(request: NextRequest) {
const requestId = randomUUID().slice(0, 8)

try {
const body = await request.json()
const params = SendMessageSchema.parse(body)

logger.info(`[${requestId}] Sending message to SQS queue ${params.queueUrl}`)

const client = createSqsClient({
region: params.region,
accessKeyId: params.accessKeyId,
secretAccessKey: params.secretAccessKey,
})

try {
const result = await sendMessage(
client,
params.queueUrl,
params.data,
params.messageGroupId,
params.messageDeduplicationId
)

logger.info(`[${requestId}] Message sent to SQS queue ${params.queueUrl}`)

return NextResponse.json({
message: `Message sent to SQS queue ${params.queueUrl}`,
id: result?.id,
})
} finally {
client.destroy()
}
} catch (error) {
if (error instanceof z.ZodError) {
logger.warn(`[${requestId}] Invalid request data`, {
errors: error.errors,
})
return NextResponse.json(
{ error: 'Invalid request data', details: error.errors },
{ status: 400 }
)
}

const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'
logger.error(`[${requestId}] SQS send message failed:`, error)

return NextResponse.json({ error: `SQS send message failed: ${errorMessage}` }, { status: 500 })
}
}
40 changes: 40 additions & 0 deletions apps/sim/app/api/tools/sqs/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { SendMessageCommand, type SendMessageCommandOutput, SQSClient } from '@aws-sdk/client-sqs'
import type { SqsConnectionConfig } from '@/tools/sqs/types'

export function createSqsClient(config: SqsConnectionConfig): SQSClient {
return new SQSClient({
region: config.region,
credentials: {
accessKeyId: config.accessKeyId,
secretAccessKey: config.secretAccessKey,
},
})
}

export async function sendMessage(
client: SQSClient,
queueUrl: string,
data: Record<string, unknown>,
messageGroupId?: string | null,
messageDeduplicationId?: string | null
): Promise<Record<string, unknown> | null> {
const command = new SendMessageCommand({
QueueUrl: queueUrl,
MessageBody: JSON.stringify(data),
MessageGroupId: messageGroupId ?? undefined,
...(messageDeduplicationId ? { MessageDeduplicationId: messageDeduplicationId } : {}),
})

const response = await client.send(command)
return parseSendMessageResponse(response)
}

function parseSendMessageResponse(
response: SendMessageCommandOutput
): Record<string, unknown> | null {
if (!response) {
return null
}

return { id: response.MessageId }
}
155 changes: 155 additions & 0 deletions apps/sim/blocks/blocks/sqs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import { SQSIcon } from '@/components/icons'
import type { BlockConfig } from '@/blocks/types'
import type { SqsResponse } from '@/tools/sqs/types'

export const SQSBlock: BlockConfig<SqsResponse> = {
type: 'sqs',
name: 'Amazon SQS',
description: 'Connect to Amazon SQS',
longDescription: 'Integrate Amazon SQS into the workflow. Can send messages to SQS queues.',
docsLink: 'https://docs.sim.ai/tools/sqs',
category: 'tools',
bgColor: 'linear-gradient(45deg, #2E27AD 0%, #527FFF 100%)',
icon: SQSIcon,
subBlocks: [
{
id: 'operation',
title: 'Operation',
type: 'dropdown',
options: [{ label: 'Send Message', id: 'send' }],
value: () => 'send',
},
{
id: 'region',
title: 'AWS Region',
type: 'short-input',
placeholder: 'us-east-1',
required: true,
},
{
id: 'accessKeyId',
title: 'AWS Access Key ID',
type: 'short-input',
placeholder: 'AKIA...',
password: true,
required: true,
},
{
id: 'secretAccessKey',
title: 'AWS Secret Access Key',
type: 'short-input',
placeholder: 'Your secret access key',
password: true,
required: true,
},
{
id: 'queueUrl',
title: 'Queue URL',
type: 'short-input',
placeholder: 'https://sqs.us-east-1.amazonaws.com/123456789012/my-queue',
required: true,
},
// Data field for send message operation
{
id: 'messageGroupId',
title: 'Message Group ID (optional)',
type: 'short-input',
placeholder: '5FAB0F0B-30C6-4427-9407-5634F4A3984A',
condition: { field: 'operation', value: 'send' },
required: false,
},
{
id: 'messageDeduplicationId',
title: 'Message Deduplication ID (optional)',
type: 'short-input',
placeholder: '5FAB0F0B-30C6-4427-9407-5634F4A3984A',
condition: { field: 'operation', value: 'send' },
required: false,
},
{
id: 'data',
title: 'Data (JSON)',
type: 'code',
placeholder: '{\n "name": "John Doe",\n "email": "john@example.com",\n "active": true\n}',
condition: { field: 'operation', value: 'send' },
required: true,
},
],
tools: {
access: ['sqs_send'],
config: {
tool: (params) => {
switch (params.operation) {
case 'send':
return 'sqs_send'
default:
throw new Error(`Invalid SQS operation: ${params.operation}`)
}
},
params: (params) => {
const { operation, data, messageGroupId, messageDeduplicationId, ...rest } = params

// Parse JSON fields
const parseJson = (value: unknown, fieldName: string) => {
if (!value) return undefined
if (typeof value === 'object') return value
if (typeof value === 'string' && value.trim()) {
try {
return JSON.parse(value)
} catch (parseError) {
const errorMsg =
parseError instanceof Error ? parseError.message : 'Unknown JSON error'
throw new Error(`Invalid JSON in ${fieldName}: ${errorMsg}`)
}
}
return undefined
}

const parsedData = parseJson(data, 'data')

// Build connection config
const connectionConfig = {
region: rest.region,
accessKeyId: rest.accessKeyId,
secretAccessKey: rest.secretAccessKey,
}

// Build params object
const result: Record<string, unknown> = { ...connectionConfig }

if (rest.queueUrl) result.queueUrl = rest.queueUrl
if (messageGroupId) result.messageGroupId = messageGroupId
if (messageDeduplicationId) result.messageDeduplicationId = messageDeduplicationId
if (parsedData !== undefined) result.data = parsedData

return result
},
},
},
inputs: {
operation: { type: 'string', description: 'SQS operation to perform' },
region: { type: 'string', description: 'AWS region' },
accessKeyId: { type: 'string', description: 'AWS access key ID' },
secretAccessKey: { type: 'string', description: 'AWS secret access key' },
queueUrl: { type: 'string', description: 'SQS queue URL' },
messageGroupId: {
type: 'string',
description: 'Message group ID (optional)',
},
messageDeduplicationId: {
type: 'string',
description: 'Message deduplication ID (optional)',
},
data: { type: 'json', description: 'Data for send message operation' },
},
outputs: {
message: {
type: 'string',
description: 'Success or error message describing the operation outcome',
},
id: {
type: 'string',
description: 'Message ID',
},
},
}
Loading