Professional pack for automating sales quotes with an AI agent. Designed for tradespeople, freelancers, SMBs and entrepreneurs who want to generate compliant quotes and PDF flyers in seconds.
Table of contents
- Architecture
- Quick Start
- BYO-LLM — bring your own AI
- Pack structure
- Quote workflow
- SMB connectors
- License
Architecture
The pack is built on an OODA loop specific to the quoting & invoicing domain:
┌─────────────────────────────────────────────────────────────┐
│ AGENT DEVIS v2.0 │
├─────────────────────────────────────────────────────────────┤
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │RECEIVING │───→│ENRICHING │───→│ PRICING │ │
│ └──────────┘ └──────────┘ └────┬─────┘ │
│ ▲ │ │
│ │ ▼ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ARCHIVING │←───│ SENDING │←───│ REVIEWING│ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ ▲ │
│ └────────────────────────────────────────┐ │
│ ▼ │
│ ┌──────────┐ │
│ │FORMATTING│ │
│ └──────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ MODULES: Brief Parser │ Product Enricher │ Price Engine │
│ PDF Generator │ Flyer Builder │ Connector Hub │ DB Core │
└─────────────────────────────────────────────────────────────┘
Internal modules
| Module | Role |
|---|---|
| Brief Parser | Extracts customer requirements from free text or a form |
| Product Enricher | Automatic lookup of photos, descriptions and catalog prices |
| Price Engine | Computes pre-tax/VAT/incl.-tax totals, discounts, shipping costs, rounding |
| PDF Generator | Generates the quote PDF in compliance with French standards |
| Flyer Builder | Creates the 1-2 page A4 flyer with photos and prices |
| Connector Hub | Interface with management software (Sage, QuickBooks, etc.) |
| DB Core | SQLite persistence of customers, products, quotes and history |
Quick Start
Turnkey deployment in one command on a Debian/Ubuntu VM:
# 1. Install (system deps + venv + LLM detection + systemd service)
cd agent-devis-v2/
sudo bash install.sh # or: bash install.sh --no-service
# 2. Verify the installation offline (deterministic, no API key)
bash smoke_test.sh
# 3. Run a quote from a free-text brief
python3 agent.py run --brief "Rénovation salle de bain 12m2, carrelage mural blanc, douche italienne pour Dupont"
# 4. (optional) JSON output for integration / connector
python3 agent.py run --brief "Peinture 30m2 pour Martin" --json
End-to-end demo with nothing to configure:
python3 EXAMPLE.py
BYO-LLM — bring your own AI
The agent's core (brief parsing, pre-tax/VAT/incl.-tax calculation, SQLite archiving) is
deterministic and runs without an API key. If you have a connected coding-agent
CLI (Claude Code / Kimi Code / Codex), the enrichment and
review steps are driven by your subscription via llm_adapter.py — no API key,
no billing by this pack. Auto-detection, or force it with PACK_LLM=claude|kimi|codex.
| Capability | Without LLM (deterministic) | With LLM (BYO) |
|---|---|---|
| Brief parsing | keyword + quantity heuristics | fine-grained natural-language understanding |
| Line enrichment | built-in catalog + fallback | contextual descriptions + estimates |
| Pre-tax/VAT/incl.-tax calculation | exact, per line | identical (always deterministic) |
| Consistency review | arithmetic checks | + detection of business inconsistencies |
| Works without an API key | ✅ | ✅ (your CLI, no key) |
Honest promise: the agent is useful without an LLM, and smarter with one.
Deterministic routing mode (prepare_devis)
The pack exposes a deterministic, LLM-free routing mode for benchmark
harnesses and offline use. It is the canonical path for the
agent-devis-v2-canonical regression scenario.
- Entry point:
agent._handle_task_deterministic("prepare_devis", payload)(consumed by the Docker no-LLM benchmark harness). - Routing buckets (always present in the JSON output):
quote_lines— complete lines, ready to be priced.rejected_lines— non-priceable lines, with a mandatoryreason(prix manquantwhen the unit price is missing,quantite incertainewhen the quantity is missing).manual_review— ambiguous lines that need a human.
- No catalogue fallback: a line without a verified unit price is rejected
(
prix manquant), never silently repaired by a default price. The internal catalogue is only used by the free-text CLI flow, not by this routing path. - Conservative VAT:
taux_tvastays at 20 % unless the payload provides an explicit, justified reduced rate. No invented "confirm reduced VAT eligibility" step. - Operator note sanitization: any
operator_noteis stripped of forbidden identifiers (facture,client,contrôle,fichier,référence,devis,DEV-AAAA-NNNN,not_provided) before it can be forwarded to a model. - Per-line totals: each
quote_linesentry carriestotal_ligne_ht,montant_tva_ligneandtotal_ligne_ttc;totaux.total_tvais the exact sum of the per-line VAT amounts (uniform 2-decimal rounding). - Prompt wiring: when an LLM adapter is available, the flow is driven by
the
route_devisprompt (Prompt 6 inPROMPTS.md); otherwise the deterministic core above is used. Both paths produce the same bucket contract.
This mode is what the benchmark harness exercises; it is fully offline, deterministic and reproducible.
Pack structure
agent-devis-v2/
├── README.md ← this file
├── SOUL.md ← quote-specific OODA states
├── PROMPTS.md ← 5 named prompts (loaded by agent.py)
├── CHECKLIST.md ← 30+ deployment steps with snippets
├── SPEC.md ← technical spec (DB, VAT, PDF)
├── CHANGELOG.md ← version history
├── CUSTOMIZE.md ← where to plug in your catalog & rates (5 min)
├── SUCCESS_METRICS.md ← quantified KPIs + failure definition
├── OPERATING_COST_ESTIMATE.md ← operating costs (provider-agnostic)
├── agent.py ← executable agent (OODA, SQLite, BYO-LLM)
├── llm_adapter.py ← BYO-LLM adapter (claude/kimi-code/codex, no key)
├── EXAMPLE.py ← end-to-end demo (no API key)
├── install.sh ← one-shot Debian installer (deps+venv+systemd)
├── agent-devis-v2.service ← reference systemd unit
├── test_agent.py ← deterministic offline test suite
├── smoke_test.sh ← offline test launcher
├── requirements.txt ← dependencies (stdlib only)
├── agent-devis-v2.json ← manifest (metadata, files, KPIs)
├── scripts/ ← helpers (config.yaml, run_agent.py, test_prompt.py, init_db.sql)
└── templates/ ← quote & flyer templates (yaml) + examples
Quote workflow
- The user or the agent fills in a brief (free text or structured JSON)
- The agent parses the brief and identifies the products/services
- The agent enriches each line: photo lookup, detailed description, unit price
- The agent calculates the pre-tax totals, applies VAT and any discounts
- The agent formats the compliant quote PDF (legal notices, SIRET, validity date)
- The agent generates the A4 PDF flyer (1 page, or 2 pages as a brochure) with product visuals
- The agent archives the quote in the SQLite database and offers sending by email / SMB connector
SMB connectors
The pack detects and interfaces with:
- Sage ( CSV export / Sage Business Cloud API )
- QuickBooks ( REST API v3 )
- EBP ( CSV export / ODBC connector )
- Pennylane ( public API )
- Holded ( API v1 )
- Wave ( GraphQL API )
- Zoho Books ( REST API )
If no software is detected, the agent uses the built-in SQLite database and exports to CSV/XLSX.
Use a local model (Ollama)
The optional LLM step can also run on your own machine through Ollama, so no text leaves your server. No account and no API key.
ollama pull <model> # any chat model you like
export PACK_LLM=ollama # prefer Ollama even if a coding-agent CLI is installed
export PACK_OLLAMA_MODEL=<model> # optional: default is the first chat model the server lists
python3 -c "import llm_adapter; print(llm_adapter.detect())" # prints: ollama
PACK_OLLAMA_HOSTpoints to another server (defaulthttp://127.0.0.1:11434);OLLAMA_HOSTis also read whenPACK_LLM=ollama.PACK_OLLAMA_NUM_CTXsets the context size if your reports or prompts are long.- Without
PACK_LLM, a local Ollama server is used only when no Claude Code, Kimi Code or Codex CLI is found. - If the server is down or the model is missing, the pack keeps working in its deterministic mode.
Learning memory (local and private)
Every LLM call this pack makes is journaled in ./.pack_memory/ next to the code, so the pack can improve for you. Nothing is ever sent anywhere.
- What is kept: the task name, the masked input, the masked answer, status and latency. Keys, tokens, e-mails, phone numbers, IP addresses, card and IBAN numbers and personal paths are masked before writing; the system prompt is never stored.
- Teach it:
python3 pack_memory.py feedback last okconfirms a result,python3 pack_memory.py feedback last bad --fix "the right answer"corrects it. Confirmed and corrected runs are reused as validated examples when a similar input comes in. Unrated runs are never injected into a prompt. - Find similar cases:
python3 pack_memory.py similar "some text"andpython3 pack_memory.py clusters(groups of near-identical failures) work in plain Python, no model needed. Optional meaning-based matching uses an embedding model you already run locally:python3 pack_memory.py enable-semantic(Ollama on this machine only). - Share, only if you want:
python3 pack_memory.py exportwrites an anonymised summary (counts, statuses, size buckets, no text) for you to review. - Control:
PACK_MEMORY=0turns it off,PACK_MEMORY_STORE_TEXT=0keeps fingerprints only,python3 pack_memory.py purge --yeswipes it.
License
Personal use per purchase — resale prohibited. 3 USD / agent.
Agent-to-agent payment supported (x402 / USDC on Base) — see the manifest
agent-devis-v2.json. No dependency on an API key: your own CLI subscription
(Claude Code / Kimi Code / Codex) is the only AI billing relationship.
