CREATORS
Research

From Soft to Hard Skills 

Creators Research07.26.2026 | 4 min read

Agent skills today are prose. A markdown file describes what the agent should do and, critically, how to invoke its tools: “run this script with bash”. All of it rides into the context window as text. The model reads it, interprets it, and improvises shell commands. Nothing is typed, nothing is verifiable before execution, and every tool description is paid again on every run. These are soft skills: suggestions the model may follow.

The fix is an old idea. MDX did it on the web years ago: one file, two readers that see different things in it. The writer sees prose; the renderer sees components. Split a skill file the same way and you get a hard skill. The prose stays soft, context the model reads. The tools become hard, typed declarations the engine executes.

The format

A hard skill is still a SKILL.md: markdown prose, plus tool code fences that declare executable tools. The grammar inside a fence is deliberately closed: an id, a description, typed params, and a run template. A malformed line is an error, not a guess.

---
skill: driver-admin
description: Administer the Driver closed beta.
---

This skill administers the Driver closed beta:
the signup waitlist and existing users' plans.

Accepting an email lets that person register and
sends them an access email. Act on one email at a
time, and never invent an address.

```tool
id: accept_user
description: Accept a waitlisted email so it can register
params:
  email:
    type: string
    format: email
    description: the waitlisted email to grant access to
run: uv run python waitlist_admin.py $email
```

The parser splits the file into two channels. The prose travels to the model as context, verbatim. The tool fences never reach the model as text: each one is compiled into a typed tool declaration, injected into the run’s contract, and replaced in the prose by its name. The model sees narrative plus a typed catalog; the engine sees commands.

The design

Because the tool blocks parse statically, you know exactly what a hard skill can touch without executing it: the capability manifest is a property of the file, not a promise in its prose. Because arguments substitute into argv words and never pass through a shell, a hostile value cannot smuggle in commands. Because the model only ever sees the declared tools, the bounded set is the contract, and every run leaves a replayable trace. And because it is plain markdown, the file renders readably anywhere.

Just as important is everything this design leaves out. No repeated token spend, no project exploration, no path caching. The agent never wanders your machine looking for context: the skill is the context, and the declaration is the guardrail. The model’s freedom is exactly as wide as the tools you wrote down, and not one command wider.

We use it

Our own closed-beta operations run on this: waitlist acceptance, plan changes, credit top-ups. One hard skill over the same admin scripts we already had. Reasoning runs in Driver cloud; the scripts run locally, with local secrets that never leave the machine.

$ driver skill "grant access to [email protected]"

  skill driver-admin · 1 tool

  accept_user([email protected])
  │  ↳ accepted

   done · 1 tool call

  Access granted to [email protected]

Try it

The parser and compiler behind all of this ships on npm today as @crtrs/skill. It never calls a model: you own the loop, and the package referees both directions of the contract: what the model may call and what it actually called. The whole thing is four lines:

const { parseSkillFile, compile, resolve } = require('@crtrs/skill')

const skill = parseSkillFile('SKILL.md')
const system = compile(skill)             // prose + call protocol
const output = await myInference(system)  // your model, your way
const call = resolve(skill.tools, output) // typed, validated, argv ready

Hard skills shine wherever a script should never be improvised: deploys with exact flags, admin operations granted one email at a time, the recurring ops request you keep typing by hand.

npm install @crtrs/skill

Citation

@online{creators2026skills,
  author = {CREATORS},
  title = {From Soft to Hard Skills},
  date = {2026-07-26},
  year = {2026},
  url = {https://creators.industries/research/hard-skills},
}