Skip to content

Comments

Expose OpenClaw skills management via obol CLI#196

Closed
bussyjd wants to merge 4 commits intomainfrom
feat/openclaw-skills-management
Closed

Expose OpenClaw skills management via obol CLI#196
bussyjd wants to merge 4 commits intomainfrom
feat/openclaw-skills-management

Conversation

@bussyjd
Copy link
Collaborator

@bussyjd bussyjd commented Feb 19, 2026

Summary

We don't expose the skill management of OpenClaw — the obol openclaw skills command only had sync. OpenClaw's CLI has full skills introspection (list, info, check) and the clawhub registry provides install/update, but none of this was surfaced through the obol wrapper.

This PR fills that gap:

Command What it does How
obol openclaw skills list <id> List loaded skills kubectl exec → openclaw skills list
obol openclaw skills info <id> <name> Skill details kubectl exec → openclaw skills info
obol openclaw skills check <id> Readiness check kubectl exec → openclaw skills check
obol openclaw skills add <id> <slug> Install from clawhub clawhub install → ConfigMap sync
obol openclaw skills remove <id> <name> Remove + re-sync rm dir → re-sync ConfigMap
obol openclaw skills sync <id> --from Direct sync (existing) tar → ConfigMap

Design

  • Query commands (list, info, check) passthrough to the in-pod openclaw binary via kubectl exec. Zero reimplementation.
  • Mutation commands (add, remove) manage a per-instance skills directory at <deployment>/skills/ and sync to the pod's ConfigMap.
  • clawhub integration: add uses clawhub install --dir (via npx fallback) to install from the registry.

Skill hierarchy

Follows OpenClaw's loading precedence (later overrides earlier):

  1. openclaw-bundled — built into the container image
  2. openclaw-managed~/.config/obol/skills/ inside container
  3. openclaw-workspace — ConfigMap mount (where sync/add puts skills)

Skills installed via add land in the workspace tier (highest precedence), cleanly overriding bundled defaults.

Testing with clawhub

obol openclaw skills add default austintgriffith/ethereum-wingman
obol openclaw skills list default
obol openclaw skills remove default ethereum-wingman

Test plan

  • TestSkillsDir — path construction for managed skills directory
  • TestSkillsNotRemoteCapable — skills routes through kubectl exec
  • TestSkillsRemove_MissingDeployment — error on missing deployment
  • TestSkillsRemove_SkillNotFound — error on missing skill
  • TestSkillsRemove_LastSkill — removes dir, skips sync when empty
  • TestSkillsRemove_WithRemainingSkills — removes target, preserves others
  • TestSkillsAdd_MissingDeployment — error on missing deployment
  • TestSkillsAdd_CreatesManagedDir — creates skills dir before binary lookup
  • TestFindClawHub_ReturnsErrorWhenMissing — error when no clawhub/npx
  • TestSkillsDirStructure — skills dir nested under deployment dir
  • TestRemoteCapableCommands — updated to include skills as non-remote
  • Full go test ./... passes
  • go build ./cmd/obol succeeds

OpenClaw has built-in skill support (list, info, check) but the obol CLI
only exposed "skills sync". This fills that gap:

- `obol openclaw skills list <id>` — list skills via kubectl exec passthrough
- `obol openclaw skills info <id> <name>` — skill details via passthrough
- `obol openclaw skills check <id>` — readiness check via passthrough
- `obol openclaw skills add <id> <slug>` — install from clawhub registry + sync
- `obol openclaw skills remove <id> <name>` — remove + re-sync remaining
- `obol openclaw skills sync <id> --from ./dir` — (existing) direct sync

The query commands (list, info, check) delegate to the in-pod openclaw
binary via kubectl exec — zero reimplementation. The mutation commands
(add, remove) manage a per-instance skills directory on the host and
sync to the pod's ConfigMap.

Skill hierarchy follows OpenClaw's loading precedence:
  bundled (image) < managed < workspace (ConfigMap mount)
Skills installed via "add" land in the workspace tier, which has highest
precedence and cleanly overrides bundled defaults.
The ConfigMap name must match what the Helm chart creates
(openclaw-skills), not include the instance ID. Also restart the
deployment after ConfigMap updates so the init container re-extracts
skills, and handle the last-skill-removed case with an empty archive
to ensure the extracted directory is cleaned.
Three skills for OpenClaw agents to interact with the Obol Stack:

- obol-blockchain: Ethereum RPC via eRPC gateway with rpc.py helper,
  ERC-20 reference, and verified contract addresses
- obol-k8s: Kubernetes awareness via ServiceAccount API with kube.py
  helper (pods, logs, events, deployments, configmaps)
- obol-dvt: DVT cluster monitoring via Obol API, imported from
  obol-mcp PR #3 with curl fallback and API examples

All facts verified on-chain and against official documentation.
Agent validation uncovered issues in all 3 skills:

obol-dvt (FAIL → PASS):
- Rewrote api-examples.md: 5 of 7 response shapes from obol-mcp PR #3
  were wrong (lock nested under cluster_definition, effectiveness is
  dict keyed by pubkey with time-period scores, exit summary uses
  operator_exits dict, techne returns tiers object, badges have
  name/description/qualified fields)
