Russian version: README.ru.md
Canonical working root for this product:
/home/clawd/.openclaw/workspace/github/repos/lead-enrichment-outreach
Reviewable AI-assisted B2B outreach workflow:
company/domain → dossier → trust review → draft → human decision
This repo now includes the local review UI/HTTP layer inside the main product. No auth, no real sending, fail-closed by default.
Older sibling projects such as b2b-outreach-editor and startup-ai-outreach-copilot are archived and should not be treated as the primary codebase.
If you want the shortest path to "show me the product", use this order:
make demo-quick
make demo
make demo-ui
make batch-demo
make ready-export-demoWhat each step proves:
make demoshows the three trust outcomes:ready,review_required,blockedmake demo-uiopens the operator review surface onhttp://127.0.0.1:8095with the demo review file and demo batch preloadedmake batch-demoandmake ready-export-demoshow the deterministic demo-batch-to-ops handoff story
Presenter docs:
docs/demo/README.md— 2-minute walkthroughdocs/demo/SCRIPT.md— literal talk track and command orderdocs/demo/PUBLIC_DEMO.md— fastest public-hosting path for a remote demodocs/demo/DEPLOY.md— systemd/nginx deploy path for a staying-up demo box
- lead enrichment into dossier JSON
- trust gating with
ready/review_required/blocked - restrained draft generation
- local review UI for:
- dossier summary
- review status, reasons, warnings, sources
- ranked contacts
- draft subject/body editing
- operator decision:
approved/rejected/needs_review
- reproducible local demo
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python3 -m unittest discover -s tests -qIf tests pass, the repo is runnable locally.
make demo-quick
make demo-storyThis gives you the demo narrative in one line:
company/domain -> dossier -> trust gate -> draft -> human decision -> ops-ready export
make demoThis prints all 3 trust outcomes:
ready-> safe to draftreview_required-> plausible lead, but human review requiredblocked-> not trustworthy enough to continue
make demo-uiThen open:
http://127.0.0.1:8095
What you should see:
- a demo-first hero with a 90-second walkthrough path
- one-click scenario jumps for
ready,review_required, andblocked - a company dossier with source-backed summary
- trust verdict and reasons
- ranked contact candidates
- editable outreach draft
- explicit human decision controls (
approved/rejected/needs_review) - a presenter guide that explains why the current lead is safe, gated, or blocked
- batch tools:
- load demo batch JSON
- upload batch JSON artifact
- upload CSV and run enrichment from the UI
- export ready-only leads as JSON or CSV from the current batch
- browse saved review files and reopen them in the UI
- export one handoff
.zipbundle for ops - import a handoff
.zipbundle back into the UI - inspect a compact ops dashboard for ready/draft/review coverage
- bulk-save missing ready review files and jump to the next ready lead without a draft
- bulk-generate drafts for ready leads that still have no draft
- bulk-approve ready saved reviews and export approved-only handoff lists
- export one-click final approved-only bundle for downstream ops
- import the approved-only final bundle back into the UI
This seeds examples/demo-review.json, rebuilds examples/demo-output.json, and opens the local review workflow with the demo batch ready to inspect.
Recommended browser order:
- click
Start 90-second demo - show the
readylead first - jump to
review_requiredandblockedto prove the safety rail - return to the ready lead and export the approved handoff bundle
make batch-demo
make ready-export-demoThis closes the story:
- deterministic demo batch rebuilds from
examples/demo/index.json - the batch artifact still mirrors the same ready / review_required / blocked operator story
- ready-only export gives downstream ops a clean handoff
make demo-artifactsOr inspect:
examples/demo/index.json— map of the demo scenariosexamples/demo/ready/— happy pathexamples/demo/review_required/— weak-contact gated pathexamples/demo/blocked/— refusal pathexamples/demo/refusal/— draft refusal artifact
For reproducible local runs, pass a known domain (live search-only enrichment can be flaky depending on DuckDuckGo HTML output/network conditions):
python3 skill/scripts/enrich_lead.py --company "DeepL" --domain deepl.comOutput: a dossier JSON with:
search_resultsacross multiple HTML search sourcesprimary_site_url,site_candidates,alternative_candidates, andwhy_chosen- summary, contact sources, addresses/region hints, confidence, warnings, and a review verdict
- optional
browser_fallbackrendering when a site is JS-gated or the first static fetch fails
python3 skill/scripts/generate_outreach.py examples/demo/ready/deepl-dossier.json \
--offer "AI-assisted lead enrichment and outreach"Weak dossiers are blocked by default:
python3 skill/scripts/generate_outreach.py examples/demo/review_required/mistral-ai-dossier.json \
--offer "AI-assisted lead enrichment and outreach"Override only after explicit human review:
python3 skill/scripts/generate_outreach.py examples/demo/review_required/mistral-ai-dossier.json \
--offer "AI-assisted lead enrichment and outreach" \
--allow-review-requiredExample artifacts live under examples/demo/ready/, examples/demo/review_required/, and examples/demo/blocked/.
python3 skill/scripts/workflow.py \
--company "DeepL" \
--domain deepl.com \
--offer "AI-assisted lead enrichment and outreach"If you omit --domain, the workflow falls back to live web search and may be less reproducible.
This emits one JSON artifact with:
- input
- dossier
- review verdict
- optional draft
You can also wrap an existing dossier instead of re-running enrichment:
python3 skill/scripts/workflow.py \
--dossier-json examples/demo/ready/deepl-dossier.json \
--offer "AI-assisted lead enrichment and outreach"python3 skill/scripts/batch_workflow_csv.py \
examples/demo-leads.csv \
--offer "AI-assisted lead enrichment and outreach"This emits one batch JSON artifact with:
- top-level summary counts for
ready,review_required,blocked - per-lead workflow artifacts
- clear visibility into how many drafts were actually generated
Optional output file:
python3 skill/scripts/batch_workflow_csv.py \
examples/demo-leads.csv \
--offer "AI-assisted lead enrichment and outreach" \
--output examples/demo-output.jsonThe local review UI can now run the same flow directly from a CSV upload:
- choose a
.csv - optionally set an offer for ready leads
- choose
smartorbasicquery mode - optionally allow draft generation for
review_requireddossiers after human review - export the current batch's ready-only leads as downloadable JSON or CSV
For the reproducible presenter path, rebuild the bundled demo batch instead of hitting live enrichment:
python3 ui/review_server.py \
--build-demo-batch-only \
--demo-batch-file examples/demo-output.jsonThis uses examples/demo/index.json and the curated demo dossiers/drafts, so the summary stays stable for demos and deploy smoke checks.
Once you have a batch artifact, export only the leads that are actually ready:
python3 skill/scripts/export_ready_leads.py \
examples/demo-output.json \
--output-json examples/ready-leads.json \
--output-csv examples/ready-leads.csvThis gives you:
- a clean
ready-onlyJSON artifact - a flat CSV for downstream ops or review
- draft subject/body bundled only for leads already marked
ready
python3 ui/review_server.py --review-file examples/demo-review.jsonOptional demo seeding:
python3 ui/review_server.py --seed-demo --review-file examples/demo-review.jsonNotes:
- this is a local-only UI served on
127.0.0.1by default make batch-demois intentionally deterministic and rebuildsexamples/demo-output.jsonfrom curated demo fixtures, not from live web enrichment- there is no auth because v1 is intentionally single-operator/local
- demo seeding currently uses the ready-path DeepL example, not the review-required Mistral example
The UI reads and writes one JSON document with:
leaddossierdraftreview_decision
Example status flow:
- dossier
review.statusshows system trust verdict - operator
review_decision.statusis one of:approvedrejectedneeds_review
This keeps trust verdict separate from human approval.
skill/— enrichment and draft scriptsexamples/— public demo dossiers/drafts/review JSONtests/— unit testsui/— local review UI + HTTP server
This is a reviewable outreach system, not black-box lead gen magic.
- weak dossier → not ready by default
review_requiredis not treated as ready- operator sees warnings, reasons, and sources before approving
- draft generation refuses weak dossiers unless explicitly overridden
- no real email send flow in v1
- local review server binds to
127.0.0.1by default
In plain English: the product helps prepare outreach, but it does not silently scrape-and-spam.
For the shortest remote demo path on a VPS:
make demo-launch-publicThen verify from the host:
make demo-public-healthHealth endpoint:
/healthz
It returns:
- active review file path
- demo batch file path
- whether the demo batch exists
- batch summary counts when readable
- saved review file count
See docs/demo/PUBLIC_DEMO.md for the compact remote-demo checklist.
Relevant checks for this v1:
python3 -m unittest discover -s tests -q
python3 ui/review_server.py --demo --review-file examples/demo-review.json --demo-batch-file examples/demo-output.json --host 127.0.0.1 --port 8095
curl -fsS http://127.0.0.1:8095/healthzUse Ctrl+C to stop the local server.
MIT