Skip to main content

8 posts tagged with "ai"

View All Tags

How to Create Agent Plugin Skills That Work

· 6 min read

I wanted a better way to create skills for an agent plugin, so I read six public skill creators to see what they agreed on. A plugin is the top-level package. It can contain several skills, with each skill providing one reusable capability. A portable skill can also stand alone.

My quick recommendation

What makes a useful SKILL.md

The description does the routing

The agent often sees the skill name and description before it loads the full file. Write the description in the words a person would use when asking for help. Include the artifacts, symptoms, or tasks that should trigger the skill.

Also say when the skill should not run. If two skills both claim "GitHub help," the router has little reason to choose the right one. "Review a pull request" and "repair a failing GitHub Actions workflow" are easier to route.

A narrow description can carry both the positive and negative routing signals:

---
name: workflow-repair
description: Diagnoses and repairs failing CI workflows. Use for failed jobs, logs, or workflow YAML. Do not use for pull request reviews or feature development.
---

The main file stays lean

Put the instructions needed for most runs in SKILL.md. Move long examples, schemas, and domain references into files the agent can open when needed. Put repeatable or fragile operations in scripts.

A lean main file protects the shared context. Every line of background material competes with the task, conversation, and source files the agent also needs.

The main file can name the common path and disclose details only when needed:

---
name: release-notes
description: Drafts release notes from completed changes.
---

## Workflow

1. Identify user-visible changes.
2. Draft the summary.
3. Check [the style guide](references/style.md) when wording is unclear.
4. Run `scripts/check-notes.py` before returning the result.

The instructions match the risk

Some work needs judgment. Give the agent principles and room to choose. Other work must happen the same way every time. Give that work a script or a strict sequence.

The OpenAI creator frames this as choosing the right degree of freedom. I find that more useful than treating every skill as a prose prompt. If a missed step can damage data or publish the wrong thing, do not rely on the agent remembering a suggestion buried in a paragraph.

The skill defines a finish line

Say what the output should contain, how to represent partial success, and when to stop. Include the smallest question the agent should ask when it cannot continue safely.

Without a finish line, a skill can produce a plausible answer while skipping the check that mattered. "Update the file" is weaker than "update the file, run the existing validator, and report any failed checks without hiding them."

The finish line should make output, validation, and stopping conditions explicit:

## Finish

- Return the updated file and a short change summary.
- Run `scripts/validate.py`.
- Report every failed check; do not claim completion if validation fails.
- If the target file is unknown, ask for its path and stop.

Activation and execution get separate tests

A skill can work perfectly when you force the agent to use it and still fail in normal conversation because the description never attracts the right prompts.

Test both:

  1. Does the skill activate for several realistic requests?
  2. Does it stay out of nearby requests owned by another skill?
  3. Once selected, does it complete the task and produce the expected result?

Anthropic's creator is especially useful here because it treats skill authoring as a loop: draft, test, review the results, revise, and add the failures to the test set.

Microsoft and Azure skill examples

These Microsoft-owned repositories provide strong Agent Skill examples for Azure and developer workflows. They are not ranked by usage. Each one demonstrates a pattern worth borrowing:

A simple way to start

I would create the next skill in this order:

  1. Write three prompts that should activate it and three that should not.
  2. Draft the description from the words used in those prompts.
  3. Write only the instructions needed to complete the common path.
  4. Move reusable facts into references and deterministic work into scripts.
  5. Test routing and results separately, then revise from the failures.

The Agent Skills specification provides the portable base. Platform guidance, such as the GitHub Copilot agent skills overview, adds its own locations and runtime behavior. When skills are packaged in a plugin, keep plugin discovery and runtime rules separate from the portable skill instructions.

I came away with a practical test: can the agent find this skill from a normal request, and can it finish the work without guessing? If both answers are yes, SKILL.md is doing its job.

Maintaining AI Slop Over 2 Years

· 5 min read

Two years ago seems like decades in the world of AI. AI slop wasn't a term I was familiar with, and the project I started with AI was meant to be short-lived—a stopgap until systems and people caught up to support the work.

