CRM Enrichment
Finds Attio companies missing a description, researches each on the web, and writes the findings back onto the record.
integrationmapsearchai
Source
/**
* CRM enrichment. Once a week it walks the companies in Attio, finds the
* ones missing a description, researches each on the web, and writes the
* description and industry back onto the record.
*
* Setup:
* 1. swirls add attio query_records update_record
* 2. Deploy, then authorize the Attio connection in Cloud -> Connections.
*/
connection team_attio {
label: "Attio CRM"
provider: attio
}
schedule weekly_enrichment {
label: "Weekly Enrichment"
cron: "0 6 * * 1"
}
workflow enrich_companies {
label: "Enrich Companies"
description: "Research companies missing a description in Attio and fill in description and industry."
root {
type: code
label: "Start"
code: @ts { return { batchSize: 25 } }
outputSchema: @json {
{
"type": "object",
"properties": { "batchSize": { "type": "number" } }
}
}
}
node fetch_companies {
type: integration
label: "Fetch companies"
connection: team_attio
action: attio_query_records
params: @ts {
return {
object: "companies",
limit: context.nodes.root.output.batchSize
}
}
}
node enrich_each {
type: map
label: "Enrich each company"
items: @ts {
const rows = context.nodes.fetch_companies.output.data || []
return rows.map(r => {
const values = r.values || {}
const nameEntry = (values.name && values.name[0]) || {}
const domainEntry = (values.domains && values.domains[0]) || {}
const descEntry = (values.description && values.description[0]) || {}
return {
record_id: r.id ? r.id.record_id : "",
name: nameEntry.value || "",
domain: domainEntry.domain || "",
description: descEntry.value || ""
}
}).filter(c => c.record_id && c.name && !c.description)
}
maxItems: 25
subgraph {
root {
type: code
label: "Company"
inputSchema: @json {
{
"type": "object",
"properties": {
"record_id": { "type": "string" },
"name": { "type": "string" },
"domain": { "type": "string" }
}
}
}
code: @ts { return context.iteration.item }
outputSchema: @json {
{
"type": "object",
"properties": {
"record_id": { "type": "string" },
"name": { "type": "string" },
"domain": { "type": "string" }
}
}
}
}
node research {
type: search
label: "Research company"
query: @ts {
const c = context.nodes.root.output
return c.name + " " + c.domain + " company overview"
}
limit: 5
}
node summarize {
type: ai
label: "Summarize"
kind: object
model: "google/gemini-2.5-flash"
prompt: @ts {
const c = context.nodes.root.output
const results = (context.nodes.research.output.results || [])
.map(r => "- " + (r.title || "") + ": " + (r.description || ""))
.join("\n")
return "Write a two-sentence factual description of the company " + c.name + " (" + c.domain + ") and name its industry in a few words. Only state what the search results support.\n\nSearch results:\n" + results
}
schema: @json {
{
"type": "object",
"required": ["description", "industry"],
"properties": {
"description": { "type": "string" },
"industry": { "type": "string" }
}
}
}
}
node update_company {
type: integration
label: "Update record"
connection: team_attio
action: attio_update_record
params: @ts {
const c = context.nodes.root.output
const s = context.nodes.summarize.output
return {
object: "companies",
record_id: c.record_id,
data: {
values: {
description: s.description + " Industry: " + s.industry
}
}
}
}
}
node done {
type: code
label: "Record result"
code: @ts {
return { name: context.nodes.root.output.name, enriched: true }
}
}
flow {
root -> research
research -> summarize
summarize -> update_company
update_company -> done
}
}
}
node summarize_run {
type: code
label: "Summarize run"
code: @ts {
const rows = (context.nodes.enrich_each.output || []).map(r => r.done).filter(Boolean)
return { enriched: rows.length, companies: rows.map(r => r.name) }
}
}
flow {
root -> fetch_companies
fetch_companies -> enrich_each
enrich_each -> summarize_run
}
}
trigger on_weekly_enrichment {
schedule:weekly_enrichment -> enrich_companies
enabled: true
}
Flow
Trigger to workflow
weekly_enrichmentschedule
enrich_companies
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.
Workflow nodes
CODE
Code Node
Start
INTEGRATION
Integration Node
Fetch companies
MAP
Map Node
Enrich each company
CODE
Code Node
Summarize run
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.