Intention Hint

Pre-scans user intent before replies and injects routing hints via before_prompt_build hook.

Audits

Pass

Install

openclaw plugins install clawhub:intention-hint

Intention Hint Plugin

OpenClaw License: MIT

An OpenClaw plugin that pre-scans user intent before main-agent replies and injects routing hints via the before_prompt_build hook.

How it works

  1. Before Prompt Build — When the user sends a message, the plugin intercepts the prompt construction.
  2. Fast Sub-agent — A lightweight sub-agent classifies the intent by matching against dynamically loaded intent definitions.
  3. Dynamic Intents — Intent definitions live in YAML-frontmatter Markdown files under intents/. Add, remove, or edit intents without rebuilding the plugin. Each intent file specifies:
    • id — unique identifier (e.g. chat, memory-recent)
    • name — human-readable label
    • enabled — whether the intent is active
    • triggers — natural-language descriptions that guide the classifier
    • examples — few-shot examples for the classifier
    • Markdown body — the injection prompt body shown to the main agent after classification
  4. Structured Output — The classifier returns a key-value format:
    intent: <id> (<name>)
    reason: <brief reason for classification>
    goal: <what the user likely wants to achieve>
    confidence: <low | medium | high>
    complexity: <simple | moderate | complex>
    suggestion: <optional correction or recommendation>
    
    The plugin parses this into an IntentionResult and injects the matching intent's body as untrusted context.
  5. Recent Context Support — In queryMode: "recent", the plugin extracts recent user / assistant turns from event.messages, strips previously injected plugin metadata blocks, and builds a recent conversation tail for the classifier.
  6. Internal Run Guard — The classifier skips internal runs for active-memory, intention-hint, and generic :subagent: session keys.
  7. Zero File Write — The plugin does not write any files to disk. All session metadata stays in memory; the embedded subagent runs with modelRun: true and no session file persistence.

Installation

This plugin is a workspace package inside /home/wei/Projects/openclaw/extensions/.
Build it with:

cd extensions/intention-hint
bun install
bun run build

Configuration (openclaw.json)

{
  plugins: {
    entries: {
      "intention-hint": {
        enabled: true,
        config: {
          agents: ["main"],
          model: "google/gemini-3-flash", // lightweight scanner model
          modelFallback: "openai/gpt-5-mini",
          allowedChatTypes: ["direct"],
          allowedChatIds: [],
          deniedChatIds: [],
          queryMode: "recent",
          timeoutMs: 3000,
          intentsDir: "./intents", // relative to plugin root
          intentsHotReload: true, // auto-reload on change
          intentsHotReloadIntervalMs: 5000, // poll interval
        },
      },
    },
  },
}

Config Options

OptionTypeDefaultDescription
agentsstring[]["main"]Agent IDs eligible for intention scanning.
modelstringLightweight model for the intention scanner. Falls back to the agent's default if empty.
modelFallbackstringFallback model when config.model cannot be resolved.
allowedChatTypesstring[]["direct"]Which chat types are eligible (direct, group, channel, explicit).
allowedChatIdsstring[][]Allow-list of chat IDs.
deniedChatIdsstring[][]Deny-list of chat IDs.
queryModestring"recent"Context sent to scanner: message (latest only), recent (recent turns), or full (full history).
timeoutMsnumber3000Budget in milliseconds for the intention scanner sub-agent.
intentsDirstring"./intents"Directory containing dynamic intent .md files. Resolved relative to the plugin installation directory.
intentsHotReloadbooleantrueAutomatically reload intent definitions when files change.
intentsHotReloadIntervalMsnumber5000How often to check for intent file changes (clamped to 1000–300000 ms).

Intent Definition Format

Create a .md file in the intents/ directory:

---
id: RESEARCH_GENERAL
name: General Research Query
enabled: true
triggers:
  - "User is asking for factual or explanatory information that should be researched from external sources"
examples:
  - "Tell me about quantum computing"
  - "Explain blockchain consensus mechanisms"
---

Detected "general research" intent. The user wants factual or explanatory information supported by external sources.

## Guidelines

- Do not answer factual questions from memory alone.
- Prefer authoritative and directly relevant sources.
- Keep the answer accurate, concise, and source-backed.

## Response Strategy

- Search for reliable external sources before answering.
- Summarize the key findings instead of dumping raw search results.
- Include source links when making factual claims.

- Read a long web page with less clutter:
  skill: defuddle

- Search for current external information:
  web_search({ query: "<topic keywords>" })

Frontmatter Fields

