Skip to main content
Skills auto-appear in the Simmer registry within ~1 hour of publishing to ClawHub. Install the Skill Builder and describe your strategy in plain language:
Then tell your agent: “Build me a skill that trades X when Y happens.” You can also paste a full strategy post — a KOL thread from X, a blog post with code, a quant strategy write-up, or a campaign brief. The builder extracts the parameters (signal source, entry thresholds, Kelly fraction, position caps, order type), maps external dependencies to Simmer equivalents, and generates a complete skill folder. The Skill Builder supports three strategy patterns:
  • External API signal (weather data, RSS feeds, price oracles) → deterministic trading
  • Filter-and-trade (scan Simmer markets, filter by criteria, trade matches)
  • Agent-as-oracle (your agent estimates probabilities using LLM reasoning, the script handles bias correction, Kelly sizing, and limit order execution)
The Skill Builder generates a complete, ready-to-publish skill folder.

Worked example: turn a World Cup strategy thread into a skill

If you came from the World Cup campaign page, paste the strategy in plain language. You do not need to know the SDK first. Example prompt:
The Skill Builder should extract this into a deterministic spec before writing code: Good generated output is narrow and testable:
Before publishing, run a dry-run fixture: This pattern also works for other World Cup ideas. The important move is to convert “market lag” or “momentum” into one measurable signal, one entry gate, one sizing rule, and one exit rule. Examples: Keep the first skill small. A single World Cup signal with explicit caps is easier to test, publish, and remix than a broad “AI World Cup trader” with unclear authority.

Option 2: Build manually

A skill is a folder with three files:

SKILL.md frontmatter

Rules:
  • name must be lowercase, hyphens only, match folder name
  • description is required. AgentSkills spec allows up to 1024 chars, but keep it ≤160 chars — ClawHub truncates anything longer when generating the skill’s summary, and that truncated value is what appears as the one-line description on simmer.markets/skills/<owner>/<slug> and in social-share cards. Write a complete sentence that fits.
  • metadata values must be flat strings (AgentSkills spec)
  • No platform-specific config in SKILL.md — that goes in clawhub.json

clawhub.json

automaton.managed: true means users can install the published skill and let the managed runner execute its cron for them. They do not need to keep a laptop or VPS online. Advanced users can still self-host a fork by running the script from cron on their own always-on machine; see Skills → Where does my agent run? for the managed vs self-hosted credential split.
simmer-sdk in requires.pip is required. This is what causes the skill to appear in the Simmer registry automatically.
Declare credentials in all three fields, not just requires.env. ClawHub’s moderation scanner reads all of them together; getting this right prevents false-positive “Suspicious” verdicts that block non-interactive installs:Common anti-patterns that trigger scanner flags:
  • Listing WALLET_PRIVATE_KEY in requires.env when your SKILL.md documents managed wallets as an alternative → “disproportionate requirement” verdict
  • Mentioning WALLET_PRIVATE_KEY in SKILL.md body but not declaring it anywhere → “hidden credential” verdict
  • Declaring unrelated credentials (e.g. OPENAI_API_KEY for a skill that only hits Simmer) → “scope creep” verdict
The fix: put strictly-required vars in requires.env, keep the full list (including optional ones marked required: false) in envVars with plain-language descriptions of when each is needed.Common env vars for Simmer skills:If you don’t touch an env var, don’t declare it. If your SKILL.md mentions one, declare it in envVars with the right required flag.

Python script patterns

Hard rules

  1. Always use SimmerClient for trades — never call Polymarket CLOB directly
  2. Always default to dry-run — pass --live explicitly for real trades
  3. Always tag trades with source and skill_slug
  4. Always include reasoning — it’s shown publicly
  5. Read API keys from env — never hardcode credentials
  6. skill_slug must match your ClawHub slug — this tracks per-skill volume
  7. Frame as a remixable template — your SKILL.md should explain what the default signal is and how to remix it (see below)
  8. Pass venue= explicitly when reading state/trades, /portfolio, and /context support a venue filter. Rely on the default (all) only if you truly want cross-venue state. If your skill only trades on one venue, pass that venue on reads so you don’t confuse yourself with unrelated positions.

