[Bug] search_skills(source="all") returns 20 results with score=0.0 — default source makes search useless

Author: shao-zhijieCreated Jun 12, 2026Updated Jul 29, 2026

Bug: search_skills(source="all") returns all 20 results with score=0.0 — default source makes search useless

Description

When calling search_skills via MCP (mcp__openspace__search_skills) with the default source="all", the function returns the top 20 local skills with score=0.0 regardless of the query. The search effectively returns a fixed list and cannot find any skill by name or topic.

When called with source="local", search works correctly and returns relevant skills with proper scores.

Reproduction (2026-06-12, 2026-06-13)

python
# Wrong: default source, search returns 0.0 for everything
r = await session.call_tool("search_skills", {"query": "svg render", "limit": 20})
# → 20 results, ALL score=0.0
# → "svg-render" (which exists locally!) NOT in top 20

r = await session.call_tool("search_skills", {"query": "playwright", "limit": 20})
# → 20 results, ALL score=0.0
# → Same fixed list

# Right: source="local", works as expected
r = await session.call_tool("search_skills", {"query": "svg render", "source": "local", "limit": 5})
# → "svg-render" at #1, score=2.50 ✅

Root Cause (inferred from behavior)

source="all" mixes local + cloud (HKUDS open-space.cloud) results. The cloud path requires a valid OPENSPACE_API_KEY; when the key is missing or invalid, the cloud call returns 401, and the search engine appears to fall back to returning the fixed top-20 local skills with score=0.0 instead of:

  1. Either returning only local results with proper scores (graceful degradation)
  2. Or raising an error that tells the caller "cloud unreachable, retry with source=local"

Impact

  • The default source="all" (which most users never override) makes search_skills useless — every call returns a meaningless list of 0-score skills.
  • Agents relying on search_skills to discover capabilities (the documented "explore-then-execute" pattern) think OpenSpace has no relevant skills and skip it entirely.
  • This is likely contributing to the issue in #84 ("Agents have OpenSpace MCP tools available but never call them") — agents see a 0-score list, conclude nothing is relevant, and fall back to local tools.

Expected Behavior

source="all" should either:

  • Return the merged + re-ranked list of local + cloud skills with proper scores
  • Or fall back to local-only results with correct scores when cloud is unreachable (rather than returning score=0.0 for everything)
  • Or raise a clear error: "Cloud auth failed, retry with source='local' or set OPENSPACE_API_KEY"

Actual Behavior

Returns 20 results with score=0.0 for any query, regardless of relevance.

Environment

  • OpenSpace: latest main, commit 228f8f7
  • OpenClaw: v2026.4.24 (macOS arm64)
  • MCP transport: streamable-http, port 8083
  • 71 local skills registered (verified by search_skills(source="local", limit=200))
  • OPENSPACE_API_KEY set in ~/.openclaw/openclaw.json (verified working via GET /api/v1/auth/me)

Suggested Fix

In openspace/skill_engine/search.py (or wherever the merge happens): when cloud search returns 401/500/timeout, log a warning AND fall back to local-only results with the same scoring function used by source="local", rather than zeroing out scores. This preserves the merged-source UX for users who don't pass source= explicitly.