Generate and edit Draw.io, Mermaid, and Excalidraw diagrams from natural language using a structured JSON spec.
Memory
Kb Keyword Graph
Try itKeyword-graph reader for a knowledge base. Trigger when the user wants to understand a KB — "what's in it / what does it cover / knowledge structure / topic...
What it does
中文版见 references/SKILL.zh.md (Chinese version).
The skill document
KB Keyword Graph
中文版见 references/SKILL.zh.md (Chinese version).
Wrap a knowledge base's "keyword graph" capability into a stably-triggerable,
read-only workflow. All four tasks share one three-level keyword tree
(keywords_tree) pulled from the backend; the four subcommands are just
different readings of the same data. Engine: scripts/kw_graph.py (python3
standard library only, no third-party deps). Current backend: 2brain
(keyword_api).
First use (install-and-go)
# Option A: private config file (recommended — token stays out of env & artifacts)
mkdir -p ~/.config/2brain-keyword-map
cat > ~/.config/2brain-keyword-map/config.json <<'JSON'
{ "token": "2B-your-graph-API-key", "base_id": 700 }
JSON
chmod 700 ~/.config/2brain-keyword-map && chmod 600 ~/.config/2brain-keyword-map/config.json
# Option B: environment variables (temporary / CI)
export TWOBRAIN_GRAPH_KEY="2B-..." # 2brain "keyword graph" API key (Bearer)
export TWOBRAIN_BASE_ID=700 # integer base_id of the target library (--base-id overrides)
# Course/test env: export TWOBRAIN_API_BASE="https://test.2brain.ai/api"
# Self-check
python3 scripts/kw_graph.py fetch --base-id 700
The graph API key is generated on the 2brain platform and differs from the
upload/chat keys. The host must be able to reach TWOBRAIN_API_BASE (default
https://test.2brain.ai/api).
Privacy & Data Flow (read-only · no personal data · no autonomy)
This is a read-only KB-interpretation skill with a very narrow capability and data-flow surface:
① Capabilities: needs only python3 (stdlib, no third-party deps). Reads/writes
only the cache dir ~/.local/state/2brain-keyword-map/ (stores the pulled keyword
tree); the skill directory itself is read-only. No shell, no cron, no autonomous
or scheduled behavior — it runs once, only when you ask.
② Data sent externally (minimal): it sends only one integer base_id to the
fixed 2brain endpoint /kbase/keywords/keyword_api and receives
that library's keyword tree. No personal data, document content, resume, or
conversation is sent — base_id is just a library number. Beyond this single
2brain endpoint it contacts no third party (no scraper, no external LLM).
③ Credential discipline: the graph API key is read only from where you
configure it — env var TWOBRAIN_GRAPH_KEY or the private file
~/.config/2brain-keyword-map/config.json (0600 recommended). It does not read
host credentials outside the skill directory (never touches the OpenClaw auth
store). The key is sent only as an Authorization: Bearer header to the fixed
endpoint and is never written into HTML/JSON artifacts, logs, URLs, or the
conversation (the engine guarantees zero-token artifacts — grep-verifiable).
④ Boundaries: no ingest, no KB creation, no edits/deletes, no Q&A; never acts on your behalf; the keywords/counts/percentages it reports come only from the API's real response — if empty it says "insufficient material", never fabricates.
Backends (pluggable)
"Getting the three-level keyword tree" is abstracted into a backend, selected by
--backend / env KWGRAPH_BACKEND / config backend (default twobrain). The
renderer and all four tasks operate on the normalized tree, so they behave
identically across backends.
| Backend | How it gets the tree | Config |
|---|---|---|
twobrain (default) | 2brain native keyword_api — a ready-made tree | token + base_id (see First use) |
local | computes the tree from a folder of .txt/.md docs (stdlib keyword extraction + co-occurrence hierarchy) — for AI Digest or any self-hosted corpus | --corpus or config corpus_dir |
elasticsearch | ES significant_text aggregation over an index | --es-url + --index or config es_url/index |
Examples:
python3 scripts/kw_graph.py graph --backend local --corpus ~/ai-digest/kb --html /tmp/g.html
python3 scripts/kw_graph.py topics --backend elasticsearch --es-url http://localhost:9200 --index market_news_rag
local / elasticsearch compute the tree themselves, so it reflects that corpus's
own keyword co-occurrence — not identical to 2brain's engine, but the same four
readings apply. Trees are cached by config fingerprint under
~/.local/state/2brain-keyword-map/graphs/.
Task routing (decide intent → read the matching execution doc → run the subcommand)
| User intent signal | Task | Subcommand | Execution doc |
|---|---|---|---|
| "what's in this library / knowledge structure / what areas / how is it structured" | Structure | structure | references/workflows.md |
| "keyword graph / knowledge graph / word cloud / draw me a graph" | Graph | graph --html | references/workflows.md |
| "what topics / topic distribution / which area has the most / what's the focus" | Topics | topics | references/workflows.md |
| "how do X and Y relate / how are these two connected" | Relate | relate --a X --b Y | references/workflows.md |
| login / 401 / connection failure / empty graph | Troubleshoot | — | references/workflows.md |
When intent is vague (e.g. just "take a look at this library"): default to
structure, lay out the level-1 topics, then ask which area to go deeper on.
Restate the task and target library to the user before executing.
Common constraints (all four tasks must follow)
Locating the KB — never hard-code base_id:
- User gave an integer base_id → use it (
--base-id). - User gave only a library name → the current backend works by base_id; if you don't know the id, ask the user for it (don't guess a number and probe).
- User gave nothing → use the default base_id from config, and note in the output which library was used.
Credential discipline (hard rule):
- The token is sent only as an
Authorization: Bearerheader to the fixed 2brain endpoint; - never print the token to the conversation, write it into HTML/JSON artifacts, logs, or URL query;
- the engine guarantees artifacts contain no token; don't repeat the key when relaying results.
Output discipline:
- Every number (node counts, count, percentage, weight) must come from
kw_graph.pystdout — never from memory or imagination. - The graph shows sibling-share percentages only (a node's count share among its direct siblings), not raw count; each sibling group sums to 100%. This is not a whole-KB absolute share.
- Empty or near-empty graph/structure → say "this library has too little material to graph", don't improvise content.
relateis based only on co-occurrence at tree levels; state explicitly it does not imply causation, semantic equivalence, or document-level provenance.
Read-only boundaries (this skill does NOT):
- ingest, scrape, create, delete, or edit a KB;
- do 2brain Q&A (chat) — that's a separate capability;
- route to Feishu/Lark Wiki / cloud docs / local files — "knowledge base" here means a 2brain platform library.
Cache & idempotency: a fetched tree is cached to
~/.local/state/2brain-keyword-map/graphs/.json. If the user asks about the
same library again shortly after, the cache serves it; use --fresh to re-pull the
latest (e.g. after new material was ingested).
Input/output example (graph)
Input (user says to the agent):
Show me the keyword graph of my job library (base 700)
Run:
python3 scripts/kw_graph.py graph --base-id 700 --html /tmp/kw-700.html
Engine stdout (relay from this; don't paste raw JSON at the user):
{"ok": true, "task": "graph", "base_id": 700, "file_count": 256,
"levels": {"l1": 10, "l2": 21, "l3": 45},
"metric": "sibling_count_percentage", "html": "/tmp/kw-700.html"}
What you tell the user (template):
The keyword graph of library 700 (256 documents) is ready: 10 level-1 topics, 21 level-2, 45 level-3. The heaviest level-1 topics are Research and Technical. The chart is at
/tmp/kw-700.html; click a level-1 topic to expand level-2/3 in the same view. Percentages are sibling-share, not whole-KB share.
Script inventory
| File | Responsibility |
|---|---|
scripts/kw_graph.py | Engine: backend dispatch + credential resolution + cache + four subcommands (structure/topics/graph/relate) + ring-HTML renderer |
scripts/backends.py | Pluggable KB backends: local (compute tree from a doc folder) + elasticsearch (significant_text); the twobrain path lives in kw_graph.py |
Boundaries (restated)
- Read-only 2brain keyword graph; no writes, no Q&A, no KB creation.
- Numbers come only from engine output; never fabricate keywords or relations.
- The token never appears in any artifact or conversation.
Related skills
Stores durable facts in a categorized, plain-markdown vault on disk, alongside your agent's built-in memory.
Find why your productivity system keeps failing, then apply the smallest fix — capacity math, bottleneck routing, durable local notes.
Join a video meeting as an AI bot with voice, avatar, and screenshare across four operating modes.
Fetch raw ad creative, app, ranking, and revenue data from AdMapix as structured JSON.
Site audit, content writing, and competitor analysis for organic search rankings.
More from ywc668
Browse all skillsAutonomous job-market watcher for OpenClaw. On a cron schedule it monitors the career pages of companies the user has EXPLICITLY configured, judges each posting against the user's own job profile (visa / seniority / red lines) with an LLM, pushes strong matches, digests the rest daily, and archives postings into a knowledge base; it also tracks the user's application status and answers questions about their own watched jobs. PRIVACY & CAPABILITIES (see the Privacy & Data Flow section): this skill collects and stores a personal job-seeking profile (resume text, visa needs, seniority, red lines); sends watched URLs and job-description text to third-party services (Firecrawl / Jina scrapers, an OpenAI-compatible LLM endpoint, and a 2brain knowledge base); reads host OpenClaw / Telegram credentials only when the user opts in (JOBWATCH_ALLOW_HOST_CREDS=1); and registers a recurring cron job — every autonomous action happens only after an explicit onboarding consent step. Use ONLY when the u