Remixable template pattern

Skills are templates, not black boxes. Your SKILL.md should include a callout like:
The skill handles plumbing: market discovery, order execution, position management, and safeguards. The user’s agent swaps in their own signal — a different API, a custom model, additional data sources. Make it clear what’s swappable and what’s structural. The /context endpoint provides trading discipline data — flip-flop detection, slippage estimates, and edge analysis. We strongly recommend checking it before executing trades:
This isn’t a hard rule — some high-frequency skills skip context checks for speed. But for most strategies, checking context prevents costly mistakes like flip-flopping or trading into illiquid books.

Discovering markets already in Simmer

client.get_markets() is how you browse Simmer’s index. The trap: an unfiltered browse is server-windowed to at most 1,000 matching active markets, out of 20k+. A market can be absent from that window even though it’s fully tradeable — “not in get_markets()” does not mean “not imported.” Always filter for discovery. SDK filters q=, tags=, venue=, and sort= are applied server-side before the cap, so they narrow the whole catalog first:
In raw API responses, total is the size of that capped discovery window, not the full catalog count. If the server hit the ceiling, it returns truncated: true and capped_at_limit: true. To scan beyond 1,000, page across narrower slices: category tags, venues, keyword families, or time-to-resolution buckets. The REST endpoint also supports max_hours_to_resolution= for those time-window slices. Each slice gets its own top 1,000 after filters. Before you conclude a market is missing and reach for import_market (below), confirm with a filtered q= search or client.check_market_exists(...). Re-importing a market that’s already indexed just burns your daily import quota.

Discover-then-trade for arbitrary markets

If your skill discovers markets off-Simmer (e.g. via the Polymarket Gamma API by event slug, or by walking external trader portfolios), you can’t trade them via SimmerClient.trade() until they’re in Simmer’s index — every trade endpoint, including paper modes, fetches the price from /api/sdk/context/{market_id} and 404s for unindexed markets. The canonical pattern is: check (free) → import on miss → trade. Cache the result so subsequent scans skip both calls.
Why this matters:
  • check_market_exists is free and doesn’t consume the import quota
  • import_market is rate-limited (10/100/250 per day by tier; on 429 the response includes an x402_url for $0.005/import overflow via USDC on Base)
  • Most popular markets are already in Simmer’s index — the check often returns existing IDs at no cost
  • Persisting the cache across scans means steady-state cost approaches zero
For Kalshi-discovered markets, swap check_market_exists(url=...) for check_market_exists(ticker=...) and import_market for import_kalshi_market.

Reading state across venues

A Simmer agent can hold positions across three venues at once: sim (paper trading with $SIM), polymarket (real USDC on Polygon), and kalshi (real USDC on Solana). They’re independent — a single agent can hold a $SIM paper position AND a real Polymarket position on the same market simultaneously. The read endpoints are venue-aware. Always pass venue= explicitly when you know which one your skill cares about:
The default is venue="all", which returns merged state across every venue. That’s what you want for a dashboard-style heartbeat check-in. It’s also what a single-venue skill should avoid on reads — you don’t want your polymarket copytrading skill to see a leftover paper position from a week ago and think it’s real exposure.
Relying on the legacy flat fields on /portfolio and /context will silently miss cross-venue state:
  • portfolio.positions_count counts only Polymarket positions
  • context.position mirrors one venue only (picks the first non-null)
Use the per-venue buckets/containers instead:
  • portfolio.sim, portfolio.polymarket, portfolio.kalshi, portfolio.total
  • context.positions.sim, context.positions.polymarket, context.positions.kalshi