FieldRequiredTypeDescription
idyesstringUnique identifier (letters, numbers, hyphens, underscores).
namenostringHuman-readable label (defaults to id).
enablednobooleanWhether this intent is active (defaults to true).
triggersyesstring[]Natural-language descriptions that guide the classifier.
examplesnostring[]Few-shot examples for the classifier.

Intent Writing Rules

1. Split responsibilities clearly

  • Frontmatter is for classification.
  • Markdown body is for the main agent hint injected after classification.

2. Keep frontmatter narrow and classifier-friendly

  • Use triggers to describe the boundary of the intent.
  • Merge similar trigger descriptions instead of listing many near-duplicates.
  • Use examples to preserve diversity without expanding the scope.
  • Do not put tool instructions, workflows, or long reasoning guides in frontmatter.

3. Keep the body short and single-intent

  • Only describe behavior that belongs to that intent.
  • Do not restate broad system rules that already exist elsewhere.
  • Do not mix multiple intent families into one file.
  • Prefer a small, direct prompt over a long SOP-style document.

4. Use a consistent body structure

Recommended shape:

Detected "<intent>" intent. <One-sentence explanation.>

## Guidelines

- ...
- ...

## Response Strategy

- ...
- ...

5. Describe skill usage with timing or purpose

When a skill is relevant, prefer this format:

- Read a large Markdown document by section:
  skill: treemd
- Read a code file by symbols before summarizing implementation details:
  skill: cx

Use short, intent-specific purpose lines. Avoid long skill descriptions.

6. Describe tool usage with exact formats

For direct tool hints, use the explicit call shape:

memory_search({ query: "<subject_A_keywords>", corpus: "memory", maxResults: 5, minScore: 0.1 })
read({ path: "<file>" })
web_search({ query: "<topic keywords>" })
web_fetch({ url: "<authoritative_url>" })

If the intent needs CLI usage through exec, show it as a shell block:

<command>

7. Prefer clean boundaries over convenience

Examples:

  • RESEARCH_GENERAL should cover broad factual or explanatory research.
  • SUMMARIZATION should cover source-driven summary or transcription.
  • PROMPT_DESIGN should cover prompt, intent, skill, or routing design discussion.
  • SYSTEM_DOCS should focus on locating recorded system-side notes, SOPs, or configs.

When an intent starts absorbing neighboring use cases, split it instead of making it broader.

Memory Retrieval Principles

The memory family is slightly different from simple routing intents because it is designed to replace heavier pre-answer memory subagent work with a lighter intent-guided retrieval handoff.

1. Treat the latest user message as primary

  • Use the latest user message as the main retrieval target.
  • Use recent conversation only to disambiguate pronouns, relative references, or scope.
  • Do not return memory just because it matches the broader recent topic.

2. Reformulate before retrieving

  • Rewrite the user's request into a self-contained retrieval target when references are ambiguous.
  • Distill 3–5 high-value concepts before searching.
  • For Traditional Chinese queries, space-separate key nouns or concepts when it improves matching.

3. Match the retrieval method to the memory intent

  • MEMORY_LOOKUP should prefer general memory retrieval.
  • MEMORY_RECENT should prefer recent raw diary files and direct recent-file search.
  • MEMORY_TIMELINE should reconstruct change over multiple points in time.
  • MEMORY_COMPARE should retrieve each subject separately before comparison.
  • MEMORY_EMOTION should prioritize emotional signals and related context.

4. Favor recorded evidence over guesses

  • Return recorded memory only when it materially helps answer the latest user message.
  • If memory is weak, missing, or incomplete, say so clearly.
  • Memory intents may include slightly more retrieval guidance than casual or research intents, but should still avoid turning into full engine specifications.

Memory Family Summary

Use the memory family to route memory questions into the smallest retrieval strategy that still preserves active-memory-style usefulness.

  • MEMORY_LOOKUP: Broad past recall for prior records, preferences, habits, routines, or personal facts without a narrow recent, emotional, comparative, or timeline-specific focus.
  • MEMORY_RECENT: Narrow recent recall such as today, yesterday, this week, or the last few days; prefer raw diary files and direct recent-file search.
  • MEMORY_TIMELINE: Time-ordered recall about change, progress, evolution, or milestones across multiple points in time.
  • MEMORY_COMPARE: Side-by-side recall for two or more remembered subjects; retrieve each subject separately before aligning differences and similarities.
  • MEMORY_EMOTION: Recall centered on feelings, mood, stress, frustration, happiness, or other emotional reactions; prioritize emotional signals before surrounding context.
  • SYSTEM_DOCS: Lookup for recorded system-side notes, SOPs, rules, configs, or project documentation rather than personal diary-style memory.

