attio-deepline-enrich — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited attio-deepline-enrich (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Enrich records that already live in Attio, without exporting to a spreadsheet, hand-mapping columns, or guessing what it'll cost. You pick the object, the size, and the fields. The skill prices the run to the credit, asks once, then does it and writes the answers back into Attio.
Attio is both the source and the sink, and Attio reads/writes are free, so every credit is spent inside Deepline on the actual enrichment. Nothing is charged before you say yes.
Powered by Deepline. We're big fans, 50+ GTM data providers behind one CLI is the reason this skill is three steps instead of thirty.
Attio (read, free) -> CSV -> Deepline enrich (paid, gated) -> CSV -> Attio (write, free)ATTIO_API_KEY in .env (Attio: Settings -> Apps & integrations -> API). Needs read + write scopes on the object you're enriching.deepline auth status. Top up at https://code.deepline.com/dashboard/billing if needed.pip install requests python-dotenv (already in this repo's requirements.txt).Pricing reference: 10 credits = $1, so 1 credit = $0.10.
Ask the user which Attio object to enrich (companies, people, or a custom object slug). Then show them what's actually on it, never guess slugs:
python skills/attio-deepline-enrich/enrich.py attrs --object companiesThis prints every attribute as slug | type | title (free, read-only). Use it to confirm the input slugs (what Deepline needs to work from, e.g. domains, name, email_addresses) and the target slugs (what you'll fill).
Ask three things and don't pick defaults silently:
| Target in Attio | Deepline source | Typical tool family |
|---|---|---|
| work email | email waterfall | bettercontact, findymail, prospeo, dropleads |
| direct/mobile phone | phone waterfall | bettercontact, datagma, trestle |
| firmographics (employees, industry, revenue) | company enrich | peopledatalabs, crustdata |
| LinkedIn URL | profile resolve | linkedin_scraper, crustdata (or the linkedin-url-lookup skill) |
| job title / seniority | person enrich | peopledatalabs, apollo |
| ICP score / segment / custom flag | classify | aiinference over the row |
If unsure which provider, read ~/.agents/skills/deepline-gtm/provider-playbooks/<provider>.md for cost and quality notes before committing.
python skills/attio-deepline-enrich/enrich.py pull \
--object companies \
--inputs domains,name \
--target estimated_arr,employee_count \
--only-missing \
--limit 50 \
--output /tmp/enrich_in.csvThe script prints the real row count. That count, not the user's round number, is N for costing. If the user wants a hard cap of complete rows, over-provision ~1.4x at pull time and filter to the best N at the end (provider coverage has natural falloff; chasing the last few rows wastes credits).
Never estimate from a price list. Run the real enrichment on exactly one row and read what it actually cost:
deepline billing balance --json # note the starting balance
deepline enrich --input /tmp/enrich_in.csv --output /tmp/enrich_out.csv --rows 0:1 \
--with '{"alias":"work_email","tool":"bettercontact_enrich","payload":{ ...from provider playbook... }}'
deepline session usage --json # credits the pilot consumedBuild the per-row cost from the pilot. Per-row credits x N = the estimate. If you're chaining several attributes (a waterfall), the pilot must include every step so the per-row number is real.
Before the full run, alert the Session UI, then show the gate verbatim and stop:
deepline session alert --message "Approval needed: enrich N rows in Attio (~X credits)"Present exactly these four sections:
Assumptions
- <object, target attributes, providers, write mode>
- <which records: only-missing? capped at N?>
CSV Preview (ASCII)
<paste the verbatim ASCII preview from the deepline enrich --rows 0:1 pilot>
Credits + Scope + Cap
- Providers: <names>
- Per-row cost (from pilot): <credits>
- Full-run scope: <N rows>
- Estimated credits: <N x per-row> (~$<N x per-row x 0.10>)
- Spend cap: <cap>
Approval Question
About to spend ~<credits> credits (~$<dollars> at $0.10/credit) enriching <N> <object> in Attio.
Reply "YES I AGREE" to proceed.Wait for the exact string YES I AGREE (case-insensitive). "yes", "ok", "go", "sure" are not consent, re-ask. One approval covers this exact run only; a new object, new attributes, or more rows needs a fresh gate.
Only after YES I AGREE. Enrich every row (omit --rows), writing to the output CSV:
deepline enrich --input /tmp/enrich_in.csv --output /tmp/enrich_out.csv \
--with '{"alias":"work_email","tool":"...","payload":{ ... }}'For multi-attribute or waterfall runs, use the deepline enrich --with-waterfall ... --end-waterfall form (see deepline --help and the deepline-gtm skill). Iterate with --in-place on /tmp/enrich_out.csv only, never on the source CSV.
Dry-run first so the user sees exactly what lands where, then write for real:
# preview
python skills/attio-deepline-enrich/enrich.py push \
--object companies \
--input /tmp/enrich_out.csv \
--map work_email=email_addresses,arr=estimated_arr \
--mode append \
--dry-run
# write
python skills/attio-deepline-enrich/enrich.py push \
--object companies \
--input /tmp/enrich_out.csv \
--map work_email=email_addresses,arr=estimated_arr \
--mode append--map is csv_column=attio_slug. Write modes:
append (default) -> PATCH. Adds values, preserves existing ones. Right for multi-value fields (emails, phones, multi-select).replace -> PUT. Overwrites the attribute's values. Use only when the user wants the old value gone (removing/replacing a single-value field).Writes are paced under Attio's 25/sec limit and auto-retry on 429. Report back: rows written, skipped (came back empty from the provider), and failed.
YES I AGREE.append/PATCH by default. Reach for replace/PUT only on explicit "overwrite it".~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.