Woman on road littered with debris

Stage 1 - time-savings over process design

Because it was meant to be a short-term solution, I didn't care about the what or how as much as the output and time savings. I didn't spend much time on it and certainly didn't architect it in any meaningful way. It was a markdown file - a prompt.

Back then, there was little concern for context size and the only harnesses were custom-made or 3rd party like LangChain.

It read source code and output what I asked it to based on my ever-growing prompt file. I fiddled with it when I had time but usually just took the output and made manual edits as needed.

Stage 2 - shifting sands of source code

There were a few bumps in the road that caused the prompt file to sputter and halt. The related source code repo moved. That was just one place in the prompt file - an easy change. Then the source code repo completely refactored into a monorepo - that was much harder. The prompt file was looking at specific folders, files, classes and property names. A much bigger change to the prompt file. And of course, I still had other things to do.

Then the source project became much more popular and the feature set grew. Lots of changes and additions. This resulted in a short cycle of my wondering if AI, or my prompt file needed another rewrite.

At this point, I thought regex and a script might be faster. Leave any LLM decision/transition until later.

This was becoming an experiment in how to gain efficiency in a rapidly changing AI world.

Stage 3 - back to reality

While I was considering shifting to a code-based solutions, the source repo created a CLI to reveal its features. That was exactly what I needed: a dependable input to my process.

The AI SDKs had also progressed, so instead of regex and a script, I switched to .NET and the OpenAI SDK for chat completions. This time I designed the process deliberately, and Copilot Chat in VS Code was available, which helped accelerate development.

This time the architecture, project structure, maintainability, and testability were top considerations as I was still relying on this thing to help me.

There were a few iterations of this but it was beginning to hum along.

Stage 4 - the infrastructure

Since I only had the OpenAI resource in Azure, I kept it live and never shut it down. However, I used keys instead of managed identity—not because I didn't know the best practices, but simply because I lacked the time to implement them.

I was doing a lot of Bicep work, not an expert but not a newbie either, so cooking up the ./infra and azure.yml for Azure Developer CLI wasn't hard. Adding the RBAC roles for managed identity helped. And then finally I had that repeatable infrastructure I told everyone else they should have.

Stage 5 - monkey on the keyboard

The underlying project repo had matured significantly, the source code had stabilized, and my system was working well for its purpose too. However, as AI slop became an industry term, the underlying project matured alongside the industry specs it supported but my project had not.

I managed the project in chat one turn at a time, and the .NET app generated the output. However, every change to the system required several to many turns, redirections, and re-runs. AI kept making the same mistakes, and I spent my time minute by minute watching the output to see when it went off track. I needed a better process—a process to manage the process.

Stage 6 - hiring a squad

It was around this time I started working with Brady Gaster's Squad. Having a team of agents accelerated progress and caught issues and inconsistencies I hadn't been able to spot before. I onboarded Squad to the repo and had them take on much of the work.

Stage 7 - industry grows up

While I was learning Squad's inner workings, SKILL.md and agent.md specifications emerged. I dug into skills first to impose structure on my manual process management. I used WAZA and other frameworks to understand context size, triggers, and evaluations.

Building and maintaining skills locally gave me practical understanding of task boundaries, debugging, and chaining. Working with these units of AI many times a week gave me opportunities to fail.

Stage 8 - leaving Squad behind

Squad is an amazing build and maintenance platform. However, I need skills that succeed independently. The plugin specification is now available, so I took my chained skills, wrapped them in an orchestrating agent to manage gates between skills and human review, and packaged everything as a plugin.

Stage 9 - the agent and the app

What about the .NET app? It's now used only when the agent determines it needs that full pipeline. The agent and skills handle most of the work.

Conclusion

You'll likely continue to hear a lot about AI slop. Just like any industry, AI is maturing and developing better specifications and expectations. Look for them and try them out.

Focus on the fundamentals available at the time. Build with principles and practices that support them. Grow with industry specifications that enable better results.

From Natural Language to Autonomous Actions

