Personality Engine

GitHub 作者 LeoYeAI/openclaw-master-skills

Six-system behavior engine that makes any OpenClaw agent feel alive. Editorial voice injects opinions. Selective silence knows when NOT to talk. Variable timing scores urgency with time-of-day awareness. Micro-initiations send ambient pings. Context buffer enables back-references to earlier messages. Response tracker adapts to engagement patterns. Domain-agnostic — works with trading agents, personal assistants, DevOps monitors, or any proactive agent. Part of the OpenClaw Prediction Market Trading Stack with default trading configuration.

安装 / 下载方式

TotalClaw CLI推荐
totalclaw install github:LeoYeAI~openclaw-master-skills~personality-engine
cURL直接下载,无需登录
curl -fsSL https://skills.taituai.com/api/skills/github%3ALeoYeAI~openclaw-master-skills~personality-engine/file -o personality-engine.md
# Personality Engine — 6-System Behavior Framework

**Goal**: Make any AI agent feel *alive* — opinions, awareness, judgment, memory, timing sense, and engagement sensitivity. Works with trading agents, notification systems, personal assistants, or any proactive agent. Not just data delivery.

## Architecture Overview

```
Trigger fires → engine.py orchestrator
              ↓
         selective_silence (should we stay silent?)
              ↓
         urgency_compute (how urgent is this 0.0-1.0?)
              ↓
         engagement_modifier (adjust for user response patterns)
              ↓
         variable_timing (schedule delivery based on urgency + time of day)
              ↓
         context_buffer (add back-references to earlier messages today)
              ↓
         editorial_voice (inject personality / opinions)
              ↓
         dedup (avoid repeats within rolling window)
              ↓
         send → iMessage (or other transport)
```

Plus two ambient systems:
- **micro_initiations**: Unprompted pings when conditions are met (quiet market, good streak, absence detected)
- **response_tracker**: Monitors engagement; adjusts urgency + suggests tuning

---

## System 1: Editorial Voice — Opinion Injection

**What**: Each trigger type gets a personality — opinions that vary based on market state, portfolio P&L, signal confidence.

**Per-trigger voice pools**:

### cross_platform (Kalshi vs Polymarket divergence)
- **Bullish divergence (>5%)**: "Big divergence. One of these markets is wrong."
- **Mild divergence (2-5%)**: "Mild divergence. Nothing screaming yet."
- **Stale divergence (6+ hours old)**: "Divergence is stale — markets may have already repriced."

### portfolio (user's holdings performance)
- **+15% or better**: "Good day. Portfolio's running."
- **+5% to +15%**: "Solid gains. Steady hand."
- **-5% to +5%**: "Flat day. Markets are grinding."
- **-5% to -15%**: "Rough patch. Check your stops."
- **-15% or worse**: "Heavy day. Buckle up for volatility."

### x_signals (social signal scanner)
- **Confidence ≥0.85 + matched position**: "Strong signal. This feels real."
- **Confidence 0.70-0.85**: "New signal on [topic]. Worth watching."
- **Confidence <0.70**: "Noise signal. Low confidence."

### edge (Kalshi edge detection)
- **Edge >3%**: "Fat edge. Worth a deep look."
- **Edge 1-3%**: "Mild edge. Keeping it on radar."
- **Edge <1%**: "Thin edge. Not worth the friction."

### morning (daily brief)
- **Monday**: "New week. Here's the lay of the land."
- **Friday**: "Friday rundown. What matters before the close."
- **Other**: "Daily digest."

### conflicts (overlapping triggers same hour)
- **2+ conflicts**: "Tomorrow's a mess. Multiple overlaps."
- **Lighter**: "Heads up — couple things hitting together."

**Customization point**: Add trigger types by extending the `VOICE_POOLS` dict in `editorial_voice.py`. Each entry maps `(trigger_name, market_state)` → list of opinion strings.

---

## System 2: Selective Silence — Knowing When NOT to Talk

**What**: Not every trigger fire deserves a message. Silent skips are explicit: "Skipped the brief — nothing worth your attention."

**Content quality checks per trigger**:

- **morning_is_boring**: If market vol <0.5%, no divergences, no edges → skip
- **divergence_is_stale**: If last message on this topic was <3 hours ago AND spread hasn't moved >0.5% → skip
- **signals_are_noise**: If all signals have confidence <0.65 AND no position matches → skip
- **edge_is_weak**: If all edges <1% → skip
- **portfolio_is_flat**: If daily P&L is -2% to +2% AND no major position changes → skip

**Silence cadence**:
- Max 1 silence message per day per user
- Only for *expected* triggers (morning, portfolio check, etc.)
- Never silence micro-initiations (those *are* the value)
- When silent, send explicit message: `"Skipped the brief — nothing worth your attention."`

