Skip to main content

Skills

Skills are smart contract plugins that extend agent wallet capabilities. The ClawSkillRegistry is an on-chain registry of approved skills — think of it as an app store for AI agents. Skills can provide DeFi operations, cross-chain bridging, oracle queries, governance voting, and any other on-chain functionality.

Overview

PropertyValue
Contract0xb9913F4fceA83fF3F9c7D56339Abc196408Cf21b
Registration Fee0.0005 ETH
ApprovalGovernance-controlled
Usage TrackingAutomatic via wallet

How Skills Work

┌────────────────┐     ┌──────────────────┐     ┌────────────────┐
│ ClawWallet │ │ ClawSkillRegistry │ │ Skill Contract│
│ │ │ │ │ │
│ installSkill()─┼────▶│ isApproved() │ │ Custom logic │
│ │ │ │ │ │
│ execute()──────┼─────┼── recordSkillCall │────▶│ execute() │
│ │ │ │ │ │
│ getInstalled() │ │ getSkillMetadata()│ │ returns data │
└────────────────┘ └──────────────────┘ └────────────────┘
  1. Registration — Anyone deploys a skill contract and registers it in the registry (0.0005 ETH fee)
  2. Approval — Governance (owner or governors) reviews and approves the skill
  3. Installation — Wallet owners install approved skills into their wallets
  4. Execution — Agents call skills through the wallet's execute() function
  5. Tracking — Each skill call is automatically recorded for usage analytics

Registering a Skill

const SKILL_REGISTRY = '0xb9913F4fceA83fF3F9c7D56339Abc196408Cf21b';

const registry = new ethers.Contract(SKILL_REGISTRY, [
'function registerSkill(address skill, string name, string version, string description) external payable',
'function registrationFee() external view returns (uint256)',
], wallet);

const fee = await registry.registrationFee();
console.log('Registration fee:', ethers.formatEther(fee), 'ETH'); // 0.0005

await registry.registerSkill(
skillContractAddress,
'DEX Aggregator',
'1.0.0',
'Aggregates trades across Abstract DEXes for optimal pricing',
{ value: fee }
);
Fee Exemptions

The contract owner and governors are exempt from registration fees, enabling free team registrations.

Skill Metadata

Each registered skill has associated metadata:

struct SkillMetadata {
string name; // Human-readable name
string version; // Semantic version (e.g., "1.0.0")
string description; // What the skill does
address author; // Who registered it (msg.sender)
bool approved; // Governance approval status
uint256 registeredAt; // Block timestamp of registration
uint256 totalCalls; // Usage counter
}

Governance

Skills must be approved by governance before wallets trust them. This prevents malicious contracts from being installed.

Approval Flow

// Approve a skill (owner or governor)
function approveSkill(address skill) external onlyGovernance;

// Revoke approval
function revokeSkill(address skill) external onlyGovernance;

// Add a governor
function addGovernor(address governor) external onlyOwner;

// Remove a governor
function removeGovernor(address governor) external onlyOwner;
// Check if a skill is approved
const isApproved = await registry.isApproved(skillAddress);

// Get all approved skills
const approvedSkills = await registry.getApprovedSkills();

Governance Model

RoleCan Approve/RevokeCan Add GovernorsFee Exempt
Owner
Governor
Anyone

Installing Skills in Wallets

Once a skill is approved in the registry, wallet owners can install it:

// Install a skill
await agentWallet.installSkill(skillAddress);

// Check installation status
const installed = await agentWallet.isSkillInstalled(skillAddress);

// List all installed skills
const skills = await agentWallet.getInstalledSkills();

// Uninstall a skill
await agentWallet.uninstallSkill(skillAddress);
Agent Execution Restriction

When the agent calls execute(), the target must be an installed skill. The owner has no such restriction and can call any contract.

Usage Tracking

Every time an agent wallet calls an installed skill via execute(), the wallet automatically calls recordSkillCall() on the registry:

function recordSkillCall(address skill) external;

This increments the skill's totalCalls counter and emits a SkillCalled event — enabling on-chain analytics and reputation tracking for skill authors.

Building a Custom Skill

A skill is just a smart contract that does something useful. There's no required interface — it's called via the wallet's generic execute() function.

Example: Simple Swap Skill

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract SimpleSwapSkill {
address public immutable dex;

constructor(address _dex) {
dex = _dex;
}

/// @notice Swap tokenIn for tokenOut through the DEX
function swap(
address tokenIn,
address tokenOut,
uint256 amountIn,
uint256 minAmountOut
) external returns (uint256 amountOut) {
IERC20(tokenIn).transferFrom(msg.sender, address(this), amountIn);
IERC20(tokenIn).approve(dex, amountIn);

// Call DEX swap function...
// amountOut = IDex(dex).swap(tokenIn, tokenOut, amountIn, minAmountOut);

IERC20(tokenOut).transfer(msg.sender, amountOut);
}
}

Calling a Skill from a Wallet

const swapSkill = new ethers.Contract(skillAddress, [
'function swap(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut) external returns (uint256)',
], provider);

// Encode the function call
const calldata = swapSkill.interface.encodeFunctionData('swap', [
tokenInAddress,
tokenOutAddress,
ethers.parseEther('100'),
ethers.parseEther('95'),
]);

// Execute through the wallet
await agentWallet.execute(skillAddress, 0, calldata);

See the full guide: Building a Custom Skill.

Querying the Registry

// Get skill metadata
const metadata = await registry.getSkillMetadata(skillAddress);
console.log('Name:', metadata.name);
console.log('Version:', metadata.version);
console.log('Author:', metadata.author);
console.log('Approved:', metadata.approved);
console.log('Total Calls:', metadata.totalCalls.toString());

// Check registration
const isRegistered = await registry.isRegistered(skillAddress);

// Get all registered skills
const allSkills = await registry.getAllSkills();

// Get only approved skills
const approved = await registry.getApprovedSkills();

// Total skill count
const count = await registry.getSkillCount();

Events

EventDescription
SkillRegistered(skill, name, author)New skill registered
SkillApproved(skill)Skill approved by governance
SkillRevoked(skill)Skill approval revoked
SkillCalled(skill, caller)Skill was called by a wallet

Fee Structure

ActionFeeExempt
Register a skill0.0005 ETHOwner, Governors
Approve/revokeFree (gas only)
Install in walletFree (gas only)
Call a skillFree (gas only)

Accumulated registration fees are withdrawable to the treasury by the contract owner.