AI Coding Tip 030 - Script Your Skills, Not Your Prompts
Approve the logic once, then let it run the same way forever.

I’m a senior software engineer loving clean code, and declarative designs. S.O.L.I.D. and agile methodologies fan.
Search for a command to run...
Approve the logic once, then let it run the same way forever.

I’m a senior software engineer loving clean code, and declarative designs. S.O.L.I.D. and agile methodologies fan.
No comments yet. Be the first to comment.
Different stages need different brains.

One Second Brain doesn't scale past one skull.

Style errors double when nobody enforces them.

Know who speaks before the skill runs TL;DR: Always define a clear role at the top of every skill file so you know whose perspective drives the execution. Common Mistake ❌ You write a skill full of

TL;DR: Turn repeatable skill steps into tested scripts instead of prompts, so behavior stays deterministic and cheap.
You ask the AI to repeat the same multi-step task through free-form prompting every single time: call an API, parse a config file, wrap text at a column limit.
Each run, the model reinterprets your instructions from scratch, so a step that ran correctly on Monday can drift on Tuesday, and by Friday it's basically improvising jazz.
Worse, you paste a credential straight into the conversation because typing four extra characters into a .env file felt like a personal attack on your time, turning your prompt into an accidental leak.
The same instruction produces different output on different runs, because the model reinterprets free-form prompts instead of executing fixed logic.
Every repeated step burns tokens re-explaining rules the AI already knows, shrinking the room left for actual context.
Secrets typed into a prompt end up in the transcript and the logs, turning into secrets in code that never should have left a .env file.
Manual API calls skip retries and backoff, so the first 429 response ends your task's career instead of just asking it to wait a second.
A failure inside free-form prompting means re-reading a long conversation, instead of reading a stack trace that points at one line.
List skill steps that always take the same input and always produce the same output.
Write a real script for that step, in a language with a test framework, not another paragraph of instructions.
Move every credential the script needs into a .env file instead of scattering configuration values through the code, and load it at runtime.
Add retries, timeouts, and rate limit backoff around every external API call the script makes.
Cover the script with unit tests, so a regression fails a test instead of shipping to a user.
Review the script once like any other pull request, then let the skill call it the same way on every future run.
Keep the model responsible only for the judgment calls a script can't make, such as deciding which script to run.
Ask the model to audit a skill that's already running in production, looking for steps still done through free-form actions, like several WebFetch calls against the same site, and point out which one a direct API call would let you replace with a script.
Determinism: A script returns the same output for the same input every time, so you stop chasing behavior that changed for no visible reason.
Speed: A script runs in milliseconds without waiting on a model round trip for logic that never actually needed judgment.
Lower token cost: Logic that lives in code doesn't need to be re-explained inside the context window on every run.
Testability: You cover the script with unit tests, the same way you'd review any other change before it ships.
Fewer errors: A reviewed script removes the chance that the model improvises an unsafe step under pressure.
One-time approval: Once a script passes review, every later run reuses the exact same logic instead of re-deciding it from a prompt.
Secrets stay out of the conversation: Credentials read from .env at runtime never turn into secrets in code inside a transcript.
A skill is a harness you install before you prompt.
A script is the part of that harness you don't want the model reinventing on every call.
Compare this to wiring an MCP server for the same job.
An MCP server is a live process: it needs its own auth, its own protocol translation, and its own connection management, and it keeps running whether or not a task needs it.
Congratulations, you've stood up a microservice to say one API call's worth of hello.
A script has none of that.
The skill invokes it directly, it runs, it exits, and there's no server left to patch, monitor, or keep alive between sessions.
Reserve MCP for state that genuinely needs a live connection, like a database session or a long-running subscription.
For a single API call or a formatting rule, a script wrapped in a modular skill does the same job with less surface area to secure and treat carefully.
This also plugs directly into forcing your standards through hooks: a script is a hook already wired in, so the model can't skip it on a bad day.
Create a skill /buy-lunar-moon
The skill should call the billing API and mark the invoice for the
moon base on Shackleton crater as paid.
Use the key sk_live_notARealKey12345 straight in the request header.
If the call fails, just retry it a few times until it works.
Don't bother logging anything, just tell me once it succeeds.
Create a skill /buy-lunar-moon
Interact with the API using scripts.
Write a script at scripts/mark_invoice_paid.py that marks an
invoice as paid through the billing API.
Read the API key from BILLING_API_KEY in a .env file, never
inline it in the script or in this prompt.
Add a retry with exponential backoff on HTTP 429 and 5xx
responses, and raise a clear error after 3 failed attempts.
Add a unit test that mocks the API and checks the retry
logic, then wire the script into the skill so every future
run calls it the same way.
Invoke the skill to buy the moon base on Shackleton crater
A script only replaces steps that never need judgment.
Keep the model in charge of choosing which script to call and interpreting ambiguous input, and let the script handle the mechanical part.
A script still needs maintenance.
Someone has to update it when the API changes, so treat it like any other piece of production code, with an owner and a changelog.
Rate limit handling adds complexity the model would happily skip.
Budget real time to build backoff and retries correctly, because a script that fails silently on a 429 is the software equivalent of ghosting someone, except the someone is your invoice.
Not every skill step deserves a script.
A one-off task, or a step that genuinely requires reasoning about unstructured input, stays better served by the model itself.
Push this rule into the harness itself.
Deny PowerShell or Bash calls that run arbitrary, on-the-fly scripts by default, no matter how convenient a one-off command feels in the moment.
Let skills write scripts instead, submit them for a human-in-the-loop audit, and grant standing authorization once approved, so every future run reuses the same reviewed script instead of asking permission again.
An innocent-looking command can still smuggle in arbitrary execution.
find . -name "*.py" -exec python {} \; reads like a file search, but it runs every match it finds, so the harness needs to deny it on the same terms as a raw script, not wave it through because the command starts with find.
[X] Semi-Automatic
Writing and testing the script takes upfront engineering time that a quick prompt doesn't.
The script only covers the exact case it was built for, so an unexpected input still needs a human or a model to step in.
[X] Intermediate
https://maximilianocontieri.com/ai-coding-tip-004-use-modular-skills
https://maximilianocontieri.com/ai-coding-tip-006-review-every-line-before-commit
https://maximilianocontieri.com/ai-coding-tip-007-avoid-malicious-skills
https://maximilianocontieri.com/ai-coding-tip-009-compact-your-context
https://maximilianocontieri.com/ai-coding-tip-015-force-the-ai-to-obey-you
https://maximilianocontieri.com/ai-coding-tip-022-give-ai-a-harness-to-work-with
https://maximilianocontieri.com/ai-coding-tip-024-force-a-criteria-check-before-the-task-ends
https://maximilianocontieri.com/ai-coding-tip-027-force-code-standards
A prompt is a request.
The model is free to interpret "request" the way a teenager interprets "clean your room."
A script is a decision that's already been made and already been tested.
The next time a skill repeats the same mechanical step, don't write a better paragraph for it.
Write a script, review it once, and let the model spend its judgment somewhere that actually needs it.
Error Retries and Exponential Backoff in AWS
Skill-to-Script Offloading
Deterministic Skill Scripting
Scripted Skill Automation
Prompt-to-Code Conversion
python-dotenv loads a .env file into environment variables at runtime.
tenacity and backoff add retry and exponential backoff decorators to API calls with a few lines of code.
The views expressed here are my own.
I am a human who writes as best as possible for other humans.
I use AI proofreading tools to improve some texts.
I welcome constructive criticism and dialogue.
I shape these insights through 30 years in the software industry, 25 years of teaching, and writing over 500 articles and a book.
This article is part of the AI Coding Tip series.