diff --git a/apps/docs/content/docs/en/tools/enrichment.mdx b/apps/docs/content/docs/en/tools/enrichment.mdx
new file mode 100644
index 0000000000..06975f05a0
--- /dev/null
+++ b/apps/docs/content/docs/en/tools/enrichment.mdx
@@ -0,0 +1,48 @@
+---
+title: Enrichment
+description: Enrich data with a Sim enrichment
+---
+
+import { BlockInfoCard } from "@/components/ui/block-info-card"
+
+
+
+## Usage Instructions
+
+Run a Sim enrichment to look up data — work email, phone number, company domain, company info, and more — from the fields you map in. Uses the same provider cascade as table enrichments.
+
+
+
+## Tools
+
+### `enrichment_run`
+
+Run a Sim enrichment (e.g. Work Email, Phone Number) and return its outputs
+
+#### Input
+
+| Parameter | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `enrichmentId` | string | Yes | Registry enrichment id \(e.g. "work-email"\) |
+| `inputs` | json | Yes | Map of the enrichment's input ids to values |
+
+#### Output
+
+The exact fields depend on which enrichment ran. `matched` and `provider` are always present.
+
+| Parameter | Type | Description |
+| --------- | ---- | ----------- |
+| `matched` | boolean | Whether the enrichment found a result |
+| `provider` | string | Provider whose result was returned (e.g. "Hunter", "People Data Labs"); `null` on no match |
+| `email` | string | Work email address (Work Email enrichment) |
+| `phone` | string | Phone number (Phone Number enrichment) |
+| `domain` | string | Website domain (Company Domain enrichment) |
+| `industry` | string | Industry (Company Info enrichment) |
+| `employeeCount` | number | Employee count (Company Info enrichment) |
+| `foundedYear` | number | Founded year (Company Info enrichment) |
+| `description` | string | Company description (Company Info enrichment) |
+
+
diff --git a/apps/docs/content/docs/en/tools/meta.json b/apps/docs/content/docs/en/tools/meta.json
index 83bad8df3b..dbc2ef5b7f 100644
--- a/apps/docs/content/docs/en/tools/meta.json
+++ b/apps/docs/content/docs/en/tools/meta.json
@@ -49,6 +49,7 @@
"elevenlabs",
"emailbison",
"enrich",
+ "enrichment",
"evernote",
"exa",
"extend",
diff --git a/apps/sim/app/api/tools/enrichment/run/route.ts b/apps/sim/app/api/tools/enrichment/run/route.ts
new file mode 100644
index 0000000000..586dc7f735
--- /dev/null
+++ b/apps/sim/app/api/tools/enrichment/run/route.ts
@@ -0,0 +1,66 @@
+import { createLogger } from '@sim/logger'
+import type { NextRequest } from 'next/server'
+import { NextResponse } from 'next/server'
+import { runEnrichmentContract } from '@/lib/api/contracts/tools/enrichment'
+import { getValidationErrorMessage, parseRequest } from '@/lib/api/server'
+import { checkInternalAuth } from '@/lib/auth/hybrid'
+import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
+import { getEnrichment } from '@/enrichments/registry'
+import { runEnrichment } from '@/enrichments/run'
+
+const logger = createLogger('EnrichmentRunAPI')
+
+/**
+ * POST /api/tools/enrichment/run
+ *
+ * Runs a registry enrichment's provider cascade and returns its outputs. Backs
+ * the Enrichment workflow block; called server-to-server by the executor, so it
+ * authenticates with the internal token. The cascade injects the workspace's
+ * BYOK / hosted key via `executeTool` using `workspaceId`.
+ */
+export const POST = withRouteHandler(async (request: NextRequest) => {
+ const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
+ if (!authResult.success) {
+ return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
+ }
+
+ const parsed = await parseRequest(
+ runEnrichmentContract,
+ request,
+ {},
+ {
+ validationErrorResponse: (error) =>
+ NextResponse.json(
+ { error: getValidationErrorMessage(error, 'Invalid request') },
+ {
+ status: 400,
+ }
+ ),
+ }
+ )
+ if (!parsed.success) return parsed.response
+
+ const { enrichmentId, inputs, workspaceId } = parsed.data.body
+ const enrichment = getEnrichment(enrichmentId)
+ if (!enrichment) {
+ return NextResponse.json({ error: `Unknown enrichment "${enrichmentId}"` }, { status: 400 })
+ }
+
+ const { result, cost, error, provider } = await runEnrichment(enrichment, inputs, {
+ workspaceId,
+ signal: request.signal,
+ })
+
+ logger.info('Enrichment block run', {
+ enrichmentId,
+ matched: Object.keys(result).length > 0,
+ provider,
+ })
+ return NextResponse.json({
+ matched: Object.keys(result).length > 0,
+ result,
+ cost,
+ error,
+ provider,
+ })
+})
diff --git a/apps/sim/blocks/blocks/enrichment.ts b/apps/sim/blocks/blocks/enrichment.ts
new file mode 100644
index 0000000000..12c700bc6b
--- /dev/null
+++ b/apps/sim/blocks/blocks/enrichment.ts
@@ -0,0 +1,117 @@
+import { EnrichmentIcon } from '@/components/icons'
+import type { BlockConfig, OutputFieldDefinition, ParamType } from '@/blocks/types'
+import { IntegrationType } from '@/blocks/types'
+import { ALL_ENRICHMENTS, getEnrichment } from '@/enrichments'
+import { mapFieldType } from '@/enrichments/providers'
+import type { EnrichmentOutputField } from '@/enrichments/types'
+import type { EnrichmentRunResponse } from '@/tools/enrichment/types'
+
+/** Stable subBlock id for an enrichment input (unique across enrichments). */
+const inputFieldId = (enrichmentId: string, inputId: string) => `${enrichmentId}__${inputId}`
+
+// One input field per (enrichment, input), shown only for its enrichment.
+const inputSubBlocks = ALL_ENRICHMENTS.flatMap((enrichment) =>
+ enrichment.inputs.map((input) => ({
+ id: inputFieldId(enrichment.id, input.id),
+ title: input.name,
+ type: 'short-input' as const,
+ placeholder: input.description ?? `Enter ${input.name.toLowerCase()}`,
+ condition: { field: 'operation', value: enrichment.id },
+ required: input.required ? ({ field: 'operation', value: enrichment.id } as const) : undefined,
+ }))
+)
+
+// Block input schema: the operation plus every per-enrichment input field.
+const blockInputs: Record = {
+ operation: { type: 'string', description: 'Enrichment to run' },
+}
+for (const enrichment of ALL_ENRICHMENTS) {
+ for (const input of enrichment.inputs) {
+ blockInputs[inputFieldId(enrichment.id, input.id)] = {
+ type: mapFieldType(input.type),
+ description: `${input.name} (for ${enrichment.name})`,
+ }
+ }
+}
+
+// Union of all enrichment outputs, each shown only for the enrichment(s) that
+// produce it.
+const outputProducers = new Map()
+for (const enrichment of ALL_ENRICHMENTS) {
+ for (const output of enrichment.outputs) {
+ const entry = outputProducers.get(output.id) ?? { field: output, operations: [] }
+ entry.operations.push(enrichment.id)
+ outputProducers.set(output.id, entry)
+ }
+}
+// Seed the enrichment outputs first so the reserved `matched` / `provider`
+// keys (assigned below) always win if a future enrichment ever declares an
+// output id that collides with them.
+const blockOutputs: Record = {}
+for (const [id, { field, operations }] of outputProducers) {
+ blockOutputs[id] = {
+ type: mapFieldType(field.type),
+ description: field.name,
+ condition: { field: 'operation', value: operations },
+ }
+}
+blockOutputs.matched = {
+ type: 'boolean',
+ description: 'Whether the enrichment found a result',
+}
+blockOutputs.provider = {
+ type: 'string',
+ description: 'Provider whose result was returned (e.g. "Hunter", "People Data Labs")',
+}
+
+/**
+ * Enrichment block — runs a code-defined Sim enrichment (Work Email, Phone
+ * Number, Company Domain, Company Info, …) and returns its outputs. Generated
+ * from the enrichment registry, so new enrichments appear automatically. Runs
+ * on the workspace's hosted / BYOK key (injected server-side); no credential.
+ */
+export const EnrichmentBlock: BlockConfig = {
+ type: 'enrichment',
+ name: 'Data Enrichment',
+ description: 'Enrich data with a Sim enrichment',
+ longDescription:
+ 'Run a Sim enrichment to look up data — work email, phone number, company domain, company info, and more — from the fields you map in. Uses the same provider cascade as table enrichments.',
+ docsLink: 'https://docs.sim.ai/tools/enrichment',
+ category: 'tools',
+ integrationType: IntegrationType.Sales,
+ tags: ['enrichment'],
+ bgColor: '#9333EA',
+ icon: EnrichmentIcon,
+
+ subBlocks: [
+ {
+ id: 'operation',
+ title: 'Enrichment',
+ type: 'dropdown',
+ options: ALL_ENRICHMENTS.map((e) => ({ label: e.name, id: e.id })),
+ value: () => ALL_ENRICHMENTS[0]?.id ?? '',
+ },
+ ...inputSubBlocks,
+ ],
+
+ tools: {
+ access: ['enrichment_run'],
+ config: {
+ tool: () => 'enrichment_run',
+ params: (params) => {
+ const enrichment = getEnrichment(params.operation)
+ const inputs: Record = {}
+ if (enrichment) {
+ for (const input of enrichment.inputs) {
+ const value = params[inputFieldId(enrichment.id, input.id)]
+ if (value !== undefined && value !== '') inputs[input.id] = value
+ }
+ }
+ return { enrichmentId: params.operation, inputs }
+ },
+ },
+ },
+
+ inputs: blockInputs,
+ outputs: blockOutputs,
+}
diff --git a/apps/sim/blocks/registry.ts b/apps/sim/blocks/registry.ts
index ace529f98c..14f3bda53f 100644
--- a/apps/sim/blocks/registry.ts
+++ b/apps/sim/blocks/registry.ts
@@ -51,6 +51,7 @@ import { ElasticsearchBlock } from '@/blocks/blocks/elasticsearch'
import { ElevenLabsBlock } from '@/blocks/blocks/elevenlabs'
import { EmailBisonBlock } from '@/blocks/blocks/emailbison'
import { EnrichBlock } from '@/blocks/blocks/enrich'
+import { EnrichmentBlock } from '@/blocks/blocks/enrichment'
import { EvaluatorBlock } from '@/blocks/blocks/evaluator'
import { EvernoteBlock } from '@/blocks/blocks/evernote'
import { ExaBlock } from '@/blocks/blocks/exa'
@@ -305,6 +306,7 @@ export const registry: Record = {
elevenlabs: ElevenLabsBlock,
fathom: FathomBlock,
enrich: EnrichBlock,
+ enrichment: EnrichmentBlock,
evaluator: EvaluatorBlock,
evernote: EvernoteBlock,
exa: ExaBlock,
diff --git a/apps/sim/components/icons.tsx b/apps/sim/components/icons.tsx
index 73ad59450b..7985328c08 100644
--- a/apps/sim/components/icons.tsx
+++ b/apps/sim/components/icons.tsx
@@ -1,6 +1,22 @@
import type { SVGProps } from 'react'
import { useId } from 'react'
+export function EnrichmentIcon(props: SVGProps) {
+ return (
+
+ )
+}
+
export function AgentMailIcon(props: SVGProps) {
return (