# Smart Trade AI — Product Requirements Document

> Compiled based on actual user business needs. Last updated: 2026-05-11.

---

## ⚠️ Core Constraint: Full Windows & macOS Compatibility

> **This project must run normally on both Windows and macOS. All feature designs, code implementations, and path handling must consider both platforms simultaneously.**

| Constraint | Requirement |
|-----------|------------|
| **Path Handling** | Use `pathlib.Path` uniformly. Hardcoding `/` or `\` is prohibited |
| **File Naming** | Use lowercase + hyphens (slug) uniformly. Windows reserved characters `<>:"/\|?*` are prohibited |
| **Directory Depth** | ≤ 3 levels, ensure no violation of Windows MAX_PATH (260 character) limit |
| **Case Sensitivity** | Windows is case-insensitive. File names must be uniformly lowercase to avoid conflicts |
| **Newlines** | Use `utf-8` + `newline=''` when reading/writing text files (Python handles `\r\n` automatically) |
| **Shell Commands** | Do not concatenate shell commands directly in code. Hermes bundles MinGit on Windows |
| **Environment Variables** | Use `TRADE_HOME` (macOS: `~/.trade/`, Windows: `%LOCALAPPDATA%\trade\`) |
| **Installation** | macOS via `curl ... | bash` (same as Hermes), Windows via PowerShell script |

**Hermes upstream Windows support status** (as of May 2026 Hermes README):
- Windows native is **Early Beta**, with a one-click PowerShell install script
- Install path: `%LOCALAPPDATA%\hermes\`
- Bundles MinGit (portable Git Bash) for shell command execution
- WSL2 path is identical to Linux (`~/.hermes/`), the most "battle-tested" Windows approach

**This project's stance on Windows**:
- Goal: Full feature parity with macOS
- Minimum requirement: Windows 10 and above
- Terminal: PowerShell 5.1+ or Hermes-bundled MinGit Bash
- Filesystem: NTFS (default) or ReFS

---

## I. Project Positioning

**AI sales assistant for foreign trade companies.** Not a simple document Q&A tool, but an intelligent sales system covering the entire "lead generation → conversion" chain.

Traditional foreign trade companies face two core problems:
1. **Lead generation (finding customers)**: How to find more potential customers?
2. **Conversion (securing orders)**: How to turn potential customers into actual orders?

Smart Trade AI trains the Hermes Agent to learn the thinking patterns and business skills of top salespeople, helping foreign trade sales staff improve efficiency in both lead generation and conversion.

**Core Architecture**: Agent Loop — The LLM autonomously decides what files to read, what information to search, and what content to generate, iterating over multiple rounds until the task is complete.

---

## ⚠️ Core Constraint: Code Architecture (High Cohesion, Low Coupling)

> Business logic must be split. Single scripts/modules must not be too long. Modules should have high internal cohesion and low coupling between modules.
> Added 2026-05-12.

### Rules Overview

| | Rule | Description |
|---|------|-------------|
| **Single Responsibility** | Each module (`.py` file) handles only one thing |
| **File Line Count Limit** | Single `.py` file ≤ 500 lines; must be split if exceeded |
| **No God Modules** | `utils.py` and `helpers.py` must not accumulate unrelated functions |
| **No Reverse Hierarchical Calls** | Upper-level modules can call lower-level ones; lower-level modules must not reference upper-level ones |
| **Dependency Direction = Call Direction** | If module A imports module B, B must not circularly import A |

### Module Layered Architecture

```
trade/                          # Business layer (topmost, calls all lower layers)
├── api.py                      # HTTP routes (≤ 800 lines), request parsing + response assembly only
├── helpers.py                  # Thin glue functions shared across modules (config parsing, prompt construction)
├── prompt.py                   # System prompt templates (pure data)
│
├── company.py                  # Company entity (single responsibility: company CRUD)
├── library.py                  # Document library entity (single responsibility: library CRUD)
├── customer.py                 # Customer entity (single responsibility: customer CRUD)
├── chat_memory.py              # Chat memory (single responsibility: conversation CRUD)
│
└── database.py                 # Data access layer (single responsibility: DB connection + schema + migration)
```

**Layer Description**:

| Layer | Module | Responsibility | Can Call |
|-------|--------|---------------|----------|
| L1 (Entry) | `api.py` | HTTP parsing, response, SSE streaming | L2 |
| L2 (Business) | `company`/`library`/`customer`/`chat_memory` | Business entity CRUD | L3 |
| L3 (Data) | `database.py` | DB connection, schema, migration | None (pure utility) |
| L4 (Data) | `helpers.py` / `prompt.py` | Config parsing, prompt templates | L3 (helpers only) |

### Split Trigger Conditions

When a module meets any of the following conditions, **it must be split immediately**:

```
1. Total lines > 500
2. Responsibility types > 1 (excluding pure data structures)
3. Import chains unrelated to the current module exist
4. Testing requires mocking more than 3 external dependencies
```

### Split Operation Guidelines

**Problematic Module** → **Split Steps**:

```
1. Identify all responsibilities handled by the module
2. Split into independent .py files by responsibility (single responsibility)
3. Place new modules at the same or next layer (dependency direction downward)
4. Demote the original module to a thin forwarding layer (import + re-export only)
5. Ensure no circular dependencies
```

**Example**: If `chat_memory.py` grows to 600 lines, handling both conversation CRUD and hindsight calls:

```
chat_memory.py (600 lines)
    ├── chat_memory.py          # conversation CRUD (demoted to thin layer, ≤ 100 lines)
    └── memory.py                # Hindsight client wrapper (new L2 module)
```

### Prohibited Patterns

```
U+274C utils.py (universal toolbox accumulating unrelated functions)
U+274C helpers.py exceeding 200 lines
U+274C api.py containing business logic (DB operations, entity validation)
U+274C L3 modules (lower layer of L2) importing L2 modules
U+274C Cross-layer call chain: api.py → database.py → api.py (circular)
```

### Code Comment Standards

> Code must contain sufficient Chinese annotations so readers can understand intent and logic without reading implementation details.
> Added 2026-05-12.

**All functions must have docstrings**:

```python
def get_library(library_id: int, company_id: int) -> dict | None:
    """Retrieve a document library by ID for the specified company.

    Args:
        library_id: Document library primary key ID
        company_id: Company primary key ID (for data isolation validation)

    Returns:
        Document library dict (containing id/name/root_path/description/created_at);
        Returns None if not found or not belonging to the company.

    Raises:
        No exceptions; all error cases return None.
    """
```

**Complex logic must have line-by-line comments**:

```python
# U+274C Bad: No comments
result = [x for x in items if x.get("active") and x.get("company_id") == cid]

# U+2705 Good: Line-by-line comments
active_items = [x for x in items if x.get("active")]      # Step 1: Filter active items
company_items = [x for x in active_items                   # Step 2: Filter by company
                 if x.get("company_id") == cid]
```

**Every if/branch must have an explanation**:

```python
if not agent_identity:
    # No company identity config: use generic system prompt (degrade strategy)
    system_parts = [TRADE_SYSTEM_PROMPT]
else:
    # Inject company identity: company name, product scope, sales style
    system_parts = [TRADE_SYSTEM_PROMPT, "", "## Company Identity Configuration", agent_identity]
```

**Code blocks between sections must be separated by comments**:

```python
# =====================================================================
# Section 1: Health Check (Provider Check → Model Config Check)
# =====================================================================

# =====================================================================
# Section 2: Query Construction (Company Identity → Prompt Assembly → Library Context Injection)
# =====================================================================
```

**Comment Coverage Requirements**:

| | Code Type | Minimum Requirement |
|---|-----------|-------------------|
| Function docstring | All (including private functions) |
| if/branches | Every branch must have an explanation |
| Loops | Complex loops must have inline comments |
| Exception handling | Explain why try/except and the handling strategy after catching |
| API routes | Inline comment explaining business meaning (e.g., `# Company ID required, otherwise data cannot be isolated`) |
| Critical business logic | Comment explaining decision basis and business rules |

**CI Check** (optional, using `radon` or `lizard`):

```bash
# Check comment density, alert below 15%
radon cc -a trade/ -e "migrations|__pycache__"
```

### Verification Mechanism

Confirm before each commit:

```bash
# Check line counts
find trade/ -name "*.py" -exec wc -l {} \; | awk '$1 > 500 {print}'

# Check circular dependencies (meld / pydeps)
python -c "import trade.api; import trade.company; print('OK')"
```

---

> **Smart Trade AI must install Hermes from `chefroger/hermes-agent`, not from any other source.**

### Version Locking Strategy

| Strategy | Description |
|----------|-------------|
| **Install Source** | `git+https://github.com/chefroger/hermes-agent.git` (only valid source) |
| **Version Declaration** | Pin to a specific git tag or commit hash in `pyproject.toml` |
| **Startup Check** | `server.py` validates the Hermes version on startup; refuses to start if mismatch |
| **Upgrade Protocol** | After Hermes upgrade, must pass compatibility check (see below) before updating Trade's version pin |

### Pre-Installation Check (pre_install_check)

Since `pip install trade` does not automatically install hermes-agent (dependency declaration is just a declaration and does not trigger installation order),
Trade provides `pre_install_check.py` to proactively detect hermes-agent status **before** installing trade:

```
Before installing trade
    │
    └─ python pre_install_check.py
           │
           ├─ hermes-agent not installed → exit 1 + print chefroger fork install instructions
           ├─ Installed but wrong source (NousResearch) → exit 2 + uninstall/reinstall instructions
           ├─ Version too low (< 0.12.0) → exit 2 + upgrade instructions
           └─ Version compatible (>= 0.12.0, chefroger fork) → exit 0 → proceed with trade install
```

**Exit Codes**:

| Exit Code | Meaning |
|-----------|---------|
| 0 | Compatible, proceed with `pip install trade` |
| 1 | hermes-agent not installed, please install first |
| 2 | hermes-agent version incompatible or wrong source |

**Installing the chefroger fork of Hermes**:

```bash
# Official one-click install (using chefroger fork, not NousResearch)
curl -fsSL \
  https://raw.githubusercontent.com/chefroger/hermes-agent/main/scripts/install.sh \
  | bash

# Or clone manually
git clone --branch main \
  https://github.com/chefroger/hermes-agent.git \
  ~/.hermes/hermes-agent
cd ~/.hermes/hermes-agent
uv pip install -e .   # or pip install -e .
```

**Pre-check script location**: Project root directory `pre_install_check.py` (343 lines, stdlib-only, no external dependencies).

### Prerequisite Software Dependency Matrix

> The following are all prerequisite software required for hermes-agent to run on various operating systems.
> **Required** = Core features cannot run without it; **Optional** = Corresponding features degrade when missing but do not block operation.

#### Windows (PowerShell)

| Priority | Software | Version Requirement | Installation Method | Description |
|----------|----------|-------------------|-------------------|-------------|
| **Required** | Python | ≥ 3.11 | Automatically installed via uv by Hermes installer | Runtime core |
| **Required** | Git (with Bash) | Any | Hermes installer automatically downloads PortableGit | Required for terminal tool and agent-browser |
| **Required** | uv | Latest | Hermes installer automatically installs | Python package manager |
| **Optional** | Node.js | ≥ 22 LTS | `winget install OpenJS.NodeJS.LTS` | Required for Hermes browser tool |
| **Optional** | ripgrep | Any | `winget install BurntSushi.ripgrep.MSVC` | Speeds up Hermes file search |
| **Optional** | ffmpeg | Any | `winget install Gyan.FFmpeg` | Required for TTS voice messages |

> **Note**: Git is **required**, not optional, on Windows. Hermes' terminal tool and agent-browser depend on the Git Bash environment.
> The Hermes installer (`install.ps1`) will automatically download PortableGit (isolated installation, no admin privileges required).

#### macOS

| Priority | Software | Version Requirement | Installation Method | Description |
|----------|----------|-------------------|-------------------|-------------|
| **Required** | Xcode Command Line Tools | Any | `xcode-select --install` | Provides git, make, clang |
| **Optional** | Homebrew | Latest | `/bin/bash -c "$(curl -fsSL ...)"` | Simplifies subsequent package management, not required |
| **Optional** | Python | ≥ 3.11 | Hermes installer manages via uv | Automatic |
| **Optional** | Node.js | ≥ 22 LTS | `brew install node@22` | Required for browser tool |
| **Optional** | ripgrep | Any | `brew install ripgrep` | Speeds up file search |
| **Optional** | ffmpeg | Any | `brew install ffmpeg` | Required for TTS voice messages |
| **Optional** | Playwright Chromium | Any | `npx playwright install --with-deps chromium` | Required for browser automation |

#### Linux (Debian/Ubuntu)

| Priority | Software | Installation Command |
|----------|----------|---------------------|
| **Required** | curl, git, ca-certificates | `sudo apt install curl git ca-certificates` |
| **Required** | build-essential (C compilation tools) | `sudo apt install build-essential python3-dev libffi-dev` |
| **Optional** | ripgrep | `sudo apt install ripgrep` |
| **Optional** | ffmpeg | `sudo apt install ffmpeg` |
| **Optional** | Node.js ≥ 22 | `curl -fsSL https://deb.nodesource.com/setup_22.x \| sudo -E bash - && sudo apt install nodejs` |
| **Optional** | Playwright Chromium | `npx playwright install --with-deps chromium` |

#### Linux (Fedora/RHEL/CentOS)

| Priority | Software | Installation Command |
|----------|----------|---------------------|
| **Required** | curl, git | `sudo dnf install curl git` |
| **Required** | gcc, gcc-c++, make, python3-devel, libffi-devel | `sudo dnf install gcc gcc-c++ make python3-devel libffi-devel` |
| **Optional** | ripgrep | `sudo dnf install ripgrep` |
| **Optional** | ffmpeg | `sudo dnf install ffmpeg` |

#### Termux (Android)

| Priority | Software | Installation Command |
|----------|----------|---------------------|
| **Required** | clang, rust, make, pkg-config, libffi, openssl, ca-certificates, curl, git | `pkg install clang rust make pkg-config libffi openssl ca-certificates curl git` |

#### One-Click Prerequisite Install Scripts

| Script | Platform | Path |
|--------|----------|------|
| `install_prereqs.sh` | macOS / Linux / Termux | `scripts/install_prereqs.sh` |
| `install_prereqs.ps1` | Windows (PowerShell) | `scripts/install_prereqs.ps1` |

Usage:

```bash
# macOS / Linux
chmod +x scripts/install_prereqs.sh
./scripts/install_prereqs.sh

# Windows (PowerShell)
powershell -ExecutionPolicy Bypass -File scripts/install_prereqs.ps1
```

> Both scripts only install system dependencies, **not including Hermes Agent itself**. Hermes is installed via the official `install.sh` / `install.ps1`.

### Version Check Flow

```
Trade startup (python server.py)
    │
    ├─ 1. Read hermes_cli.__version__ → "0.12.0"
    ├─ 2. Compare against Trade's declared compatible version range
    │      ├─ Match → Normal startup
    │      └─ No match → Print error and exit:
    │           "Hermes version 0.13.0 is not compatible.
    │            Foreign Trade Assistant requires hermes-agent>=0.12.0,<0.13.0.
    │            Please run: pip install 'hermes-agent>=0.12.0,<0.13.0'"
    └─ 3. Startup log records Hermes version number
```

### Upgrade Compatibility Checklist

When Hermes releases a new version, the following checks must be performed on the Trade side before updating the version pin:

1. [ ] `from hermes_agent import AIAgent` imports successfully
2. [ ] `AIAgent(quiet_mode=True, max_iterations=90, ...)` initializes successfully
3. [ ] `agent.chat("Hello")` returns a string
4. [ ] `from hermes_cli.config import load_config` works normally
5. [ ] `from hermes_cli.auth import PROVIDER_REGISTRY` works normally
6. [ ] `MemoryProvider` ABC interface unchanged (all method signatures match in cognee plugin)
7. [ ] Trade's `/api/trade/chat` and `/api/trade/chat/stream` endpoints respond normally
8. [ ] `trade_chat.html` frontend loads normally

### Version Record

After each Hermes upgrade, record in the `COMPATIBILITY.md` file in the Trade repository:

```markdown
| Hermes Version | Compatibility Status | Test Date | Notes |
|---------------|---------------------|-----------|-------|
| 0.12.0        | U+2705 Compatible   | 2026-05-11 | Current locked version |
| 0.13.0        | U+23F3 Pending Test | -         |       |
```

---

## II. Target Users & Runtime Environment

| Dimension | Description |
|-----------|-------------|
| Users | Foreign trade company owners / sales staff, non-technical background |
| Hardware | 16 GB office machine (Windows / macOS) |
| Concurrency | No concurrency needed |
| Privacy | Documents analyzed locally, API keys provided by users |
| Platform | macOS / Linux / Windows (native + WSL2) |

### 2.1 Cross-Platform Path Design

Referencing the `HERMES_HOME` pattern from Hermes Agent, Trade uses the `TRADE_HOME` environment variable to control the data directory.

| Platform | Hermes Directory | Trade Directory |
|----------|-----------------|----------------|
| macOS | `~/.hermes/` | `~/.trade/` |
| Linux / WSL2 | `~/.hermes/` | `~/.trade/` |
| Windows native | `%LOCALAPPDATA%\hermes\` | `%LOCALAPPDATA%\trade\` |

**Windows compatibility measures**:
- All path operations use `pathlib.Path` uniformly, no hardcoded separators
- Directory names / file names are uniformly lowercase + hyphens (slug format), avoiding case sensitivity issues
- Directory depth ≤ 3 levels, not exceeding Windows MAX_PATH limit
- Reuse MinGit bundled with Hermes on Windows for shell command execution

---

## III. Multi-Company Architecture (Multi-Tenancy)

> Each company has independent AI identity, document libraries, customers, and conversation records. Data is completely isolated.
> Added 2026-05-11.

### Architecture Overview

```
companies ──────────── trade_companies
    │                        │
    │ 1:N                    │ 1:1 (each company corresponds to one Trade config record)
    ▼                        ▼
libraries ──────────── conversations
    │
    ▼
customers
```

**Data isolation**: All API endpoints and database queries filter by `company_id`. Cross-company data is completely isolated.

### Database Changes

| | Table | Change | Description |
|---|-------|--------|-------------|
| | `companies` | New | Basic company info (name, slug, contact, is_active) |
| | `trade_companies` | New | Trade-specific config (data_dir, agent_identity_md) |
| | `libraries` | +company_id | FK → companies(id), cascade delete |
| | `customers` | +company_id | FK → companies(id), cascade delete |
| | `conversations` | +company_id | FK → companies(id), cascade delete |

**Spare Columns**: All tables reserve 3 TEXT-type spare columns (`extra1`/`extra2`/`extra3`), default `'{}'`, for storing JSON-structured extension fields, avoiding the need for ALTER TABLE on future schema changes. All 6 tables have a total of 18 spare columns.

| | Table | extra1 | extra2 | extra3 |
|---|-------|--------|--------|--------|
| | `companies` | `{"industry":"","country":""}` | `{"employee_count":"","annual_revenue":""}` | Reserved for future extension |
| | `trade_companies` | `{"max_iterations":90,"temperature":0.7}` | `{"model":"","provider":""}` | Reserved for future extension |
| | `libraries` | `{"scan_depth":3,"file_count":0,"last_scan":""}` | `{"indexed":false,"index_version":1}` | Reserved for future extension |
| | `customers` | `{"country":"","website":"","linkedin_url":""}` | `{"customer_type":"","tier":"","source":""}` | Reserved for future extension |
| | `customer_libraries` | `{"relevance_score":0.0,"notes":""}` | Reserved for future extension | Reserved for future extension |
| | `conversations` | `{"tokens_used":0,"model":"","duration_ms":0}` | `{"rating":null,"feedback":""}` | `{"tools_used":[],"iterations":0}` |

Idempotent supplement mechanism: `_add_spare_columns(conn)` is called once each in `init_db()` and `_migrate_from_v0()`, using `ALTER TABLE ADD COLUMN` (SQLite silently ignores if column already exists), supporting safe repeated execution.

### v0 Migration

On first startup, detect the old schema (without `company_id` column), automatically execute migration:
1. Create `companies` and `trade_companies` tables
2. Create default company "My Company" (slug=default)
3. Add `company_id` column to existing `libraries`/`customers`/`conversations` tables, set to 1
4. Add new indexes: `idx_libraries_company`, `idx_customers_company`, `idx_conversations_company`

### Agent Identity Injection

Each company can configure its own AI identity (`agent-identity.md` content or `agent_identity_md` field). Injected into system prompt during Chat:

```
TRADE_SYSTEM_PROMPT

## Company Identity Configuration     ← Injected from company agent_identity_md
You are a sales assistant for a professional foreign trade company...
```

**Priority**: `trade_companies.agent_identity_md` (database field) > `~/.trade/{slug}/agent-identity.md` (file) > Empty (use generic prompt)

### API Route Changes

All data endpoints (libraries/customers/conversations) require the `X-Company-ID` Header.

| Endpoint | Change |
|----------|--------|
| `GET /companies` | New |
| `POST /companies` | New |
| `GET/PUT/DELETE /companies/{id}` | New |
| `GET/PUT /companies/{id}/agent-identity` | New |
| `GET /libraries` | + X-Company-ID, changed to `list_by_company()` |
| `POST /libraries` | + company_id |
| `GET /customers` | + X-Company-ID, changed to `list_by_company()` |
| `POST /customers` | + company_id |
| `GET/POST /conversations` | + X-Company-ID |
| `POST /chat` | + X-Company-ID required | `HERMES_YOLO_MODE=true` set automatically, no user approval needed |
| `POST /chat/stream` | + X-Company-ID required | Same as above |

### Frontend Multi-Company UI

- Top of sidebar: Company selection dropdown + Add Company button
- Show onboarding page when no company exists, do not allow sending messages
- Switching companies automatically clears the current conversation and loads the new company's library/customer list
- `sessionStorage['trade_company_id']` saves the current company ID (persists across refreshes)

### File Structure

```
~/.trade/                         # TRADE_HOME (runtime data)
├── default/                      # slug=default company data directory
│   ├── company-profile.md
│   ├── agent-identity.md
│   ├── products.md
│   ├── clients/
│   └── libraries/
└── another-company/              # Second company
    ├── company-profile.md
    └── ...

.trade-template/                  # Showcase templates in repository (copied to ~/.trade/ on install)
```

---

## III. Core Business Features

### 3.1 Lead Generation — Finding Customers

#### 3.1.1 B2B Platform Diagnosis & Optimization

Users provide product links from Alibaba International Station / Made-in-China / independent websites. The Agent diagnoses the platform store and provides improvement suggestions:
- Analyze the quality and coverage of product titles, keywords, and descriptions
- Check whether product images and videos comply with platform best practices
- Compare with top competitor stores, identify gaps and optimization directions
- Output directly executable product publishing / modification checklists

**Input**: Platform store link or product link
**Output**: Diagnostic report + improvement plan (title optimization, keyword suggestions, description templates, image requirements)

#### 3.1.2 Social Media Content Strategy & Material Generation

Users provide competitor social media account links (Facebook / Instagram / TikTok / YouTube). The Agent learns the competitor's content strategy and generates a social media publishing plan based on the company's products:
- Analyze competitor content types, publishing frequency, engagement data, and hashtag strategies
- Generate a social media content calendar suitable for the company's products (weekly / monthly plan)
- Provide ready-to-publish specific posts (copy + image suggestions + hashtags)

**Input**: Competitor social media links (multiple allowed) + company product materials
**Output**: Social media publishing plan + content calendar + specific posts (ready to copy-paste and publish)

#### 3.1.3 LinkedIn Marketing Plan

Users provide company product materials. The Agent generates a complete LinkedIn marketing plan using LinkedIn B2B development methods:
- **Customer Profile**: Define target customers based on product characteristics (position, industry, region, company size)
- **Personal Account Setup**: Content templates for profile photo, background image, headline, About section
- **Company Page Setup**: Company introduction, product showcase, employee invitation strategy
- **Annual Marketing Plan**: Includes planned timeline and specific execution content, ready to copy-paste and use
- **Content Material Library**: Template library for industry insight posts, product value posts, customer case posts

**Input**: Company product catalog / specification sheet + industry materials
**Output**: Customer profile + account setup templates + company page content + annual marketing plan (with schedule)

#### 3.1.4 Customs Data / Canton Fair Data Mining

Users upload customs data (import/export records) or Canton Fair exhibitor data. The Agent automatically filters:
- Extract target customers (buyers / importers) in the industry from the data
- Analyze customer purchasing patterns (frequency, quantity, category, season)
- Output prioritized target customer list
- Provide development suggestions for each customer (entry point, recommended products, expected order volume)

**Input**: Customs data file (CSV / Excel) + company product scope
**Output**: Industry target customer list + development priority + development strategy for each customer

---

### 3.2 Conversion — Securing Orders

#### 3.2.1 AI Senior Salesperson

The Agent trains to become an AI with senior foreign trade salesperson thinking patterns and business skills by learning the following materials:

**Training materials**:
1. Senior salesperson thinking methodology

**Capability requirements**:
- Understand B2B sales psychology and decision-making chains
- Master the full foreign trade process: Inquiry → Quote → Negotiation → Close → Order follow-up
- Adjust communication strategies based on different customer types (price-sensitive / quality-oriented / relationship-oriented)
- Handle common customer objections (price too high, existing supplier, no immediate need, etc.)

#### 3.2.2 Customer Analysis & Outreach Emails

Users paste potential customer information found on LinkedIn or other channels to the Agent. The Agent analyzes the customer and generates outreach emails:

**Analysis Dimensions**:
- **Customer Company**: Size, main products, market positioning, supply chain characteristics
- **Contact Person**: Position, decision-making authority, potential purchasing focus areas
- **Fit**: Alignment points with our products, entry angle

**Output Content**:
- Customer analysis report (company profile + contact persona + entry suggestions)
- Customized outreach email / LinkedIn InMail (ready to copy-paste and send)
- Follow-up message sequence (Day 1 / Day 3 / Day 7 / Day 14)
- Initial communication talking points and common question contingency plans

**Input**: LinkedIn customer link or customer information text (company name + contact + position)
**Output**: Customer analysis report + outreach email / message + follow-up plan

---

### 3.3 Document Library Management & Product Q&A

#### 3.3.1 Document Library Management

- Create document library → Link to local directory
- Each customer can be linked to multiple document libraries (many-to-many)
- Supports 16 file formats:

| Category | Format | Processing Method |
|----------|--------|------------------|
| Text-based PDF | `.pdf` | PyMuPDF text extraction; OCR if < 500 characters |
| Scanned PDF | `.pdf` | Tesseract OCR |
| Modern Word | `.docx` | python-docx extract paragraphs + tables |
| Legacy Word | `.doc` | LibreOffice → `.docx` → python-docx |
| Modern Excel | `.xlsx` | openpyxl read cells |
| Legacy Excel | `.xls` | xlrd read |
| Excel Template | `.xlt` | LibreOffice → `.xlsx` → openpyxl |
| CSV | `.csv` | Python csv module |
| Numbers | `.numbers` | zipfile parse internal XML |
| Modern PPT | `.pptx` | python-pptx extract text |
| Legacy PPT | `.ppt` | LibreOffice → `.pptx` → python-pptx |
| HTML | `.html` | BeautifulSoup extract body text |
| Markdown / Plain Text | `.md` / `.txt` | Native read |
| Images | `.jpg` / `.png` / `.jpeg` | Tesseract OCR |

#### 3.3.2 Intelligent Product Q&A

```
User natural language question
  → Agent lists directory files
  → Agent determines which are relevant to the question
  → Agent reads files one by one (natively understands PDF / Excel / Word / image OCR)
  → Not enough info? Continue reading more
  → Cross-reference and synthesize all information
  → Generate answer + annotate source files
```

- Agent autonomously decides what to read, how much to read, and when to stop — no hard truncation
- Answers must include precise data + units + source file annotations
- Maximum 90 rounds of tool-calling iterations, maximum 10 minutes per session

---

### 3.4 New Company Marketing Onboarding

New companies wanting to deploy a complete marketing strategy with Smart Trade AI need to prepare the following materials:

| # | Required Material | Description |
|---|------------------|-------------|
| 1 | **Company Introduction** | Own core advantages. Basic version can be polished and optimized by the Agent |
| 2 | **Product Introduction** | Product catalog, product specification sheets, industry product scope list |
| 3 | **Competitor Companies** | Competitor company names / links (for competitive analysis and differentiation positioning) |
| 4 | **LinkedIn Account** | Company page + sales representative personal account (provide if available) |

After receiving the above materials, the Agent can output at once: Optimized company introduction + product marketing positioning + differentiation strategy + complete LinkedIn plan + outreach email templates + social media content calendar.

---

### 3.5 Automated Scheduled Tasks (Daily Sales Engine)

> Detailed design in [Foreign Trade Knowledge Base.md - Chapter 12](Foreign Trade Knowledge Base.md)

Formalizes the daily work routine of foreign trade salespeople into Hermes cron scheduled tasks. The Agent triggers on time and automatically prepares content; the salesperson only needs to execute and copy-paste.

**Core Mechanism**: Using Hermes' built-in cron system (`cron.create_job`), automatically creates 7 scheduled tasks based on the foreign trade salesperson's daily workflow. The Agent automatically executes prompts at the set time, generating executable content pushed to the salesperson.

**7 Scheduled Tasks Overview**:

| Time | Task | Trigger Action |
|------|------|---------------|
| 08:00 (Weekdays) | Morning Briefing | Agent summarizes yesterday's interactions + today's follow-up list + customer time zone window reminders |
| 09:30 (Weekdays) | LinkedIn Content Publishing | Agent generates today's Post + Article drafts (ready to copy-paste and publish) |
| 10:00 (Weekdays) | European Customer Outreach | Agent filters European customers → generates follow-up emails → salesperson sends |
| 11:00 (Weekdays) | B2B Platform Data Check | Agent checks platform inquiries, product rankings, competitor activity |
| 14:00 (Weekdays) | Social Media Content Publishing | Agent generates FB / Insta / TikTok posts |
| 16:00 (Weekdays) | North American Customer Outreach | Agent filters North American customers → generates follow-up emails → salesperson sends |
| 17:30 (Weekdays) | Daily Work Summary | Agent compiles today's data → appends to daily work report |
| 17:30 (Every Friday) | Weekly Report Generation | Agent compiles this week's daily reports → generates weekly report |

**Initialization Method**:
```
trade cron setup-trade-tasks
```
One-click creation of all scheduled tasks, no manual configuration needed.

### 3.6 Standardized Data Directory (`~/.trade/`)

> See [Trade Data Directory Structure Design.md](Trade Data Directory Structure Design.md)

Referencing Hermes `~/.hermes/` design, establish a standardized local Markdown knowledge base for each company. Unified structure, fixed filenames, progressive filling.

**Top-level Structure** (`~/.trade/` or `%LOCALAPPDATA%\trade\`):
```
.trade/
├── companies/{slug}/              # Companies (one directory each, 8 fixed files)
│   ├── company-profile.md         # Company introduction
│   ├── products.md                # Product catalog and advantages
│   ├── business-scope.md          # Business scope
│   ├── agent-identity.md          # Agent role definition
│   ├── competitors.md             # Competitor analysis
│   ├── certifications.md          # Qualifications and certifications
│   ├── marketing-strategy.md      # Marketing strategy
│   ├── sales-playbook.md          # Sales playbook
│   ├── libraries/{lib}/           # Document libraries (3 fixed files + extracts/)
│   │   ├── index.md               # File index
│   │   ├── changelog.md           # Content change log
│   │   ├── metadata.md            # Meta information
│   │   └── extracts/{file}.md     # Document analysis extracts
│   └── clients/{client}/          # Customers (7 fixed files)
│       ├── profile.md             # Customer profile
│       ├── contacts.md            # Contacts
│       ├── interactions.md        # Interaction records and taboos
│       ├── requirements.md        # Requirements record
│       ├── quotes.md              # Quote history
│       ├── orders.md              # Order records
│       └── notes.md               # Notes
```

**Core Design**: File names are identical across all company directories. Initially empty templates, progressively filled. On startup, the Agent automatically reads the current company's `agent-identity.md` as its role definition.

**Initialization Command**: `trade init-company --name "Company Name" --slug "slug"`

### 3.7 Customer Management

- Customer CRUD + linked document libraries (many-to-many)
- Each customer's quotations, contracts, and communication records managed independently
- Customer profiles automatically compiled (extracting customer-related information from multiple documents)

### 3.8 First-Run Onboarding

> When new users open the app for the first time, guide them through company registration and Agent identity configuration in one step.
> Added 2026-05-12.

**User Flow**:

```
First time opening /trade
    │
    ├─ GET /api/trade/onboarding/status
    │      └─ {done: false}  → Show onboarding page
    │
    └─ POST /api/trade/onboarding/first-company
           Body: {company_name, contact_name, contact_email,
                  identity_data: {role, products, differentiation, target_region}}
           │
           ├─ company.create()              # Create company record + ~/.trade/{slug}/ directory
           ├─ update_trade_company()        # Write agent_identity_md to DB
           ├─ Write ~/.trade/{slug}/agent-identity.md  # File backup
           └─ Return {company, trade_company}
                  └─ Frontend navigates to normal chat interface
```

**Unified API**:

| Endpoint | Method | Description |
|----------|--------|-------------|
| `/api/trade/onboarding/status` | GET | Returns `{done: bool}`, frontend decides whether to show onboarding page or normal UI |
| `/api/trade/onboarding/first-company` | POST | Atomic creation of company + Agent identity configuration |

**Idempotent Protection**: `POST /onboarding/first-company` returns 409 when active companies already exist. Refreshing the page won't trigger duplicate execution.

**Agent Identity Template**:

```markdown
## Company Identity Configuration

You are an AI sales assistant for a professional foreign trade company.

**Company Name**: {company_name}
**Product Scope**: {products}
**Differentiation Selling Points**: {differentiation}
**Target Market**: {target_region}

**Communication Style**: Professional, concise, no fluff...
```

**Onboarding Module**: `trade/onboarding.py` (single responsibility: onboarding status detection + first company creation), `api.py` only handles HTTP parsing and response assembly.

### 3.9 Conversation Memory & Knowledge Graph

- Conversation history persists across sessions (`conversations` table)
- Cognee Knowledge Graph memory: Document content, customer requirements, product parameters automatically establish entity-relationship connections
- Agent proactively uses `cognee_remember` to store important facts, `cognee_recall` to retrieve across sessions

### 3.11 OSINT Customer Background Check & Risk Assessment (Upgraded Due Diligence)

> Added 2026-05-12. Originates from real needs identified in customer due diligence conversations: single email platform detection is insufficient; multi-signal cross-validation is needed.

#### 3.11.1 Current Status & Gaps

**Current `b2b-email-intel` capabilities**:
- Only detects email registration status on 121+ mainstream platforms (`holehe`)
- Output: Platform name | Registered or not | Username | Profile URL

**Real due diligence needs revealed in conversations** — Complete due diligence requires cross-validation across 5 dimensions:

| Verification Dimension | Current | Target |
|----------------------|---------|--------|
| Email platform registration | U+2705 `holehe` | Retain |
| Domain registration info | U+274C Missing | WHOIS lookup (registration date/registrar/expiry date) |
| Corporate email verification | U+274C Missing | `@company.com` vs Gmail/QQ personal email detection |
| Website tech stack | U+274C Missing | BuiltWith detection (WordPress/Shopify/Custom) |
| Sanctions list screening | U+274C Missing | OFAC/UN/EU/China sanctions cross-referencing |

**Core Insight (from conversations)**: A single signal is insufficient; multi-signal cross-validation is needed. For example:
- LinkedIn page looks real, but the domain was registered 3 months ago → Red flag
- Corporate email uses `gmail.com` instead of `@company.com` → Red flag
- Website tech stack is a free blogging platform → Red flag

#### 3.11.2 Multi-Layer Verification Architecture

```
User input: Company name / Email / Website URL
    │
    ├─────────────────────────────────────────────────────────────┐
    │  Layer 1: Email Basic Detection (holehe, existing)            │
    │  ├─ holehe email registration check (121+ platforms)         │
    │  └─ Output: found_count, social profile URL list              │
    └─────────────────────────────────────────────────────────────┘
                          ↓
    ├─────────────────────────────────────────────────────────────┐
    │  Layer 2: Domain Deep Lookup (New)                           │
    │  ├─ WHOIS query: Registration date / Registrar / Expiry / DNS servers │
    │  ├─ Registration < 1 year → U+26A0 Newly registered domain (scammer trait) │
    │  ├─ Registration > 3 years → U+2705 Old domain (normal)                   │
    │  └─ BuiltWith tech stack detection                                        │
    └─────────────────────────────────────────────────────────────┘
                          ↓
    ├─────────────────────────────────────────────────────────────┐
    │  Layer 3: Corporate Email Verification (New)                 │
    │  ├─ Extract email domain: xxx@company.com → company.com      │
    │  ├─ Compare against website domain: company.com vs company.com│
    │  ├─ @gmail.com / @qq.com / @163.com → U+1F6A9 Personal email red flag  │
    │  └─ @company domain → U+2705 Corporate email (bonus)                    │
    └─────────────────────────────────────────────────────────────┘
                          ↓
    ├─────────────────────────────────────────────────────────────┐
    │  Layer 4: Sanctions List Screening (New)                     │
    │  ├─ OFAC (US)                                               │
    │  ├─ UN Security Council                                     │
    │  ├─ EU Consolidated List                                    │
    │  ├─ UK HM Treasury                                          │
    │  └─ China MOFCOM Unreliable Entity List                     │
    └─────────────────────────────────────────────────────────────┘
                          ↓
    ┌─────────────────────────────────────────────────────────────┐
    │  Layer 5: LinkedIn Company Page Verification (New)           │
    │  ├─ Domain vs LinkedIn company page domain consistency       │
    │  ├─ Employee LinkedIn count (reflects company size)          │
    │  └─ Company founded date vs domain age comparison            │
    └─────────────────────────────────────────────────────────────┘
                          ↓
              ┌───────────────────────────────────┐
              │  Comprehensive Risk Score Report     │
              │  (Structured Output)                 │
              └───────────────────────────────────┘
```

#### 3.11.3 Tool Selection (Free + No API Key Preferred)

> **Architecture Principle**: Prioritize free tools that require no API Key. Any tool requiring a paid account (such as Hunter.io, RocketReach, Dun & Bradstreet) is marked as 🅱️ Optional and only called when the user provides their own account. Core detection logic must run completely in zero-configuration mode.

| Layer | Tool | Purpose | Type | Cost | API Key | Priority |
|-------|------|---------|------|------|---------|----------|
| L1 Email | `holehe` | 121+ platform registration detection | Python library | Free | Not needed | U+2705 Required |
| L2 WHOIS | socket WHOIS protocol | Domain registration/expiry/registrar | stdlib socket | Free | Not needed | U+2705 Required |
| L3 Corporate Email | MX DNS query + regex | @company.com vs Gmail | stdlib | Free | Not needed | U+2705 Required |
| L4 Sanctions | OFAC CSV download | OFAC/UN/EU screening | HTTP + stdlib | Free | Not needed | U+2705 Required |
| L5 Tech Stack | HTML regex + HTTP Header | Detect Shopify/WordPress | stdlib | Free | Not needed | U+2705 Required |
| L6 LinkedIn | Google search `site:linkedin.com` | Company page existence verification | browser_navigate | Free | Not needed | U+2705 Required |
| L3 Extended | **Hunter.io** | Domain email discovery/corporate email verification | Web API | Free tier | **Required** | 🅱️ Optional |
| L6 Extended | **LinkedIn API** | Employee count/company details | Web API | Free tier | **Required** | 🅱️ Optional |
| Global Companies | **SEC EDGAR** | US company SEC filings | Web | Free | Not needed | 🅱️ Optional |
| UK Companies | **Companies House** | UK company registration info | Web API | Free | Not needed | 🅱️ Optional |
| China Companies | **Qichacha/Tianyancha** | China company business info | Page scraping | Paid | **Required** | 🅱️ Optional |
| OFAC/UN/EU | Sanctions lists | Public CSV | Free | Requires download parsing implementation |
| LinkedIn | Company page verification | Web scraping | Free | `browser_navigate` |

#### 3.11.4 Risk Scoring System

**Cross-Validation Scorecard** (each item scored independently, aggregated into overall rating):

```
U+2705 Positive Items                           U+26A0 Negative Items
─────────────────────────────────────────────────────
Domain > 3 years                            Domain < 1 year
Has corporate email (@company.com)          Only uses gmail/qq/163
LinkedIn company page exists with many employees    No LinkedIn company page
Website tech stack is legitimate (enterprise-grade)  Free blog/temporary website builder
Domain age ≈ company founding date          Domain much older than company
WHOIS registration info complete            WHOIS privacy protection/info missing
Not on any sanctions list                   Appears on any sanctions list
```

**Overall Rating Definitions**:

| Rating | Condition | Recommendation |
|--------|-----------|---------------|
| Low Risk | Positive items ≥ 4 and no red flags | Proceed normally |
| Medium Risk | 1-2 red flags | Proceed with caution, request more verification |
| High Risk | Red flags ≥ 3 or hit on any sanctions list | Strongly recommend rejection, or executive approval required |

#### 3.11.5 Implementation Priority

| Priority | Improvement | Effort | Corresponding Module |
|----------|------------|--------|---------------------|
| P0 | WHOIS domain lookup (`python-whois`) | Small | `trade/osint.py` |
| P0 | Corporate email verification (regex + DNS MX query) | Small | `trade/osint.py` |
| P0 | Sanctions list screening (OFAC/UN/EU CSV parsing) | Small | `trade/osint.py` |
| P1 | BuiltWith tech stack detection | Medium | `trade/osint.py` |
| P1 | LinkedIn company page verification (browser_navigate) | Medium | `trade/osint.py` |
| P2 | Multi-country company registration info lookup (Qichacha/Tianyancha/Companies House) | Large | Independent skill |

#### 3.11.6 Country/Region-Specific Company Registration Info Lookup

Conversations explicitly identified different lookup tools needed for different regions:

| Region | Tool | Description |
|--------|------|-------------|
| US | SEC EDGAR, Corporation Wiki | Public company disclosure, free |
| UK | Companies House | Free public, company registration info |
| China | Qichacha, Tianyancha | Requires API or page scraping |
| Global | Dun & Bradstreet | Paid, business data |
| Middle East | Oman Chamber of Commerce, DED (UAE) | Various national chamber of commerce websites |
| India | MCA India | Free, company registration info |

**Note**: Qichacha/Tianyancha have no public free API. It is recommended to implement via browser_navigate simulating login or page scraping.

#### 3.11.7 API Design

```python
# trade/osint.py

def domain_whois(domain: str) -> dict:
    """WHOIS domain lookup.

    Args:
        domain: Domain name (e.g., "example.com")

    Returns:
        {
            "domain": str,
            "registered": bool,
            "registrar": str,
            "creation_date": str,
            "expiry_date": str,
            "days_old": int,
            "age_category": "new" | "medium" | "old",
            "dns_servers": list[str],
            "registrant_name": str | None,
            "error": str | None,
        }
    """

def verify_corporate_email(email: str, website: str | None = None) -> dict:
    """Verify corporate email vs personal email.

    Args:
        email: Email address (e.g., "john@acme.com")
        website: Optional, company website (for domain cross-validation)

    Returns:
        {
            "email": str,
            "domain": str,
            "is_personal": bool,       # True = gmail/qq/163 and other personal emails
            "is_corporate": bool,      # True = corporate domain email
            "risk_flag": bool,         # True = U+1F6A9 Personal email red flag
            "domain_match": bool | None, # Verifiable when website is provided
            "mx_found": bool,          # Whether MX records were found
            "suggestion": str,         # Action suggestion
        }
    """

def check_sanctions(name: str, country: str | None = None) -> dict:
    """Screen sanctions lists.

    Args:
        name: Company name or person name
        country: Country (for narrowing the search)

    Returns:
        {
            "query": str,
            "hits": [
                {"list": "OFAC", "matched_field": str, "score": float},
                {"list": "UN", "matched_field": str, "score": float},
                ...
            ],
            "is_sanctioned": bool,
            "risk_level": "none" | "low" | "medium" | "high",
        }
    """

def detect_tech_stack(url: str) -> dict:
    """BuiltWith-style tech stack detection.

    Args:
        url: Website URL (e.g., "https://example.com")

    Returns:
        {
            "url": str,
            "technologies": list[str],
            "platforms": list[str],   # ["Shopify", "WordPress", "CloudFlare"]
            "is_free_platform": bool, # True = U+1F6A9 Free website builder red flag
            "is_enterprise": bool,    # True = U+2705 Enterprise-grade platform
        }
    """

def linkedin_company_verify(domain: str, company_name: str) -> dict:
    """LinkedIn company page verification.

    Args:
        domain: Company domain (e.g., "acme.com")
        company_name: Company name

    Returns:
        {
            "domain": str,
            "company_name": str,
            "linkedin_found": bool,
            "linkedin_url": str | None,
            "employee_count": str | None,
            "industry": str | None,
            "founded": int | None,
            "domain_match": bool,
        }
    """

async def osint_full_check(
    target: str,                    # Email / Domain / Company name (auto-detect)
    *,
    include_sanctions: bool = True,
    include_tech_stack: bool = True,
    include_linkedin: bool = True,
) -> dict:
    """Complete OSINT due diligence (async streaming, suitable for LLM streaming calls).

    Executes detection layer by layer, yielding results immediately upon completion of each layer.
    """
```

#### 3.11.8 Output Report Format

```json
{
  "target": "john@acme.com",
  "target_type": "email",
  "overall_rating": "medium",
  "overall_score": 65,
  "flags": ["personal_email_domain", "domain_age_new"],
  "layers": {
    "email_registration": {
      "rating": "good",
      "checked_count": 121,
      "found_count": 3,
      "profiles": ["GitHub", "LinkedIn", "Twitter"]
    },
    "domain_intel": {
      "rating": "warning",
      "domain": "acme.com",
      "age_days": 120,
      "age_category": "new",
      "registrar": "GoDaddy",
      "whois_warning": "Domain registered < 1 year"
    },
    "email_verification": {
      "rating": "danger",
      "is_corporate": false,
      "is_personal": true,
      "risk_flag": true,
      "suggestion": "Uses personal email (gmail.com), request the other party to provide corporate email"
    },
    "tech_stack": {
      "rating": "neutral",
      "platforms": ["Shopify", "CloudFlare"],
      "is_free_platform": false,
      "is_enterprise": true
    },
    "sanctions": {
      "rating": "good",
      "is_sanctioned": false,
      "hits": []
    },
    "linkedin": {
      "rating": "good",
      "linkedin_found": true,
      "domain_match": true,
      "employee_count": "50-200"
    }
  },
  "recommendations": [
    "U+26A0 The other party uses a personal email. It is recommended to request a corporate email before proceeding with in-depth negotiations",
    "U+26A0 Domain registered only 120 days ago, newly registered domain; supporting information needs verification",
    "U+2705 LinkedIn company page exists with normal employee count, credibility +1",
    "U+2705 Not found on any sanctions lists"
  ]
}
```

---

## IV. Interaction Methods

| Method | Entry Point | Description |
|--------|-------------|-------------|
| Web Chat Interface | `http://127.0.0.1:9119/trade` | Sidebar + Chat layout, SSE real-time display of Agent tool call progress |
| CLI Command Line | `trade` | Terminal interactive conversation |
| Admin Panel | `/dashboard` | React backend (config, sessions, scheduled tasks) |

---

## V. Output Quality Standards

### 5.1 Language Strategy

- **Single document, single language**: Full English for overseas customers, full Chinese for domestic customers. Mixing Chinese and English in the same document is prohibited
- Product models and SKUs remain in their original form, not translated

### 5.2 Content Standards

- All output content (posts, outreach emails, marketing plans) is **ready to copy-paste and use**, requiring no manual formatting by the user
- When citing sources, annotate with `U+1F4C4 {filename} | Sheet: {sheet} | Row: {row range}`
- Clearly inform the user of uncertain information; do not fabricate data
- No placeholders ("XXX", "Lorem ipsum", "[TBD]"); omit missing information rather than leaving blanks

### 5.3 Business Document Generation Standards (PPTX / DOCX / XLSX)

| Dimension | Standard |
|-----------|----------|
| Color Scheme | Maximum 3 colors, matching the industry. Don't use generic blue |
| Font Size | Title 36-44pt, section title 18-24pt, body 12-16pt |
| Tables | Complete data filled, dark header + alternating row backgrounds |
| Layout | Each page has visual elements (color bars, cards, icons), plain text boxes prohibited |

### 5.4 Industry Knowledge

- Trade terms: FOB / CIF / EXW / MOQ / Lead Time / T/T / L/C / Incoterms
- Currency recognition: U+00A5/CNY, $/USD, U+20AC/EUR, U+00A3/GBP
- Unit conversion: mm U+2194 inch, kg U+2194 lb, MPa U+2194 psi, U+00B0C U+2194 U+00B0F
- Platform knowledge: Alibaba International Station operations, LinkedIn B2B development methods, social media content best practices

---

## VI. Knowledge & Training Materials

> Detailed content in [Foreign Trade Knowledge Base.md](Foreign Trade Knowledge Base.md), compiled from foreign trade training materials.

The Agent needs to be trained as a senior foreign trade salesperson and must learn the following materials:

### 6.1 Thinking Patterns
- Senior salesperson thinking methodology
- B2B sales psychology and decision-making chain
- Full foreign trade process: Inquiry → Quote → Negotiation → Close → Order follow-up
- Kaleidoscope customer profiling reverse engineering method (Product Power → Delivery Power → Brand Reality → Service Power)

### 6.2 Business Skills
- Communication strategies for three customer types (price-sensitive / quality-oriented / relationship-oriented)
- Account IQ in-depth customer analysis framework (Strategic Priority → Key Challenges → Financial Signals → Supplier Pain Points)
- GAP Selling value matching method: [Customer Pain Point] + [Our Advantage] = [Breakthrough Solution]

### 6.3 Platform Knowledge
- Operating rules and optimization techniques for Alibaba International Station / Made-in-China / independent websites
- LinkedIn 5-dimension marketing method (Post video / photo / article / poll / document)
- LinkedIn personal account 5-section optimization (Headline / About / Skills / Experience / Media)
- Facebook / Instagram / TikTok / YouTube social media content strategy
- Customs data / Canton Fair data filtering and analysis methods

### 6.4 Output Templates
- Consultative outreach email (Account IQ Cold Email structure)
- LinkedIn connection request messaging (≤ 300 characters)
- Customer analysis report (four-dimensional framework)
- LinkedIn Profile complete optimization (5 sections)
- Annual marketing plan (schedule + executable content)

---

## VII. New Company Onboarding Document Checklist

New companies deploying a complete marketing plan need to prepare:

| # | Document | Description |
|---|----------|-------------|
| 1 | Company Introduction | Core advantages. Basic version can be polished by the Agent |
| 2 | Product Introduction | Product catalog, product specification sheets, industry product scope list |
| 3 | Competitor Companies | Competitor company names / links (for competitive analysis and differentiation positioning) |
| 4 | LinkedIn Account | Company page + sales representative personal account (provide if available) |

---

## VIII. Project History & Lessons Learned

### 8.1 VibeRAG Three Iterations (Deprecated)

| Version | Architecture | Result |
|---------|-------------|--------|
| V0.21 | Pure vector retrieval (ChromaDB + embedding chunk) | Vector matching rate lower than irrelevant documents |
| V2 | Pure FTS + LLM direct file reading | Three AI reviewers objected (semantic recall missing) |
| V3 Improved | FTS primary recall + five auxiliary paths + LLM precise segment reading | Two-week field testing, significant gap compared to Hermes |

### 8.2 Five Fatal Architecture Issues

1. FTS keyword matching missed recall
2. Page-level truncation lost context
3. Table JSON conversion caused information loss
4. Single LLM call had no error correction capability
5. Gap compared to Hermes Agent Agent Loop

### 8.3 Lessons Summary

- The essence of B2B scenarios is Agent Loop + Tool Calling, not a retrieval pipeline
- Forking mature open-source projects as a foundation is more practical than building from scratch
- Do not underestimate the complexity of table parsing and OCR

---

## IX. Known Issues & To-Do Items

| Issue | Status |
|-------|--------|
| Automated scheduled tasks (7 daily tasks + weekly report) | U+2705 Implemented (b2b-daily-automation) |
| B2B platform diagnosis & optimization | U+2705 Implemented (b2b-platform) |
| Social media content strategy & material generation | U+2705 Implemented (b2b-social-media) |
| LinkedIn marketing plan | U+2705 Implemented (b2b-linkedin-marketing) |
| Customs data / Canton Fair data mining | U+2705 Implemented (b2b-customs-data) |
| Customer analysis & outreach emails | U+2705 Implemented (b2b-lead-generation) |
| Document library management (16 file formats) | U+2705 Implemented (b2b-document) |
| New company onboarding wizard | U+2705 Implemented (b2b-onboarding) |
| Customer management (CRUD + document library linking) | U+2705 Implemented (b2b-customer-mgmt) |
| Standardized data directory (~/.trade/) | U+2705 Implemented (b2b-data-directory) |
| Business document generation (PPTX/DOCX/XLSX) | U+2705 Implemented (b2b-doc-generation) |
| Cognee knowledge graph memory | U+2705 Available |
| Agent `max_iterations=25` too low → fixed to 90 | U+2705 Fixed |
| AI senior salesperson training | U+2705 Integrated into system prompt (trade/prompt.py) |
| B2B frontend customer management UI | Pending development |
| Messaging platform integration (Telegram / WeChat / Feishu) | Planning |
| Windows native compatibility full testing | Pending testing |
| macOS compatibility full testing | Pending testing |
| Cross-platform installation scripts (macOS curl + Windows PowerShell) | Pending development |
| b2b-osint WHOIS domain lookup (P0) | Pending implementation |
| b2b-osint corporate email verification (P0) | Pending implementation |
| b2b-osint sanctions list screening (P0) | Pending implementation |
| b2b-osint BuiltWith tech stack detection (P1) | Pending implementation |
| b2b-osint LinkedIn company page verification (P1) | Pending implementation |

**Skills List**: 14 industry-general skills created (#15 chat-memory newly added), covering all core features in sections 3.1–3.11 of this requirements document.

---

## X. Skills Implementation Checklist

> All designed as industry-general (industry-agnostic), without specific product or industry constraints.

### Skills Summary Table

| # | Skill | Corresponding Section | Trigger Condition |
|---|-------|---------------------|-----------------|
| 1 | `b2b-document` | 3.3.1 Document Library Management | Analyze documents, extract PDF/Excel/Word content |
| 2 | `b2b-platform` | 3.1.1 B2B Platform Diagnosis | Alibaba International Station / Made-in-China store diagnosis |
| 3 | `b2b-social-media` | 3.1.2 Social Media Content Strategy | FB/Insta/TikTok/YouTube content calendar |
| 4 | `b2b-linkedin-marketing` | 3.1.3 LinkedIn Marketing | LinkedIn Profile/content/outreach |
| 5 | `b2b-lead-generation` | 3.2.2 Customer Analysis & Outreach | Customer analysis, cold emails, follow-up sequences |
| 6 | `b2b-customs-data` | 3.1.4 Customs Data Mining | Customs import/export data, Canton Fair data |
| 7 | `b2b-onboarding` | 3.4 New Company Deployment | Complete marketing launch plan for new companies |
| 8 | `b2b-customer-mgmt` | 3.7 Customer Management | Customer lifecycle, quotations, orders |
| 9 | `b2b-daily-automation` | 3.5 Daily Automation | 7 scheduled tasks, weekly report automation |
| | 10 | `b2b-data-directory` | 3.6 Standardized Data Directory | ~/.trade/ directory structure, file templates |
| | 11 | `b2b-doc-generation` | 3.10 Business Document Generation | PPTX/DOCX/XLSX professional documents |
| | 12 | `b2b-email-intel` | 3.11 Customer Background Check | Email OSINT background check (120+ platforms) |
| | 13 | `b2b-osint` | 3.11 Upgraded Due Diligence | WHOIS + corporate email verification + sanctions + tech stack + LinkedIn cross-validation |
| 15 | `chat-memory` | 3.13 Long-term Conversation Memory | Historical query tool, search DB by time range/keywords, supports Hindsight vector retrieval |

#

---

## 3.12 Prompt Isolation Architecture (User-Editable System/Skill Prompt)

> Added 2026-05-12. All prompts injected into the LLM by the system support user editing, with file priority and DB caching.

### 3.12.1 Architecture Principles

| Principle | Description |
|-----------|-------------|
| **File is Source of Truth** | `.md` files under `~/.trade/` are the authoritative source for prompts |
| **DB is Runtime Cache** | Fields like `agent_identity_md` serve as hot caches for files; file changes take effect automatically |
| **mtime Cache** | Avoids re-reading files on every request; changes to files automatically invalidate and reload the cache |
| **Skill reads from SKILL.md** | `injection_prompt` exists in `SKILL.md` frontmatter; users change behavior by editing the skill file |

### 3.12.2 Prompt File Layout

```
~/.trade/                                  # Runtime data (.gitignore)
├── prompts/
│   └── system.md                         # Global system prompt (user-editable)
├── companies/{slug}/
│   └── agent_identity.md                 # Company-level agent identity (overrides global system)
└── companies.db                          # agent_identity_md field = hot cache

~/.hermes/skills/b2b-osint/
└── SKILL.md                              # injection_prompt in frontmatter
```

### 3.12.3 Read Priority

**System Prompt (vertical override, highest priority wins):**
1. `~/.trade/companies/{slug}/agent_identity.md` — Company-level
2. `~/.trade/prompts/system.md` — Global custom
3. Code fallback (`TRADE_SYSTEM_PROMPT` in `trade/prompt.py`)

**Skill Injection (vertical override, highest priority wins):**
1. `injection_prompt` in `~/.hermes/skills/{skill}/SKILL.md` frontmatter
2. Code fallback (`_SKILLS` dict in `skill_router.py`)

**Final Assembly (horizontal):**
```
system_prompt + skill_injection + doc_context + user_query
```

### 3.12.4 Automatic File Change Detection

`trade/prompts.py` maintains an mtime cache (`_PROMPT_CACHE`):
- File `mtime` unchanged → Use cache directly
- File `mtime` changed → Re-read file, update cache
- User `vim ~/.trade/prompts/system.md` → Next request automatically takes effect, no restart needed

### 3.12.5 Implementation Files

| File | Purpose |
|------|---------|
| `trade/prompts.py` | Unified prompt file loader (mtime cache) |
| `trade/skill_router.py` | Reads `injection_prompt` from SKILL.md frontmatter |
| `trade/helpers.py` | Uses `prompts.resolve_system_prompt()` |
| `trade/onboarding.py` | Dual write to identity file + DB |
| `.trade-template/prompts/system.md` | System prompt installation template |
| `.trade-template/companies/company-slug/agent_identity.md` | Agent identity installation template |


## 3.13 Long-term Conversation Memory & History Query

> Added 2026-05-12. Solves the problem of "not knowing today what was discussed yesterday" — all conversations are permanently stored with timestamps, and the Agent can proactively query at any time.

### 3.13.1 Core Principles

- **All conversations stored permanently**: No compression, no summarization, no deletion. `created_at` is a required field
- **Default recent history injection**: 10-20 rounds (~10k tokens), ensuring recent context coherence
- **Earlier history queried on demand**: Agent proactively queries via tools; LLM determines when to execute based on tool descriptions
- **Thresholds controlled by code**: Completely transparent to users
- **Hermes native memory interop**: `save_with_context()` automatically writes a summary to `~/.hermes/memories/MEMORY.md` after each conversation save; Hermes Agent can remember B2B business conversations across projects

### 3.13.2 Token Budget Allocation

| Segment | Limit | Description |
|---------|-------|-------------|
| System prompt | ~5k | Company identity + doc context |
| Skill injection | ~1k | Currently triggered skill augment |
| **Recent history** | **~10k** | **Fixed 10-20 rounds, most recent context** |
| Current query | ~1k | User's current question |
| Reserved space | ~83k | Reserved for Agent reasoning and response |

### 3.13.3 Prompt Construction Logic (build_query)

**Threshold evaluation target: total token count of the entire prompt**

```python
# Thresholds hardcoded, not exposed to the user
if total_tokens < 20_000:
    history_limit = 20   # Ample space, inject more history
    hint = None
elif total_tokens < 50_000:
    history_limit = 10    # Start compressing history volume
    hint = "For earlier conversation history, please use the chat_memory_list tool."
else:
    history_limit = 5     # Force trimming
    hint = "Current context is long. Conversation history has been trimmed. To query earlier content, please use the chat_memory_list tool."
```

**History injection is always a fixed number of rounds (history_limit), not growing indefinitely with thresholds.**

### 3.13.4 Tool Description Driven (No Trigger Words)

When the Agent queries history is not determined by trigger words, but by tool descriptions:

```json
{
  "name": "chat_memory_list",
  "description": "Query historical conversation records for the current company. When the user mentions time-related words
                 like 'before', 'last time', 'previously', or asks about content discussed in the past,
                 use this tool to retrieve relevant history.",
  "parameters": {
    "time_range": {
      "type": "string",
      "enum": ["today", "this_week", "this_month", "all"],
      "description": "Time range: today/this week/this month/all"
    },
    "limit": {
      "type": "integer",
      "default": 20,
      "description": "Maximum number of messages to return"
    }
  }
}
```

The LLM reads the tool description from SKILL.md and decides when to call it — when the user says "what was the name of that supplier you recommended last time", the LLM will proactively query `chat_memory_list`.

### 3.13.5 Division of Labor: Hindsight vs SQLite

| Query Type | Example | Storage / Retrieval |
|-----------|---------|-------------------|
| **Time-series query** | "Yesterday's conversation", "What was discussed last week" | SQLite `ORDER BY created_at` |
| **Semantic query** | "That chip supplier", "The plan mentioned earlier" | Hindsight vector retrieval |

- Has Hindsight API Key → Time-series via SQLite, semantic via Hindsight
- No Hindsight API Key → Semantic queries degrade to SQLite `WHERE query LIKE '%keyword%'`

### 3.13.6 Implementation Plan

| Priority | Content | File |
|----------|---------|------|
| ~~P0 U+2705~~ | `build_query()` injects recent 10-20 rounds of history + token threshold hint | `helpers.py` |
| ~~P0 U+2705~~ | `chat-memory` skill: SKILL.md + tool description (no trigger words) | `skills/chat-memory/` |
| ~~P0 U+2705~~ | `chat_memory_list(time_range, limit)` function | `chat_memory.py` |
| P1 | `chat_memory_summarize(days)` summary function | `chat_memory.py` |
| P1 | `memory.retain()` asynchronous write to Hindsight after each conversation (optional) | `memory.py` |
| P2 | Agent proactive semantic recall (recognizing "this is about that previous matter") | Subsequent iteration |
| ~~P2 U+2705~~ | `retain_to_hermes_memory()` writes to `~/.hermes/memories/MEMORY.md` | `memory.py` |

## AI Senior Salesperson

> Not an independent skill; built into the system prompt in `trade/prompt.py`.

- Corresponding section: 3.2.1 AI Senior Salesperson
- Training materials: Senior salesperson thinking
- Capabilities: Customer type identification, price negotiation, follow-up classification, objection handling

### Skills Directory Location

```
skills/
├── b2b-document/           # Existing
├── b2b-platform/           # New
├── b2b-social-media/       # New
├── b2b-linkedin-marketing/ # New
├── b2b-lead-generation/    # New
├── b2b-customs-data/       # New
├── b2b-onboarding/         # New
├── b2b-customer-mgmt/      # New
├── b2b-daily-automation/   # New
├── b2b-data-directory/     # New
├── b2b-doc-generation/     # New
├── b2b-email-intel/        # New
└── b2b-osint/              # New (WHOIS + corporate email + sanctions + tech stack)
```

---

## XI. Cross-Platform Development Checklist

> Before each code commit, confirm the following items pass on both platforms.

### Paths & Files

- [ ] All path operations use `pathlib.Path`, no hardcoded `/` or `\`
- [ ] File names contain only lowercase letters, numbers, hyphens, underscores, and dots
- [ ] Directory depth ≤ 3 levels
- [ ] Read/write text files explicitly specify `encoding='utf-8'`
- [ ] Do not use Windows reserved names (CON, PRN, AUX, NUL, COM1-COM9, LPT1-LPT9)

### Processes & Commands

- [ ] Do not concatenate shell command strings in code
- [ ] Subprocess calls use `subprocess.run([...])` list form
- [ ] System-level commands (e.g., `rm`, `cp`) replaced with Python standard library (`os.remove`, `shutil.copy`)

### Network & Ports

- [ ] Default bind to `127.0.0.1` (not `localhost`, to avoid IPv6 resolution differences)
- [ ] Port number configurable (`--port` parameter)

### Data & Configuration

- [ ] User data stored under `TRADE_HOME` (no hardcoded paths)
- [ ] Config reading uses `TRADE_HOME` environment variable + reasonable platform defaults
- [ ] Newlines handled automatically by Python (`newline=None` for reading, `\n` for writing)

---

## XII. Upgrade Logic (Data Integrity Protection)

> When Trade is upgraded, existing business data (database, company directory files) must remain intact and usable.
> No user data may be lost due to schema changes. Added 2026-05-12.

### 12.1 Design Principles

| Principle | Description |
|-----------|-------------|
| **Backward Compatibility** | New version code must be able to read and write data created by old versions |
| **Automatic Migration** | Detect and execute migration automatically on startup, no manual user intervention required |
| **Atomicity** | Database rolls back on migration failure, leaving no half-finished state |
| **Idempotency** | Migration scripts can be safely re-executed without duplicating data |
| **Reversibility** | Migration scripts have clear `up()` / `down()` logic (implemented in Python, not SQL comments) |

### 12.2 Migration Detection Mechanism

Each time `init_db()` executes, the database layer checks the current schema version in the following order:

```
1. Read PRAGMA table_info(libraries) — get current column set
2. Determine whether the "company_id" column exists
   ├─ Does not exist → v0 schema (single-company version)
   └─ Exists → v1 schema (multi-company version)
3. Subsequent version detection follows the same pattern, progressing version by version
```

**Important**: Does not use a separate `schema_version` table. Instead, detects the version by checking whether key columns exist.
Reason: Avoids atomicity risks from multi-table writes; the column's existence proves that version's migration is complete.

### 12.3 Version Evolution & Migration Paths

#### v0 → v1: Single Company → Multi-Company (Multi-Tenancy)

**Trigger Condition**: Detected that the `libraries` table has no `company_id` column.

**Data State Before Migration** (v0):
```
libraries:     id, name, root_path, description, created_at, updated_at
customers:     id, name, contact, note, created_at, updated_at
conversations: id, query, response, files_read, created_at
```

**Data State After Migration** (v1):
```
companies:        id, name, slug, logo_url, website, contact_name, ...,
                 extra1='{}', extra2='{}', extra3='{}'
trade_companies: company_id(PK), data_dir, agent_identity_md, is_active, created_at,
                 extra1='{}', extra2='{}', extra3='{}'
libraries:       + company_id (FK → companies(id), DEFAULT 1),
                 extra1='{}', extra2='{}', extra3='{}'
customers:       + company_id (FK → companies(id), DEFAULT 1),
                 extra1='{}', extra2='{}', extra3='{}'
conversations:   + company_id (FK → companies(id), DEFAULT 1),
                 extra1='{}', extra2='{}', extra3='{}'
```

**Migration Operation Steps** (`database.py:_migrate_from_v0()`):

```
Step 1: Create new tables
  CREATE TABLE companies (...)
  CREATE TABLE trade_companies (...)
  INSERT OR IGNORE INTO companies (name='My Company', slug='default', ...)
  INSERT OR IGNORE INTO trade_companies (company_id=1, data_dir='', ...)

Step 2: ALTER TABLE (add columns per table)
  ALTER TABLE libraries     ADD COLUMN company_id INTEGER REFERENCES companies(id) ON DELETE CASCADE
  ALTER TABLE customers     ADD COLUMN company_id INTEGER REFERENCES companies(id) ON DELETE CASCADE
  ALTER TABLE conversations ADD COLUMN company_id INTEGER REFERENCES companies(id) ON DELETE CASCADE

Step 3: Fill company_id (all existing data belongs to company 1)
  UPDATE libraries    SET company_id = 1
  UPDATE customers    SET company_id = 1
  UPDATE conversations SET company_id = 1

Step 4: Create indexes
  CREATE INDEX idx_libraries_company     ON libraries(company_id)
  CREATE INDEX idx_customers_company     ON customers(company_id)
  CREATE INDEX idx_conversations_company ON conversations(company_id)

Step 5: Add spare columns (all 6 tables)
  _add_spare_columns(conn)  # Idempotent ADD COLUMN, silently ignores if column exists
```

**Data Integrity Guarantees**:
- All existing data automatically belongs to company 1 ("My Company"), no records lost
- New tables and old table data are completed in the same transaction; failure rolls back everything
- `ON DELETE CASCADE` ensures deleting a company automatically cleans up all its business data

---

#### v1 → v2 (Example, Future Extension)

Every future schema change follows the same pattern, appending a new `_migrate_v1_to_v2()` function in `database.py`:

```python
def _migrate_v1_to_v2(conn):
    # Step 1: Check if migration is needed (idempotency)
    cur = conn.execute("PRAGMA table_info(libraries)")
    cols = {row[1] for row in cur.fetchall()}
    if "new_column" in cols:
        return False  # Already migrated

    # Step 2: Execute migration (within the same transaction)
    conn.execute("ALTER TABLE libraries ADD COLUMN new_column TEXT DEFAULT ''")
    # ... other operations

    # Step 3: Add spare columns (required for every new table in the future)
    _add_spare_columns(conn)

    conn.commit()
    return True
```

### 12.4 Directory File Migration

Company data directory (`~/.trade/{slug}/`) migration is handled in `company.py:_ensure_data_dir()`:

```
Trigger timing: Called during company.create() or company.get()
Trigger condition: Target directory ~/.trade/{slug}/ does not exist

Migration operation:
  1. Read .trade-template/ as source
  2. Copy template to temporary directory
  3. Rename placeholder directories:
       companies/company-slug  → companies/{slug}
       libraries/library-slug  → libraries/{slug}
       clients/client-slug     → clients/{slug}
  4. Move temporary directory → ~/.trade/{slug}/
```

**Data Integrity Guarantees**:
- `if target.exists(): return target` — Existing company directories are never overwritten
- New companies use the template for creation, not affecting existing company directory files
- `shutil.move()` is an atomic operation (within the same filesystem)

### 12.5 Upgrade Failure Handling

| Failure Scenario | Handling Method |
|-----------------|-----------------|
| Database migration SQL execution failure | `conn.rollback()` rollback, process exits with error message |
| Company directory creation failure | `company.create()` throws exception, DB transaction not committed |
| Template directory does not exist | `_ensure_data_dir()` silently creates empty directory, does not block company creation |
| Insufficient disk space | Python IOError, process exits, DB not written |

**Log Output**:
- Migration start: `Detected v0 schema — migrating to multi-company v1 ...`
- Migration complete: `Migration complete. Default company 'My Company' (slug=default) created.`
- Migration failure: Complete SQLite error message for diagnostic purposes

### 12.6 Version Downgrade

Trade **does not support** downgrading from a higher version to a lower version. Downgrade requires manual user action:
1. Back up the `~/.trade/` directory and `data/trade.db`
2. Reinstall the old pip package
3. Manually restore data

Downgrade protection rationale: ALTER TABLE is irreversible (SQLite does not support DROP COLUMN), downgrading could lead to data loss.

### 12.7 Pre-Upgrade Checklist (For Maintainers)

Before releasing any new schema change, confirm:

```
[ ] New migration function implements up() logic, idempotency verified
[ ] Execute migration on old-version database, all existing data preserved
[ ] Rollback new-version database to pre-migration state, verify rollback works
[ ] Company directory structure correct after migration (companies/{slug}/ etc. renamed)
[ ] Frontend correctly accesses migrated company data (X-Company-ID routing works)
[ ] Unit tests cover the migration path (test_v0_to_v1_migration)
```

---

*Document Sources:*
- `trade/database.py` — `_migrate_from_v0()` migration implementation
- `trade/company.py` — `_ensure_data_dir()` / `_rename_template_placeholders()` directory migration
- `trade/library.py` / `trade/customer.py` / `trade/chat_memory.py` — company_id field isolation
