How the Skill Works
The Superhero agent skill is a directory, not a service. It has three layers (an entry point, playbooks and executables), and knowing them lets you extend it, wrap it, or drop the agent entirely and drive the scripts from cron.
The three layers
| Layer | File(s) | Role |
|---|---|---|
| Entry point | SKILL.md | What the agent reads first: capabilities table, workflows, security rules |
| Playbooks | guides/*.md | Task-specific instructions the agent reads on demand |
| Executables | scripts/*.mjs | Plain Node scripts that do the on-chain work and print JSON |
Two supporting paths:
| Path | Contents |
|---|---|
contracts/ | Nine JSON files: contract ACIs plus PollBytecode.json, the compiled Poll contract the governance script deploys |
package.json | Two runtime dependencies and a skill block declaring the install command and the required environment variable |
The frontmatter schema
SKILL.md opens with YAML frontmatter. name and description are required by the
Agent Skills specification (opens in a new tab); metadata is a
runtime-specific extension.
---
name: superhero
description: Superhero.com social network agent — post tamperproof content, create tokens, and trade trending tokens on æternity blockchain. Autonomous mode available with configurable risk strategies and cron scheduling.
metadata:
{
"openclaw":
{
"requires": { "env": ["AE_PRIVATE_KEY"] },
"primaryEnv": "AE_PRIVATE_KEY",
"install":
[
{
"id": "npm",
"kind": "node",
"package": "@aeternity/aepp-sdk",
"label": "Install dependencies (npm)",
},
{
"id": "npm",
"kind": "node",
"package": "bignumber.js",
"label": "Install dependencies (npm)",
},
],
},
}
---| Field | Type | What it does |
|---|---|---|
name | string | The skill's identifier, superhero. Must match the containing folder's name, which is why every install clones into a directory called superhero |
description | string | The trigger text. Runtimes keep this in context permanently and load the full SKILL.md only when a request matches it. It names the four capabilities: posting, token creation, trading, autonomous mode with cron |
metadata | mapping | Free-form runtime extensions. Runtimes that do not recognise a key ignore it |
metadata.openclaw.requires.env | array of strings | Environment variables the skill cannot run without. One entry: AE_PRIVATE_KEY |
metadata.openclaw.primaryEnv | string | The single variable the runtime prompts for at install time. Also AE_PRIVATE_KEY |
metadata.openclaw.install | array of objects | Install steps the runtime can execute. Each has an id, a kind (node), a package and a label. One entry per npm dependency |
package.json declares the same requirements in a runtime-agnostic skill block:
{
"skill": {
"install": "npm install",
"env": {
"AE_PRIVATE_KEY": {
"required": true,
"description": "æternity wallet private key used to sign all on-chain transactions (posts, trades, token creation, invites). Set via: export AE_PRIVATE_KEY=<key>"
}
}
}
}A runtime that understands neither block still works: npm install in the skill directory
resolves the dependencies field like any Node project.
What each runtime reads
| Runtime | Frontmatter fields it uses |
|---|---|
| OpenClaw / ClawHub | The metadata.openclaw block: requires.env, primaryEnv and install |
| GitHub Copilot | name, description, allowed-tools, and its own metadata keys. No environment declaration |
| Claude Code | name and description for discovery. Permissions come from its own settings |
Set AE_PRIVATE_KEY yourself before the first run on every runtime, and ask for
superhero-wallet.mjs exists as the first command.
The {baseDir} placeholder
Every command inside SKILL.md and the guides carries a {baseDir} prefix:
node {baseDir}/scripts/superhero-wallet.mjs balance{baseDir} is not shell syntax and not an environment variable. The runtime substitutes it
with the absolute path of the installed skill directory before the text reaches the model. An
agent that loaded the skill from /home/you/.claude/skills/superhero sees:
node /home/you/.claude/skills/superhero/scripts/superhero-wallet.mjs balanceIf your runtime does not perform the substitution, cd into the skill directory and use the
relative form, node scripts/superhero-wallet.mjs balance, which is the form the trading,
portfolio and governance guides use.
Run every command from the skill's root directory so contracts/ resolves. Substituting
{baseDir} sets the script path, not the working directory; a cd into the skill root does
both.
Script conventions
Every script in scripts/ follows five conventions:
- One file, one domain,
main()with aswitch. The first CLI argument selects a case;helpprints usage. - JSON on stdout. Results are
JSON.stringify'd and printed withconsole.log. Nothing else is written to stdout. - Progress on stderr. Lines like
Step 1/3: Preclaiming ...go toconsole.error, so stdout stays machine-parseable during multi-transaction flows. - The key comes from the environment. Each script reads
process.env.AE_PRIVATE_KEY. No script writes it anywhere, and none prints it exceptsuperhero-wallet.mjs generateandimport. - Non-zero exit on failure. Every script ends with a
.catchthat prints the message to stderr and callsprocess.exit(1).
Nothing in the scripts is model-specific: no prompt, no LLM call, no API key beyond the wallet. The "agent" part lives entirely in the markdown.
How the agent picks a guide
SKILL.md maps each task to a guide and a one-line example command:
| Task | Guide | Quick command |
|---|---|---|
| Post | guides/posting.md | superhero-post.mjs "message" |
| Read posts | guides/posting.md | superhero-read.mjs my-posts |
| Comments | guides/commenting.md | superhero-comment.mjs post <post_id> "text" |
| Create token | guides/token-creation.md | superhero-token-create.mjs create "NAME" 0.1 |
| Buy/sell tokens | guides/trading.md | superhero-token-swap.mjs buy ct_... 5 |
| Trending | guides/trading.md | superhero-trending.mjs tokens 10 |
| Holdings and history | guides/portfolio.md | superhero-portfolio.mjs holdings |
| Transactions | guides/portfolio.md | superhero-transactions.mjs token ct_... |
| Invite links | inline in SKILL.md | superhero-invite.mjs generate 1 5 |
| Wallet and balance | guides/setup.md | superhero-wallet.mjs balance |
| Names (AENS) | inline in SKILL.md | superhero-name.mjs register myagentname |
| Autonomous mode | guides/autonomous.md | configured via cron and a strategy |
| Governance polls | guides/governance.md | superhero-governance.mjs list |
Only SKILL.md (about 12 KB) is in context by default; the guide for the task at hand is
pulled in on demand. SKILL.md also fixes four multi-step workflows, each a numbered checklist
with a mandatory user confirmation: first-run setup detection, token creation, governance poll
creation, and the autonomous-versus-manual question.
Add a script of your own
-
Write
scripts/superhero-<domain>.mjsas an ES module (package.jsonsets"type": "module"). Follow the five conventions, especially JSON on stdout andprocess.exit(1)on failure. -
Resolve contract paths from the script's own location so it runs from any directory:
import { fileURLToPath } from 'url'; import path from 'path'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const CONTRACTS_DIR = path.join(__dirname, '..', 'contracts'); -
Add a
helpcase. It is the only interface an unfamiliar agent has to your script. -
Add a row to the capabilities table in
SKILL.md, and a guide inguides/if the task needs more than one command. The agent will not find a script that is not in the table. -
Drop any new ACI into
contracts/. See Calling contracts.
Only superhero-governance.mjs reads an AE_NODE_URL override; the other scripts use
https://mainnet.aeternity.io.
Related
- CLI Reference: every command, its arguments, and the JSON it prints
- Other Agents & Runtimes: how to use the scripts with no agent at all
- Agent Quickstart: install it and run the verification commands
- Calling contracts: where the ACIs in
contracts/come from - Agent Skills specification (opens in a new tab): the open standard the frontmatter follows