· 12 min read

A pink-haired working with scientific equipment

You've built a workflow that works. But automating it requires engineering. Now you're stuck.

You know exactly how the process should run—you do it repeatedly, correctly, and it saves your team real time. But the moment you try to automate it, you hit a wall: write a script (and maintain it forever), hire engineers (and lose control to the project backlog), or give up and do it manually. None of these are wins.

There's a better way. What if you could capture your workflow in plain language, test it out, refine it, and gradually promote it to automation—keeping ownership the whole time? No developers required until you're absolutely sure the workflow is stable.

This is the progressive promotion model. Domain expertise starts as a natural language skill. You run it, refine it, test it. When repeated correct outcomes prove the flow is deterministic, the stable parts move behind MCP tools—reusable logic anyone can call. Then the skill can run autonomously. Ownership stays with the person who understands the process the whole time.


The automation tradeoff changed

The old tradeoff was simple: business value or engineering time. Only high-value workflows got built. Mid-tier work died in the backlog because no developer had bandwidth. The domain expert had to describe the process, hand it to a team, and wait months for the software to arrive.

This model shifts that cost to zero. The domain expert writes and runs the workflow in a skill right now, while they work. When the process proves reliable through repeated correct outcomes, the stable parts move behind MCP tools without a full rewrite. Cached tool definitions and typed contracts mean even small workflows can graduate.

The payoff is ownership. You hone your own process, keep control of your decisions, and run it yourself while it matures.


The four layers

Here is the path at a high level. The model puts each concern in its own layer. MCP stands for Model Context Protocol. In this post, an MCP tool is the typed interface that lets a skill, agent, or CI job call code in a predictable way:

LayerWhat it doesWho uses it
ScriptThe actual logic (API calls, file operations, data transforms)Everything below
MCP toolTyped interface around the script (JSON input → JSON output)Skills, agents, CI, other tools
SkillNatural language orchestration (when to call which MCP tool, in what order)Human-driven sessions
AgentAutonomous driver (same skill logic, but it decides when to run)Cron, webhooks, event triggers

The script is the logic. The MCP tool wraps it in a typed interface. The skill decides when to call which MCP tools. The agent runs the skill without you. Each layer has one job.

The key move: pull the script out of the skill and put it behind the MCP tool. Now any consumer can call it—another skill, an agent, a CI pipeline, an external system. The script is no longer locked inside one skill.

01 Script In Skill To Mcp Tool

The resulting stack looks like this:

02 Resulting Stack

The script gets written once, wrapped in a typed tool once, and then only the driver changes during promotion from interactive to autonomous.


How work naturally evolves

Start in natural language. Let the domain expert hone the process. Promote only after repeated correct outcomes prove the flow.

Here's how that progression works in practice:

A new skill starts with the LLM doing everything inline. Your instructions might say "query the GitHub API for recent releases, then compare against our changelog." The first version is written in plain language, not code. You stay in control.

Correctness matters more than speed here. You run the skill, adjust the instructions, and decide if the outcome matches your judgment. Repeat it several times until it consistently produces the right result.

Phase B: Determinism emerges

After a few runs, you spot a pattern. Step 2 is always the same. Same API call, same parsing, same output format. The LLM isn't adding judgment here—it's just following a mechanical procedure that you've already validated.

This is your signal to move. When the same API calls and parsing steps keep showing up, and the outcomes have been consistently correct, that part is ready to extract.

Phase C: Extract to MCP (not script-in-skill)

Now make the move. Extract the deterministic logic into a typed MCP tool instead of keeping it inside the skill. You still control the workflow through the skill. The stable, reusable part moves behind a typed interface.

03 Wrong Vs Right Path

The skill now calls detect_releases instead of embedding the logic. The MCP tool has a JSON input schema, a JSON output schema, and error handling. It's independently testable. Any consumer—another skill, an agent, a CI pipeline, or an external system—can call it.

Phase D: Promote to agent