Use the smallest matching memory intent. If a query primarily asks about recent events, emotion, change over time, or comparison, prefer that specialized intent over MEMORY_LOOKUP.

Memory Escalation Rules

Use escalation to keep memory retrieval rich enough to be useful, but small enough to stay fast.

  1. Reformulate first

    • Turn the latest user message into a self-contained retrieval target.
    • Distill a few high-value keywords before searching.
    • For subjective or ambiguous questions, consider multiple retrieval angles instead of relying on a single literal phrasing.
  2. Start with the smallest intent-matched retrieval

    • Use the narrowest matching memory intent first.
    • Prefer direct recent-file search for MEMORY_RECENT.
    • Prefer regular memory_search for broader MEMORY_LOOKUP.
  3. Stop when results are already sufficient

    • Do not expand retrieval just because more related memory might exist.
    • If the current hits are already strong, relevant, and enough to answer the latest user message, stop there.
  4. Escalate only when cross-note context is needed

    • If the initial hits are sparse, fragmented, or clearly incomplete, use structural expansion as a second stage.
    • Use tags, linked notes, backlinks, or hub notes as enrichment after promising initial hits.
  5. Optimize for adequacy, not exhaustiveness

    • The goal is not to retrieve every related memory.
    • The goal is to retrieve enough high-confidence context to materially improve the final answer.

Injection Format

When the classifier matches an intent, the plugin injects the following structure as untrusted context:

<intention_hint_plugin>
reason: <brief reason for classification>
goal: <what the user likely wants to achieve>
suggestion: <optional correction or recommendation>
[Intent Hint] <the Markdown body from the matched intent definition>
</intention_hint_plugin>

The subagent output fields (reason, goal, suggestion) are placed above the intent's Markdown body. The body itself is injected as-is without any template substitution.

Default Intents

The plugin ships with these pre-defined intents:

IDNameDescription
CHATCasual ChatGreetings, small talk, or emotional connection.
CODE_REVIEWCode ReviewReviewing code, architecture, or quality concerns.
MEMORY_TIMELINEMemory Timeline QueryHow something changed, progressed, or evolved over time.
MEMORY_COMPAREMemory CompareComparing two topics or time periods.
MEMORY_EMOTIONEmotional Memory QueryFeelings, mood, emotional state, or subjective reactions in past records.
SYSTEM_DOCSSystem Docs / SOP LookupLocating recorded system rules, SOPs, configs, or project-side documentation.
PROMPT_DESIGNPrompt / Intent / Skill DesignDesigning or refining prompts, intents, skills, or routing behavior.
MEMORY_RECENTMemory RecentTime-bounded queries ("today", "yesterday").
MEMORY_LOOKUPGeneral Memory LookupBroad past-record lookup without a recent, comparative, emotional, or timeline-specific focus.
RESEARCH_GENERALGeneral ResearchFactual or explanatory questions supported by external sources.
BROWSER_AUTOMATIONBrowser Automation / Web App TaskInteractive or authenticated browser tasks delegated to the browser agent.
RESEARCH_GOOGLE_DEVGoogle Developer Products QueryGoogle developer products and documentation covered by the Google developer corpus.
RESEARCH_OPENSOURCEOpen-Source Library / Framework / Repo Docs QueryVersion-sensitive information about third-party open-source libraries, frameworks, SDKs, APIs, GitHub repositories, or project documentation.
RESEARCH_REALTIMEReal-Time / Current Data QueryTime-sensitive, fast-changing, or current real-world information.
SUMMARIZATIONContent Summary / Transcript QuerySummarizing or transcribing a provided source such as a URL, video, PDF, transcript, or file.
TYPOTypo CorrectionObvious typos or unclear phrasing.

To customize, edit the files in intents/ or create new ones. Files are loaded in alphabetical order; duplicate ids override previous definitions.

Architecture

index.ts
    → createPlugin(api)
        → src/plugin.ts
            → loadIntents(intentsDir)      // scan .md files
            → before_prompt_build Hook
                ├── Gate checks (agent whitelist, chat type, chat id, internal runs)
                ├── extractRecentTurns + applyQueryFilters (message / recent / full)
                ├── runIntentionSubagent (lightweight embedded Pi agent)
                │       ├── buildIntentionPrompt (dynamic from IntentDefinition[])
                │       ├── parseIntentionResult (key-value → IntentionResult)
                │       └── buildPromptPrefix (template replacement → XML injection)
                └── prependContext

Credits


🌸 Powered by Ani | [OpenClaw Plugin] © 2026