Skills are the "npm moment" for AI agents. Instead of copy-pasting the same instructions into every session, you install a skill once. The agent loads it when relevant. Clean. Efficient. Reusable.

The catch: most implementations rely on the AI to decide when a skill is relevant. That decision is probabilistic. Sometimes it works. Sometimes it doesn't. Users report activation rates as low as 20%.

Let's talk about what AI agent skills are, why auto-activation is hard, and what we're building in Octomind to make it deterministic.

What Are Agent Skills, Exactly?

A skill is a folder with a SKILL.md file. That file has two parts:

  1. Metadata (frontmatter) — name, description, when to use
  2. Body (markdown) — the actual instructions the AI follows
yaml
---
name: programming-rust
title: 'Rust Development'
description: 'Rust conventions, idiomatic patterns, cargo tooling.'
---
## Conventions
[... the actual instructions ...]

When the AI decides this skill is relevant, it reads the full SKILL.md into context. The instructions become part of the system prompt for that task.

This is progressive disclosure: load metadata upfront (cheap), load full content only when needed (expensive). With 20 skills, you might have 1,000 tokens of metadata at session start instead of 20,000 tokens of full instructions. The AI only pays for what it uses.

The Auto-Activation Problem

This is where it breaks down.

Current tools — Claude Code, OpenAI Codex, others — use the skill's description for pattern matching. The AI reads all descriptions at session start. When your message seems relevant to a description, the AI loads that skill.

Sounds reasonable. But "seems relevant" is probabilistic.

The AI doesn't follow deterministic rules. It makes a judgment call based on semantic similarity between your message and the skill description. Sometimes that works great. Other times:

  • You mention "rust" in a sentence, and the skill doesn't activate
  • You ask about memory safety, and it fires the Rust skill even though you're working in Go
  • You explicitly ask for a skill, and it still doesn't load

Reddit threads and blog posts are full of workarounds. Hooks that detect trigger words. Explicit slash commands. Adding example prompts to skill descriptions to improve odds. One engineer reported getting activation from 20% to 84% by rewriting descriptions and adding trigger instructions.

84% is better than 20%. But it's still not 100%. And it requires constant tuning.

The Deeper Problem: LLMs Ignore Instructions

The uncomfortable truth: even when you explicitly tell an LLM to do something, it might not do it.

Research on instruction following reveals troubling patterns. A 2024 paper from OpenAI introduced the "instruction hierarchy" problem — LLMs often treat system prompts (from developers) with the same priority as user messages, leading to inconsistent behavior when instructions conflict [source]. Another study found a 39% performance drop in multi-turn conversations. Meta-cognitive instructions like "check yourself" and "verify"? They're "the first to fall" [source].

The "Curse of Instructions" research shows that as you add more instructions, adherence drops. Models can follow one directive reliably. Ten? Much harder.

So when skill auto-activation relies on the AI noticing a skill is relevant and deciding to load it, you're stacking probabilities:

  1. Probability the AI recognizes relevance (semantic match)
  2. Probability the AI follows through (instruction adherence)
  3. Probability nothing else in context distracts it

Multiply those together and you get 20-84% activation rates. The AI isn't being difficult; this is how these models work. Attention is finite, instructions compete, and things get lost in the noise.

This is where deterministic systems win. A file check doesn't get distracted. A string match doesn't forget. The rules evaluate the same way every time.

What We're Building in Octomind

We're taking a different approach: declarative activation rules.

Instead of relying on the AI to decide, you define explicit rules in the skill's frontmatter. The system evaluates these rules deterministically — no AI judgment involved.

yaml
---
name: programming-cpp
title: 'C++ Development'
description: 'Modern C++ conventions, RAII, smart pointers, CMake.'
domains: developer
rules:
  - file(CMakeLists.txt)
  - file(meson.build)
  - content(c++)
  - content(cpp)
---

The rules field is the key. Each line is an OR-group. If any group matches, the skill activates. Within a line, space-separated checks are AND.

So this skill activates if CMakeLists.txt exists in the project, or meson.build exists, or the user mentions "c++" or "cpp" in their message.

The evaluation is deterministic. The system checks file existence, content matches, environment variables — all in-process, no AI involved. If the rule matches, the skill loads. Period.

How the Rules Work

The check types:

CheckExampleWhat it does
file(pattern)file(Cargo.toml)File or glob exists in working directory
content(word)content(rust)Case-insensitive word match in user message
grep(pattern)grep(fn main)Search file contents in project
env(VAR)env(CI)Environment variable is set
bin(name)bin(cargo)Executable exists on PATH
workdir(pattern)workdir(rust)Working directory path contains pattern

You can combine them:

yaml
rules:
  - content(rust) file(Cargo.toml) # mentions rust AND Cargo.toml exists
  - file(go.mod) # OR: go.mod exists

The system evaluates rules on every user message. Already-active skills are skipped. No redundant loading.

Domain Scoping

There's another piece: domains.

yaml
domains: developer devops

This limits which agents even check this skill's rules. A "developer" agent checks skills with domains: developer. A "writer" agent doesn't.

Why does this matter? If you have 50 skills across development, writing, research, design — you don't want every agent checking every skill's rules on every message. Domain scoping reduces the pool to relevant skills only.

Skills without domains are manual-only. They never auto-activate.

Why This Matters

Two things happen when auto-activation is deterministic.

Predictability. You know when a skill will load. If Cargo.toml exists in your project, the Rust skill activates. If you type "help me with c++", the C++ skill activates. No guessing. No 20% vs 84% tuning.

Token efficiency stays intact. Progressive disclosure still works — metadata loads at session start, full content loads only when rules match. But the matching doesn't burn tokens on AI judgment calls. It's a file check. A string match. An environment variable lookup. All deterministic.

There's a third benefit too. Research on "needle in a haystack" retrieval shows that as context grows, LLMs struggle to find relevant information buried in the middle — accuracy drops significantly for long contexts [source]. This is one face of context rot. By keeping irrelevant skills out of context entirely, you reduce the haystack. The AI doesn't have to find what isn't there.

The goal isn't to replace AI decision-making entirely; deterministic vs probabilistic AI is a division of labor, not a contest. The AI still decides how to use the skill once it's loaded. But the when? That's declarative.

What's Next

This shipped in Octomind 0.29.0. The skill system is part of our tap architecture — skills live in Git repositories (taps), distributed alongside agents and capabilities.

If you're building with AI agents and have hit the auto-activation reliability problem, this approach should feel familiar. The idea is simple: let the AI do what it's good at, and handle deterministic work with deterministic logic. (The same philosophy now drives our AI agent guardrails.)


Skills shouldn't be a guessing game. If your project has Cargo.toml, you're writing Rust. The AI doesn't need to infer that — and with the right rules, it won't have to.