If I count what I’ve shipped this year, most of it turns out to be procedures: a folder with a Markdown file that says when to fire, what to do, what to check, and what done looks like, plus a references folder and, where it matters, a script or two. Twenty of them run the jobs that come around every week at work: CRM routing and triage, outreach enrichment, production speed tables, mailer address formatting, artwork prep, and SOP writing. Forty-odd more run my own life, from a morning briefing to the voice a book is written in.

A procedure is still software. It has a trigger, an interface, a version, a test suite, and failure modes, but no compiler. Its executor is a model, and that changes what the engineer’s job actually is.

What a Skill Is Made Of

A skill is one folder with one job.

The file at the top carries a name, a description, and a list of phrases that fire it. Then comes the procedure itself, numbered and written in plain prose. After that is a statement of what the output has to contain before the skill is allowed to say it’s finished.

Next to it, a references folder holds the facts the procedure needs: a rate sheet, three worked examples, a house style. The procedure reads them instead of remembering them, and that’s what keeps a skill from inventing a number in month three.

Next to that, a scripts folder holds the deterministic parts. The model calls them instead of doing that work itself.

name: production-speed-tables
description: >
  Build the production speed table for a quote. Use when Matt says
  "speed table", "how fast can we make", "production timeline for",
  or pastes a quote with quantities and asks for turnaround.

That description is the whole trigger surface. Every skill has one, and the lists are written to be mutually exclusive, because the most common failure in a library of forty skills is two of them firing on the same sentence.

What Prose Can Do That Code Can't, and the Reverse

A program needs structured input. A procedure can take a consultation form written in someone’s own words, a category page, a photo caption, or a client’s email, and do something sensible with it. That’s the unstructured middle of most real jobs, and it’s where a procedure earns its place. Nobody was ever going to write the parser for “we need something for the booth, budget is tight, the show is in three weeks.”

What a procedure can’t do is promise the same output twice. It can’t promise it parsed all twenty-four feeds instead of twenty-three plus a headline it made up. It can’t promise the totals in a table add up. Those steps were always going to need code.

The rule I build to is that if a step’s input is prose, it gets a procedure. If a step’s failure would be silent, it gets a script. Most jobs end up as a procedure that calls scripts at exactly those points.

The daily briefing is the cleanest example. A deterministic parser stages the day’s news from two dozen feeds and writes a list. Only after that does the model read the chosen articles, cluster them, write the body, and fact-check every claim against a live search. The parser never hallucinates a story, and the model never has to count feeds. Each one does the part it’s good at, and they hand off to each other through a file.

The CRM connector has the same shape one layer down. The model decides what to do, and the write tools are gated by code against the schema the CRM reports at run time.

Where Procedures Fail

They fail in ways programs don’t, and those ways are worth naming because most of them are quiet.

Trigger overlap. Two skills claim the same phrase. The wrong one fires, and the output looks plausible. The fix is boring: one phrase list per skill, audited against the others whenever a skill is added.

Drift when the model changes. The same procedure, read by a new model version, gets read slightly differently. A step that used to be followed closely now gets paraphrased, and nothing errors. The fix is a test battery you re-run after any change to the model or the procedure. I keep one for my own preferences block and re-run it whenever anything moves.

Silent narrowing. The model skips a step and the output still passes a quick glance. This is why the done-criteria are written down, and why the check is an actual step in the loop instead of a gut feeling.

Stale references. The rate sheet in the references folder is from March, and the procedure follows it faithfully, which is exactly the problem. The fix is a dated inventory that says which version is installed where, so a stale skill is visibly stale.

These are the same failure modes any software has, translated into prose, and the fixes are the familiar ones: version it, test it, inventory it, and audit its interfaces. The difference is that no compiler will catch any of them for you, so the discipline has to live in the procedure and the checks around it.

Where the Job Moved

If the executor is a model, the engineer’s job shifts from writing the loop to writing a specification an executor can actually run, and to deciding which steps can’t be left to judgment.

That second part is the one I think most people underrate. Choosing where the scripts go is an engineering decision with consequences. Put in too few, and the system quietly lies to you. Put in too many, and you’ve rebuilt the brittle program the procedure was supposed to replace. The right split comes from knowing the job well enough to say which steps are allowed to be approximate.

I still write code, just less of it, and what I write is smaller and sharper: a parser, a gate, a check. The rest is prose that a model executes on a schedule, and I think the fact that prose is now the deployable unit is the most underreported shift in how software gets made.