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
CODEBLOCK0
Plus two ambient systems:
- - microinitiations: Unprompted pings when conditions are met (quiet market, good streak, absence detected)
- responsetracker: 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:
- - morningisboring: If market vol <0.5%, no divergences, no edges → skip
- divergenceisstale: If last message on this topic was <3 hours ago AND spread hasn't moved >0.5% → skip
- signalsarenoise: If all signals have confidence <0.65 AND no position matches → skip
- edgeisweak: If all edges <1% → skip
- portfolioisflat: 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: INLINECODE3
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:
- - 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
- - xsignals: (confidence * 0.8) + (positionmatch ? 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:
CODEBLOCK2
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:
- - 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):
CODEBLOCK4
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:
- - crossplatform: If divergence was flagged earlier, compare current spread to earlier spread
- portfolio: If earlier portfolio message, show change since then
- xsignals: If same signal fired earlier, acknowledge the repeat with new data
- edge: Compare edge size to earlier edge on same market
Persistence: JSON file at ~/.openclaw/state/daily_context.json:
CODEBLOCK6
Auto-reset: At midnight (UTC), clear context for fresh day.
Back-reference example:
CODEBLOCK7
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:
- - sends: Count of messages sent
- engagements: Count of messages user responded to (within 1-hour window)
- ignores: Count of messages user didn't respond to
- avgresponsetime: Average time from message to user response (minutes)
1-hour engagement window: If user responds to a message within 60 minutes, count it as engagement. After 60 min, assume ignored.
Urgency modifier:
- - Engagement ≥70%: Multiply urgency by 1.3 (user likes these alerts, send more)
- Engagement 40-70%: Urgency × 1.0 (balanced)
- Engagement <10%: Urgency × 0.5 (user ignoring, tone it down)
Adaptation suggestion: After 10+ sends of a trigger type with <20% engagement, log:
CODEBLOCK9
Persistence: ~/.openclaw/state/response_tracker.json:
CODEBLOCK10
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:
CODEBLOCK12
Integration with OpenClaw Agents
Step 1: Import the engine
CODEBLOCK13
Step 2: Hook into proactive trigger system
In your agent's trigger handler (e.g., proactive_agent.py):
CODEBLOCK14
Step 3: Hook engagement tracker
When user responds to a message:
CODEBLOCK15
Step 4: Run micro-initiations
Add a separate cron job (every 30 min, low-overhead):
CODEBLOCK16
Step 5: Daily context reset
At midnight, engine auto-resets context. Manually trigger if needed:
CODEBLOCK17
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
CODEBLOCK18
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" - Lower variabletiming thresholds (
variable_timing.py): Fewer messages slip through outside peak hours - Check editorialvoice: Opinions might not match user's style
- 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 it
Scenario 3: Your agent's opinions feel generic
- 1. Open
editorial_voice.py and expand voice pools per trigger - 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 init
Performance & State Management
State files (user's home directory):
- -
~/.openclaw/state/daily_context.json (~5KB, resets daily) - INLINECODE25 (~2KB, persistent)
Engine overhead:
- - editorialvoice: <5ms (dict lookup)
- selectivesilence: <10ms (threshold comparisons)
- variabletiming: <15ms (urgency calculation + time lookup)
- microinitiations: <20ms (condition evaluation)
- contextbuffer: <5ms (history lookup)
- responsetracker: <5ms (metrics lookup)
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)
- - Initial 6-system framework
- Default configuration tuned for prediction market trading agents
- All systems designed for domain adaptation — swap voice pools, thresholds, and micro-initiation conditions for any use case
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.
人格引擎 — 6系统行为框架
目标: 让任何AI智能体显得鲜活——拥有观点、意识、判断力、记忆、时间感知和参与敏感度。适用于交易智能体、通知系统、个人助理或任何主动型智能体。不仅仅是数据传递。
架构概览
触发器触发 → engine.py 编排器
↓
选择性静默(我们是否应该保持沉默?)
↓
紧急度计算(此事紧急程度如何 0.0-1.0?)
↓
参与度修正器(根据用户响应模式调整)
↓
可变时机(根据紧急度+时段安排投递)
↓
上下文缓冲区(添加对今日早些消息的回溯引用)
↓
编辑语气(注入个性/观点)
↓
去重(避免滚动窗口内重复)
↓
发送 → iMessage(或其他传输方式)
外加两个环境系统:
- - 微发起: 条件满足时主动推送(市场平静、连胜、检测到缺席)
- 响应追踪器: 监控参与度;调整紧急度+建议调优
系统1:编辑语气 — 观点注入
内容: 每种触发器类型都有个性——观点根据市场状态、投资组合盈亏、信号置信度而变化。
每种触发器的语气池:
cross_platform(Kalshi vs Polymarket分歧)
- - 看涨分歧(>5%): 重大分歧。这两个市场中必有一个是错的。
- 温和分歧(2-5%): 温和分歧。暂无警示信号。
- 陈旧分歧(超过6小时): 分歧已过时——市场可能已重新定价。
portfolio(用户持仓表现)
- - +15%或更好: 好日子。投资组合运行良好。
- +5%至+15%: 稳健收益。操作稳健。
- -5%至+5%: 平淡日。市场在磨底。
- -5%至-15%: 艰难时期。检查你的止损位。
- -15%或更差: 沉重日。系好安全带应对波动。
x_signals(社交信号扫描器)
- - 置信度≥0.85 + 匹配仓位: 强信号。这感觉真实。
- 置信度0.70-0.85: [主题]出现新信号。值得关注。
- 置信度<0.70: 噪声信号。置信度低。
edge(Kalshi边缘检测)
- - 边缘>3%: 丰厚边缘。值得深入研究。
- 边缘1-3%: 温和边缘。保持关注。
- 边缘<1%: 薄边缘。不值得费力。
morning(每日简报)
- - 周一: 新的一周。以下是当前局势。
- 周五: 周五总结。收盘前的重要事项。
- 其他: 每日摘要。
conflicts(同一小时重叠触发器)
- - 2个以上冲突: 明天一团糟。多个重叠。
- 较轻: 提醒——有几件事同时发生。
自定义点: 通过扩展editorialvoice.py中的VOICEPOOLS字典添加触发器类型。每个条目映射(triggername, marketstate) → 观点字符串列表。
系统2:选择性静默 — 知道何时不说话
内容: 并非每次触发器触发都值得发送消息。静默跳过是明确的:跳过了简报——没有值得你关注的内容。
每种触发器的内容质量检查:
- - morningisboring: 如果市场波动率<0.5%,无分歧,无边缘 → 跳过
- divergenceisstale: 如果关于此主题的最后一条消息在3小时内且价差未变动超过0.5% → 跳过
- signalsarenoise: 如果所有信号置信度<0.65且无仓位匹配 → 跳过
- edgeisweak: 如果所有边缘<1% → 跳过
- portfolioisflat: 如果每日盈亏在-2%至+2%之间且无重大仓位变动 → 跳过
静默节奏:
- - 每个用户每天最多1条静默消息
- 仅针对预期触发器(早晨、投资组合检查等)
- 永不静默微发起(那些就是价值所在)
- 静默时,发送明确消息:跳过了简报——没有值得你关注的内容。
自定义点: 在selective_silence.py中调整阈值:
python
SILENCE_THRESHOLDS = {
vol_floor: 0.5, # 早晨静默的波动率阈值%
divergenceagelimit: 3, # 小时
signalconfidencefloor: 0.65,
edge_floor: 1.0, # %
portfolioflatrange: 2.0 # 盈亏范围%
}
系统3:可变时机 — 紧急度评分+时段感知
内容: 根据紧急度(0.0-1.0)和时段安排消息投递。早上6点的温和分歧立即发送(早上7点前阈值为0.9)。同一分歧在晚上10点被保留(阈值为0.35)。
每种触发器的紧急度基数:
- - cross_platform: (价差/10%) * 0.6,上限1.0
- 5%价差 = 0.3紧急度
- 10%价差 = 0.6紧急度
- 15%+价差 = 1.0紧急度
- - portfolio: (abs(每日盈亏)/10%) * 0.7,上限1.0
- ±5%盈亏 = 0.35紧急度
- ±15%盈亏 = 1.0紧急度
- - x_signals: (置信度 * 0.8) + (仓位匹配 ? 0.2 : 0),上限1.0
- 置信度0.85 + 匹配 = 0.88紧急度
- 置信度0.70 + 无匹配 = 0.56紧急度
- - edge: (边缘大小/5%) * 0.8,上限1.0
- 2%边缘 = 0.32紧急度
- 5%边缘 = 0.8紧急度
- - meeting: (1.0 - 剩余分钟数/120) 上限1.0
- 剩余30分钟 = 0.75紧急度
- 剩余5分钟 = 0.96紧急度
时段投递阈值:
- - 早上7点前: 阈值0.90(几乎所有消息都发送)
- 早上7点-9点: 阈值0.75(早高峰——中等门槛)
- 上午9点-晚上10点: 阈值0.45(白天——较低门槛,让警报通过)
- 晚上10点-11点: 阈值0.35(放松时间——仅高紧急度)
- 晚上11点-12点: 阈值0.85(深夜——回到高门槛)
- 凌晨12点-7点: 阈值0.90(睡眠时间——非常高门槛)
修正器:
- - 周末: +0.10紧急度(周末无聊,降低参与门槛)
- 聚类预防: 如果消息在10分钟内发送过,-0.20紧急度(分散消息)
- 每日疲劳: 如果今天已发送10+条消息,+0.20紧急度阈值(用户疲劳,更少但更高质量的警报)
- 随机抖动: ±5%紧急度(避免机器般的精确度)
发送逻辑:
adjustedurgency = baseurgency * engagement_modifier ± jitter
if adjustedurgency >= timeofdaythreshold:
schedule_send(now or delayed based on urgency)
else:
hold for next trigger
自定义点: 在variabletiming.py中修改TIMEOFDAYTHRESHOLDS和修正器常量:
python
TIMEOFDAY_THRESHOLDS = {
(0, 7): 0.90, # 凌晨-早上7点
(7, 9): 0.75, # 早上7-9点
(9, 22): 0.45, # 上午9点-晚上10点
(22, 23): 0.35, # 晚上10-11点
(23, 24): 0.85, # 晚上11点-凌晨
}
MODIFIERS = {
weekend: 0.10,
clustering_prevention: 0.20,
dailyfatiguestep: 0.20,
}
系统4:微发起 — 环境感知推送
内容: 条件满足时的主动消息。不由市场事件触发——由元状态触发。
池:
| 池 | 触发条件 | 消息 |
|------|---------|