Skip to main content
A skill is a packaged prompt + metadata that any SimpleFunctions agent can invoke as a slash command. SimpleFunctions ships ~19 built-in skills (cognitive guardrails like /precheck, /discipline, plus 16 topical context packs), and authenticated users can author and publish their own. There are two layers:
LayerSourceAuthPurpose
Built-inGET /api/skillsnoneCognitive guardrails and topical context packs maintained by SimpleFunctions.
User skills/api/skill* (CRUD) and /api/public/skill* (catalog)required for writeCustom skills the user authored. Forkable. Optionally publishable.

Built-in skills

The CLI ships built-in skills directly. Inside sf agent, type /<trigger> to run one. List them via the public API:
curl https://simplefunctions.dev/api/skills
{
  "count": 19,
  "description": "Agent cognitive guardrails and workflows for prediction markets.",
  "install": "npm install -g @spfunctions/cli",
  "usage": "Inside sf agent, type /<skill-name> to run a skill.",
  "skills": [
    {
      "name": "precheck",
      "trigger": "/precheck",
      "description": "Pre-trade adversarial check — argue against the trade before executing it.",
      "author": "simplefunctions",
      "version": "1.0.0",
      "category": "risk-management",
      "tags": ["trading", "pre-trade", "adversarial", "bias-check"],
      "toolsUsed": ["inspect_book", "get_context", "what_if", "scan_markets"],
      "estimatedTime": "1-2 minutes",
      "auto": "before_trade"
    }
  ]
}
This endpoint is public, cached 1h. It is the single source of truth for what built-in skills the running CLI exposes.

User skills — full schema

A user skill row contains:
FieldTypeNotes
iduuidPrimary key.
userIduuidOwner.
namestringDisplay name.
triggerstringSlash command (e.g. /my-screener). Must be unique per user.
descriptionstringOne-line description.
promptstringThe instructions the agent runs.
categorystringcustom (default), trading, research, monitoring.
tagsstring[]Discovery tags.
toolsUsedstring[]SimpleFunctions tools this skill calls (informational).
estimatedTimestring | nullE.g. “1-2 minutes”.
autostring | nullAuto-trigger condition (e.g. before_trade).
isPublicbooleanDefault false.
publicSlugstring | nullSet when published. 3–60 chars, lowercase, numbers, hyphens.
publishedAttimestamp | nullTime of first publish.
forkedFromIduuid | nullParent skill if this row is a fork.
forkCountnumberTimes this skill has been forked (only meaningful when public).
runCountnumberTimes this skill has been retrieved via run_skill.
versionstringUser-managed semver. Defaults to 1.0.0.
createdAt, updatedAttimestampServer-set.

Authentication

Every endpoint below except GET /api/public/skills* and GET /api/skills requires Authorization: Bearer sf_live_xxx. Mutating endpoints additionally enforce ownership: only the row’s userId can update, delete, fork (their own), or publish it.

CRUD endpoints

Create a skill

POST /api/skill
curl -X POST "https://simplefunctions.dev/api/skill" \
  -H "Authorization: Bearer $SF_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Fed cut adversarial check",
    "trigger": "/fed-precheck",
    "description": "Argues against any FOMC-rate-cut market before recommending entry.",
    "prompt": "You are about to recommend a trade on a Fed-rate-cut market...",
    "category": "trading",
    "tags": ["fed", "rates", "precheck"],
    "toolsUsed": ["inspect_ticker", "what_if", "get_context"],
    "estimatedTime": "1-2 minutes"
  }'
Required body fields: name, trigger, description, prompt. Returns 201 with the new row.
StatusBodyCause
400{ error: "name, trigger, description, and prompt are required" }Missing required field.
401{ error: "unauthorized" }Bearer key missing or invalid.
500{ error: "Internal server error" }DB write failed.

List your skills

GET /api/skill
Returns built-in skills + the caller’s custom skills:
{
  "skills": [
    { "name": "precheck", "trigger": "/precheck", "isBuiltIn": true, "...": "..." },
    { "id": "sk_...", "name": "Fed cut adversarial check", "isBuiltIn": false, "...": "..." }
  ],
  "count": 20
}

Get one skill

GET /api/skill/{id}
Returns the full skill row. 404 if not found or not owned by the caller.

Update a skill

PUT /api/skill/{id}
Partial update. Send only the fields you want to change. Mutable fields: name, trigger, description, prompt, category, tags, toolsUsed, estimatedTime, auto, version.
curl -X PUT "https://simplefunctions.dev/api/skill/$SKILL_ID" \
  -H "Authorization: Bearer $SF_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "version": "1.1.0", "description": "Updated copy" }'
404 when the row doesn’t exist or isn’t owned by the caller. Server stamps updatedAt.

Delete a skill

DELETE /api/skill/{id}
Returns { deleted: true, id }. Hard delete. 404 if not found.

Fork a public skill

POST /api/skill/{id}/fork
Forks a public skill into the caller’s collection. The fork copies name (with ” (fork)” suffix), trigger, description, prompt, category, tags, toolsUsed, estimatedTime, and sets forkedFromId to the original. forkCount on the original is atomically incremented.
curl -X POST "https://simplefunctions.dev/api/skill/$ORIGINAL_ID/fork" \
  -H "Authorization: Bearer $SF_API_KEY"
Returns 201 with the new row. 404 if the source skill isn’t public or doesn’t exist.

Publish / unpublish

POST   /api/skill/{id}/publish    # publish
DELETE /api/skill/{id}/publish    # unpublish
Publishing flips isPublic = true and pins a public slug:
curl -X POST "https://simplefunctions.dev/api/skill/$SKILL_ID/publish" \
  -H "Authorization: Bearer $SF_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "slug": "my-fed-precheck" }'
Slug rules: ^[a-z0-9-]{3,60}$. Unique across all published skills.
StatusBodyCause
400{ error: "slug is required" }Body missing slug.
400{ error: "Slug: 3-60 chars, lowercase, numbers, hyphens only" }Slug regex failed.
404{ error: "Skill not found" }Not owned by caller.
409{ error: "Slug already taken" }Another skill owns the slug.
Successful publish returns { published: true, slug, skill }. The skill is then live at simplefunctions.dev/skills/{slug} and discoverable via GET /api/public/skills. Unpublish flips isPublic = false and returns { unpublished: true }. The slug is kept so future publishes can reuse it.

Public catalog

GET /api/public/skills?category=&q=&sort=
GET /api/public/skill/{slug}
/api/public/skills returns up to 100 published skills, optionally filtered:
QueryTypePurpose
categorystringFilter by category.
qstringSubstring match on name and description.
sortpopular | newpopular ranks by forkCount + runCount; new (default) ranks by createdAt.
/api/public/skill/{slug} returns the full row including prompt text. Both endpoints are no-auth, Cache-Control: public, s-maxage=300.

Discovering skills from MCP

These tools are also available over MCP — see MCP tools reference:
  • create_skill, list_skills, run_skill, publish_skill, fork_skill — authenticated.
  • browse_public_skills — public.
run_skill returns the skill’s prompt and metadata; execution happens in the calling agent (Claude Code, Cursor, sf agent, etc.) — the SimpleFunctions server does not run the prompt itself.

See also

MCP tools reference

create_skill, fork_skill, publish_skill, full schemas.

Build agents

How skills compose with the SimpleFunctions agent loop.

Agentic CLI

Built-in skills are bundled here; sf agent recognizes their slash commands.

Browse public skills

Live catalog on the website.