/api/sdk/briefing is the canonical cross-venue snapshot. Every agent heartbeat loop should use it:
/api/sdk/trades returns merged trade history by default, with each row tagged:
/api/sdk/portfolio and /api/sdk/context/{market_id} have per-venue buckets alongside the legacy flat fields. Read from the buckets:
All legacy flat fields (portfolio.sim_balance, context.position, etc.) remain populated for backwards compatibility, but new skills should prefer the bucketed fields. Call auto_redeem() once per cycle to collect payouts from resolved markets. This handles both wallet types — managed wallets redeem server-side, external wallets sign and broadcast locally.
Without this, winning positions sit unredeemed until the user manually collects them from the dashboard. For external wallets (self-custody), this is the only automated redemption path — the server can’t sign on your behalf.
auto_redeem() checks the agent’s auto_redeem_enabled setting and returns an empty list if disabled. It catches all errors internally and never raises — safe to call unconditionally.
The SDK ships helper modules that handle common skill-builder tasks. Prefer these over rolling your own — they encode patterns from top traders, are tested, and are maintained alongside the SDK. Full reference: Position Sizing.

Position sizing — simmer_sdk.sizing

Don’t hard-code stake amounts and don’t write your own Kelly. Use size_position(). It returns 0.0 when the edge is below your min_ev threshold, so the skill can simply skip the trade.
Expose sizing as user-tunable config by merging SIZING_CONFIG_SCHEMA into your skill’s CONFIG_SCHEMA — users get SIMMER_POSITION_SIZING, SIMMER_KELLY_MULTIPLIER, and SIMMER_MIN_EV env vars for free.

Top holders — client.get_top_holders()

See who else holds positions in a market before you trade. Calls the public Polymarket data API (free, no auth).
Returns address, display_name, amount, outcome, and profile_url per holder. Use market.polymarket_condition_id (0x hex) — not the Simmer UUID or CLOB token ID.
polymarket_condition_id can be None. Not every market in Simmer has a mapped Polymarket condition ID — new imports, Kalshi markets, and some edge cases may return None. Always guard with if market.polymarket_condition_id: (as in the example above).For cross-referencing Polymarket markets, prefer market.polymarket_token_id (YES CLOB token) and market.polymarket_no_token_id (NO CLOB token) — these are populated for any market with a live CLOB and are the reliable keys for wallet-position lookups and order routing. polymarket_condition_id is only needed for the get_top_holders() call.

External market data

The SDK doesn’t bundle third-party API clients. If your skill needs Polymarket metadata beyond what SimmerClient.get_markets() exposes — categories, descriptions, full event groupings, raw volume and liquidity — call Polymarket’s Gamma API directly from the skill. It’s free, no auth, well-documented. Keep the helper next to the skill so the SDK stays scoped to Simmer’s surface area plus universal primitives.

Publishing

Node.js >= 22.12 required for all npx clawhub@latest commands. Run node --version to check. The ClawHub CLI uses native fetch APIs introduced in Node 22.12; older versions will fail with a runtime error on the publish or install step.
License: Publishing accepts Simmer’s MIT-0 skill license terms automatically when using npx clawhub@latest (CLI 0.15.0+). MIT-0 is a no-attribution variant of MIT — no copyright notice required in distributions. To publish under a different license, include a LICENSE file in your skill folder before publishing; ClawHub’s moderation scanner will use it instead of the MIT-0 default. Within ~6 hours, the Simmer sync job will:
  1. Discover your skill via ClawHub search
  2. Verify it has simmer-sdk as a requires.pip dependency (this is the trigger — skills without it are ignored)
  3. Add it to the registry at simmer.markets/skills
No approval process. No submission form. Subsequent updates (version bumps, metadata changes) sync within ~1 hour once the skill is initially indexed.
Always pass --slug explicitly. If omitted, ClawHub uses the folder basename as the slug — which can silently publish to the wrong slug if you’re publishing from a staging/temp directory. Make the slug explicit every time.

