Skip to main content

Setup & Usage Guide: Skills Middleware Integration

Feature: 097-skills-middleware-integration | Date: 2026-03-23

Overview​

The skills middleware provides a single, shared skill catalog for both the CAIPE UI and the supervisor (platform engineer agent). Skills come from three sources:

  1. Built-in / Default β€” SKILL.md files on disk (SKILLS_DIR)
  2. Custom (agent_skills) β€” User-created skills stored in MongoDB
  3. Skill Hubs β€” External GitHub repositories registered by admins

The merged catalog is exposed via a REST API and injected into the supervisor's system prompt through the upstream deepagents SkillsMiddleware.


Prerequisites​

DependencyMinimum VersionPurpose
Python3.11+Supervisor backend
Node.js20+Next.js UI
MongoDB6.0+Storage for skills, hubs, API keys
deepagentsβ‰₯0.3.8SkillsMiddleware + StateBackend
uvlatestPython package manager

1. Backend Setup (Python β€” Supervisor)​

1.1 Install dependencies​

uv venv --python python3.13 --clear .venv
uv sync

1.2 Environment variables​

Set these in your shell, .env, or Helm values. Only MONGODB_URI is required for a minimal setup; everything else has sensible defaults.

VariableDefaultDescription
MONGODB_URIβ€”MongoDB connection string (e.g. mongodb://localhost:27017)
MONGODB_DATABASEcaipeDatabase name
SKILLS_DIRauto-detectedPath to built-in SKILL.md directory
SKILLS_CACHE_TTL3600Seconds to cache the merged catalog (1 hour)
HUB_CACHE_TTL3600Seconds to cache GitHub hub skills separately
GITHUB_TOKENβ€”Default GitHub PAT for fetching hub skills
GITHUB_API_URLhttps://api.github.comGitHub API base (for GHE)
OIDC_ISSUERβ€”OIDC issuer URL; enables JWT validation on /skills
OIDC_DISCOVERY_URL{OIDC_ISSUER}/.well-known/openid-configurationOIDC discovery endpoint
OIDC_CLIENT_IDβ€”Expected JWT audience
OIDC_TEAMS_CLAIMgroupsJWT claim holding team/group IDs for visibility
MAX_SKILL_SUMMARIES_IN_PROMPT0 (no cap)Max skill summaries injected into the supervisor system prompt
CAIPE_CATALOG_API_KEY_HEADERX-Caipe-Catalog-KeyHTTP header name for catalog API key auth
CAIPE_CATALOG_API_KEY_PEPPERchange-me-in-productionHMAC pepper for hashing stored API keys
SKILL_SCANNER_GATEwarnScanner policy: warn (advisory) or strict (block flagged skills)
SKILL_SCANNER_POLICYbalancedPolicy passed to cisco-ai-skill-scanner CLI
SKILL_SCANNER_FAIL_ONhighMinimum severity to fail under strict gate

1.3 Start the supervisor​

# Development (standalone)
PYTHONPATH=. uv run python -m ai_platform_engineering.multi_agents.platform_engineer.protocol_bindings.fastapi.main

# The FastAPI app starts on port 8000 by default
# Skills middleware router is mounted at /skills and /skills/refresh

1.4 Verify the catalog API​

# List all skills (no auth required in dev mode when OIDC_ISSUER is unset)
curl http://localhost:8000/skills | jq .

# With content included
curl "http://localhost:8000/skills?include_content=true" | jq .

# Search
curl "http://localhost:8000/skills?q=kubernetes" | jq .

# Filter by source
curl "http://localhost:8000/skills?source=agent_skills" | jq .

# Refresh (invalidates cache + triggers graph rebuild)
curl -X POST http://localhost:8000/skills/refresh | jq .

2. UI Setup (Next.js)​

2.1 Install dependencies​

cd ui
nvm use # if available
npm ci

2.2 Configure environment​

Copy env.example to .env.local and set at minimum:

cp env.example .env.local

Key skills-related variables in .env.local:

# MongoDB (required for skills storage)
MONGODB_URI=mongodb://admin:changeme@localhost:27017
MONGODB_DATABASE=caipe
NEXT_PUBLIC_MONGODB_ENABLED=true

# Supervisor A2A URL
NEXT_PUBLIC_A2A_BASE_URL=http://localhost:8000

# Skills middleware backend (required for skill scanning on save)
BACKEND_SKILLS_URL=http://localhost:8000

2.3 Start the UI​

npm run dev
# UI available at http://localhost:3000

2.4 MongoDB migration​

When upgrading from a previous version that used agent_configs, the UI automatically runs a one-time migration on startup: documents in the legacy agent_configs collection are copied to agent_skills, and the old collection is renamed to agent_configs_migrated. No manual intervention is needed.


3. Docker Compose (Full Stack)​

docker compose -f docker-compose.dev.yaml up

The compose file starts MongoDB, the supervisor (with skills middleware), and the UI. Skills-related environment variables are pre-configured in the compose file.


4. Using Skills​

4.1 View skills in the UI​

Navigate to /skills in the browser. The Skills Gallery shows all available skills grouped by source:

LabelSourceDescription
Built-indefaultPlatform-packaged skills from SKILLS_DIR
Customagent_skillsUser-created skills stored in MongoDB
Skill HubhubSkills from registered GitHub repositories

4.2 /skills chat command​

In any chat conversation, type /skills and press Enter. The system displays the current skill catalog inline without sending the message to the assistant. This replaces the legacy "Run in Chat" flow.

4.3 Create a custom skill​

  1. Go to Skills β†’ click New Skill (or +).
  2. Fill in the skill name, description, and SKILL.md content.
  3. Click Save.
  4. If BACKEND_SKILLS_URL is configured, the skill is scanned before save. The response includes scan_status: passed, flagged, or unscanned.
  5. Under SKILL_SCANNER_GATE=strict, flagged skills are excluded from the catalog until remediated.

4.4 Register a GitHub skill hub (admin)​

  1. Go to Admin β†’ Skills tab β†’ Skill Hubs section.
  2. Click Add Hub.
  3. Enter the repository in owner/repo format (e.g. cnoe-io/agent-skills-collection).
  4. Optionally specify a Credentials Env Var (name of an env var holding a GitHub PAT for private repos).
  5. Click Crawl to preview discovered SKILL.md paths before committing.
  6. Click Register to save the hub.
  7. Click Refresh Skills to immediately load new skills into the catalog.

The hub fetcher discovers SKILL.md files via the GitHub tree API and fetches content via the contents API. Both Anthropic/agentskills.io and OpenClaw-style SKILL.md formats are supported.

4.5 Refresh the catalog​

Skills are cached in memory (default TTL: 1 hour). To force a refresh:

  • UI: Admin β†’ Skills tab β†’ Refresh Skills button
  • API: POST /skills/refresh (or POST /api/skills/refresh via UI proxy)
  • Automatic: Cache expires after SKILLS_CACHE_TTL seconds

A refresh invalidates the in-memory cache and triggers a supervisor graph rebuild, so the assistant picks up changes without a pod restart.


5. Catalog API Reference​

GET /skills​

Returns the merged skill catalog. Auth: JWT (OIDC/JWKS) or catalog API key when OIDC_ISSUER is set; no auth required in dev mode.

Query parameters:

ParamTypeDefaultDescription
qstringβ€”Free-text search on name and description
sourcestringβ€”Filter by source: default, agent_skills, hub
visibilitystringβ€”Filter within entitlement: global, team, personal
include_contentboolfalseInclude full SKILL.md body
pageint1Page number (1-based)
page_sizeint50Items per page (max 200)

Response (200):

{
"skills": [
{
"id": "create-argocd-application",
"name": "Create ArgoCD Application",
"description": "Creates a new ArgoCD application...",
"source": "default",
"source_id": null,
"visibility": "global",
"team_ids": [],
"owner_user_id": null,
"content": null,
"metadata": {}
}
],
"meta": {
"total": 12,
"page": 1,
"page_size": 50,
"sources_loaded": ["default", "agent_skills"],
"unavailable_sources": []
}
}

POST /skills/refresh​

Invalidates the skills cache and triggers a supervisor graph rebuild. Auth: same as GET /skills.

Response (200):

{
"status": "refreshed",
"graph_generation": 3,
"skills_loaded_count": 15
}

GET /api/skills (Next.js proxy)​

UI-facing proxy. Forwards to BACKEND_SKILLS_URL/skills if configured; otherwise aggregates locally from filesystem + MongoDB. Returns the same response shape as the Python endpoint.


6. Skill Hub API Reference​

All endpoints require admin role.

MethodPathDescription
GET/api/skill-hubsList all registered hubs
POST/api/skill-hubsRegister a new hub
PATCH/api/skill-hubs/[id]Update hub (enable/disable, change location)
DELETE/api/skill-hubs/[id]Remove a hub
POST/api/skill-hubs/crawlPreview SKILL.md paths from a repo (no persistence)

Register a hub​

curl -X POST http://localhost:3000/api/skill-hubs \
-H "Content-Type: application/json" \
-d '{
"type": "github",
"location": "cnoe-io/agent-skills-collection",
"enabled": true,
"credentials_ref": "GITHUB_TOKEN"
}'

