Autonomous Procurement Agent
by @d-zhangz
Enterprise procurement quote parsing and fraud detection. Use when: (1) A supplier quote arrives as messy plain-text, OCR scan, or SAP export, (2) Cross-plat...
clawhub install autonomous-procurement-agentπ About This Skill
name: autonomous-procurement-agent description: "Enterprise procurement quote parsing and fraud detection. Use when: (1) A supplier quote arrives as messy plain-text, OCR scan, or SAP export, (2) Cross-platform invoice reconciliation is needed across CNY/USD/EUR, (3) B2B finance teams need real-time risk auditing on vendor submissions, (4) Approval escalation thresholds need to be enforced automatically. Handles non-standard formats with dual-engine AI (regex + GPT-4o fallback), F1/F2/F3 fraud detection, and Lemon Squeezy MoR subscription."
Autonomous Procurement Agent
Stop overpaying. Stop missing fraud. Every week, procurement teams lose money because a supplier's quote arrived as a messy email, a merged-cell SAP export, or a PDF scan with OCR artifacts. The unit price got misread. The line math was wrong. Nobody caught it β until the invoice was already paid.
Autonomous Procurement Agent handles every format. Every currency. With fraud detection that actually blocks, not just warns.
First-Use Initialisation
Before processing any quotes, configure your environment:
# Required in production β server refuses to start without this
export LS_WEBHOOK_SECRET="your_ls_webhook_secret"Optional: enables GPT-4o fallback for messy formats (plain-text, OCR scans).
Without this, Engine 2 is skipped and only regex parsing runs.
All parsing is LOCAL without this key.
export OPENAI_API_KEY="sk-..."Optional: override default ports and directories
export PARSER_DATA_DIR="$HOME/.procurement-agent-data"
export PROCU_WEBHOOK_PORT="3002"Start the webhook server (receives LS payment events β activates license)
node webhook-handler.js &
β Listening on http://localhost:3002/webhook/lemon-squeezy
Never log raw quote content, vendor names, or API keys to stdout. The parser runs entirely locally unless OPENAI_API_KEY is set β in which case Privacy Shield scrubs all sensitive fields before any external call.
Quick Reference
| Situation | Action |
|-----------|--------|
| Supplier quote in plain-text or email | Parse with Engine 1 (regex, <50ms) |
| Invoice has merged cells or OCR artifacts | Engine 2 triggers automatically (if OPENAI_API_KEY set) |
| F1 math error detected on a line item | Line blocked β whole PO escalated to REVIEW |
| F2 price spike >20% above historical avg | CRITICAL alert β auto-block |
| F3 duplicate PO within 7 days | Warning logged β duplicate flagged |
| Circuit breaker trips 2 consecutive approver failures | Safety-Freeze β all POs held for manual approval |
| Lemon Squeezy payment confirmed | Webhook writes to data/licenses.json automatically |
| High-value PO (>$50,000) needs LLM hint | generateLLMHint() called with USD-normalised structure |
| Receiving a quote without API key | Engine 1 regex only; no external calls made |
Installation
Via ClawHub (recommended)
clawhub install autonomous-procurement-agent
Manual
git clone https://github.com/arya-openclaw/autonomous-procurement-agent.git \
~/.openclaw/skills/autonomous-procurement-agent
cd ~/.openclaw/skills/autonomous-procurement-agent
npm install
Lemon Squeezy Webhook Setup
1. Go to your Lemon Squeezy dashboard β Webhooks
2. Add endpoint: https://your-domain.com/webhook/lemon-squeezy
3. Copy the signing secret β set as LS_WEBHOOK_SECRET
4. For local dev, use ngrok: ngrok http 3002
> No PayPal: Lemon Squeezy handles global tax (VAT/GST included in price) and supports Payoneer / World First / Wise payouts. PayPal is not supported due to high dispute fees and China-market account ban risk.
Environment Variables
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| LS_WEBHOOK_SECRET | Yes (prod) | β | HMAC-SHA256 signing secret from LS dashboard. Server refuses to start without it. |
| OPENAI_API_KEY | No | β | OpenAI key. Only needed for Engine 2 (GPT-4o fallback). Without it, all parsing is local. |
| LS_PRO_VARIANT_ID | No | 999 | Lemon Squeezy variant ID for Pro tier |
| LS_ENT_VARIANT_ID | No | 2999 | Lemon Squeezy variant ID for Enterprise tier |
| PARSER_DATA_DIR | No | ~/.procurement-agent-data | Local directory for license DB + historical price baseline |
| CB_THRESHOLD | No | 2 | Circuit breaker failures before Safety-Freeze triggers |
| PROCU_WEBHOOK_PORT | No | 3002 | Webhook HTTP server port |
| LS_STORE_ID | No | β | Lemon Squeezy store ID for API calls |
| LS_API_KEY | No | β | Lemon Squeezy API key for license management |
| OPENAI_MODEL | No | gpt-4o | OpenAI model for LLM fallback (only when OPENAI_API_KEY is set) |
| EXCHANGE_RATE_URL | No | Fixed table | Optional live FX rate API endpoint |
| HISTORICAL_PRICE_URL | No | Built-in baseline | Optional API for F2 historical price baseline |
| PROCU_ALLOWED_TIER | No | β | Dev override β bypasses webhook signature check. Do not use in production. |
Scenarios
1. Cross-Platform Quote Reconciliation > A manufacturing firm receives quotes from three suppliers: one as a CSV export, one as a plain-text email ("qty 8 Γ $2,800 = $22,400"), one as a scanned PDF forwarded from a WhatsApp photo. Procurement Agent normalises all three to a structured comparison table in under a second.
2. B2B Finance Real-Time Risk Audit > Finance receives a β¬47,000 PO from a long-term vendor. The line items all check out mathematically β but F2 flags that the unit price for the primary component is 34% above the 6-month average. The PO is auto-blocked before the CFO's signature is requested.
How F1 / F2 / F3 Work
F1 β Calculation Verification (Enterprise only)
Every line: unit_price Γ quantity β line_total β line blocked, PO escalated.
> Supplier quotes "8 units Γ $2,800 = $22,400". You calculate the same. F1 checks it. Supplier made a $200 arithmetic error in their favour. You catch it before signing.
F1 runs automatically on every parse. No configuration required.
F2 β Price Spike Detection (Enterprise only)
Current price > historical average Γ 1.20 β CRITICAL alert + auto-block.
> Ball bearings purchased at $12/unit for 6 months. New quote: $16/unit. F2 flags this 34% spike before approval.
Baseline import (one-time):
node self-healing-parser.js import-baseline ./historical-prices.json
F3 β Duplicate Quote Detection (Enterprise only)
Same vendor + same total + within 7 days β duplicate warning.
> Two RFQs sent. Supplier responds twice. Finance processes both. F3 catches the duplicate before you pay twice.
Architecture
Supplier quote (any format)
β
βΌ
βββββββββββββββββββββββ
β Engine 1: Regex β β JSON β HTML table β CSV β Plain text
β (< 50ms) β
ββββββββββββ¬βββββββββββ
β
confidence < 0.5
or messy format
β
βΌ
βββββββββββββββββββββββ
β Engine 2: GPT-4o β β Only runs if OPENAI_API_KEY is set.
β (opt-in LLM) β All parsing is LOCAL without this key.
ββββββββββββ¬βββββββββββ
β
ββββββββ΄βββββββ
β Risk Engine β
β F1 / F2 /F3 β β Enterprise only
ββββββββ¬βββββββ
β
risk_score > 0.5
β
βΌ
STATUS: REJECTED_FOR_REVIEW
Parsing Output Format
Every parseQuote() call returns a structured result. Here is the canonical schema:
{
"vendor_name": "Acme Corp",
"po_number": "PO-2024-0041",
"currency": "USD",
"line_items": [
{
"description": "Industrial Ball Bearing",
"quantity": 8,
"unit_price": 2800.00,
"line_total": 22400.00,
"extracted_raw": "8 Γ $2,800 = $22,400",
"f1_flag": false, // true if unit_price Γ qty β line_total
"f2_flag": false, // true if >20% above historical avg
"anomaly": false,
"reason": null
}
],
"subtotal": 22000.00,
"tax": 1980.00,
"total": 23980.00,
"confidence_score": 0.93,
"parse_method": "regex", // "regex" | "llm_fallback" | "html_table" | "csv"
"is_llm_fallback": false,
"variant_detected": null, // "V4" | "V8" | "V10" | null
"anomaly_flags": [],
"fraud_flags": [],
"recommendation": "AUTO_APPROVED", // "AUTO_APPROVED" | "REVIEW" | "REJECT"
"safety_freeze": false,
"llm_error": null
}
Confidence Tiers
| Score | Tier | Meaning |
|-------|------|---------|
| β₯ 0.85 | high | Regex pipeline succeeded cleanly |
| β₯ 0.5 | medium | Partial parse; some fields recovered |
| < 0.5 | low | Unparseable; falls back to LLM or returns error |
Privacy Shield (v1.0.0+)
Before any quote content is sent to the OpenAI API, it passes through a Privacy Shield β a local regex sanitiser that runs before the HTTP request is made. No external services are called; no data leaves your server at this stage.
| Field | Replacement | Example |
|-------|-------------|---------|
| Supplier/vendor name | [VENDOR_MASKED] | "Acme Corp" β "[VENDOR_MASKED]" |
| Monetary amounts | [AMOUNT_MASKED] | "$1,234.56" β "[AMOUNT_MASKED]" |
| Email / phone / fax | [PII_REDACTED] | "john@corp.com" β "[PII_REDACTED]" |
| Street addresses | [PII_REDACTED] | "12 Main St, Shenzhen" β "[PII_REDACTED]" |
Trigger: Privacy Shield is applied automatically whenever OPENAI_API_KEY is set and a quote requires GPT-4o fallback. It does not run in local-only regex mode.
GPT-4o receives enough structure to validate mathematical consistency and detect anomalies β but cannot see actual supplier prices or identities.
License Tiers
| | Free | Pro ($9.99/mo) | Enterprise ($29.99/mo) | |---|---|---|---| | Quotes/month | 20 | 500 | Unlimited | | Parse formats | JSON, HTML, CSV | All formats | All formats + LLM fallback | | F1 Calculation Check | β | β | β Built in | | F2 Price Spike Detection | β | β | β Built in | | F3 Duplicate Detection | β | β | β Built in | | CNYβUSD Normalization | β | β | β | | Approval flow | β | β | β | | Safety-Freeze circuit breaker | β | β | β | | Historical price baseline | β | β | β | | Priority support | β | β | β |
Generic Setup (Other AI Agents)
For Claude Code, Codex, Copilot, or other agents:
mkdir -p ~/.openclaw/skills/autonomous-procurement-agent
git clone https://github.com/arya-openclaw/autonomous-procurement-agent.git \
~/.openclaw/skills/autonomous-procurement-agent
cd ~/.openclaw/skills/autonomous-procurement-agent
npm install
Parse a quote:
node self-healing-parser.js parse '' [format] '{"email":"user@example.com"}'
Periodic Review
Review flagged POs regularly:
# List POs with active risk flags
grep -r "REJECTED_FOR_REVIEW\|CRITICAL\|suspicious" \
~/.procurement-agent-data/logs/ 2>/dev/null | tail -20Check Safety-Freeze status
grep "Safety-Freeze" ~/.procurement-agent-data/logs/*.log 2>/dev/null | tail -5Check license DB health
cat ~/.procurement-agent-data/data/licenses.json | python3 -m json.tool
Best Practices
1. Always set LS_WEBHOOK_SECRET in production β the server refuses to start without it. There is no bypass flag.
2. OPENAI_API_KEY is opt-in β without it, no quote content is ever sent to any external API.
3. Import your historical price baseline before using F2 β without it, F2 spike detection uses a conservative built-in table.
4. Keep PARSER_DATA_DIR backed up β data/licenses.json is the source of truth for all license state.
5. Do not commit data/licenses.json to git β add it to .gitignore. License records are per-install, not per-repo.
6. Use PROCU_ALLOWED_TIER only in local dev β it bypasses webhook signature validation and must never be set in production.
7. Webhook logs are sanitised automatically β sanitize() redacts email addresses and API keys before writing logs.
8. Review F2 spike alerts promptly β F2 is silent until a spike is detected; configure alerts accordingly.
Multi-Agent Support
OpenClaw (primary platform)
Activation: Automatic skill loading via ClawHub or workspace injection.
Detection: Trigger keywords (supplier quote, purchase order, vendor risk, price spike, fraud detection, approval escalation, safety freeze).
Claude Code / Codex
Activation: Direct invocation or workspace injection.
Setup: Copy skill to ~/.openclaw/skills/autonomous-procurement-agent, then:
export LS_WEBHOOK_SECRET="your_secret"
node webhook-handler.js &
Detection: Chat triggers listed above.
GitHub Copilot
Activation: Manual prompt β reference the skill directly in conversation.
Setup: Add to .github/copilot-instructions.md:
## Procurement Fraud DetectionWhen reviewing vendor quotes or purchase orders, use:
~/.openclaw/skills/autonomous-procurement-agent/self-healing-parser.js
Set OPENAI_API_KEY for LLM fallback on messy formats.
Agent-Agnostic Guidance
Regardless of agent, apply Autonomous Procurement Agent when:
1. A supplier quote arrives in a non-standard format β plain-text, merged-cell spreadsheet, OCR scan. 2. Multiple currencies need to be compared β CNY, USD, EUR reconciliation. 3. A high-value PO needs validation β F1 catches math errors; F2 catches price spikes. 4. Duplicate invoices are suspected β F3 detects same-vendor same-total within 7 days. 5. Approval thresholds need to be enforced automatically β Safety-Freeze on circuit breaker trip.
π Tips & Best Practices
1. Always set LS_WEBHOOK_SECRET in production β the server refuses to start without it. There is no bypass flag.
2. OPENAI_API_KEY is opt-in β without it, no quote content is ever sent to any external API.
3. Import your historical price baseline before using F2 β without it, F2 spike detection uses a conservative built-in table.
4. Keep PARSER_DATA_DIR backed up β data/licenses.json is the source of truth for all license state.
5. Do not commit data/licenses.json to git β add it to .gitignore. License records are per-install, not per-repo.
6. Use PROCU_ALLOWED_TIER only in local dev β it bypasses webhook signature validation and must never be set in production.
7. Webhook logs are sanitised automatically β sanitize() redacts email addresses and API keys before writing logs.
8. Review F2 spike alerts promptly β F2 is silent until a spike is detected; configure alerts accordingly.