- Fixed all workflow scripts in SKILL.md to match real API fields
- Added gold tier to Techne (API returns it, was previously removed)

obol-blockchain (WARN → PASS):
- Added Paths section with absolute pod path
- Fixed misleading "always works" comment on evm/chainId curl example

obol-k8s (WARN → PASS):
- Added Paths section with absolute pod path
- Fixed constraints: describe outputs JSON, not human-readable text
- Added configmaps to Quick Start examples

Also adds skills/_tests/smoke_test.py (18 tests, all passing).
@bussyjd
Copy link
Collaborator Author

bussyjd commented Feb 19, 2026

OpenClaw Skills: Test Suite Results (#180)

Three OpenClaw skills created, fact-checked, and validated end-to-end in the running cluster.

Skills Overview

Skill Purpose Scripts References
obol-blockchain Ethereum RPC via eRPC gateway rpc.py (JSON-RPC helper) erc20-methods.md, common-contracts.md
obol-k8s Kubernetes awareness via ServiceAccount API kube.py (K8s API helper)
obol-dvt DVT cluster monitoring via Obol API — (curl-based) api-examples.md

Part 1: Smoke Tests (18/18 PASS)

Automated test script (skills/_tests/smoke_test.py) piped into the OpenClaw pod. All tests assert against live data.

--- obol-blockchain ---
  PASS  blockchain/files_exist
  PASS  blockchain/block_number
  PASS  blockchain/chain_id
  PASS  blockchain/gas_price
  PASS  blockchain/eth_balance
  PASS  blockchain/erc20_total_supply
  PASS  blockchain/hoodi_chain_id

--- obol-k8s ---
  PASS  k8s/files_exist
  PASS  k8s/pods
  PASS  k8s/services
  PASS  k8s/deployments
  PASS  k8s/events
  PASS  k8s/configmaps
  PASS  k8s/logs
  PASS  k8s/describe_deployment

--- obol-dvt ---
  PASS  dvt/files_exist
  PASS  dvt/api_health
  PASS  dvt/network_summary

Results: 18 passed, 0 failed, 18 total

Part 2: Agent-Driven Validation

Three Claude agents each read a SKILL.md and attempted the documented workflows as if they were an OpenClaw agent. Results after fixes:

Skill First Run Issues Found After Fix
obol-blockchain WARN Relative paths don't resolve from /app; "always works" comment misleading PASS
obol-k8s WARN Relative paths; describe outputs JSON not text; missing configmaps example PASS
obol-dvt FAIL 5/7 API response shapes wrong (imported from obol-mcp PR #3); all workflow scripts broken PASS

Fact-Checking (Prior Commit)

All facts verified on-chain or against official sources:

  • ERC-20 selectors: All 9 function selectors + 2 event topics verified via Keccak-256
  • Contract addresses: 14 mainnet addresses verified via eth_getCode + name()/symbol() calls
  • OBOL token: Corrected address (original from PR was wrong — no code at that address)
  • Chain IDs: Hoodi = 560048 (not 17000/Holesky)
  • Techne tiers: base > bronze > silver > gold (verified against live API)
  • Obol API response shapes: All 8 endpoint shapes verified against live responses
  • K8s RBAC: All 11 resource types verified accessible; cross-namespace correctly blocked

DVT API Response Shape Fixes (Detail)

The original api-examples.md was imported from ObolNetwork/obol-mcp#3. The response shapes documented there were idealized and didn't match the live API:

Endpoint What Was Wrong
GET /v1/lock/{lockHash} Flat structure → actually nested under cluster_definition; operators have enr_signature/config_signature, not approved bool; validator pubkeys in distributed_validators
GET /v1/effectiveness/{lockHash} Array of objects → actually dict keyed by pubkey with oneDay/sevenDay/thirtyDay/all scores
GET /v1/state/{lockHash} Array of validators → actually dict keyed by pubkey; balance in ETH (not Gwei)
GET /v1/exp/exit/status/summary/{lockHash} validators_ready_to_exit + operators array → actually ready_exits + operator_exits dict
GET /v1/address/techne/{address} credential_level string → actually tiers object with arrays per level
GET /v1/address/badges/{address} type field → actually name/description/qualified/earned_at
GET /v1/lock/network/summary/{network} Had network/total_validators/avg_effectiveness → actually only eth_staked/total_clusters/total_operators

How to Run Smoke Tests

obol kubectl exec -i -n openclaw-default deploy/openclaw -- \
  python3 - < skills/_tests/smoke_test.py

@bussyjd
Copy link
Collaborator Author

bussyjd commented Feb 20, 2026

Superseded by #199, which integrates these rich skills (obol-blockchain, obol-k8s, obol-dvt) on top of the host-path PVC injection architecture from #197.

@bussyjd bussyjd closed this Feb 20, 2026
@OisinKyne OisinKyne deleted the feat/openclaw-skills-management branch February 20, 2026 12:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant