{"id":39644,"plugin_id":"plugin_asdk_app_6947c583d8308191844af6213ceabe16","kind":"skill","collection_source":"plugin_package","comparison_source":null,"observed_at":"2026-10-24T12:48:33.118Z","digest":"2d2b7ecdd468eb9044b15084e8c3f76748ee002430cf7aa847ff1d59f24ce91d","against":null,"payload":{"description":"Tidy a pasted list of companies or contacts before matching or enrichment: normalize company names, domains, countries and emails, flag invalid rows with a reason, match each row to Vibe Prospecting records, and remove duplicates that resolve to the same company or person. Use for 'clean this list', 'match these companies to domains', 'dedupe these contacts', 'which of these emails are valid', 'prep this list for enrichment'. Works on lists pasted in chat, up to roughly 100 rows. Not for building a new list (use list-builder).","included_files":[{"relative_path":"agents/openai.yaml","size_in_bytes":349}],"name":"clean-data","skill_md_contents":"---\nname: clean-data\ndescription: \"Tidy a pasted list of companies or contacts before matching or enrichment: normalize company names, domains, countries and emails, flag invalid rows with a reason, match each row to Vibe Prospecting records, and remove duplicates that resolve to the same company or person. Use for 'clean this list', 'match these companies to domains', 'dedupe these contacts', 'which of these emails are valid', 'prep this list for enrichment'. Works on lists pasted in chat, up to roughly 100 rows. Not for building a new list (use list-builder).\"\n---\n\n# Clean Data\n\nStandardize and check a pasted list, then match it so duplicates collapse onto real company or person records. Nothing is deleted: every row stays, with a status and reason.\n\n## Connector rules\n\nUse only the Vibe Prospecting tools in your tool list. Each tool's live description and input schema are authoritative; if this skill disagrees with a tool, follow the tool.\n\n- **`tool_reasoning`** is required on every call: one short sentence (≤200 characters) that paraphrases what the user wants. No earlier conversation, contact details, or other personal data.\n- **Chaining:** copy `session_id` and `table_name` from the previous tool response; never invent either. After an enrich or events step, use the new `table_name`.\n- **`autocomplete` first**, one concept per call, for `linkedin_category`, `naics_category`, `company_tech_stack_tech`, `job_title`, `interests`, `skills`, `business_intent_topics`, and US `city_region`. Use the returned values as-is.\n- **What you can see:** `match-business` and `match-prospects` return complete results; fetch, enrich, and events tools return only a masked preview, so never quote values from it; `fetch-entities-statistics` returns aggregates; `show-sample` reveals up to 5 full rows.\n- **Finish with `show-sample`**, once per final `table_name`, then reply. Match-only and statistics-only work does not need it. The widget displays the sample rows, so do not repeat them as a table; use them for your analysis. If `display_status` is `masked`, say the full rows could not be revealed.\n- **Export** only after the user explicitly confirms, because it consumes credits. Show the returned download `url`. Never mention table names or session IDs to the user.\n- **Uploads:** you cannot upload files to Vibe Prospecting. Pasted lists and text from attached files are fine to use. If the user asks how to upload a list, point them to the Vibe Prospecting Hub: https://app.vibeprospecting.ai/lists\n\n## Input\n\nA list of companies or contacts pasted in chat, or the text of an attached file. Roughly 100 rows is the practical limit in one conversation; for more, work in batches. Note which column is the company name, domain, email, LinkedIn URL, phone or country; ask only if it is unclear. For a very large file, suggest the user clean it in a spreadsheet first.\n\n## Workflow\n\n1. **Profile the input.** Report row count, fill rate for each field, and obvious problems: placeholder text (\"N/A\", \"none\", \"-\"), pasted addresses in the name field, many spellings of one country, free-email providers, and role addresses.\n2. **Standardize,** keeping the raw value beside the normalized one:\n   - *Company name:* trim, collapse spaces, remove stray punctuation, and drop a trailing legal suffix (Inc, LLC, Ltd, GmbH, S.A.) for matching only.\n   - *Domain:* strip the protocol and `www`, keep the registrable domain, lowercase. Flag free-email domains separately.\n   - *Country:* convert to ISO two-letter codes (`United States` → `US`, `UK` → `GB`, `Deutschland` → `DE`).\n   - *Email:* trim and lowercase.\n   - *LinkedIn:* keep the full profile URL.\n3. **Validate** each field and tag the row; never delete one:\n   - *Email:* syntax, role addresses (`info@`, `sales@`, `noreply@`, `support@`), well-known free or disposable providers. You cannot check deliverability or mail servers, so say that valid means well-formed.\n   - *Domain:* looks like a real domain, no IP address or spaces.\n   - *Country:* resolves to a code.\n   Give each problem a short reason code (`role_address`, `free_provider`, `invalid_syntax`, `placeholder`).\n4. **Match the valid rows.**\n   - Companies with a name and/or domain: `match-business`, up to 50 per call.\n   - People: `match-prospects`, up to 40 per call, by email, LinkedIn URL or phone number, or full name plus company name (add the company's `business_id` when you have it). Skip rows tagged as role addresses or disposable domains so you do not spend matching on them.\n   Match results are complete, so read them directly. Check a resolved company for the shell-entity pattern (a big brand with 1-50 employees under \"Corporate Managing Offices\") and retry with the other domain. An email miss stays a miss; never retry it as a name search.\n5. **Deduplicate on the IDs.** Rows that resolve to the same business ID or prospect ID are duplicates; keep the first, mark the others with the ID of the survivor. Different IDs are different entities even if the names look alike, and subsidiaries or brands under one parent (for example a parent and its product domains) are separate companies; `enrich-business-company-hierarchies` shows the tree.\n6. **Report** and offer next steps.\n\n## Reply\n\n- **Profile:** a short before-and-after summary of fill rates and the issues found.\n- **Standardization:** three to five example changes (`\"  ACME, Inc. \"` → `acme`, `\"WWW.Acme.COM\"` → `acme.com`).\n- **Validation:** counts of valid and invalid rows and a frequency list of reason codes.\n- **Result table:** the input row, normalized value, status (matched, unmatched, invalid, duplicate of row N), reason, and the matched name and domain. Show the first rows in chat and offer the rest in batches; do not export unless asked.\n- **Next steps:** enrich the matched rows with `enrich-company` or `enrich-contact`, or score them with `score-leads`. If the match rate is low, suggest adding LinkedIn URLs, company domains or work emails.\n\n## Limitations\n\n- Validation checks format only: no deliverability or mail-server check, and no phone verification.\n- Person-name parsing is simple; non-Western name orders and compound surnames may need the user's confirmation.\n- Free-email addresses cannot be tied to a company by themselves; pair them with a name and company for a prospect match.\n- Matching returns an ID or nothing, with no confidence score.\n- Works in chat, so very large files need to be split.\n"},"changes":[],"summary":"First saved snapshot. No earlier version is available for comparison.","summary_kind":"deterministic","summary_metadata":{}}