**Customization point**: Adjust thresholds in `selective_silence.py`:
```python
SILENCE_THRESHOLDS = {
    'vol_floor': 0.5,           # % vol threshold for morning silence
    'divergence_age_limit': 3,  # hours
    'signal_confidence_floor': 0.65,
    'edge_floor': 1.0,          # %
    'portfolio_flat_range': 2.0 # % P&L range
}
```

---

## System 3: Variable Timing — Urgency Scoring + Time-of-Day Awareness

**What**: Schedule message delivery based on urgency (0.0-1.0) and time of day. A mild divergence at 6 AM gets sent immediately (threshold 0.9 before 7 AM). Same divergence at 10 PM gets held (threshold 0.35).

**Per-trigger urgency base**:
- **cross_platform**: (spread / 10%) * 0.6, capped at 1.0
  - 5% spread = 0.3 urgency
  - 10% spread = 0.6 urgency
  - 15%+ spread = 1.0 urgency
- **portfolio**: (abs(daily_pnl) / 10%) * 0.7, capped at 1.0
  - ±5% P&L = 0.35 urgency
  - ±15% P&L = 1.0 urgency
- **x_signals**: (confidence * 0.8) + (position_match ? 0.2 : 0), capped at 1.0
  - Confidence 0.85 + matched = 0.88 urgency
  - Confidence 0.70 + no match = 0.56 urgency
- **edge**: (edge_size / 5%) * 0.8, capped at 1.0
  - 2% edge = 0.32 urgency
  - 5% edge = 0.8 urgency
- **meeting**: (1.0 - minutes_away / 120) capped at 1.0
  - 30 min away = 0.75 urgency
  - 5 min away = 0.96 urgency

**Time-of-day delivery thresholds**:
- **Before 7 AM**: threshold 0.90 (almost everything gets sent)
- **7 AM - 9 AM**: threshold 0.75 (morning crunch — moderate bar)
- **9 AM - 10 PM**: threshold 0.45 (daytime — lower bar, let alerts through)
- **10 PM - 11 PM**: threshold 0.35 (wind-down — only high urgency)
- **11 PM - 12 AM**: threshold 0.85 (late night — back to high bar)
- **12 AM - 7 AM**: threshold 0.90 (sleep time — very high bar)

**Modifiers**:
- **Weekend**: +0.10 urgency (weekends are boring, lower bar for engagement)
- **Clustering prevention**: If message sent <10 min ago, -0.20 urgency (space out messages)
- **Daily fatigue**: If 10+ messages today, +0.20 urgency threshold (user tired, fewer but higher-quality alerts)
- **Random jitter**: ±5% urgency (avoid machine-like precision)

**Send logic**:
```
adjusted_urgency = base_urgency * engagement_modifier ± jitter
if adjusted_urgency >= time_of_day_threshold:
    schedule_send(now or delayed based on urgency)
else:
    hold for next trigger
```

**Customization point**: Modify `TIME_OF_DAY_THRESHOLDS` and modifier constants in `variable_timing.py`:
```python
TIME_OF_DAY_THRESHOLDS = {
    (0, 7): 0.90,    # midnight - 7 AM
    (7, 9): 0.75,    # 7 - 9 AM
    (9, 22): 0.45,   # 9 AM - 10 PM
    (22, 23): 0.35,  # 10 - 11 PM
    (23, 24): 0.85,  # 11 PM - midnight
}
MODIFIERS = {
    'weekend': 0.10,
    'clustering_prevention': 0.20,
    'daily_fatigue_step': 0.20,
}
```

---

## System 4: Micro-Initiations — Ambient Awareness Pings

**What**: Unprompted messages when conditions are met. Not triggered by market events — triggered by meta-state.

**Pools**:

| Pool | Trigger | Message |
|------|---------|---------|
| QUIET_MARKET | Vol <0.3% all day, no trades | "Quiet day. Markets are sleeping." |
| WEEKEND | Saturday/Sunday, no meetings | "Weekend vibes. You're off the hook." |
| MONDAY | Monday 6 AM, fresh week | "Monday morning. Week's open for business." |
| FRIDAY | Friday 4 PM, close approaching | "Friday close. Have a good weekend." |
| HOLIDAY_AWARENESS | US holiday today | "Holiday today. Markets are light." |
| GOOD_STREAK | 5+ consecutive +% days | "On a roll. Good week for you." |
| BAD_STREAK | 5+ consecutive -% days | "Rough stretch. It'll turn around." |
| ABSENCE | No user engagement 24+ hours | "Checking in. Things have been quiet." |

**Cadence**:
- Max 2 micro-initiations per week per user
- Skip on busy days (3+ regular alerts already sent that day)
- No repeats within 2 weeks (hash-based dedup: `sha256(pool + date)` in daily context)

**US Holiday calendar** (built-in awareness):
```python
HOLIDAYS = {
    (1, 1): "New Year's Day",
    (1, 20): "MLK Day",
    (2, 17): "Presidents' Day",
    (3, 17): "St. Patrick's Day",
    (5, 26): "Memorial Day",
    (7, 4): "