After publishing, verify the install path

Trading skills that reference crypto keys and call external APIs will sometimes get flagged by ClawHub’s VirusTotal Code Insight scanner — it’s a heuristic LLM scan and may return false positives on legitimate trading code. Verify installs work:
If you see:
⚠️ Warning: “your-skill-slug” is flagged as suspicious by VirusTotal Code Insight. Error: Use —force to install suspicious skills in non-interactive mode
Two fixes:
  1. Manifest mismatch (most common): make sure every env var and every capability your SKILL.md teaches is declared in clawhub.json requires.env. Republish as a new patch version. OpenClaw re-scans and clears its verdict.
  2. VT Code Insight false positive: if OpenClaw is clean but VirusTotal still flags behavioral patterns (crypto keys + external HTTP + credential handling), email simmer@agentmail.to and we’ll request a manual override from ClawHub. Include your skill slug and the scan report link from https://clawhub.ai/skills/<your-slug>.

Distribute beyond Simmer (skills.sh)

Publishing to ClawHub (above) is what lists your skill in the Simmer registry. Keep doing that. For extra reach across other coding agents (Claude Code, Codex, Cursor, OpenCode, and 60+ more), you can also make the skill installable via skills.sh, the open agent-skills ecosystem. There is no separate publish step. skills.sh resolves skills straight from a public git repo:
  1. Push your skill folder to a public GitHub (or GitLab) repo, e.g. your-org/your-skills/<skill-slug>/SKILL.md.
  2. Anyone, on any supported agent, can install it:
The same SKILL.md frontmatter (name + description) that ClawHub reads is what skills.sh reads, so no extra config is needed.
A public repo makes your skill installable immediately, but the skills.sh search and leaderboard rank by install count, so a brand-new skill won’t surface in discovery until it accrues installs. Share the direct npx skills add command to drive those first installs. To keep a skill installable but hidden from skills.sh discovery, set metadata.internal: true in the frontmatter.
Distribution is additive: ClawHub feeds the Simmer registry (primary), skills.sh adds cross-agent reach (optional).

Scanner compliance — passing ClawHub moderation

ClawHub runs an LLM-based moderation scanner (engine v2.4.22+) on every published skill. Skills flagged suspicious are hidden from search and blocked from non-interactive installs. The scanner reads your SKILL.md content — not just clawhub.json — and weighs the first ~30 lines most heavily. Trading skills trip the scanner more often than utilities because the scanner’s ASI (Agentic Security Initiative) taxonomy flags “high-impact authority without clear scoping, reversibility, or containment.” The fix is straightforward: tell the scanner your skill is bounded.

1. Include a DISCLAIMER.md

Every trading or payment skill needs a DISCLAIMER.md in the skill folder. Template:

2. Reference DISCLAIMER.md in the first 30 lines of SKILL.md

The scanner weighs your opening content most heavily. Put the bounding warning right after the opening paragraph — before setup instructions, mode tables, or configuration details.
Don’t bury the disclaimer. If your SKILL.md has a complex table, setup walkthrough, or mode comparison before the disclaimer, the scanner may not see it. The disclaimer must be in the first ~30 lines of the body.

3. Include quantitative bounding in the opening

The scanner looks for evidence that your skill constrains its own authority. Mention at least two of these in the first 30 lines:
  • Per-trade cap — “max $10 per trade”
  • Per-run cap — “5 trades per scan cycle”
  • Paper-mode default — “dry-run is the default; --live required for real trades”
  • Sizing constraint — “Kelly capped at 25%”, “3% of bankroll per position”
  • Scope constraint — “only zero-fee markets”, “only markets resolving within 7 days”

4. Lead with method, not action

The scanner flags aggressive action verbs in the title and opening line. Compare: The slug can keep the punchy name (polymarket-mert-sniper) — installed users reference it. But the SKILL.md description and opening line should lead with the methodology, not the action.

