Skip to main content

Pre-call due-diligence intelligence and On-fly live coaching for sales reps โ€” action tips + fact dossiers from one research pass.

Project description

๐ŸŸก SalesBuff โ€” Backend (FastAPI)

The Python service for Pre-call due diligence (citation-grounded Actions + Facts) and On-fly live coaching (real-time tips during a call). Built with FastAPI + asyncio.

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


Features

Pre-call

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.

On-fly

Live coaching during a call:

  1. Session start โ€” extract a structured deal brief from seed context; optional bootstrap Tavily search when pre-call data is thin.
  2. Transcript chunks โ€” browser sends speech every ~25s or on manual "Get tip now".
  3. Tip generation โ€” fast LLM pass with conversation memory (compacted summary + raw tail + current chunk), stage/tip-type metadata, dedup filters.
  4. Reactive research โ€” async Tavily quick (one search) or deep (multi-query synthesis) when the coach flags a gap; never blocks immediate tips.
  5. Session end โ€” optional JSON log of every chunk, candidate, rejection, and tip.

On-fly uses Core only (CoreContainer) โ€” it never imports the pre-call pipeline.


Two ways to use it

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

Install You get
pip install salesbuff Shared core โ€” LLM + search clients, config, models.
pip install "salesbuff[precall]" The pre-call due-diligence feature (SalesBuff, research_once).
pip install "salesbuff[onfly]" Live coaching โ€” Core only; no pre-call dependencies pulled in.
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 (includes On-fly routes).
pip install "salesbuff[all]" Everything.

Extras are additive โ€” they layer optional dependencies onto the core. Pre-call SDK symbols load lazily so salesbuff[onfly] never forces pre-call-only deps like rapidfuzz.

Host it from the terminal (no code)

pip install "salesbuff[precall,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 pre-call 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. See salesbuff/.env.example for the full template.

Required

Var Purpose
OPENAI_API_KEY Brief + facts + entity resolution + On-fly tips
TAVILY_API_KEY Web search + deep research + On-fly reactive lookup

Core / pre-call

Var Default Purpose
OPENAI_MODEL gpt-4o-mini Default 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 search depth
LEGAL_BATCH_SIZE 10 Court cases processed per batch
TAVILY_RESEARCH_MODEL mini Tavily Deep Research model (pre-call)
TAVILY_RESEARCH_CONCURRENCY 6 Max in-flight deep-research tasks
TAVILY_RESEARCH_POLL_INTERVAL 4.0 Seconds between poll attempts
TAVILY_RESEARCH_MAX_POLLS 60 Max polls before timeout
TAVILY_RESEARCH_OUTPUT_LENGTH standard Deep research output size

On-fly live coaching

Var Default Purpose
ONFLY_TIP_MODEL OPENAI_MODEL Fast model for hot-path JSON tips
ONFLY_COMPACTION_MODEL OPENAI_MODEL Model for async transcript compaction
ONFLY_COMPACT_CHUNK_THRESHOLD 10 Compact when unsummarized chunks exceed this
ONFLY_COMPACT_TOKEN_THRESHOLD 3000 โ€ฆor when raw unsummarized text exceeds this
ONFLY_SUMMARY_MAX_TOKENS 3000 Target size for compacted summary
ONFLY_RAW_TAIL_CHUNKS 3 Recent chunks kept verbatim
ONFLY_REACTIVE_SEARCH_MAX 3 Max quick reactive searches per session
ONFLY_DEEP_RESEARCH_MAX 2 Max deep (multi-query) research runs per session
ONFLY_DEEP_MAX_QUERIES 3 Tavily queries per deep research run
ONFLY_TIP_TYPE_WINDOW 3 Dedup window for repeated tip types
ONFLY_SESSION_LOG 1 Dump JSON session log on end (0/false to disable)
ONFLY_LOG_DIR salesbuff/onfly_log/ Directory for session log files

API

Pre-call

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.

On-fly

Method Path Description
POST /onfly/sessions Create session { pasted_context, spoken_setup, precall_brief?, precall_facts?, max_tips, tts_enabled } โ†’ { session_id, expires_at }
POST /onfly/sessions/{id}/chunks Ingest transcript chunk { text, manual? }
GET /onfly/sessions/{id} Current session state (tips, stage, etc.)
GET /onfly/sessions/{id}/events SSE stream of new tips
DELETE /onfly/sessions/{id} End session; returns { ended, log } path if logging enabled

Sessions are in-memory (2-hour TTL). Keep one backend instance in production.


Project structure

salesbuff/
โ”œโ”€โ”€ api.py              # FastAPI app: pre-call jobs + mounts /onfly
โ”œโ”€โ”€ core.py             # CoreContainer โ€” shared LLM + search (no feature deps)
โ”œโ”€โ”€ container.py        # Container extends Core โ€” wires pre-call pipeline (DI)
โ”œโ”€โ”€ pipeline.py         # orchestrates resolve โ†’ research โ†’ brief
โ”œโ”€โ”€ config.py           # env โ†’ frozen Config
โ”œโ”€โ”€ client.py           # SDK entry (SalesBuff, research_once)
โ”œโ”€โ”€ ports/              # abstract interfaces (LLM, web, legal)
โ”œโ”€โ”€ adapters/           # OpenAI, Tavily, CourtListener implementations
โ”œโ”€โ”€ precall/            # pre-call feature: resolve, web, legal, deep, brief, facts
โ”œโ”€โ”€ onfly/              # live coaching: coach, session, prompts, api routes
โ”œโ”€โ”€ 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, onfly

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. Core is shared; precall and onfly are separate features that both build on Core.


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, usage counter, and live sessions live in memory, so multiple instances would split state.

Set OPENAI_API_KEY and TAVILY_API_KEY (and optionally COURTLISTENER_TOKEN) as dashboard secrets. On-fly vars are optional โ€” defaults work out of the box.

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.2.0.tar.gz (68.9 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.2.0-py3-none-any.whl (81.8 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for salesbuff-0.2.0.tar.gz
Algorithm Hash digest
SHA256 75e7ebc7de32374956de6a4e5726e441a0ec759d59979e7989fce071877f7434
MD5 64f1d7790e4753d699935f814f561738
BLAKE2b-256 2402eb27ae570fec3cd08c9d83ffaa00973048f141fad407500ff5afee09a573

See more details on using hashes here.

File details

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

File metadata

  • Download URL: salesbuff-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 81.8 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.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1a8ac9c3f026170b65e0eb2b621688b42442055fbe695542db40ee35e31fcabd
MD5 b254fe4be7a652d542d74b36700db686
BLAKE2b-256 da4e0528b2499488b94bd5f8059fd41780f5e42b3dee06e539134ad0f8d91e3e

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