# Falcon AI Agent — Configuration Reference

Complete guide to every environment variable supported by the [Falcon AI Agent](https://app.falconai.pro/app/signals/agent-client) (`client/falcon-ai-client`).

**Quick start:** copy `.env.example` to `.env`, set `FALCON_API_KEY`, keep `DRY_RUN=true`, run the agent, open http://localhost:8050.

---

## Table of contents

1. [Minimum setup](#minimum-setup)
2. [Falcon platform](#falcon-platform)
3. [Polymarket wallet](#polymarket-wallet)
4. [Signal subscription](#signal-subscription)
5. [Risk and position sizing](#risk-and-position-sizing)
6. [Execution mode and telemetry](#execution-mode-and-telemetry)
7. [Local dashboard and logging](#local-dashboard-and-logging)
8. [Recommended profiles](#recommended-profiles)
9. [How risk sizing works](#how-risk-sizing-works)
10. [Signal types cookbook](#signal-types-cookbook)
11. [Test vs production](#test-vs-production)
12. [Command-line reference](#command-line-reference)
13. [Troubleshooting](#troubleshooting)

---

## Minimum setup

| Variable | Required for dry-run? | Required for live? |
|----------|----------------------|------------------|
| `FALCON_API_KEY` | Yes | Yes |
| `POLYMARKET__PK` | No | Yes |
| `POLYMARKET__CLOB_FUNDER` | No | Yes (types 1 & 2) |
| Everything else | No (defaults apply) | Recommended |

```bash
cp .env.example .env
# Edit FALCON_API_KEY, then:
python main.py --check   # optional but recommended
python main.py
```

Open http://localhost:8050 for the dashboard; **Help** or http://localhost:8050/docs for this full reference.

---

## Falcon platform

| Variable | Type | Default | Description | Best practice |
|----------|------|---------|-------------|---------------|
| `FALCON_API_KEY` | string | *(empty)* | API key from **Developer → API keys** in the Falcon app | Use Setup wizard; never share or commit |
| `FALCON_WS_URL` | URL | `wss://api.falconai.pro/ws/signals` | WebSocket signal stream | Use test URL only for staging |
| `FALCON_API_BASE` | URL | `https://api.falconai.pro/api/polymarket` | REST API for reports + strategy sync | Must match WS environment (prod vs test) |

---

## Polymarket wallet

All wallet variables use the `POLYMARKET__` prefix (double underscore). **These values never leave your machine.**

| Variable | Type | Default | Description | Best practice |
|----------|------|---------|-------------|---------------|
| `POLYMARKET__PK` | hex string | *(empty)* | Polygon EOA private key | Export from Falcon Trade desk or MetaMask; required for live |
| `POLYMARKET__CLOB_SIGNATURE_TYPE` | int | `0` in code, `2` in `.env.example` | `0` EOA/MetaMask, `1` legacy Polymarket proxy, `2` Gnosis Safe, `3` deposit wallet (POLY_1271) | See wallet paths below |
| `POLYMARKET__CLOB_FUNDER` | address | *(empty)* | Address that holds USDC (proxy, Safe, or deposit wallet) | Required for types `1`, `2`, and `3` |
| `POLYMARKET__CHAIN_ID` | int | `137` | Polygon network ID | `137` mainnet; `80002` Amoy testnet |
| `POLYMARKET__DERIVE_CLOB_API_CREDS` | bool | `true` | Auto-derive CLOB API key/secret/passphrase from PK | Keep `true` unless you have manual creds |
| `POLYMARKET__API_KEY` | string | *(empty)* | Manual CLOB API key | Only if `DERIVE_CLOB_API_CREDS=false` |
| `POLYMARKET__API_SECRET` | string | *(empty)* | Manual CLOB secret | Same |
| `POLYMARKET__API_PASSPHRASE` | string | *(empty)* | Manual CLOB passphrase | Same |

### Wallet setup paths

**Falcon email + Safe (recommended)**

1. Complete Trade desk on app.falconai.pro (deploy Safe, approvals).
2. Export EOA key → `POLYMARKET__PK`.
3. Copy Safe address → `POLYMARKET__CLOB_FUNDER`.
4. `POLYMARKET__CLOB_SIGNATURE_TYPE=2`, `POLYMARKET__DERIVE_CLOB_API_CREDS=true`.

**MetaMask EOA**

- `POLYMARKET__CLOB_SIGNATURE_TYPE=0`, leave funder empty.
- Place one small manual trade on polymarket.com first (V2 approvals).

**Polymarket.com email wallet (signed up on polymarket.com)**

Per [Polymarket CLOB authentication](https://docs.polymarket.com/api-reference/authentication):

1. On [polymarket.com/settings](https://polymarket.com/settings), copy the **wallet address where your USDC balance shows** → `POLYMARKET__CLOB_FUNDER`.
2. Export your private key (**Settings → Export private key**) → `POLYMARKET__PK`.
3. Set `POLYMARKET__DERIVE_CLOB_API_CREDS=true` (do not paste manual API keys unless you derived them for this exact signer).
4. Set signature type by wallet generation:
   - **Legacy email/Google proxy:** `POLYMARKET__CLOB_SIGNATURE_TYPE=1`
   - **New deposit wallet (POLY_1271):** `POLYMARKET__CLOB_SIGNATURE_TYPE=3`
5. Run `python main.py --check` — if type `1` fails with 401, try type `3` (or vice versa) with the same funder.
6. Place at least one small manual trade on polymarket.com (V2 contract approvals).
7. **Do not** use `signature_type=2` unless you trade through Falcon’s Trade desk Safe.

Wrong `signature_type` or `funder` causes `401 Unauthorized/Invalid api key`. The signer EOA (from your exported key) and funder address (where USDC sits) are **different** for email wallets — that is normal.

---

## Signal subscription

| Variable | Type | Default | Description | Best practice |
|----------|------|---------|-------------|---------------|
| `SIGNAL_CATEGORIES` | csv | *(empty = all)* | Topic filters: `crypto`, `sports`, `politics`, etc. | Start narrow (e.g. `crypto`) until comfortable |
| `SIGNAL_TYPES` | csv | *(empty = all)* | Allowlist of `signal_type` values | Use to copy only watchlist or only pack whales |
| `SIGNAL_MIN_EDGE` | float 0–1 | `0` | Reject signals below this edge | `0.05`–`0.08` for stricter quality |
| `SIGNAL_MIN_CONFIDENCE` | float 0–1 | `0` | Reject signals below this confidence | `0.55`–`0.65` optional extra gate |
| `SYNC_STRATEGIES_ON_START` | bool | `true` | Pull Strategy Lab strategies on boot | Disable only if you never use Strategy Lab |

---

## Risk and position sizing

| Variable | Type | Default | Description | Best practice |
|----------|------|---------|-------------|---------------|
| `TRADING__BANKROLL_USDC` | float | `1000` | Total capital for sizing math | Set to actual USDC you allocate to the bot |
| `TRADING__MAX_POSITION_USDC` | float | `50` | Hard cap per trade | Keep ≤ 5–10% of bankroll |
| `TRADING__MAX_DAILY_SPEND_USDC` | float | `200` | UTC daily spend circuit-breaker | ~15–25% of bankroll for cautious runs |
| `TRADING__MAX_OPEN_POSITIONS` | int | `10` | **Concurrent** open positions (unresolved) | `5`–`10` for small bankrolls; slot frees when market resolves |
| `RISK_LEVEL` | enum | `balanced` | `conservative` \| `balanced` \| `aggressive` | Start `conservative` or `balanced` |

### `TRADING__MAX_OPEN_POSITIONS` explained

This limits how many positions can be **open at the same time** — not how many trades you can take over the lifetime of the agent.

- A position counts as open from successful execution until the market **resolves** (dry-run: tracked via Polymarket resolution API; shown as resolved in the trade log).
- When a market resolves, that slot becomes available again.
- Restarting the agent reloads open count from your local trade log — resolved trades do not block new signals.

**Dashboard:** the mode bar shows `Open positions: N / max`.

### Advanced risk controls (optional)

All use `0`, `false`, or empty to disable unless noted.

| Variable | Type | Default | Description |
|----------|------|---------|-------------|
| `TRADING__MAX_DRAWDOWN_USDC` | float | `0` | Pause trading when peak-to-trough resolved loss in window exceeds this USD |
| `TRADING__MAX_DRAWDOWN_PCT` | float | `0` | Same, as % of `TRADING__BANKROLL_USDC` |
| `TRADING__DRAWDOWN_WINDOW_DAYS` | int | `7` | Lookback for drawdown (1–90) |
| `TRADING__MAX_DAILY_LOSS_USDC` | float | `0` | Max realized loss per UTC day |
| `TRADING__MAX_TRADES_PER_DAY` | int | `0` | Cap successful trades per UTC day |
| `TRADING__MAX_PENDING_EXPOSURE_USDC` | float | `0` | Max total staked in unresolved positions |
| `TRADING__MAX_PER_MARKET_USDC` | float | `0` | Max exposure per market (open + new trade) |
| `TRADING__ONE_POSITION_PER_MARKET` | bool | `false` | Block second position in same market |
| `TRADING__COOLDOWN_MINUTES_AFTER_LOSS` | int | `0` | Pause after any resolved loss |
| `TRADING__CATEGORY_DAILY_CAPS` | csv | *(empty)* | e.g. `crypto:100,sports:50` |
| `TRADING__TRADING_HOURS_UTC` | string | *(empty)* | Allowed windows e.g. `09:00-17:00` (empty = 24/7) |
| `TRADING__BLACKOUT_HOURS_UTC` | string | *(empty)* | Blocked windows e.g. `22:00-06:00` |
| `TRADING__MIN_MINUTES_BETWEEN_TRADES` | int | `0` | Rate limit between executions |
| `TRADING__WALLET_MARKET_COOLDOWN_HOURS` | float | `0` | Skip duplicate wallet+market copies |
| `TRADING__STOP_LOSS_PCT` | float | `0` | **Live only** — auto-sell when unrealized loss ≥ % |
| `TRADING__STOP_LOSS_POLL_SECONDS` | int | `300` | How often stop-loss checks run (≥60) |
| `TRADING__USE_LIVE_OPEN_POSITIONS` | bool | `false` | **Live only** — open count from Data API vs local log |

---

## Execution mode and telemetry

| Variable | Type | Default | Description | Best practice |
|----------|------|---------|-------------|---------------|
| `DRY_RUN` | bool | `true` | `true` = log only; `false` = real CLOB orders | Keep `true` ≥ 1 week; verify win rate and filters |
| `REPORT_STATS_TO_PLATFORM` | bool | `true` | Anonymised weekly stats to Falcon community | Safe to leave on; no wallet or trade details sent |

---

## Local dashboard and logging

| Variable | Type | Default | Description | Best practice |
|----------|------|---------|-------------|---------------|
| `DASHBOARD_PORT` | int | `8050` | Local HTTP dashboard port | Change if 8050 is in use |
| `LOG_LEVEL` | string | `INFO` | `DEBUG`, `INFO`, `WARNING`, `ERROR` | `DEBUG` only when diagnosing |
| `SETUP_COMPLETE` | bool | auto | Set by Setup wizard | Do not edit manually |

Most settings can also be edited in the dashboard **Settings** panel (saved to `.env`; restart required).

---

## Recommended profiles

### First week (dry-run, learn the UI)

```env
FALCON_API_KEY=fai_your_key
SIGNAL_CATEGORIES=crypto
DRY_RUN=true
RISK_LEVEL=conservative
TRADING__BANKROLL_USDC=500
TRADING__MAX_POSITION_USDC=25
TRADING__MAX_DAILY_SPEND_USDC=75
TRADING__MAX_OPEN_POSITIONS=5
REPORT_STATS_TO_PLATFORM=true
```

### Conservative live (single category)

```env
DRY_RUN=false
POLYMARKET__PK=0x...
POLYMARKET__CLOB_SIGNATURE_TYPE=2
POLYMARKET__CLOB_FUNDER=0x...
SIGNAL_CATEGORIES=crypto
SIGNAL_TYPES=user_whale_copy
RISK_LEVEL=conservative
TRADING__BANKROLL_USDC=1000
TRADING__MAX_POSITION_USDC=20
TRADING__MAX_DAILY_SPEND_USDC=100
TRADING__MAX_OPEN_POSITIONS=5
SIGNAL_MIN_EDGE=0.06
```

### Aggressive multi-signal (experienced)

```env
SIGNAL_CATEGORIES=crypto,sports
SIGNAL_TYPES=whale_copy,user_whale_copy,strategy_lab
RISK_LEVEL=aggressive
TRADING__BANKROLL_USDC=5000
TRADING__MAX_POSITION_USDC=150
TRADING__MAX_DAILY_SPEND_USDC=750
TRADING__MAX_OPEN_POSITIONS=15
```

### Watchlist-only copy

```env
SIGNAL_TYPES=user_whale_copy
SIGNAL_CATEGORIES=
TRADING__MAX_OPEN_POSITIONS=8
```

---

## How risk sizing works

For each approved signal:

1. **Server** broadcasts `suggested_size_pct` (quarter-Kelly style sizing).
2. **Client** multiplies by `RISK_LEVEL` preset (e.g. balanced = 0.25×).
3. **Client** caps at `max_bankroll_pct` for the preset (balanced = 5% of bankroll).
4. **Client** caps at `TRADING__MAX_POSITION_USDC` and remaining `TRADING__MAX_DAILY_SPEND_USDC`.
5. **Strategy Lab** signals may use fixed `position_size_usdc` from metadata instead.

Order of rejection checks: signal type allowlist → edge/confidence gates → expiry → **open positions** → daily spend → minimum size ($1).

---

## Signal types cookbook

| `signal_type` | Dashboard label | Meaning |
|---------------|-----------------|---------|
| `whale_copy` | pack | Curated roster from Falcon signal packs |
| `user_whale_copy` | watchlist | Wallets you follow in the app |
| `price_signal` | — | Price / edge alerts |
| `strategy_lab` | strategy | Your Strategy Lab rules |
| `strategy_regime` | regime | Regime-based strategy signals |

Examples:

```env
# Only pack whales
SIGNAL_TYPES=whale_copy

# Only your watchlist
SIGNAL_TYPES=user_whale_copy

# Pack + watchlist, no strategies
SIGNAL_TYPES=whale_copy,user_whale_copy
```

---

## Test vs production

| | Production (`falconai.pro`) | Test (`falconai.bot`) |
|---|---|---|
| App (sign in, API keys) | [app.falconai.pro](https://app.falconai.pro) | [app-test.falconai.bot](https://app-test.falconai.bot) |
| `FALCON_WS_URL` | `wss://api.falconai.pro/ws/signals` | `wss://api-test.falconai.bot/ws/signals` |
| `FALCON_API_BASE` | `https://api.falconai.pro/api/polymarket` | `https://api-test.falconai.bot/api/polymarket` |

Use a **test API key** with test URLs. Mixing prod key + test URL (or vice versa) will fail connection checks.

---

## Command-line reference

Run all commands from the **client folder** (where `main.py` and `.env` live). On Windows, use the `.bat` helpers after `install.bat` has created `.venv`.

### Everyday commands

| Command | What it does |
|---------|----------------|
| `python main.py` | Start the agent, WebSocket listener, and dashboard at http://localhost:8050 |
| `python main.py --check` | **Preflight** — test `.env`, Falcon API, WebSocket, and (if live) Polymarket CLOB auth |
| `python main.py -c` | Same as `--check` |
| `python main.py check` | Same as `--check` |
| `python preflight.py` | Same checks as `--check` (standalone script) |

**When to run `--check`:** after editing `.env`, before enabling `DRY_RUN=false`, after changing Polymarket wallet settings, or when you see connection / `401` errors.

### Windows shortcuts

| Script | Equivalent |
|--------|------------|
| `install.bat` | Create `.venv`, install deps, copy `.env.example` → `.env` if missing |
| `run.bat` | Start agent + open http://localhost:8050 in browser |
| `check.bat` | `python main.py --check` |

### Mac / Linux shortcuts

```bash
chmod +x install.sh run.sh check.sh
./install.sh    # venv + deps + .env
./check.sh      # preflight
./run.sh        # start agent
```

### Manual install (any OS)

```bash
python -m venv .venv
# Windows:  .venv\Scripts\activate
# Mac/Linux: source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env    # Windows: copy .env.example .env
python main.py --check
python main.py
```

### Docker / VPS

```bash
cp .env.example .env
# edit .env, then:
docker compose up -d
# Dashboard: http://localhost:8050
```

Ubuntu VPS one-time bootstrap: `bash scripts/setup-vps.sh`

### Maintenance

| Command | When |
|---------|------|
| `pip install -r requirements.txt` | After upgrade, or if you see `order_version_mismatch` |
| `build-windows.bat` | Developers: build `dist\falcon-ai-agent.exe` |
| `install-exe.bat` | End users running the Windows executable (no Python) |

### Local dashboard URLs

| URL | Purpose |
|-----|---------|
| http://localhost:8050 | Main dashboard (signals, open & resolved positions) |
| http://localhost:8050/docs | This configuration reference (in browser) |
| http://localhost:8050/api/preflight | JSON preflight results (used by Setup **Test connection**) |

Change the port with `DASHBOARD_PORT` in `.env` (default `8050`).

### Stopping the agent

Press **Ctrl+C** in the terminal where `python main.py` is running. The agent sends a final stats report on shutdown when `REPORT_STATS_TO_PLATFORM=true`.

---

## Troubleshooting

| Symptom | Likely cause | Fix |
|---------|--------------|-----|
| Dashboard says **Setup required** | Missing/placeholder `FALCON_API_KEY` | Setup wizard → paste real key → restart |
| **Disconnected** | Wrong WS URL or invalid key | Run `python main.py --check`; verify key and URL pair |
| **Max open positions reached** | All concurrent slots in use | Wait for markets to resolve; or raise `TRADING__MAX_OPEN_POSITIONS`; check mode bar `N / max` |
| **Daily spend limit reached** | `TRADING__MAX_DAILY_SPEND_USDC` hit | Wait until UTC midnight or raise cap |
| **Computed size too small** | Kelly × bankroll below $1 | Raise bankroll, `RISK_LEVEL`, or `TRADING__MAX_POSITION_USDC` |
| **order_version_mismatch** | Old CLOB client | `pip install -r requirements.txt` (py-clob-client-v2) |
| **Allowance / insufficient** | Token approvals | One small manual trade on polymarket.com with same wallet |
| Settings saved but unchanged | Agent not restarted | Restart after editing `.env` or Settings panel |
| Live mode exits immediately | No `POLYMARKET__PK` | Add key or set `DRY_RUN=true` |

---

## Files on disk

| Path | Purpose |
|------|---------|
| `.env` | Your live configuration (never commit) |
| `.env.example` | Annotated template |
| `logs/dry_run_trades.csv` | Trade log (dry-run and live) |
| `logs/falcon_client.log` | Application log |

---

## Further reading

- [Client README](../README.md) — install, Docker, Windows exe
- Dashboard **Help** → http://localhost:8050/docs (this reference in the browser)
- [OpenClaw integration](../../docs/OpenClaw-Falcon-Integration.md)
