Personality Engine
by @kingmadellc
Six-system behavior engine that makes any OpenClaw agent feel alive. Editorial voice injects opinions. Selective silence knows when NOT to talk. Variable tim...
clawhub install personality-engineπ About This Skill
name: Personality Engine description: "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."
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:
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)
portfolio (user's holdings performance)
x_signals (social signal scanner)
edge (Kalshi edge detection)
morning (daily brief)
conflicts (overlapping triggers same hour)
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:
Silence cadence:
"Skipped the brief β nothing worth your attention."Customization point: Adjust thresholds in selective_silence.py:
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:
Time-of-day delivery thresholds:
Modifiers:
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:
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:
sha256(pool + date) in daily context)US Holiday calendar (built-in awareness):
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): "Independence Day",
(9, 1): "Labor Day",
(10, 13): "Columbus Day",
(11, 11): "Veterans Day",
(11, 27): "Thanksgiving",
(12, 25): "Christmas",
}
Customization point: Add pools in micro_initiations.py:
MICRO_POOLS = {
'QUIET_MARKET': {
'condition': lambda ctx: ctx.vol < 0.3 and ctx.trade_count == 0,
'messages': ["Quiet day. Markets are sleeping.", "No action today."],
},
'YOUR_POOL': {
'condition': lambda ctx: your_logic_here(),
'messages': ["Message 1", "Message 2"],
}
}
System 5: Context Buffer β Daily Memory + Back-References
What: Messages can reference earlier messages from today. "That Kalshi/PM divergence I flagged at 9 AM widened to 15%." This makes the agent feel like it's *thinking about* past events, not just firing isolated alerts.
Per-trigger back-reference generation:
Persistence: JSON file at ~/.openclaw/state/daily_context.json:
{
"date": "2026-03-09",
"messages": [
{
"time": "09:15",
"trigger": "cross_platform",
"spread": 7.2,
"markets": ["kalshi", "polymarket"],
"message_id": "msg_abc123"
},
{
"time": "14:30",
"trigger": "portfolio",
"pnl": 12.5,
"message_id": "msg_def456"
}
],
"silence_count": 1,
"micro_count": 0,
"sent_count": 5
}
Auto-reset: At midnight (UTC), clear context for fresh day.
Back-reference example:
Earlier (9:15 AM): "Mild divergence. Kalshi 52%, Poly 48%."
Later (2:30 PM): "That Kalshi/Poly spread I flagged this morning widened to 7% β now 55/48. Worth watching."
Customization point: Add back-reference logic for new trigger types in context_buffer.py:
def generate_backreference(trigger_type, current_data, history):
if trigger_type == 'cross_platform':
earlier = find_similar_trigger(history, 'cross_platform')
if earlier:
spread_change = current_data['spread'] - earlier['spread']
return f"That spread I flagged {time_ago(earlier)} widened to {spread_change}%."
return None
System 6: Response Tracker β Engagement Adaptation
What: Track user's response patterns. If user engages with 70%+ of messages, urgency stays high. If engagement <10%, adjust urgency down or suggest tuning.
Metrics per trigger type:
1-hour engagement window: If user responds to a message within 60 minutes, count it as engagement. After 60 min, assume ignored.
Urgency modifier:
Adaptation suggestion: After 10+ sends of a trigger type with <20% engagement, log:
β οΈ ADJUSTMENT SUGGESTION:
Trigger: x_signals
Sends: 12 | Engagement: 8% | Avg response time: NeverConsider:
β Lower signal confidence floor (currently 0.65)
β Reduce frequency (increase silence thresholds)
β Check if message editorial voice is mismatched
Persistence: ~/.openclaw/state/response_tracker.json:
{
"cross_platform": {
"sends": 15,
"engagements": 9,
"ignores": 6,
"avg_response_time": 23.5,
"last_engagement": "2026-03-09T14:32:00Z"
},
"x_signals": {
"sends": 12,
"engagements": 1,
"ignores": 11,
"avg_response_time": null,
"last_engagement": null
}
}
Customization point: Adjust engagement thresholds and modifier multipliers in response_tracker.py:
ENGAGEMENT_THRESHOLDS = {
'high': 0.70, # β₯70% β 1.3x urgency
'low': 0.10, # <10% β 0.5x urgency
}
URGENCY_MULTIPLIERS = {
'high': 1.3,
'low': 0.5,
}
SUGGESTION_TRIGGERS = {
'min_sends': 10,
'max_engagement_for_suggestion': 0.20,
}
OpenClaw Ecosystem Integration
The Personality Engine works with any OpenClaw agent β it's domain-agnostic. Designed alongside the Prediction Market Trading Stack but applicable to any proactive agent that sends alerts, digests, or notifications.
Install the complete Prediction Market Trading Stack:
clawhub install kalshalyst kalshi-command-center polymarket-command-center prediction-market-arbiter xpulse portfolio-drift-monitor market-morning-brief personality-engine
Integration with OpenClaw Agents
Step 1: Import the engine
from personality_engine.engine import PersonalityEngineengine = PersonalityEngine(user_id="user@example.com")
Step 2: Hook into proactive trigger system
In your agent's trigger handler (e.g., proactive_agent.py):
async def fire_trigger(trigger_type, data):
# Your normal trigger logic
message_content = generate_message(trigger_type, data) # Pass through personality engine
should_send, scheduled_message = await engine.process_trigger(
trigger_type=trigger_type,
raw_message=message_content,
market_data=data,
urgency_context={'vol': market_vol, 'pnl': portfolio_pnl, ...}
)
if should_send:
if scheduled_message.delayed:
schedule_send(scheduled_message.content, delay=scheduled_message.delay_seconds)
else:
send_now(scheduled_message.content)
else:
log_silence_skip(trigger_type)
Step 3: Hook engagement tracker
When user responds to a message:
def handle_user_response(message_id, trigger_type, response_time_seconds):
engine.response_tracker.log_engagement(trigger_type, response_time_seconds)
Step 4: Run micro-initiations
Add a separate cron job (every 30 min, low-overhead):
async def micro_initiations_check():
micro_message = await engine.check_micro_initiations(context={
'vol': market_vol,
'trade_count': trades_today,
'user_absence_hours': hours_since_last_engagement,
'portfolio_streak': consecutive_days,
}) if micro_message:
send_now(micro_message)
Step 5: Daily context reset
At midnight, engine auto-resets context. Manually trigger if needed:
engine.context_buffer.reset_daily()
Use Cases Beyond Trading
While the default voice pools and thresholds are tuned for prediction market trading, every system is designed for domain adaptation:
| Domain | Editorial Voice | Silence Rules | Micro-Initiations | |--------|----------------|---------------|-------------------| | Trading (default) | Market commentary, edge opinions | Skip flat days, stale divergences | Quiet market, good/bad streaks | | Personal Assistant | Task prioritization opinions | Skip low-urgency reminders | "Quiet week. Inbox is clean." | | DevOps/Monitoring | Incident severity opinions | Skip routine health checks | "Uptime streak: 30 days." | | Sales/CRM | Deal stage opinions | Skip stale leads | "Pipeline looking thin this quarter." | | Content/Social | Engagement commentary | Skip low-performing posts | "Your last post is outperforming." |
To adapt: swap the VOICE_POOLS dict in editorial_voice.py, update thresholds in selective_silence.py, and add domain-specific MICRO_POOLS in micro_initiations.py. See references/customization.md for full guide.
File Structure
personality-engine/
βββ SKILL.md # This file
βββ scripts/
β βββ __init__.py
β βββ engine.py # Main orchestrator
β βββ editorial_voice.py # Opinion injection
β βββ selective_silence.py # Content quality checks
β βββ variable_timing.py # Urgency + time-of-day
β βββ micro_initiations.py # Ambient pings
β βββ context_buffer.py # Daily memory
β βββ response_tracker.py # Engagement tracking
βββ references/
β βββ systems-overview.md # Architecture diagram + flow
β βββ customization.md # Per-system customization guide
βββ examples/
βββ integration-example.py # Copy-paste integration template
Customization Quick-Start
Scenario 1: Your agent fires 50 alerts/day and user ignores most
1. Increase silence thresholds (selective_silence.py): Higher bars for what counts as "worth sending"
2. Lower variable_timing thresholds (variable_timing.py): Fewer messages slip through outside peak hours
3. Check editorial_voice: Opinions might not match user's style
4. Review response_tracker: Which trigger types have <20% engagement? Mute those.
Scenario 2: Your agent never initiates, only reacts
1. Customize micro_initiations pools: Add domain-specific conditions
'LOW_VOLATILITY_OPPORTUNITY': {
'condition': lambda ctx: ctx.vol < 0.2 and ctx.last_edge_size > 2.0,
'messages': ["Calm market, good edge conditions. Might be time to scout."],
}
2. Tune MICRO_CADENCE: Increase max from 2/week to 3-4/week if user loves itScenario 3: Your agent's opinions feel generic
1. Open editorial_voice.py and expand voice pools per trigger
2. Add market-specific opinions:
'VOICE_POOLS': {
'cross_platform': {
'big_divergence': [
"Big divergence. One of these markets is wrong.",
"Spreads are blown out. Arb opportunity.",
"Thick divergence β reality check time.",
],
...
3. Vary by user profile (trader vs long-term investor) by passing user_profile to engine initPerformance & State Management
State files (user's home directory):
~/.openclaw/state/daily_context.json (~5KB, resets daily)~/.openclaw/state/response_tracker.json (~2KB, persistent)Engine overhead:
Total pipeline: ~60ms per trigger (negligible for async message delivery)
License
Part of the OpenClaw portfolio. Use freely in any agent.
Version History
v1.0.0 (2026-03-09)
Feedback & Issues
Found a bug? Have a feature request? Want to share results?
Part of the OpenClaw Prediction Stack β the first prediction market skill suite on ClawHub.