marketing-social-listening
Preamble (run first)
_KS_REPO=""
_KS_REAL_SKILL="$(cd "$HOME/.claude/skills/marketing-social-listening" 2>/dev/null && pwd -P || true)"
for _candidate in \
"${KAITO_SKILLS_DIR:-}" \
"$( [ -n "$_KS_REAL_SKILL" ] && cd "$_KS_REAL_SKILL/../.." 2>/dev/null && pwd -P || true )" \
"$HOME/kaito-skills" \
"$HOME/.kaito-skills/repo"
do
[ -n "$_candidate" ] || continue
if [ -f "$_candidate/skills.json" ] && [ -x "$_candidate/bin/kaito-skills-update-check" ]; then
_KS_REPO="$_candidate"
break
fi
done
if [ -n "$_KS_REPO" ]; then
echo "KAITO_SKILLS_REPO $_KS_REPO"
_UPD=$("$_KS_REPO/bin/kaito-skills-update-check" 2>/dev/null || true)
[ -n "$_UPD" ] && echo "$_UPD" || true
fi
If output shows KAITO_SKILLS_REPO <path>, remember that path as KAITO_SKILLS_REPO.
If output shows UPGRADE_AVAILABLE <old> <new>, read <KAITO_SKILLS_REPO>/docs/update-kaito-skills.md and follow the "Inline upgrade flow" before continuing. If the user snoozes or disables update checks, continue with the current skill.
If output shows JUST_UPGRADED <from> <to>, tell the user Running kaito-skills v{to} (just updated!) and continue.
Social Listening
Use this skill for the redesigned hot-topics social listening workflow.
Inputs
token: project name, ticker, or resolved Kaito token value; optional only when an upstream workflow already suppliesunresolved_stringplus a confirmedofficial_handleofficial_handle: optional upfront hint; required whenever unresolved mode is finalizedunresolved_string: optional prebuilt keyword string fromshared-entity-resolution; use it only when it already comes with a confirmedofficial_handleduration:24h,48h,7d,30d,90d, or an explicit past window withstartandendfocus_mode:presetorcustom(defaultpreset)preset_topics: optional multi-select. Default to all current preset topics:Engagement opportunitiesRisk watchKey voicesEmerging narrativesProduct discussionMarket discussionBugs & issuesCompetitor comparisonsQuestions & evaluationFeature requests
custom_topic_focus: optional free text used only whenfocus_mode="custom"excluded_handles: optional exclusion set that should be merged with canonical official and affiliate handles when already known. For unindexed fallback mode, this usually contains only the confirmed official handle.max_tweets: fixed at100
Workflow
Organize the workflow into four stages: Resolve Entity, Data Gathering, Analysis, and Output.
1. Resolve Entity
Resolve the project identity, exclusion set, and exact analysis window before pulling any tweets.
Use shared-entity-resolution first unless an upstream workflow already hands you a confirmed unresolved identity package.
- If
unresolved_stringis already supplied together with a confirmedofficial_handle, treat that pair as the unresolved identity package fromshared-entity-resolutionand do not rebuild it. - Otherwise, follow
../shared-entity-resolution/SKILL.mdfor all token ambiguity handling, official-handle research, handle confirmation, and unresolved keyword-string construction. - Carry forward the identity package returned by
shared-entity-resolution:- resolved mode:
RESOLUTION_MODE = resolved,RESOLVED_TOKEN = <kaito token>, plusOFFICIAL_HANDLEandAFFILIATE_HANDLESwhen available fromkaito_twitter_official_account - unindexed mode:
RESOLUTION_MODE = unresolved,OFFICIAL_HANDLE = <confirmed official handle>, andUNRESOLVED_STRING = <keyword string>
- resolved mode:
- Do not re-ask the user to restate the whole project if
shared-entity-resolutionhas already narrowed the identity down to one handle candidate that only needs confirmation. - Treat
OFFICIAL_HANDLEas mandatory before continuing in unindexed mode. - In resolved mode, identify the project display name and official X handle when available so the report header and exclusion filters use the correct account identity.
- In resolved mode, if the carried identity package is missing
OFFICIAL_HANDLEorAFFILIATE_HANDLES, callkaito_twitter_official_accountforRESOLVED_TOKENbefore building exclusions. - Build
DISPLAY_PROJECT_NAMEfor output rendering:- prefer the resolved project display name when available
- otherwise fall back to
@<OFFICIAL_HANDLE>
- Build a reusable project search filter for downstream steps:
- resolved mode:
PROJECT_SEARCH_FILTER = tokens=<RESOLVED_TOKEN> - unindexed mode:
PROJECT_SEARCH_FILTER = keyword=<UNRESOLVED_STRING>
- resolved mode:
- Build
EXCLUDED_HANDLESas an optional exclusion set when the needed handles are known:- resolved mode: include the canonical official X handle plus any affiliate handles returned by
kaito_twitter_official_account, then merge any extra confirmedexcluded_handles - unindexed mode: include the confirmed official X handle plus only any extra
excluded_handlesthat were already confirmed upstream
- resolved mode: include the canonical official X handle plus any affiliate handles returned by
- In unindexed mode, do not invent affiliate handles. If only the official handle is confirmed, exclude only that handle.
- Convert any relative duration into exact
window_startandwindow_endtimestamps and use those exact bounds throughout the workflow.
2. Data Gathering
2.1 Fetch the top 100 tweets first
Always pull the full broad corpus before topic filtering.
Run kaito_advanced_search five times in parallel with:
sources="Twitter"- the project search filter from
Resolve Entity:tokens=<RESOLVED_TOKEN>in resolved mode orkeyword=<UNRESOLVED_STRING>in unindexed mode exclude_handles=<EXCLUDED_HANDLES>wheneverEXCLUDED_HANDLESis availablesort_by="smart_engagement"size=20from=0,20,40,60, and80min_created_at=<window_start>max_created_at=<window_end>
Rules for the search stage:
- Do not prefilter by preset topics or custom focus. Fetch the same top 100 tweet corpus first, then apply focus during clustering and ranking.
- Exclude tweets authored by the official project handle and any known affiliate handles. This workflow is for external conversation, not owned-media output.
- In unindexed mode, exclude only the confirmed official handle. Do not guess or invent affiliate handles.
- In unindexed mode, run a quick query-quality check before trusting the full corpus:
- inspect the first-page results and confirm they are materially about the intended project
- if the query is noisy, tighten
UNRESOLVED_STRINGby removing ambiguous names and keeping only low-ambiguity aliases plus the handle - if the query is still noisy after refinement, pause and confirm the handle or alternate project names with the user before continuing
- Treat
EXCLUDED_HANDLESas required retrieval logic whenever those handles are known:- pass
exclude_handles=<EXCLUDED_HANDLES>directly in every Twitter corpus pull - if
EXCLUDED_HANDLESis unavailable because the relevant handles are still unknown, continue with the smaller known exclusion set instead of inventing handles
- pass
- If the official handle has not been confirmed yet, stop and confirm it before proceeding with unindexed mode.
- Deduplicate by tweet ID after pagination.
- Keep replies and quote tweets if they rank in the top corpus, but still exclude them whenever the author is known to belong to
EXCLUDED_HANDLES. - If fewer than 100 tweets are returned, proceed with the available set and say so in the output.
- If the project is unindexed, say clearly that the corpus is keyword-based and entity precision may still be weaker than in resolved-token mode even with a confirmed handle.
2.2 Enrich authors once and reuse the data
Build a unique author list from the fetched tweets and cache one author profile per handle.
For each unique author:
- use
kaito_get_twitter_userwhenauthor_user_idis available so you can retrieve:- display name
- username
- profile image / avatar
- bio and classification when helpful for interpretation
- use
kaito_smart_followersincountmode for every unique author so you always have the latest normalized smart-follower count - use
kaito_twitter_account_typefor every unique author handle when available so you can retrieve:- account type classification
- crypto role
- determine whether the author is
neworexistingby checking for historical mentions of the same project before the current analysis window:- call
kaito_advanced_searchwith:sources="Twitter"usernames=<author_handle>- the same project search filter from
Resolve Entity:tokens=<RESOLVED_TOKEN>when the token is resolvedkeyword=<UNRESOLVED_STRING>for unindexed projects
size=1sort_by="relevance"max_created_at=<window_start_minus_1s>
- use all available history before the current window, not the current window itself
- search against the full project entity expression for the active mode, not only the resolved-token path
- if at least one prior matching tweet is found, set
existing="existing" - if no prior matching tweet is found, set
existing="new"only when the project search filter includes at least one sufficiently unique project name or alias in addition to the handle - if no prior matching tweet is found and the unindexed filter is effectively handle-only, set
existing="unknown"instead ofnewbecause recall is too weak - if the historical query cannot be completed or the handle is unavailable, set
existing="unknown"
- call
Author-enrichment rules:
- Do not rely on the search result's author smart-follower count as the primary source. Always refresh it with
kaito_smart_followersbecause the search payload can be stale or return0. - Use the search result's smart-follower count only as a last-resort fallback when the dedicated
kaito_smart_followerscall fails. - Use
kaito_twitter_account_typeas the primary source forrolewhen the call succeeds. - Always derive
tierfrom the refreshed smart-follower count using the thresholds below. - Every tweet shown in the final output must display: avatar, display name, handle, smart followers, smart engagement,
existing,role, andtier. - If avatar or profile metadata is unavailable, leave it blank rather than inventing values.
Author-status fields:
existing:new | existing | unknown- classify this by checking whether the author mentioned the same project before the current window
- use
kaito_advanced_searchwithusernames=<author_handle>,max_created_at=<window_start_minus_1s>, and the same project search filter fromResolve Entity - if there is at least one prior match, use
existing - if there are no prior matches and the search filter includes at least one sufficiently unique project name or alias, use
new - if there are no prior matches but the unindexed search filter is handle-only, use
unknown - use
unknownonly when the lookup cannot be completed reliably
role:research/trader | builder | kol | community member | unknown- this is a role classification field, not a boolean researcher flag
- this should come from
kaito_twitter_account_type - normalize the endpoint output into the allowed UI values above when needed
- if the endpoint is unavailable or does not return a confident role, use
unknown - keep the output lowercase and structured for UI rendering
tier:mega | large | medium | small | micro | unknown- convenience UI size tier derived from smart-follower count for frontend rendering
- definition:
megawhensmart_followers > 2000largewhen1000 <= smart_followers <= 2000mediumwhen300 <= smart_followers < 1000smallwhen100 <= smart_followers < 300microwhensmart_followers < 100
- if smart-follower data is unavailable, use
unknown - keep the output lowercase and structured for UI rendering
- this is a simplified UI tier; still show the raw smart-follower count separately
3. Analysis
3.1 Score each tweet for urgency and actionability
For every tweet, assign:
urgency:not urgent,low urgency,moderate urgency, orurgenturgency_reason: one short sentence explaining whysuggested_action: one concrete response line that combines the action and objective in a single field
Urgency definitions
urgent: high-leverage content that should be handled in the current monitoring cycle. Usually combines at least two of:- high-author importance such as
megaorlargesmart-follower tier, major media, major partner, major investor, or another clearly influential external voice - unusually high smart engagement for the corpus
- time-sensitive content such as bugs, outages, misinformation, serious competitor framing, high-quality evaluation threads, or influential endorsements that are still open for engagement
- high-author importance such as
moderate urgency: meaningful signal worth replying to, amplifying, clarifying, or monitoring in the next response cycle, but it is not yet a current-cycle escalationlow urgency: low-spread or weakly actionable content that is still worth logging and lightly monitoringnot urgent: repetitive, stale, purely contextual, or non-actionable content that can be recorded without near-term follow-up
The urgency_reason must cite the actual drivers, such as author importance, smart engagement, content sensitivity, novelty, or timing.
Suggested actions
Use suggested_action as a single output field. Write it as:
<action> + <objective>- example:
Reply now to amplify product angle
UI brevity rules for suggested_action:
- Keep it short enough for a compact UI chip or single-line field.
- Target 2 to 6 words and stay under roughly 60 characters.
- Do not include rationale, evidence, account names, metrics, lists, or multiple clauses.
- Do not write a paragraph after
Suggested Action:. The explanation belongs inurgency_reasonor the topic overview, not in the action field.
Use a concrete communications or product action, not trading advice. Good action verbs include:
Reply nowAmplify from official accountClarify nowRoute to supportRoute to productDM / follow up privatelyPrepare internal briefMonitor only
Objective guidance
Each suggested_action should still carry one clear objective. Common objectives include:
Amplify product angleConvert evaluator into advocateCorrect misinformationContain reputational riskSupport affected usersReinforce competitive differentiationCollect product feedbackBuild relationship with key voiceTrack signal without overreacting
Suggested actions should match the tweet:
- strong positive product commentary from a key voice ->
Reply now to amplify product angleorAmplify from official account to extend third-party validation - credible skeptical question ->
Reply now to convert evaluator into advocate - bug report or outage claim ->
Route to support to help affected usersorClarify now to contain reputational risk - competitor comparison ->
Reply now to reinforce competitive differentiationorPrepare internal brief to align the team on response - low-signal praise or stale commentary ->
Monitor only to track signal without overreacting
3.2 Cluster tweets into hot topics
Cluster the fetched tweets into coherent hot topics using tweet content, author context, smart engagement, and the selected focus.
Hot-topic rules:
- Build topic groups around a concrete discussion thread or narrative angle, not around generic sentiment buckets.
- Each hot topic should contain a short title, a concise thesis, and the ordered list of supporting tweets.
- Rank tweets inside each topic by smart engagement first, then by author importance, then by recency.
- Aim for selective topics rather than exhaustive fragmentation. Merge obviously overlapping clusters.
3.3 Apply topic focus and tagging
The output tagging system uses the current preset topic taxonomy plus Other:
Engagement opportunitiesRisk watchKey voicesEmerging narrativesProduct discussionMarket discussionBugs & issuesCompetitor comparisonsQuestions & evaluationFeature requestsOther
Tagging rules:
- Multi-tagging is allowed. Assign up to 3 labels per topic when justified.
- Use
Otheronly when none of the current preset labels fit. - If
focus_mode="preset", default to all current preset topics selected. If the user narrows the preset multi-select, prioritize and keep topics that match the selected preset labels. - If
focus_mode="custom", usecustom_topic_focusto change clustering and prioritization logic, but do not invent new output labels. Final topics must still be tagged with the current output taxonomy.
Use these label definitions:
Engagement opportunities: clear chances to reply, quote, thank, or build a relationshipRisk watch: negative claims, controversy, misinformation, or reputation-sensitive discussionKey voices: clusters dominated by important accounts or notable new entrantsEmerging narratives: new or accelerating storylinesProduct discussion: features, launches, integrations, usage, demos, or UXMarket discussion: price, valuation, flows, listings, or trading-related discussionBugs & issues: reliability problems, exploits, outages, broken flows, or support painCompetitor comparisons: direct versus framing, category benchmarks, or substitution argumentsQuestions & evaluation: due-diligence threads, skeptical questions, or evaluative discussionFeature requests: explicit asks for missing or improved functionalityOther: relevant discussion that does not fit the preset taxonomy
3.4 Compute topic-level rollups
For each hot topic, compute:
tweet_count: total number of tweets in the topictotal_smart_engagement: sum of smart engagement across all tweets in the topicurgency: the highest urgency found in any tweet in the topickey_accounts: the most important or most repeated authors in the cluster
Topic-ranking rules:
- Order hot topics by highest topic urgency first using
urgent > moderate urgency > low urgency > not urgent, then total smart engagement, then tweet count. - A topic inherits the highest urgency found in its tweets using the same severity order:
urgent > moderate urgency > low urgency > not urgent. - Use the aggregate metrics in both the topic summary card and the detailed section.
3.5 Resolve narratives for the summary
Before writing the Summary, do one lightweight narrative check.
- Call
kaito_narrativesto get the canonical Kaito narrative set. - Check whether the
Summarymentions any narrative from that set. - If a mentioned narrative matches a canonical Kaito narrative, render it with the structured narrative token using the returned
narrativevalue exactly as shown, but keep it embedded naturally inside the sentence that is already making the point. - If a theme in the
Summarydoes not match the canonical narrative set, mention it in plain language only and do not invent a structured narrative token.
4. Output
Prefer the output structure below. If the user asks a specific question, answer it more directly within that structure, especially in Summary. If the user does not ask a specific question, use the same structure as the default summary or report.
Start with a Summary section in exactly three short paragraphs:
- the most direct response to the user's request, together with the overall conclusion for the selected project and time window
- the most important hot topics, the most important accounts driving them, and any resolved narratives that matter most
- the most important suggested actions and the objectives embedded in them
Summary-only structured rendering rules:
- Do not add a standalone report title before
Summary. The UI can render the project name and time window separately. - When the UI or surrounding workflow needs a project label, use
DISPLAY_PROJECT_NAME. - Keep each summary paragraph compact: no more than 2 sentences per paragraph.
- Keep
Summaryhigh-level. Do not restate full topic cards, long tweet examples, or per-topic metric breakdowns there. - Mention only the most important 1 to 2 themes and the most important actions at a high level.
- If you mention an account handle in the
Summary, render it as@handle. The leading@is the parsing signal for frontend account rendering. - If you mention a resolved narrative in the
Summary, render it as[[narrative:<narrative>]], where<narrative>is the exactnarrativefield returned bykaito_narrativessuch asAIorL2. The[[narrative:...]]wrapper is the parsing signal for frontend narrative rendering, but it must appear inline in natural prose. - Do not add standalone labels or trailing token lists such as
Matched narratives: [[narrative:AI]], [[narrative:L2]]. - Prefer wording like
discussion concentrated around [[narrative:AI]] and [[narrative:L2]]instead of breaking the sentence to enumerate matches mechanically. - Keep this structured narrative token in the
Summaryonly. TheHot Topicssection does not need this special rendering.
Then add Hot Topics.
For each hot topic, show:
- topic title
- topic labels from the current output taxonomy, with up to 3 labels when applicable
- overview explaining what the topic is about and why it matters in this time window
Tweets: NSmart Engagement: NUrgency: not urgent | low urgency | moderate urgency | urgent- key accounts
Hot-topic formatting rules:
- Topic cards are summary containers only. They should contain exactly the topic-level fields above plus the tweet list below, and nothing else.
- Use the exact tag labels from the taxonomy. Do not change capitalization or wording.
Urgencymust be one of the exact lowercase values:not urgent,low urgency,moderate urgency, orurgent.Smart Engagementmust be a numeric aggregate, not qualitative text such asHighorMedium.key accountsshould be a short comma-separated list, preferably handles only.- Do not add a topic-level
Suggested Actionparagraph or any extra block such asSource Credibility. - The topic
overviewcan be 2 to 3 short sentences. The first sentence is the most important and should work as the compact card summary; the full 2 to 3 sentences can be used in the detail view. - Do not add separate topic-level prose sections such as
Why it matters,Recommended response,Takeaway, orSource notesoutside the singleoverviewfield. - Keep the topic body compact for UI scanning. Show at most 5 tweets per topic, prioritized by smart engagement and author importance.
Then list the tweets in that topic. Every tweet entry must include:
- avatar
- display name
- handle
- smart followers
- smart engagement
- existing
- role
- tier
- tweet text or a concise factual summary
- tweet URL
Urgency: <level> - <reason>Suggested Action: <action + objective>
Tweet-entry formatting rules:
- Tweet entries are the only place where
Suggested Actionappears. - Do not render tweets as markdown tables. Use one compact entry per tweet so the UI can map fields cleanly.
- Use a real tweet URL, never a placeholder such as
link. - Keep the tweet text as the original text or a concise factual summary only.
- Do not add unsupported fields such as
Source Credibility, free-form sentiment columns, or long prose after the tweet entry. Suggested Actionmust remain a short single line, not a mini recommendation paragraph.existing,role, andtiermust stay structured and compact. Do not replace them with prose.
Rules
- This workflow is content-first and topic-first, not KPI-first.
- Always anchor the answer to the user's actual request. The output structure is a response format, not a substitute for addressing the user's prompt directly.
- Always fetch the top 100 tweets for the resolved ticker or the confirmed keyword-based project query before applying focus logic.
- The top-tweets corpus should reflect external discussion only, excluding the project's own handle and any known affiliate handles when available.
- The summary and topic sections must use the exact selected time window, not a fuzzy rolling description.
- Do not invent author identity, avatar, or account role. Use factual profile data only.
- Keep
suggested_actiontied to the actual tweet, author context, and embedded objective. - Keep actions practical for comms, community, support, or product teams.
- Do not output trading advice or market calls such as
buy signal,sell signal, or price-target language. - Do not include owned or affiliated project accounts in the external-conversation topic corpus or topic tweet lists. In unindexed mode, enforce this only for handles you actually know.
- If the project is unindexed or keyword-only, say so explicitly and note any limitations around entity precision, existing-voice recall, affiliate exclusion, and structured token-dependent coverage.
- If the dataset is sparse, say so directly rather than overstating confidence.
- Say
smart accounts, neversmart money.