diff --git a/docs/content/docs/tools/clay.mdx b/docs/content/docs/tools/clay.mdx new file mode 100644 index 000000000..8af82db83 --- /dev/null +++ b/docs/content/docs/tools/clay.mdx @@ -0,0 +1,246 @@ +--- +title: Clay +description: Populate Clay with data +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + + + + `} +/> + +{/* MANUAL-CONTENT-START:intro */} +[Clay](https://www.clay.com/) is a data enrichment and workflow automation platform that helps teams streamline lead generation, research, and data operations through powerful integrations and flexible inputs. + + + +With Clay, you can: + +- **Enrich agent outputs**: Automatically feed your Sim Studio agent data into Clay tables for structured tracking and analysis +- **Trigger workflows via webhooks**: Use Clay’s webhook support to initiate Sim Studio agent tasks from within Clay +- **Leverage data loops**: Seamlessly iterate over enriched data rows with agents that operate across dynamic datasets + +In Sim Studio, the Clay integration allows your agents to push structured data into Clay tables via webhooks. This makes it easy to collect, enrich, and manage dynamic outputs such as leads, research summaries, or action items—all in a collaborative, spreadsheet-like interface. Your agents can populate rows in real time, enabling asynchronous workflows where AI-generated insights are captured, reviewed, and used by your team. Whether you're automating research, enriching CRM data, or tracking operational outcomes, Clay becomes a living data layer that interacts intelligently with your agents. By connecting Sim Studio with Clay, you gain a powerful way to operationalize agent results, loop over datasets with precision, and maintain a clean, auditable record of AI-driven work. +{/* MANUAL-CONTENT-END */} + + +## Usage Instructions + +Populate Clay with data from a JSON file. Enables direct communication and notifications with timestamp tracking and channel confirmation. + + +## Tools + +### `clay_populate` + +Populate Clay with data from a JSON file. Enables direct communication and notifications with timestamp tracking and channel confirmation. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `webhookId` | string | Yes | The webhook ID to populate | +| `data` | json | Yes | The data to populate | +| `authToken` | string | No | Optional auth token for WebhookURL | + +#### Output + +| Parameter | Type | +| --------- | ---- | +| `data` | string | + + + +## Block Configuration + +### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | No | Auth Token - Enter your Clay Auth token | + + + +### Outputs + +| Output | Type | Description | +| ------ | ---- | ----------- | +| `response` | object | Output from response | +| ↳ `data` | any | data of the response | + + +## Notes + +- Category: `tools` +- Type: `clay` diff --git a/docs/content/docs/tools/meta.json b/docs/content/docs/tools/meta.json index 14abdd6a1..06c72df2b 100644 --- a/docs/content/docs/tools/meta.json +++ b/docs/content/docs/tools/meta.json @@ -4,6 +4,7 @@ "airtable", "autoblocks", "browser_use", + "clay", "confluence", "dropdown", "elevenlabs", diff --git a/sim/blocks/blocks/clay.ts b/sim/blocks/blocks/clay.ts new file mode 100644 index 000000000..041ae4fa7 --- /dev/null +++ b/sim/blocks/blocks/clay.ts @@ -0,0 +1,58 @@ +import { ClayIcon } from '@/components/icons' +import { ClayPopulateResponse } from '@/tools/clay/types' +import { BlockConfig } from '../types' + +export const ClayBlock: BlockConfig = { + type: 'clay', + name: 'Clay', + description: 'Populate Clay workbook with data', + longDescription: + 'Populate Clay workbook with data using a JSON or plain text. Enables direct communication and notifications with channel confirmation.', + category: 'tools', + bgColor: '#E0E0E0', + icon: ClayIcon, + subBlocks: [ + { + id: 'webhookURL', + title: 'Webhook URL', + type: 'short-input', + layout: 'full', + placeholder: 'Enter Clay webhook URL', + }, + { + id: 'data', + title: 'Data (JSON or Plain Text)', + type: 'long-input', + layout: 'full', + placeholder: 'Enter your JSON data to populate your Clay table', + description: `JSON vs. Plain Text: +JSON: Best for populating multiple columns. +Plain Text: Best for populating a table in free-form style. + `, + }, + { + id: 'authToken', + title: 'Auth Token', + type: 'short-input', + layout: 'full', + placeholder: 'Enter your Clay Auth token', + password: true, + connectionDroppable: false, + }, + ], + tools: { + access: ['clay_populate'], + }, + inputs: { + authToken: { type: 'string', required: true }, + webhookURL: { type: 'string', required: true }, + data: { type: 'json', required: true }, + }, + outputs: { + response: { + type: { + data: 'any', + }, + }, + }, +} diff --git a/sim/blocks/index.ts b/sim/blocks/index.ts index 629f80c3b..3901f0f31 100644 --- a/sim/blocks/index.ts +++ b/sim/blocks/index.ts @@ -49,6 +49,7 @@ import { BlockConfig } from './types' import { Mem0Block } from './blocks/mem0' import { S3Block } from './blocks/s3' import { TelegramBlock } from './blocks/telegram' +import { ClayBlock } from './blocks/clay' // Export blocks for ease of use export { @@ -101,6 +102,7 @@ export { StagehandAgentBlock, S3Block, TelegramBlock, + ClayBlock, } // Registry of all block configurations, alphabetically sorted @@ -154,6 +156,7 @@ const blocks: Record = { x: XBlock, youtube: YouTubeBlock, telegram: TelegramBlock, + clay: ClayBlock, } // Helper functions diff --git a/sim/components/icons.tsx b/sim/components/icons.tsx index bafafd95f..580b39ccf 100644 --- a/sim/components/icons.tsx +++ b/sim/components/icons.tsx @@ -2218,4 +2218,171 @@ export function TelegramIcon(props: SVGProps) { ) -} \ No newline at end of file +} + +export function ClayIcon(props: SVGProps) { + return ( + + + + + + ) +} + diff --git a/sim/tools/clay/index.ts b/sim/tools/clay/index.ts new file mode 100644 index 000000000..301792027 --- /dev/null +++ b/sim/tools/clay/index.ts @@ -0,0 +1,3 @@ +import { clayPopulateTool } from './populate' + +export { clayPopulateTool } \ No newline at end of file diff --git a/sim/tools/clay/populate.ts b/sim/tools/clay/populate.ts new file mode 100644 index 000000000..f24e8cc93 --- /dev/null +++ b/sim/tools/clay/populate.ts @@ -0,0 +1,72 @@ +import { ToolConfig } from '../types' +import { ClayPopulateParams, ClayPopulateResponse } from './types' + +export const clayPopulateTool: ToolConfig = { + id: 'clay_populate', + name: 'Clay Populate', + description: + 'Populate Clay with data from a JSON file. Enables direct communication and notifications with timestamp tracking and channel confirmation.', + version: '1.0.0', + + params: { + webhookURL: { + type: 'string', + required: true, + requiredForToolCall: true, + description: 'The webhook URL to populate', + }, + data: { + type: 'json', + required: true, + description: 'The data to populate', + optionalToolInput: true, + }, + authToken: { + type: 'string', + required: false, + description: 'Optional auth token for WebhookURL', + }, + }, + + request: { + url: (params: ClayPopulateParams) => params.webhookURL, + method: 'POST', + headers: (params: ClayPopulateParams) => ({ + 'Content-Type': 'application/json', + Authorization: `Bearer ${params.authToken}`, + }), + body: (params: ClayPopulateParams) => ({ + data: params.data, + }), + }, + + transformResponse: async (response: Response) => { + const contentType = response.headers.get('content-type') + let data + + if (contentType?.includes('application/json')) { + data = await response.json() + if (!data.ok) { + throw new Error(data.error || 'Clay API error') + } + } else { + // Handle text response + data = await response.text() + if (data !== 'OK' && !response.ok) { + throw new Error(data || 'Clay API error') + } + } + + return { + success: true, + output: { + data: contentType?.includes('application/json') ? data : { message: data }, + }, + } + }, + + transformError: (error: any) => { + const message = error.message || 'Clay populate failed' + return message + }, +} diff --git a/sim/tools/clay/types.ts b/sim/tools/clay/types.ts new file mode 100644 index 000000000..e107ea7ba --- /dev/null +++ b/sim/tools/clay/types.ts @@ -0,0 +1,13 @@ +import { ToolResponse } from "../types" + +export interface ClayPopulateParams { + webhookURL: string + data: JSON + authToken?: string +} + +export interface ClayPopulateResponse extends ToolResponse { + output: { + data: any + } +} \ No newline at end of file diff --git a/sim/tools/registry.ts b/sim/tools/registry.ts index 7ad39a63e..4b572ff60 100644 --- a/sim/tools/registry.ts +++ b/sim/tools/registry.ts @@ -42,6 +42,7 @@ import { ToolConfig } from './types' import { s3GetObjectTool } from './s3' import { jiraRetrieveTool, jiraUpdateTool, jiraWriteTool, jiraBulkRetrieveTool } from './jira' import { telegramMessageTool } from './telegram' +import { clayPopulateTool } from './clay' // Registry of all available tools export const tools: Record = { @@ -128,4 +129,5 @@ export const tools: Record = { elevenlabs_tts: elevenLabsTtsTool, s3_get_object: s3GetObjectTool, telegram_message: telegramMessageTool, + clay_populate: clayPopulateTool, } \ No newline at end of file