Skills

There is no skills field in any of the three request surfaces. Nothing in the Anthropic Messages API, the OpenAI Responses API or Chat Completions carries a list of an agent’s skills.

That is worth saying first, because it bounds everything below.

What the firewall can see

A dispatching tool. Claude Code exposes skills through a tool named Skill, whose input schema enumerates the available skill names. The firewall reads that enum and records each name — marked inferred, because it is a read of a schema’s shape rather than of a documented field. A client that presents skills differently produces nothing here.

An invocation. When a skill actually runs, it appears in the replayed conversation as a tool_use block naming the dispatcher and the skill:

{ "type": "tool_use", "name": "Skill", "input": { "skill": "deploy" } }

That is exact. Those rows are recorded as invoked, and it is the one place skills are visible as fact rather than as a guess.

The deterministic control

If you need certainty, do not govern the skill. Govern the tool that dispatches it:

vulnetix ai-firewall policy guardrail no-skills \
  --rule-type tool_deny --action strip --pattern 'Skill' \
  --priority 100 --enable

strip removes the dispatcher from the request. Without it the model has no route to any skill, whatever the schema said. This is a real boundary, it costs granularity, and it is honest about which it is.

Skill rules

skill_deny and skill_allow match against the names above:

vulnetix ai-firewall policy guardrail no-deploy-skill \
  --rule-type skill_deny --action block --pattern 'deploy' \
  --priority 100 --enable

They accept block and flag only. strip is rejected, and that rejection is deliberate: a skill is a value inside another tool’s schema, so there is nothing to remove from a request array. Accepting strip would give you a rule that stored cleanly, showed as enabled in the dashboard, and enforced nothing — the failure this whole product treats as worse than an outage.

If a strip reaches the engine on a skill rule anyway, it is escalated to block rather than silently skipped.

What to actually do

For most organisations the useful posture is:

  1. Run with no skill rules and read the inventory for a fortnight.
  2. If skills appear that should not, and the set is stable, write skill_deny rules at flag, then block.
  3. If you need a hard guarantee rather than a good control, strip the Skill tool and accept that you have removed the feature.

Treat skill rules as advisory-grade. They are built on a convention, that convention will change as clients evolve, and this page will say so when it does.