Crawl preview​

curl -X POST http://localhost:3000/api/skill-hubs/crawl \
-H "Content-Type: application/json" \
-d '{
"type": "github",
"location": "cnoe-io/agent-skills-collection"
}'

7. Try Skills Gateway (External Integrations)​

The skills catalog can be consumed by external tools like Claude and Cursor using either:

  1. OIDC Bearer token β€” Use your Okta/OIDC access token
  2. Catalog API key β€” Create one in the Admin panel or via API

Using with Bearer token​

curl -H "Authorization: Bearer $ACCESS_TOKEN" \
"https://your-caipe.example.com/skills?q=kubernetes&include_content=true"

Using with API key​

curl -H "X-Caipe-Catalog-Key: sk_live_your_key_here" \
"https://your-caipe.example.com/skills?q=deploy"

Claude integration​

  1. Navigate to Skills β†’ Try Skills Gateway in the UI.
  2. Copy the curl example with your token/key.
  3. In Claude's tool configuration, point to the catalog endpoint.
  4. Skills are available as context for Claude's responses.

Cursor integration​

  1. In the Try Skills Gateway panel, copy the SKILL.md export.
  2. Place SKILL.md files in your project's .cursor/skills/ directory (or equivalent).
  3. Cursor reads the skills and applies them to code generation.

