Teach an agent to read the room. Detect urgency, frustration, skepticism, confusion, caution, satisfaction, and openness from wording, punctuation, retries, delay pressure, and dialogue history, then turn that signal into work-mode changes such as routing priority, verification depth, explanation style, and guard behavior after success.
让 Agent 听懂空气,不只是听懂任务。
Teach an agent to read the room, not just the task.
这个 skill 做的事情很简单:
What this skill does:
它不是语气美化器,它更像一个后台导演。
It is not a tone-polisher. It is a backstage director.
它盯着一轮对话里那些细小但真实的东西:
不一定It watches the small but real signals inside a turn:
not necessarily然后把这些信号翻译成 Agent 的工作模式。
Then it turns those signals into execution policy.
当前特化校准只覆盖两种语言:
The current specialized calibration covers two languages:
这两条线有单独整理过的共性情绪表达、社区语料、标点习惯、节奏停顿、赶打错拼和 agent-coding 抱怨模式。
These two tracks have explicit calibration for shared emotion cues, community phrasing, punctuation habits, rhythmic pauses, rushed typos, and agent-coding complaint patterns.
其他语言目前只有弱支持:
Other languages currently receive only light support:
发布说明里应该明确写这一点:当前版本没有对其他语言做专门特化训练或独立语料校准。
The release notes should say this plainly: the current version does not include language-specific tuning or dedicated calibration corpora for languages beyond Chinese and English.
采集层一直是四路并行:
The collection layer always runs four signals in parallel:
先跑一轮,把当前用户消息丢进引擎里看看它怎么读空气:
python scripts/emotion_engine.py run --input <turn.json> --pretty
Start with one run. Feed the latest turn in and see how the engine reads the room:
python scripts/emotion_engine.py run --input <turn.json> --pretty
然后按这个顺序接进去:
overlay_prompt 塞进当前这一轮,当成一个很小的动态前置提示。routing.thread_interface 接到队列、线程、heartbeat 和子任务路由。guidance.hook_mode 是 latent,先用 guidance.hidden_hook。只有真的值得打断用户时,再用 guidance.question。analysis.semantic_pass。它是 fast 的时候,再去跑模型语义复核。references/model-prompts.md,把结果按 llm_semantic 回填。confirmed_state.emotion_vector 和 mode_scores。情绪可以并存,dominant_mode 只负责决定这轮谁来主导编排。calibration_state.consistency_rate 和 consistency_samples 长起来,再慢慢抬高前置权重。Then wire it in like this:
overlay_prompt into the current turn as a small dynamic pre-prompt.routing.thread_interface into queueing, thread priority, heartbeat, and subagent routing.guidance.hook_mode is latent, start with guidance.hidden_hook. Reach for guidance.question only when the interruption is worth it.analysis.semantic_pass first. Only run the semantic model pass when it says fast.references/model-prompts.md and feed the result back as llm_semantic.confirmed_state.emotion_vector and mode_scores together. Emotions can coexist. dominant_mode only decides who drives the turn.calibration_state.consistency_rate and consistency_samples become believable.Pass a JSON object with any of these fields:
{
"message": "latest user message",
"context": {
"timezone": "Asia/Shanghai",
"now_iso": "2026-04-17T14:20:00+08:00"
},
"history": [
{"role": "user", "text": "earlier user turn"},
{"role": "assistant", "text": "earlier assistant turn"}
],
"user_profile": {
"id": "user-123",
"timezone": "Asia/Shanghai",
"work_hours_local": [9, 22],
"persona_traits": {
"patience": 0.55,
"skepticism": 0.48,
"caution": 0.52,
"openness": 0.44,
"assertiveness": 0.38
},
"big5": {
"openness": 0.7,
"conscientiousness": 0.62,
"extraversion": 0.41,
"agreeableness": 0.56,
"neuroticism": 0.36
},
"affective_prior": {
"urgency": 0.12,
"frustration": 0.1,
"confusion": 0.08,
"skepticism": 0.42,
"satisfaction": 0.12,
"cautiousness": 0.28,
"openness": 0.2
},
"baseline": {
"response_delay_seconds": 35,
"politeness": 0.2,
"terseness": 0.35,
"punctuation": 0.15,
"directness": 0.3
}
},
"runtime": {
"response_delay_seconds": 18,
"unresolved_turns": 4,
"bug_retries": 2,
"task_age_minutes": 25,
"queue_depth": 1,
"background_tasks_running": 2,
"same_issue_mentions": 2
},
"last_state": {
"vector": {
"urgency": 0.4,
"frustration": 0.2,
"clarity": 0.6,
"satisfaction": 0.1,
"trust": 0.5,
"engagement": 0.7
},
"emotion_vector": {
"urgency": 0.4,
"frustration": 0.2,
"confusion": 0.3,
"skepticism": 0.35,
"satisfaction": 0.1,
"cautiousness": 0.2,
"openness": 0.5
},
"ttl_seconds": 1200
},
"calibration_state": {
"observed_turns": 18,
"posthoc_samples": 11,
"consistency_samples": 9,
"stable_prediction_hits": 6,
"prediction_agreement": 0.58,
"consistency_rate": 0.63
},
"llm_semantic": {
"labels": ["urgent", "frustrated"],
"confidence": 0.78,
"emotion_vector": {
"urgency": 0.88,
"frustration": 0.82,
"confusion": 0.41,
"skepticism": 0.28,
"satisfaction": 0.08,
"cautiousness": 0.12,
"openness": 0.2
}
},
"posthoc_semantic": {
"labels": ["skeptical"],
"confidence": 0.71,
"emotion_vector": {
"urgency": 0.14,
"frustration": 0.18,
"confusion": 0.12,
"skepticism": 0.58,
"satisfaction": 0.05,
"cautiousness": 0.26,
"openness": 0.18
},
"cue_spans": [
{"text": "不一定", "signal": "skepticism", "kind": "hedge", "strength": 0.4}
]
}
}
Run screen when you need a fast deterministic first pass from text, history, and runtime hints.
python scripts/emotion_engine.py screen --input turn.json --pretty
Use this stage to get:
featuresinitial_vectoremotion_vectorevidencelabelsRun confirm after you have either:
screen result onlyscreen result plus an LLM semantic judgmentpython scripts/emotion_engine.py confirm --input turn.json --pretty
Use this stage to produce the final state that should drive behavior:
confirmed_statedominant_modeemotion_vectormode_scoresconfidencettl_secondsweight_scheduleconsistency_snapshotRun predict or run to estimate where the conversation is heading.
Prediction covers:
Use guidance.question only when the user state is unclear or tension is rising and a short probe can improve alignment.
Keep the question short. Ask for one dimension at a time:
Use routing.thread_interface to drive orchestration.
Key fields:
queue_modeprefer_main_threaddefer_heartbeatallow_parallel_subagentsprogress_update_interval_secopenclawhermesThe engine keeps three layers:
emotion_vector: concurrent affect axes. Current axes are urgency, frustration, confusion, skepticism, satisfaction, cautiousness, openness.interaction_state: task-reading axes. Current axes are clarity, trust, engagement.constraint_signals: execution constraints. Current axes are boundary_strength, verification_preference, scope_tightness, evidence_requirement.Each axis is continuous and concurrent.
0.8 means the axis is currently dominant enough to steer runtime behavior.
Intensity bands:
0.00-0.29: background0.30-0.54: present0.55-0.74: strong0.75-1.00: dominantUse mode_scores to decide which mode should win orchestration when several emotions are present at once.
Insert overlay_prompt as a compact dynamic system or developer overlay for the next turn.
Use it for:
Use debug_overlay_prompt only for inspection or logging.
Use profile_state as the session-global baseline snapshot.
Use constraint_signals for boundary strength, verification preference, and scope tightness.
Use memory_update as the persistence payload for USER.md, sqlite, or another durable profile store.
It tracks:
proposed_calibration_stateconsistency_rate is the long-run front versus posthoc吻合率。
系统会在冷启动阶段优先采信后置反问,当 consistency_rate 和 consistency_samples 升高后,自动抬升前置情绪标签的采信权重。
USER.md can feed the engine through user_profile.persona_traits, user_profile.big5, and user_profile.affective_prior.
These are treated as low-weight priors for the current turn.
Do not make it the permanent personality. Treat it as per-turn state.
Read references/integration-openclaw-hermes.md when wiring the output into runtime hooks.
Use this mapping:
message_received or before_agent_start computes state, agent:bootstrap or before_agent_start injects the overlay, queue and subagent logic consume thread_interface.SOUL.md, store durable user tendencies in USER.md, and apply the per-turn state through /personality, local orchestration, or tool-driven overlays.scripts/emotion_engine.py: screening, confirmation, prediction, guidance, overlay, and routing CLI.scripts/ablation_test.py: real-world community-case ablation against a no-skill baseline.scripts/posthoc_calibration_pack.py: build the v2 cold-start posthoc calibration pack from community issue samples.assets/community-posthoc-calibration-v2.jsonl: expanded community-style calibration set with GitHub issues, discussions, and forum-style failure reports.assets/community-posthoc-calibration-56.jsonl: frozen first-pass snapshot for reproducibility.references/examples.md: side-by-side examples that show how the layer changes agent behavior.references/model-prompts.md: prompt blocks for initial screen, confirmation, and guidance.references/prompt-chain-audit.md: condensed design logic for external review and critique.references/research-cues-v2.md: source-backed notes for punctuation, textisms, pauses, misspellings, and confidence weighting.references/emotion-value-model.md: what this layer changes in routing, work quality, guard mode, and user alignment.references/emotion-policy-matrix.md: mapping from emotion state to behavior.references/integration-openclaw-hermes.md: runtime wiring notes and example flow.