When the process is reliable and you want it to run without you, promote to autonomous execution. The agent uses the same MCP tools. The only difference is who drives: you (interactive) or the agent (autonomous).

04 Phase C Phase D Promotion

The MCP server does not change. The tools do not change. The scripts do not change. Only the driver changes.


Where my first design stopped

My forty-skill portfolio showed me where this breaks if you stop too early. My original approach was:

  1. Write a skill (natural language instructions)
  2. Notice a pattern is deterministic (same inputs → same outputs)
  3. Extract that logic into a script inside the skill
  4. Done

The problem is step 4. The skill works. The script works. But only that skill can use it. No other skill can call it. No agent can use it. No CI pipeline can run it. When you need that logic elsewhere, you copy-paste the whole thing.

After forty skills, I had forty pieces of scattered process knowledge with scripts locked inside individual skills, no typed contracts, no reusability, and no clear path to autonomous execution. The scripts weren't going anywhere.

Why MCP tools instead of scripts-in-skills

The decision to extract into MCP rather than keep scripts inside skills comes down to three things:

Reusability

A script locked inside one skill is only callable by that skill. An MCP tool is callable by any skill, any agent, any CI pipeline, and any external system. Reuse changes everything.

Typed contracts

A script takes string arguments. An MCP tool has a JSON input schema and JSON output schema. The LLM knows exactly what to send and what to expect back. No parsing surprises.

Prompt caching

The cost reason is direct: MCP tool definitions live in the system prompt and get cached at a 50-90% discount. Every time you spawn an agent fresh, you lose that cache.

WhatCostCache
Skill instructions~0Part of system prompt (cached)
MCP tool definitions~400-1600Part of system prompt (cached)
Agent spawn~10-25K per runFresh context (uncached)

Using MCP tools instead of spawning fresh agents cut uncached tokens by roughly 90%.


The decision point

When you find yourself writing a script inside a skill, ask one question:

Will anything other than this skill ever need to call this logic?

  • If yes → extract to MCP immediately
  • If maybe someday → extract to MCP (future reuse is cheaper than a later move)
  • If truly never (one-off, will be deleted soon) → script-in-skill is fine

In my forty-skill portfolio, the answer was almost always yes.


What promotion looks like in practice

I have a content pipeline called Echo that detects new SDK releases, generates documentation metadata, and produces content reports. It started as a Squad agent spawning fresh context every time.

After extracting to MCP + skill:

BeforeAfter
~25K uncached tokens per run~1-2K uncached tokens per run
Squad agent spawned freshSkill in cached system prompt
Two separate context windowsOne cached context window
Scripts locked inside agentTools callable by anything

The scripts themselves didn't change. The structured JSON output envelopes they produced already matched MCP tool responses—same schema, different transport.

Before: Script → JSON file → next skill reads file from disk
After: Script → JSON → MCP protocol → any consumer gets it directly


The cost model across stages

Each stage changes the driver but reuses the same tools. Costs drop because the driver changes:

StagePer-run costDriverWhat saves
Skill + MCP~1-2K uncachedYou, interactivelyLowest token use. Tools cached. Only I/O is new.
Agent + MCP~5-10K uncachedAgent, autonomouslyAgent charter is fresh, but tools stay cached.
CI/CD0 tokensGitHub ActionNo LLM at all for deterministic steps.
Agent spawn (old way)~25K uncachedSquad coordinatorTwo fresh windows every time. Highest token use.

As work matures, it needs less LLM reasoning per run, until CI/CD needs none at all.


Context occupation cost of MCP

MCP tools have lower per-token cost when cached, but they occupy context window space every turn, even when unused. A 4-tool server adds ~600-1600 tokens to every conversation.

Control this with grouping and toggling:

StrategyHow it works
Group by workflowCombine related tools into one server (content-pipeline-mcp for all content work)
Toggle per taskEnable the server when doing that work, disable when doing something else
Skill as gatekeeperThe skill reminds you to enable MCP if it's off

The pattern: skill triggers workflow (zero idle cost) → skill activates MCP (cost only when needed) → tools do work (cached calls). The MCP stays enabled only when you're using it.