8. Visibility and Entitlement (FR-020)​

Each skill has a visibility level:

VisibilityWho can see it
globalAll authenticated users
teamUsers whose JWT groups/teams claim matches team_ids
personalOnly the owner (owner_user_id matches JWT sub)

A user sees the union of: global skills + their team skills + their personal skills. Visibility is enforced at the API layer for all surfaces (UI gallery, /skills chat command, gateway API, supervisor prompt injection).


9. Skill Scanner Integration (FR-023)​

Skills from hubs and user-created skills are optionally scanned by Skill Scanner (provided by Cisco AI Defense).

Configuration​

VariableDefaultDescription
SKILL_SCANNER_GATEwarnwarn: advisory only; strict: exclude flagged skills from catalog
SKILL_SCANNER_POLICYbalancedPolicy profile passed to scanner CLI
SKILL_SCANNER_FAIL_ONhighMinimum severity to flag under strict gate

CI pipeline scanning​

For packaged/built-in skills, run the scanner in CI:

SKILLS_DIR=/path/to/skills SKILL_SCANNER_GATE=strict scripts/scan-packaged-skills.sh

On-save scanning (agent_skills)​

When BACKEND_SKILLS_URL is configured, saving a skill in the UI triggers a synchronous scan. The document is always persisted but tagged with scan_status:

  • passed β€” No blocking findings
  • flagged β€” Findings met severity threshold
  • unscanned β€” Scanner unavailable or no content

Under SKILL_SCANNER_GATE=strict, flagged skills are excluded from the merged catalog.


10. Precedence Rules​

When the same skill ID appears from multiple sources:

