01About AgentSkills #
OpenClaw follows the AgentSkills specification: a skill is a folder with a SKILL.md whose frontmatter names and describes it. The prompts in this chapter build to that model. The second half covers check-quotas.sh, a small script for watching API quotas from your own scripts.
Agents can also write skills on their own through Skill Workshop. Those land in the agent's state directory with change history and undo; review them with openclaw skills workshop list.
02Why hard constraints matter #
Vague instructions produce bloated, token-hungry skills every time. A hard constraint on line count (~500 lines) forces the agent to:
- Put the core workflow in SKILL.md
- Move details into
references/for on-demand loading - Keep token usage low
- Keep the skill maintainable
03Skill structure #
A well-structured skill looks like this:
<workspace>/skills/
└── your-skill-name/
├── SKILL.md # Core workflow (~500 lines max)
├── references/ # Loaded on-demand
│ ├── api-docs.md
│ └── examples.md
└── scripts/ # Optional executables
└── helper.sh Workspace skills/ has the highest precedence; ~/.openclaw/skills is shared by every local agent. Declare what the skill needs in its frontmatter so OpenClaw can hide it when a binary or key is missing, and reference bundled files through {baseDir}:
---
name: your-skill-name
description: One line on what it does and when to use it.
metadata:
openclaw:
requires:
bins:
- curl
env:
- YOUR_API_KEY
primaryEnv: YOUR_API_KEY
---
Run the helper at {baseDir}/scripts/helper.sh ...Every eligible skill adds its name and description to the system prompt, about 24 tokens plus the text itself, so keep descriptions to one line.
04Skill prompt template #
Copy and customize this prompt to have your agent create or refactor a skill:
I need help creating or optimizing an AgentSkill.
Skill name:
[your-skill-name]
Purpose:
What the skill does and when it should activate.
Triggers:
What kinds of tasks or questions should activate this skill.
Tools needed:
Any tools, commands, or APIs the skill will use.
Reference docs:
Docs or specs that should live in references/ for on-demand loading.
Existing skill (if applicable):
Path to the current SKILL.md if this is a refactor.
Please:
- Create or optimize the skill following AgentSkills best practices
- Keep the core workflow in SKILL.md and move details into references/
- Keep SKILL.md under ~500 lines
- Declare required binaries and env vars under metadata.openclaw.requires
- Confirm it shows as eligible with `openclaw skills check`
- Show the final file structure and contents05Example: creating a new skill #
I need help creating an AgentSkill.
Skill name:
weather-checker
Purpose:
Check current weather and forecasts using wttr.in (no API key required).
Triggers:
Questions about weather, temperature, forecast.
Tools needed:
curl to fetch from wttr.in, parsing text output.
Reference docs:
wttr.in documentation should live in references/wttr-in-docs.md
Please:
- Create the skill following AgentSkills best practices
- Keep the core workflow in SKILL.md under ~500 lines
- Move API details into references/
- Show the final file structure and contents06Example: refactoring an existing skill #
I need help optimizing an AgentSkill.
Existing skill:
~/.openclaw/workspace/skills/my-bloated-skill/SKILL.md
Purpose:
The skill works but SKILL.md is 1,800 lines and burns too many tokens.
Please:
- Refactor following AgentSkills best practices
- Keep core workflow in SKILL.md under ~500 lines
- Move details into references/ for on-demand loading
- Confirm it still loads with `openclaw skills check`
- Show what changed07Best practices #
Keep SKILL.md focused
- Describe when to trigger
- Show the core workflow
- Reference details in references/
Use references/ for
- API documentation
- Detailed examples
- Error handling tables
- Command syntax reference
Test before deploying
- Invoke it directly with /skill <name>
- Check token usage with /context list
- Verify it loads only what it needs
08Community skills #
If you do install one from ClawHub, read it first, check its security scan on the ClawHub page, and run openclaw skills verify @owner/<slug>. Owner-qualified refs avoid installing a lookalike from another publisher.
Building your own gives you:
- Full understanding of what it does
- Control over token usage
- No dependency on external maintainers
- Better debugging at 2am
09Skill security #
Set basic rules in your workspace memory files:
- Never expose secrets or API keys
- Ask before external actions
- Verify before destructive operations
Secrets set through skills.entries.*.env or apiKey are injected into the host process for that turn only, not into the sandbox. Keep them out of prompts and logs.
Not foolproof, but it helps as a guardrail. See the Security Hardening chapter for more.
10Quota monitoring check-quotas.sh#
OpenClaw now reads provider quotas itself: Claude subscriptions, OpenAI plans, OpenRouter, MiniMax, z.ai and more show up in /status, the Control UI and the CLI. Start there:
openclaw status --usage # every provider with usage auth
openclaw models status # auth profiles + usage windowscheck-quotas.sh is still handy when a script or a skill needs the numbers as JSON, or for a provider OpenClaw doesn't track, such as Synthetic. Pipe it to jq or use it in agent prompts.
Installation
cp check-quotas.sh ~/.local/bin/check-quotas
chmod +x ~/.local/bin/check-quotas
# Verify ~/.local/bin is in your PATH
echo $PATH | grep -q "$HOME/.local/bin" || \
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrcConfiguration
The script reads keys from the environment, or from an env file it sources. Keep that file outside ~/.openclaw/credentials/, which OpenClaw owns for channel credentials and pairing allowlists.
mkdir -p ~/.config/check-quotas
cat > ~/.config/check-quotas/env <<'EOF'
export OPENROUTER_API_KEY="your-api-key-here"
export SYNTHETIC_API_KEY="your-api-key-here"
export ANTHROPIC_API_KEY="your-api-key-here"
EOF
# Readable by you only
chmod 700 ~/.config/check-quotas
chmod 600 ~/.config/check-quotas/env11Full script #
#!/bin/bash
# Check API quotas for various providers
# Returns JSON with quota status
#
# Usage: check-quotas
#
# Keys come from the environment, or from an env file:
# CHECK_QUOTAS_ENV - env file to source (default: ~/.config/check-quotas/env)
# CLAUDE_KEYCHAIN_ITEM - macOS Keychain item name for Claude Code credentials
set -euo pipefail
ENV_FILE="${CHECK_QUOTAS_ENV:-$HOME/.config/check-quotas/env}"
[ -f "$ENV_FILE" ] && source "$ENV_FILE"
CLAUDE_KEYCHAIN="${CLAUDE_KEYCHAIN_ITEM:-Claude Code-credentials}"
# Check Claude Code subscription usage (macOS Keychain, unofficial endpoint)
check_claude_code() {
if ! command -v security &> /dev/null; then
echo "null"
return
fi
local token=$(security find-generic-password \
-s "$CLAUDE_KEYCHAIN" -w 2>/dev/null | \
jq -r '.claudeAiOauth.accessToken' 2>/dev/null || echo "")
if [ -z "$token" ] || [ "$token" = "null" ]; then
echo "null"
return
fi
curl -s https://api.anthropic.com/api/oauth/usage \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "User-Agent: claude-code/2.0.32" \
-H "Authorization: Bearer $token" \
-H "anthropic-beta: oauth-2025-04-20" 2>/dev/null || echo "null"
}
# Check Synthetic quota
check_synthetic() {
local api_key="${SYNTHETIC_API_KEY:-}"
if [ -z "$api_key" ]; then echo "null"; return; fi
curl -s https://api.synthetic.new/v2/quotas \
-H "Authorization: Bearer $api_key" 2>/dev/null || echo "null"
}
# Check OpenRouter key usage and limit
check_openrouter() {
local api_key="${OPENROUTER_API_KEY:-}"
if [ -z "$api_key" ]; then echo "null"; return; fi
curl -s https://openrouter.ai/api/v1/key \
-H "Authorization: Bearer $api_key" 2>/dev/null || echo "null"
}
# Check the Anthropic API key is valid (no quota endpoint; costs no tokens)
check_anthropic() {
local api_key="${ANTHROPIC_API_KEY:-}"
if [ -z "$api_key" ]; then echo "null"; return; fi
curl -s https://api.anthropic.com/v1/models \
-H "x-api-key: $api_key" \
-H "anthropic-version: 2023-06-01" \
2>/dev/null | \
jq -r 'if .error then "error" else "valid" end' || echo "null"
}
# Build combined JSON output
claude_quota=$(check_claude_code)
synthetic_quota=$(check_synthetic)
openrouter_quota=$(check_openrouter)
anthropic_quota=$(check_anthropic)
jq -n \
--argjson claude "$claude_quota" \
--argjson synthetic "$synthetic_quota" \
--argjson openrouter "$openrouter_quota" \
--arg anthropic "$anthropic_quota" \
'{
claude_code: $claude,
synthetic: $synthetic,
openrouter: $openrouter,
anthropic_api: $anthropic,
checked_at: (now | strftime("%Y-%m-%dT%H:%M:%SZ"))
}'12Output format #
{
"claude_code": { ... },
"synthetic": { ... },
"openrouter": { "data": { "usage": 45.23, "limit": 100, ... } },
"anthropic_api": "valid",
"checked_at": "2026-10-15T09:28:00Z"
}13Parsing output #
# Is the OpenRouter key over 90% of its limit? (null limit = unlimited)
check-quotas | jq '.openrouter.data | .limit != null and (.usage / .limit) > 0.9'
# Raw Synthetic quota response
check-quotas | jq '.synthetic'
# Pretty print for humans
check-quotas | jq .14Integration with OpenClaw #
Use it in agent prompts or skills to pick a fallback before quota runs out:
# Before spawning an expensive agent, check quotas
if check-quotas | jq -e '.openrouter.data | .limit != null and (.usage / .limit) > 0.9' > /dev/null; then
echo "OpenRouter quota high, using fallback"
fi15Adding new providers #
check_yourprovider() {
local api_key="${YOURPROVIDER_API_KEY:-}"
if [ -z "$api_key" ]; then
echo "null"
return
fi
curl -s https://api.yourprovider.com/quota \
-H "Authorization: Bearer $api_key" 2>/dev/null || echo "null"
}Then add it to the final jq output.
16Requirements and limitations #
Requirements
bashcurljqsecurity(macOS only, for Keychain)
Limitations
- The Claude Code check only works on macOS and uses an unofficial endpoint
- Anthropic API has no public quota endpoint; the script only verifies the key
- Rate limits may apply to quota check APIs
Adapted from digitalknk/openclaw-runbook. OpenClaw changes fast: check the official docs before copying config into production.