Running autonomously with Copilot CLI

Once a skill is promoted to an agent, the next need is running it without a human session. Copilot CLI supports this today:

# Simplest autonomous run
copilot -p "Run the echo pipeline" --yolo --silent

# With specific agent and model
copilot -p "Execute" \
--agent echo-pipeline \
--autopilot --no-ask-user \
--yolo --silent \
--model gpt-5.4

# Sealed sandbox: only specific tools available
copilot -p "Sync releases" \
--additional-mcp-config @workflows/echo-sync/mcp-config.json \
--available-tools='content-pipeline-mcp/*' \
--no-ask-user --autopilot --silent

The key flags:

FlagWhat it does
-p "prompt"Non-interactive mode (exits after completion)
--agent nameUse a specific .agent.md file
--autopilotAgent continues without asking permission
--no-ask-userDisable all user questions
--yoloApprove all tools, paths, and URLs
--available-tools='...'Only these tools exist (sealed sandbox)
--silentOutput only the agent's response

For CI/CD, authenticate with a fine-grained PAT:

COPILOT_GITHUB_TOKEN=github_pat_xxx copilot -p "Run pipeline" \
--agent echo-pipeline --yolo --silent --no-auto-update

The sealed sandbox

When something runs autonomously, the context must be fully specified at launch and locked in place. The agent gets exactly the tools it needs and nothing extra. The glass bell jar is boring on purpose.

A sealed sandbox manifest specifies:

  1. Identity: who the agent is
  2. Available tools: exhaustive list—nothing else exists
  3. Execution plan: exact steps, no deviation
  4. Error handling: complete rules, no improvisation
  5. Output routing: where results go
  6. Boundaries: hard constraints (violation = immediate exit)

Copilot CLI does this through --available-tools and the "tools" allowlist in MCP config. The MCP server might have twenty tools. The agent only sees three.

{
"mcpServers": {
"content-pipeline": {
"command": "node",
"args": ["./mcp-servers/content-pipeline/index.js"],
"tools": ["detect_releases", "generate_metadata", "analyze_impact"]
}
}
}

Similar progressions appear in other domains under different names:

SourceTheir patternMaps to this model
Anthropic, "Building Effective Agents"Start simple, increase complexityAugmented LLM → Workflows → Agents
Claude Agent SDKPermission modes as autonomy dialplanacceptEditsdontAsk
MCP Skills Working GroupProgressive disclosureTools → Skills → Agents
SAE J3016 (autonomous vehicles)L0–L5 autonomy levelsHuman-in-loop → human-on-loop → human-out-of-loop
SRERunbook → Automation → Self-HealingManual → scripted → autonomous
LangGraphinterrupt() architectureRemove interrupts = autonomous

The pattern exists in pieces across many domains. What was missing: a practical "Skill → MCP → Agent → CI" progression with extraction checklists and validation gates, tailored specifically for domain experts who want to keep ownership.


The rule I use now

When a process proves repeatable, reusable logic moves to an MCP tool. Scripts-in-skills are prototype code.

Ask three questions: Who owns this? How stable is it? What driver does it need now?

If the work is...Use...
Still being figured outSkill (cheap exploration)
Repeatable and deterministicMCP tool (reusable, typed)
Needs to run without youAgent (autonomous driver)
Fully deterministic, no judgmentCI/CD (no LLM at all)

What's next

Echo is the pilot. Once the content-pipeline MCP server wraps Echo's three scripts and the /echo-sync skill drives them interactively, validation has two parts: the process still produces the right output, and the token savings are real.

Then come Finn, the reporting tools, and the rest one by one.

The pattern is straightforward: Start with the person who owns the domain knowledge. Capture the workflow in a skill. Run it until the outcomes are consistently correct. Move the repeatable parts behind MCP tools. Change the driver only when autonomy helps.

Ownership stays with the person who understands the process. The system matures around that expertise.

CLI version

CLI examples written for GitHub Copilot CLI v1.0.77. Flag names and behavior may change in later releases.