PrioritySourceLabel
1 (highest)default (filesystem)Built-in
2agent_skills (MongoDB)Custom
3 (lowest)hub (GitHub)Skill Hub

Among hubs, earlier registration wins.


11. Architecture​

  Filesystem (SKILLS_DIR)
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ default loader │─────▢│ β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ catalog.py │───▢ GET /skills (FastAPI)
β”‚ agent_skills │─────▢│ get_merged_ │───▢ GET /api/skills (Next.js)
β”‚ loader (MongoDB) β”‚ β”‚ skills() β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ precedence + β”‚
β”‚ hub_github │─────▢│ TTL cache │───▢ build_skills_files()
β”‚ fetcher β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β–Ό
StateBackend (files dict)
β”‚
β–Ό
SkillsMiddleware
(system prompt injection)

Key modules​

ModulePurpose
skills_middleware/catalog.pyMerges skills from all sources with TTL cache
skills_middleware/loaders/default.pyLoads built-in SKILL.md from disk
skills_middleware/loaders/agent_skill.pyLoads custom skills from MongoDB agent_skills
skills_middleware/loaders/hub_github.pyFetches skills from GitHub repos
skills_middleware/precedence.pyDeterministic merge with source priority
skills_middleware/entitlement.pyVisibility filtering (global/team/personal)
skills_middleware/router.pyFastAPI endpoints (/skills, /skills/refresh)
skills_middleware/backend_sync.pyWrites merged skills to StateBackend for middleware
skills_middleware/api_keys_store.pyCatalog API key management
skills_middleware/hub_skill_scan.pySkill Scanner integration for hubs

12. Helm Deployment​

The supervisor Helm chart (charts/ai-platform-engineering/charts/supervisor-agent/) supports all skills middleware environment variables through the generic env map in values.yaml:

# values.yaml
env:
SKILLS_CACHE_TTL: "3600"
HUB_CACHE_TTL: "3600"
OIDC_ISSUER: "https://your-idp.example.com"
OIDC_CLIENT_ID: "your-client-id"
OIDC_TEAMS_CLAIM: "groups"
MAX_SKILL_SUMMARIES_IN_PROMPT: "100"
SKILL_SCANNER_GATE: "warn"

# Sensitive values via secrets
llmSecrets:
GITHUB_TOKEN: "ghp_..."
CAIPE_CATALOG_API_KEY_PEPPER: "your-pepper"

The deployment template iterates over env and injects each key-value pair as an environment variable into the supervisor container.


13. Troubleshooting​

Skills not appearing after save​

  • Verify MONGODB_URI and MONGODB_DATABASE are set on both UI and supervisor.
  • Check that the UI's BACKEND_SKILLS_URL points to the running supervisor.
  • Click Refresh Skills in Admin β†’ Skills, or call POST /skills/refresh.

Hub skills not loading​

  • Check the hub status in Admin β†’ Skills β†’ Skill Hubs (look for error indicators).
  • Verify GITHUB_TOKEN is set if the repo is private.
  • Check supervisor logs for Hub <id> fetch failed messages.
  • GitHub API rate limits may apply; the hub cache TTL (HUB_CACHE_TTL) avoids excessive calls.

Skill scanner returning "unscanned"​

  • Ensure BACKEND_SKILLS_URL is set in the UI's .env.local.
  • The scanner requires the cisco-ai-skill-scanner CLI to be available in the supervisor's PATH.
  • Without the scanner CLI, scan_status defaults to unscanned (skills are still saved and available).

Cache not expiring​

  • Default cache TTL is 1 hour (SKILLS_CACHE_TTL=3600). Use POST /skills/refresh for immediate invalidation.
  • Hub cache has its own TTL (HUB_CACHE_TTL) to avoid expensive GitHub API calls.

Migration from agent_configs​

  • The one-time migration runs automatically when the UI connects to MongoDB.
  • If agent_configs exists and has documents, they are copied to agent_skills.
  • The old collection is renamed to agent_configs_migrated (never runs again).
  • Check UI startup logs for βœ… Migrated agent_configs β†’ agent_skills confirmation.