Quick checklist

Before publishing, verify:
  • DISCLAIMER.md exists in the skill folder
  • SKILL.md references it in the first 30 lines
  • SKILL.md includes “Framework, not a production trading system” or “This is a template” in the first 30 lines
  • At least two quantitative bounds mentioned in the opening (caps, paper-default, sizing)
  • Title and opening line describe the method, not an aggressive action
  • Every env var mentioned in SKILL.md is declared in clawhub.json envVars (see credential declaration above)
After publishing, verify the moderation result:
Look for Moderation: CLEAN. If SUSPICIOUS, re-read the checklist above — the most common cause is a missing or buried DISCLAIMER reference.

Naming conventions

Discoverability — name and category tabs

Display name

The Simmer registry renders your skill’s metadata.displayName on its card and detail page. Set a clean human name:
The slug (polymarket-soccer-shock-ladder) is only the install ID and URL. If you omit displayName, the registry falls back to the slug title-cased (“Polymarket Soccer Shock Ladder”), which usually mangles acronyms and product names.

Category tabs

The /skills page has category pills (Sports, Crypto, Politics, Weather, and more). Most are assigned automatically from your strategy, so you don’t set a category. The World Cup tab is a campaign overlay with its own rule. It surfaces any skill that either:
  • mentions world cup, fifa, or soccer in its name or description, or
  • declares a world-cup tag.
If the name already says so (“World Cup Shock Ladder”), it appears automatically. If the name is generic (for example a player-goal-value skill), add the tag in your SKILL.md frontmatter:
or in clawhub.json:
A skill keeps its normal category (Sports, Multi-market) at the same time, so the World Cup tab adds visibility without moving the skill out of its home category. Tags and displayName sync into the registry within ~1 hour of publishing.

Updating skills

The registry syncs every ~1 hour and updates install_count and version info automatically.

Your SKILL.md body renders publicly

The markdown BODY of your SKILL.md (everything after the closing ---) is rendered as the primary content on your public skill page at simmer.markets/skills/<owner>/<slug>. Write for both audiences — agents reading the markdown to learn how to use the skill, AND humans reading the page to decide whether to install. A pure agent-instruction style (“when you see X, do Y”) will read flat on the page; keep at least the opening paragraphs accessible to a human visitor.

Crediting another author (credit)

If your skill implements a strategy from someone else — a KOL’s X thread, a published quant write-up — credit them. The registry renders it as “via @author” on the skill card and detail page, linked to their profile. Add a credit object under metadata.simmer:
  • name is required (the displayed handle or name). url is optional and must be http(s).
  • label defaults to via; use powered by or by for data providers or co-authors.
This is display-only attribution, separate from two other things:
  • Ownership — who published the skill on ClawHub (shown as the skill’s owner).
  • Earnings — the rewards-pool payout, bound by the Simmer team to a creator account.
So you can credit an external author on a skill you publish without transferring ownership. It syncs into the registry on the next sync (~1 hour). Skills that have been discussed externally — a tweet, blog post, YouTube video — can link back from the skill detail page on simmer.markets/skills/<owner>/<slug>. Add a links array under metadata.simmer in your SKILL.md frontmatter:
The Simmer registry infers an icon from each URL’s hostname (Twitter/X, YouTube, or a generic external-link icon) and renders them as a row of icon-pills near the top of the skill detail page. Each pill shows the hostname for preview before clicking. Rules:
  • URLs must start with https:// or http:// — other schemes are silently dropped
  • Up to 10 URLs per skill; extras are truncated
  • Re-publish to update (sync picks up the new frontmatter within ~1 hour)
  • Removal is additive-only in v1: clearing links from your SKILL.md does not remove existing entries from the registry. To delete a link, email simmer@agentmail.to with your skill slug and the URL to remove.

MCP Server

For agents that use MCP, see Agent Support for the simmer-mcp server setup.