Install
openclaw skills install outclaw-styleLearn the user's writing style per outreach channel (email, LinkedIn, Twitter/X, WhatsApp, Slack, SMS, Discord, Telegram — whatever is connected for this tenant). Runs the Prompt Learning Protocol from https://gist.github.com/milstan/3b12f938f344f4ae1f511dd19e56adce on ≥20 outbound samples per channel (falls back to what's available). Triggers on: 'learn my style', 'learn my voice', 'retrain style for <channel>', 'style report', 'how's my style score'. Auto-invoked (no user prompt) by outclaw-plan when a planned channel lacks a learned style for the current tenant.
openclaw skills install outclaw-styleLearns a per-channel style prompt for the current tenant and persists
it at ~/.openclaw/outclaw/styles/<tenant>/<channel>_style.md. Each style
prompt is what outclaw-plan uses to draft messages on that channel.
Before writing styles, memory entries, or any KB update, read
shared/references/RESOLVER.md. Styles go in
styles/<tenant>/<channel>_style.md. NEVER hand-craft a different path.
A trained-style summary goes to tenant memory as
type=user, key=style_trained_<channel> so outclaw-plan can find it
quickly without re-reading the style file.
learn my style, retrain style for email.outclaw-plan builds a plan that
includes a channel with no learned style for this tenant, it invokes
this skill for that one channel, waits for completion, then continues.
No user prompt. No interruption.The gist at https://gist.github.com/milstan/3b12f938f344f4ae1f511dd19e56adce prescribes:
confidence accordingly.
Do not fabricate samples.~/.openclaw/outclaw/styles/<tenant>/<channel>_style.md with YAML
frontmatter (tenant, channel, trained_at, sample_count, best_score,
best_iteration, dimensions).See references/style-learning.md for the detailed steps and
agents/style-learner.md for the delegated sub-agent spec.
For each channel we care about, list where outbound samples can be read
from. The agent picks only channels this tenant has ready in the
capability map (capabilities/<tenant>.json).
| Channel | Sample source |
|---|---|
| Gmail | gog gmail messages search "from:me" --max 50 |
linkedin-cli posts --author me --max 50 (if connected) or export | |
| Twitter/X | XActions or direct API via xurl |
| Slack | slack-mcp-server message history where sender=me |
whatsapp-mcp-ts conversation export, filter author=me | |
| Telegram | telegram-mcp sent messages |
| Discord | discord-mcp messages where author=me |
| iMessage/SMS | mac_messages_mcp sent messages |
| Bluesky | bsky-mcp-server user posts |
Pick channels — from memory tool_inventory, enumerate channels
that have a ready plugin AND a sample source. Skip channels with
no connected plugin entirely (no point training).
For each selected channel, run a sub-task:
a. Pull outbound samples via the channel's plugin. Write raw samples
to kb/raw/style-<tenant>-<channel>-<ts>.jsonl (NOT into the KB's
people/orgs — this is training data, filed under raw/).
b. If the sample count is <20 or <1 000 words, log a memory
observation and proceed anyway:
{type: observation, key: "style_thin_<channel>", insight: "only <N> samples — learned prompt confidence will be lower", source: "observed", confidence: 6}.
c. Two-stage classify: heuristic pre-filter (outbound, non-trivial
length, not auto-reply) → LLM OUTREACH_COLD/FOLLOWUP/WARM vs.
NOT_OUTREACH (see scripts/message_classifier.py).
d. Run the 5-iteration Prompt Learning Protocol
(scripts/style_evaluator.py).
e. Write the learned style to
~/.openclaw/outclaw/styles/<tenant>/<channel>_style.md.
f. Log: {type: user, key: "style_trained_<channel>", insight: "<channel> style trained; score <N>/100; <K> samples", source: "observed", confidence: <N/10>}.
If auto-invoked (from outclaw-plan): do ONE channel (the one
requested), silent, then return to the caller. NEVER ask the user
for "preferred tone" or "desired format" — the whole point of this
skill is that we infer style from samples. If a channel has no
outbound samples at all (e.g. user just connected Discord today),
log an observation:
{type: observation, key: "style_nosamples_<channel>", insight: "no outbound samples on <channel>; using neutral template", source: "observed", confidence: 6}
and emit a minimal neutral template at
styles/<tenant>/<channel>_style.md with sample_count: 0,
best_score: null, and a generic "direct, concise, warm-professional"
prompt. Return to caller.
If user-invoked: show a compact report — which channels were trained, best score each, sample count, confidence.
styles/<tenant>/<channel>_style.md — NEVER
kb/styles/*, NEVER kb/me/styles/*.kb/raw/style-<tenant>-<channel>-<ts>.jsonl.type=user,
key=style_trained_<channel>.kb/me/self.md — voice description there
is for context, the style prompt lives separately.Sample collection is a one-time opt-in, captured during
outclaw-setup Step 2 as a memory preference entry. If no consent
entry exists when this skill runs:
style_consent entry. If missing, log an observation and fall back
to a neutral template style. Never silently scrape without consent.---
tenant: outclaw
channel: gmail
trained_at: 2026-04-22T12:00:00Z
sample_count: 42
best_score: 82
best_iteration: 3
dimensions: [sentence_length, formality, personalization, cta_style, structure, tone, greeting_pattern, signoff_pattern]
conformity_log:
- {iter: 1, score: 64}
- {iter: 2, score: 71}
- {iter: 3, score: 82}
- {iter: 4, score: 80}
- {iter: 5, score: 78}
---
# Gmail style — outclaw (tenant)
## Instructions
<the learned prompt — 500-2000 words, direct + actionable>
## Avoid
- <anti-pattern 1>
- <anti-pattern 2>
## Reference samples
- <path>/raw/style-outclaw-gmail-<ts>.jsonl (not included verbatim here;
pointer only)
This format lets outclaw-plan parse the "Instructions" section directly
into the draft-generation prompt.