Skip to main content

Pre-call due-diligence intelligence for sales reps — action tips + fact dossiers from one research pass.

Project description

🟡 SalesBuff — Backend (FastAPI)

The Python service that turns a sales rep's prompt into a citation-grounded Actions brief and a Facts dossier. Built with FastAPI + asyncio.

Architecture deep-dive (folders, data flow, prompts): see ARCHITECTURE.md.


What it does

One request runs a 3-stage pipeline:

  1. Resolve — figure out the real buyer, contact, seller, meeting motion (expansion vs displacement), and any competitor to beat. (LLM → Tavily search → LLM)
  2. Research — deep-research each entity on the web; optionally search court records. (Tavily Deep Research + CourtListener)
  3. Brief — from one shared fact pack, generate Actions (coaching moves) and Facts (evidence dossier) concurrently, then ground every card to a real source URL. (OpenAI)

Because a full run takes ~1–2 minutes, the API is job-based: submit, then poll.


Two ways to use it

It's one package with feature extras you mix and match:

Install You get
pip install salesbuff Shared core — enough to call the SDK from your code.
pip install "salesbuff[precall]" The pre-call due-diligence feature (this product).
pip install "salesbuff[onfly]" Live on-the-fly insights (planned).
pip install "salesbuff[api]" The FastAPI host layer + the salesbuff-serve command.
pip install "salesbuff[precall,api]" Pre-call and host it as an API.
pip install "salesbuff[all]" Everything.

Extras are additive — they layer optional dependencies onto the core. One pip install pulls the package and all the deps for the extras you pick; there's no separate requirements step.

Host it from the terminal (no code)

pip install "salesbuff[api]"
# set OPENAI_API_KEY + TAVILY_API_KEY in your env (or a .env), then:
salesbuff-serve --port 8000        # defaults to $PORT or 8000

As a library (SDK)

from salesbuff import SalesBuff

async with SalesBuff(openai_api_key="sk-...", tavily_api_key="tvly-...") as sb:
    result = await sb.research("Meeting the VP of Ops at Acme Health next week...")
    print(result.brief)   # Actions brief (or None)
    print(result.facts)   # Facts dossier (or None)

One-shot synchronous helper (for scripts/notebooks):

from salesbuff import research_once

result = research_once(
    "Expanding our rollout at Acme Health...",
    openai_api_key="sk-...",
    tavily_api_key="tvly-...",
)

courtlistener_token=... is optional (enables court-record lookups). Advanced tuning (research_concurrency, openai_model, …) can be passed as keyword args.

The FastAPI service is just a thin host over this same SDK — both share one engine, so they never drift.


Setup (local)

Run everything from the SalesBuff/ directory (the parent of the salesbuff package).

cd SalesBuff
pip install -r salesbuff/requirements.txt
cp salesbuff/.env.example salesbuff/.env     # fill in your keys
uvicorn salesbuff.api:app --port 8000 --reload

Health check: curl http://127.0.0.1:8000/health{"status":"ok"}.

There's also a CLI for quick local runs:

python -m salesbuff "Meeting the VP of Ops at Acme Health next week..."

Environment variables

Set in salesbuff/.env locally, or in the Render dashboard in production.

Var Required Default Purpose
OPENAI_API_KEY Brief + facts + entity resolution
TAVILY_API_KEY Web search + deep research
OPENAI_MODEL gpt-4o-mini Chat model
COURTLISTENER_TOKEN Legal/court records (optional)
USAGE_MAX 25 Shared-quota runs before users must bring their own keys
USAGE_CURRENT 0 Runs already consumed (in-memory counter)
MAX_CASES_PER_ENTITY 8 Court cases kept per company
TAVILY_MAX_RESULTS 5 Web search results
TAVILY_SEARCH_DEPTH basic Tavily depth

API

Method Path Description
POST /research Submit { "prompt": "...", "keys"?: {openai, tavily, courtlistener} }{ request_id, status, usage }
GET /research/{id} Poll → { status, stage, progress, brief, facts, warnings, error }
GET /usage { used, limit, remaining }
GET /health Liveness probe
  • Without user keys, runs count against the shared USAGE_MAX (HTTP 429 when exhausted).
  • With valid user keys, the run bypasses the quota and uses a throwaway client; bad keys return 400 with a clear message.

Project structure

salesbuff/
├── api.py            # FastAPI app: submit/poll jobs, usage limiter
├── pipeline.py       # orchestrates resolve → research → brief
├── container.py      # wires adapters into the pipeline (DI)
├── config.py         # env → frozen Config
├── ports/            # abstract interfaces (LLM, web, legal)
├── adapters/         # OpenAI, Tavily, CourtListener implementations
├── research/         # resolve, web, legal, deep, brief, facts
├── domain/           # prompts, framing, grounding rules, source tiers, YAML loader
├── domain_logic_sales/   # editable YAML: categories, questions, ranking, compliance
└── models/           # typed shapes: entities, findings, brief, facts

The ports/adapters split is what lets a user bring their own keys at runtime (a different adapter, same pipeline) and makes the LLM/search providers swappable.


Deploy (Render)

Use the blueprint at the repo root (../render.yaml) or set manually:

  • Root Directory: SalesBuff
  • Build: pip install -r salesbuff/requirements.txt (or pip install ".[api]" — same result via pyproject.toml)
  • Start: uvicorn salesbuff.api:app --host 0.0.0.0 --port $PORT
  • Health check path: /health
  • Instances: 1 — the job store and usage counter live in memory, so multiple instances would split state.

Set OPENAI_API_KEY and TAVILY_API_KEY (and optionally COURTLISTENER_TOKEN) as dashboard secrets.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

salesbuff-0.1.0.tar.gz (52.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

salesbuff-0.1.0-py3-none-any.whl (63.1 kB view details)

Uploaded Python 3

File details

Details for the file salesbuff-0.1.0.tar.gz.

File metadata

  • Download URL: salesbuff-0.1.0.tar.gz
  • Upload date:
  • Size: 52.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for salesbuff-0.1.0.tar.gz
Algorithm Hash digest
SHA256 b86c67d0864195ff281ae7eb6da78d9189ac8174ca0f0244999d79804874cbcf
MD5 42c90cd7c733ee38257b24732094734a
BLAKE2b-256 0049da6cdd35e12fcac05fc511a70f09be61a0f3044dc06122336387597d2520

See more details on using hashes here.

File details

Details for the file salesbuff-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: salesbuff-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 63.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for salesbuff-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5edf5d55b4b1c22f1e3411f142df13dcc732d9670a3ae9dd8f80875f9db8a7d5
MD5 f6ee1303565a234bc74ed170a674efe2
BLAKE2b-256 9eec4bb02c16d852d388f9338340099fc9ed1dfb1f3e870ac8b8c185f42059de

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page