You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit ba998b6
Browse filesBrowse the repository at this point in the historyBrowse files
* fix(enrichments): verified-first waterfalls, billing fixes, and an error state for outages
- Work email: hold unverified hits (Hunter accept_all, Wiza risky,
Dropcontact non-nominative) as a fallback while later providers look for a
verified one; the held hit still fills the cell if none verifies. Ask
Prospeo for verified emails only, keep personal addresses out of Wiza
results, and move People Data Labs (unverified, $0.28 per hit) to the end,
skipping it once a fallback is held. Order is otherwise unchanged.
- Phone: skip PDL on a bare name (not a valid match), pass the LinkedIn
profile to PDL, prefer its mobile, and ask Prospeo for verified mobiles
only (no billed person match without one).
- Email verification: unverified/error verdicts fall through; bill nothing
for ZeroBounce unknown or MillionVerifier catch-all/unknown, which those
vendors do not charge for.
- Table cells: when every provider errored, mark the cell errored instead of
completing it blank, so an outage no longer silently finalizes empty rows.
* fix(enrichments): address review — blank outputs on an all-error run, LeadMagic verified check, toArray
* fix(enrichments): accept both Dropcontact verified-address labels
Copy file name to clipboardExpand all lines: .agents/skills/add-enrichment/SKILL.md
+6-3Lines changed: 6 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -22,7 +22,7 @@ Because enrichments run on Sim's hosted keys by default, **every provider tool y
22
22
23
23
## Architecture (what you're plugging into)
24
24
25
-
-**`enrichments/types.ts`** — `EnrichmentConfig { id, name, description, icon, inputs, outputs, providers }` and `EnrichmentProvider { id, label, toolId, buildParams, projectFailure, mapOutput }` — `toolProvider` fills `projectFailure` with the standard HTTP projection; override it only for a provider whose failure shape is nonstandard (see `enrichments/provider-failures/`). Providers are **plain data** (no `@/tools` import) so the catalog stays client-safe.
25
+
-**`enrichments/types.ts`** — `EnrichmentConfig { id, name, description, icon, inputs, outputs, providers }` and `EnrichmentProvider { id, label, toolId, buildParams, projectFailure, mapOutput, isVerified? }` — `toolProvider` fills `projectFailure` with the standard HTTP projection; override it only for a provider whose failure shape is nonstandard (see `enrichments/provider-failures/`). Providers are **plain data** (no `@/tools` import) so the catalog stays client-safe.
26
26
-**`enrichments/providers.ts`** — `toolProvider(...)` (typed passthrough) plus shared input helpers: `str(v)`, `normalizeDomain(v)`, `firstNonEmpty(arr)`, `splitName(fullName)`, and `projectEnrichmentProviderFailure`.
27
27
-**`enrichments/run.ts`** — the server-only cascade runner. Calls `executeTool(provider.toolId, { ...params, _context: { workspaceId, userId } })`, accumulates hosted-key cost, returns the first non-empty mapped result. **You do not edit this** — it works for any registry entry.
@@ -37,7 +37,9 @@ For each output the enrichment produces, decide which existing tool provides it.
37
37
- Its `params` accept what you can derive from table columns (read the tool's `params`).
38
38
- Its `outputs` / `transformResponse` actually expose the field you need (read the real output shape — don't assume).
39
39
40
-
Order providers **cheapest / most-likely-to-hit first**; the cascade stops at the first non-empty result. Apollo and LinkedIn APIs are not hosted-safe (ToS) — never call them as providers.
40
+
Order providers by **accuracy first, then price per hit**. Order decides which answer wins when two providers would disagree, so a cheaper but less accurate provider ahead of a better one trades quality for cost; reorder for price only with benchmark evidence. Among similarly accurate providers, put the ones that bill on a miss or charge a high price per hit after the cheaper, free-on-miss ones (check each vendor's billing docs and the tool's `hosting.pricing`); never move a more accurate provider behind a less accurate one to save cost. The cascade stops at the first non-empty, verified result. Apollo and LinkedIn APIs are not hosted-safe (ToS) — never call them as providers.
41
+
42
+
Prefer a vendor's own verified-only option (e.g. Prospeo `only_verified_email`) when it turns an unverified result into a free miss. Otherwise, when a provider can return an unconfirmed hit (a catch-all guess, a `risky` status), declare `isVerified(output)`: an unconfirmed hit is held while later providers look for a confirmed one, and fills the cell only if none does. `isVerified: false` marks a provider that never confirms its hits (a database record); it runs only while nothing is held.
41
43
42
44
## Step 2: Verify hosted-key support — chain to `/add-hosted-key` if missing
0 commit comments