{"slug": "the-governed-skills-registry-policy-as-code-for-enterprise-agent-capabilities", "title": "The Governed Skills Registry: Policy-as-Code for Enterprise Agent Capabilities", "summary": "A new governance framework for enterprise agent capabilities, the Governed Skills Registry, extends the Platform Planning Gateway to validate Claude Code skills against Rego policies before distribution. The system treats skills as semantic directives that must pass policy checks for versioning, description quality, and workflow compliance to prevent agents from bypassing execution governance. The companion repository adds a /validate_skill endpoint and skill-governance policy directory to enforce enterprise-valid skill distribution.", "body_md": "The [previous article](https://blog.owulveryck.info/2026/07/07/amplified-agentic-loop.html) closed the architecture of the Platform Planning Gateway: a proof of concept that governs *how* agents execute. Plans are linted against Rego policies derived from Architecture Decision Records, capability tickets constrain every tool call, and the smart tools verify the ticket before acting. The execution plane is governed.\n\nThere is a second plane that is not: the **capability plane**. Before an agent can plan or execute, it needs to know *what it can do*. In Claude Code, that answer arrives through **skills**: slash-command workflows that encapsulate reusable agentic patterns and make them invocable by any agent in the organization with a single `/skill-name`\n\ninvocation.\n\nSkills are the distribution unit of the agentic workforce. An enterprise that governs plans but leaves capabilities ungoverned has solved the wrong half of the problem: a well-governed plan built on a poorly-governed skill is still a risk.\n\nThis article asks: what makes a skill enterprise-valid? What policies must accompany it? How does a distribution mechanism (the skills equivalent of a package manager) enforce those policies? And how does the existing Platform Planning Gateway fit into the picture?\n\nThe companion repository [poc-agentic-platform](https://github.com/owulveryck/poc-agentic-platform) has been extended with a new `POST /validate_skill`\n\nendpoint and a `skill-governance/`\n\nRego policy directory. The patterns are the same ones established for plan governance; the domain shifts from execution to capability.\n\nA Claude Code skill is a `SKILL.md`\n\nfile. Its front matter is deliberately minimal:\n\n```\n---\nname: patch-payment\ndescription: \"Applies targeted changes to the payment service, following platform ADRs for proxy and migration ordering.\"\nversion: 1.0.0\nargument-hint: \"[description of the change]\"\n---\n\n# Skill body\n\nAnalyse the intent passed as $ARGUMENTS against the repository context.\nCall `get_platform_guidelines_for_intent` to retrieve the relevant ADR invariants.\nProduce a structured plan and submit it through `lock_in_plan` before using Edit.\n```\n\nSkills are discovered automatically from `~/.claude/skills/<name>/`\n\n(user-global) and `.claude/skills/<name>/`\n\n(project-local), and can be bundled inside plugins. They are not code: a skill is a **semantic directive**: natural language instructions that the agent interprets at invocation time. The model fills the business logic; the skill encodes the organizational invariants and workflow choreography.\n\nThe body is not documentation. It is the instruction set the agent executes literally when the skill is invoked. When a developer types `/patch-payment \"add idempotency key\"`\n\n, Claude reads the skill body and follows it step by step: it calls `get_platform_guidelines_for_intent`\n\nto retrieve the ADR invariants, it submits a structured plan through `lock_in_plan`\n\n, and it uses `Edit`\n\nto apply the changes. **The tools named in the skill body are the tools the agent will actually call at runtime.** Those tool calls are what the smart tools intercept and scope-check against the JWT capability ticket.\n\nThat semantic nature is precisely why governance matters. A skill that instructs the agent to modify files without going through `lock_in_plan`\n\nbypasses the execution governance entirely. As a reminder, `lock_in_plan`\n\nis the deterministic gate at the center of the [previous article’s Platform Planning Gateway](https://blog.owulveryck.info/2026/07/07/amplified-agentic-loop.html): before touching any file, the agent submits its plan as a structured JSON contract; OPA/Rego policies reject non-conforming plans with semantic violations, and conforming plans receive a signed capability ticket that scoped tools verify in-tool. A skill distributed without a version cannot be audited or rolled back. A skill with a 10-character description is invisible in `/help`\n\n. These are not implementation bugs: they are governance gaps.\n\nA skills APM (Application Package Manager) does the right things: versioning, discovery, installation, dependency resolution. These are hard problems and the existing ecosystem solves them well.\n\nWhat an APM cannot see:\n\n`SKILL.rego`\n\n) that the plan linter can load at `lock_in_plan`\n\ntime to enforce those requirements automatically.These gaps are not APM failures: they are governance responsibilities the APM was never designed to carry. The solution is a **policy layer on top of the APM**: a skill governance linter that validates every skill before publication, and optionally at install time.\n\nAside: Microsoft APM — a concrete implementation\n\n[Microsoft APM](“like npm for agent context”) is the closest existing project to what this article calls “a skills APM.” It handles exactly the distribution concerns described above: a single`apm.yml`\n\nmanifest installs skills, MCP servers, and agent definitions across Claude Code, GitHub Copilot, Cursor, and several other harnesses. A lockfile pins content hashes for byte-for-byte reproducibility. An`apm-policy.yml`\n\nenforces enterprise → org → repo tighten-only inheritance at install time, and`apm audit --ci`\n\nruns as a mandatory CI gate on pull requests.That is a strong foundation. Where it stops is precisely where the Skill Linter starts. APM’s\n\n`apm-policy.yml`\n\nis apackage-levelpolicy: it governs which packages are allowed or blocked, which MCP servers can be declared. It does not inspect the content of a skill’s body. It cannot classify a skill by security tier (see below), require a companion Rego file for file-modifying skills, or check whether the skill’s instructions contradict an active ADR. Those are semantic questions about what the skillinstructs the agent to do: a dimension the distribution layer was never designed to reach.The two layers are complementary, not competing. APM is the right choice for distribution, integrity, and package-level policy. The PPG\n\n`POST /validate_skill`\n\nendpoint is the semantic gate APM can call (in CI before publication, or as an install hook) to enforce the governance policies that live above the package boundary. Together, they cover the full chain: APM ensures the right packages arrive intact; the Skill Linter ensures they deserve to.One more nuance: APM’s git-source model (GitHub, GitLab, Azure DevOps, Bitbucket) maps to the\n\nrepositorylayer described in the next section. The authoritative install source that APM points consumers at is theregistry. The`apm-policy.yml`\n\ngovernance operates at the registry-install boundary, which is exactly where the Skill Linter gate belongs.\n\nBefore describing the governance architecture, it is worth establishing two concepts that the software ecosystem has kept distinct for decades but that the skills world often collapses into one.\n\nA **skill repository** is any Git source: a GitHub repository, a GitLab project, an internal Bitbucket server. It is where skills are authored and versioned. Multiple repositories can coexist: a platform team’s internal repo, an open-source community repo, a vendor-published repo. A repository carries no inherent authority: it is a source, not a trust boundary.\n\nA **skill registry** is the enterprise’s authoritative catalog: the single source that agents and APMs install *from*. A skill enters the registry only after passing the policy gate. The registry maintains provenance (which repository a skill came from, which version, which policy approved it) and a **dependency graph**: a skill can declare dependencies on other skills or on specific MCP servers, and the registry validates that all transitive dependencies are themselves registered and approved before the skill can be installed.\n\nThe npm analogy is exact: a GitHub repository is where you write and commit code; npmjs.com is the registry you publish to and that others install from. The `npm publish`\n\nstep (and the policy checks that can gate it) is the governance boundary. The same structure applies here: `git push`\n\nlands the skill in a repository; the CI-triggered Skill Linter validates it; a passing validation promotes it to the registry.\n\nThis separation has two important consequences:\n\n**Decentralization is a feature at the repository level.** Any team, any open-source project, any vendor can author and version skills in their own repository. The ecosystem grows without central coordination.\n\n**The registry is the trust boundary.** Only skills that have passed the Skill Linter enter the registry. Consumers (developers, agents, CI pipelines) install from the registry, not directly from repositories. The dependency graph in the registry ensures that a skill cannot pull in an unapproved transitive dependency: every node in the graph was independently validated.\n\nThe governance gate (`POST /validate_skill`\n\n) sits precisely at the boundary between repository and registry. This is the point at which the policy questions the APM cannot answer (security tier, companion Rego requirement, ADR alignment, structural quality) are answered deterministically, before any installation can occur.\n\nThese rules are always enforced, regardless of what the skill does:\n\n| Field | Constraint | Nature |\n|---|---|---|\n`name` |\nlowercase-kebab-case, ≤ 32 characters | amplifier |\n`description` |\n50–500 characters, starts with a verb | amplifier |\n`version` |\nsemver, required for registry publication | amplifier |\n`argument-hint` |\nrequired when body uses `$ARGUMENTS` |\namplifier |\n| Body length | ≤ 500 lines, no hardcoded secrets | amplifier |\n| Companion Rego | required for tier ≥ 1 skills | amplifier |\n\nAll structural rules are tagged `amplifier`\n\n: they enforce durable SDLC invariants that become *more* valuable as the model improves, not less.\n\nThe tier is derived from the tools the skill instructs the agent to use:\n\n| Tier | Trigger | Publication gate |\n|---|---|---|\n0 — Read-only |\nBody mentions only Read, Glob, Grep | Auto-approved by Rego |\n1 — Standard |\nBody mentions Edit or Write → file modifications | CI + Rego validation |\n2 — Privileged |\nBody mentions Bash → shell commands | Human review required |\n\nThe tier is not a prediction; it is a direct consequence of what the body instructs. Because the agent executes the body literally, a body that says `Edit`\n\nwill produce file modifications and a body that says `Bash`\n\nwill execute shell commands. This is why the linter classifies on tool mentions: deliberately binary, keyword-based, blind to intent. A skill that *could* be safe but mentions `Bash`\n\nis tier 2 regardless, for the same reason the plan linter is not an LLM: determinism and reproducibility take priority over nuance.\n\nThe insight from the previous article applies directly here. An ADR in the Platform Planning Gateway is a **dual-representation governance artifact**: its Markdown body (the semantic directive) is injected at `enrich()`\n\ntime into the agent’s planning context; its companion `.rego`\n\nfile is evaluated deterministically at `lock_in_plan`\n\ntime by the plan linter.\n\nA skill with programmatic enforcement follows the same pattern:\n\n| Representation | File | Consumed by | Moment |\n|---|---|---|---|\n| Semantic directive | `SKILL.md` body |\nAgent at invocation | Planning |\n| Governance policy | `SKILL.rego` companion |\nSkill Linter at publish + Plan Linter at lock_in_plan | Validation |\n\nThe skill’s `SKILL.rego`\n\nserves two distinct purposes:\n\nThis is the durability axis applied to capabilities: the semantic directive is a permanent amplifier (the skill instructions get more useful as the model improves); the Rego companion may be compensatory scaffolding (required today because the model does not yet reliably honor the invariant without enforcement, but removable once it does). Note that the two durability tags live at different levels and do not conflict: the structural rule *requiring* a companion Rego for tier ≥ 1 skills is an amplifier (the obligation to declare enforceable requirements ages well), while the *content* of a particular companion Rego may be compensatory and carry its own sunset condition.\n\nThree gates validate a skill before and during use. Each addresses a distinct failure mode.\n\nThe Skill Linter is a new endpoint on the Platform Planning Gateway: `POST /validate_skill`\n\n. A skill author pushes `SKILL.md + SKILL.rego`\n\nto a skill repository (any git host); CI triggers the linter. The endpoint receives the skill’s metadata and body (and optionally its companion Rego content), evaluates them against the governance policies in `skill-governance/`\n\n, and returns either `SKILL_VALID`\n\nwith the computed security tier or `SKILL_REJECTED`\n\nwith structured violations. Only a passing skill is promoted to the authoritative registry.\n\nEvery violation carries a `nature`\n\nfield: the same `amplifier`\n\n/ `compensatory`\n\ntagging used for plan policies. This makes the violation actionable: an amplifier violation must be fixed because the rule is a durable invariant; a compensatory violation signals scaffolding that the author can accept now and schedule for removal later.\n\nThe publish sequence:\n\nWhen a consumer installs a skill from the registry (using `apm install`\n\nor equivalent), the PPG re-runs the validation. Two distinct threats live at this boundary, and they call for two distinct defenses. Tampering (a skill modified in the registry after publication) is a job for content hashes: APM’s lockfile already pins each package byte-for-byte, and the registry records the approved hash at publish time; revalidating the content is redundant with verifying the hash. What revalidation uniquely catches is *policy drift*: the governance policies may have been tightened since publication, and a skill that passed last quarter’s rules may fail today’s. Install-time revalidation is therefore the last structural check before the skill enters a project’s `.claude/skills/`\n\n.\n\nThe third gate is the existing `POST /lock_in_plan`\n\nmechanism, extended. When the agent submits a plan that originates from a skill invocation, it can include the `skill_id`\n\n. The Plan Linter loads the base ADR policies (the existing `adr/*.rego`\n\nfiles) *and* the skill’s companion `SKILL.rego`\n\nfrom the policy store, evaluating the union of all violation rules against the plan.\n\nThis is the runtime sequence:\n\nThe result: a skill-invoked plan is held to both the organizational ADR invariants *and* the skill-specific plan requirements. A `/patch-payment`\n\nskill can require, in its companion Rego, that any resulting plan include a `go test`\n\nstep, on top of the ADR-060 requirement that already enforces this for all Go plans. The governance rules compose without coupling.\n\nOne scoping note for the honest reader: the PoC implements Gate 1 end to end (`POST /validate_skill`\n\n, replayable against the repository); install-time revalidation (Gate 2) and the `skill_id`\n\nwiring at `lock_in_plan`\n\n(Gate 3) are the documented production path, tracked in the repository’s `AUDIT.md`\n\n.\n\n`/validate_skill`\n\nThe [poc-agentic-platform](https://github.com/owulveryck/poc-agentic-platform) now exposes:\n\n```\nPOST /validate_skill\n```\n\nRequest body (JSON, mirrors the `Skill`\n\nstruct):\n\n```\n{\n  \"name\": \"patch-payment\",\n  \"description\": \"Applies targeted changes to the payment service, following platform ADRs for proxy and migration ordering.\",\n  \"version\": \"1.0.0\",\n  \"argument_hint\": \"[description of the change]\",\n  \"body\": \"Analyse the intent... Use Edit to patch...\",\n  \"rego_policy\": \"package ppg.skills.patch_payment\\nimport rego.v1\\n...\"\n}\n```\n\nResponse on failure:\n\n```\n{\n  \"status\": \"SKILL_REJECTED\",\n  \"violations\": [\n    {\n      \"field\": \"rego_policy\",\n      \"message\": \"Skills that instruct file modifications (tier ≥ 1) must include a companion SKILL.rego declaring their plan governance requirements.\",\n      \"nature\": \"amplifier\"\n    }\n  ],\n  \"guidance\": \"Fix the violations above before publishing the skill to the registry.\"\n}\n```\n\nResponse on success:\n\n```\n{\n  \"status\": \"SKILL_VALID\",\n  \"tier\": 1\n}\n```\n\nThe `internal/skill`\n\npackage follows exactly the same pattern as `internal/linter`\n\n: a `NewLinter(governancePolicyDir string)`\n\nconstructor loads all `.rego`\n\nfiles from `skill-governance/`\n\ninto a single OPA `PreparedEvalQuery`\n\nover `data.ppg.skills.governance.violation`\n\n; `Validate(*Skill)`\n\nevaluates the query and unmarshals violations; `Tier(*Skill)`\n\ncomputes the security tier in Go (keyword-based, deterministic).\n\nThe governance policies live in two Rego files that share `package ppg.skills.governance`\n\n:\n\n`skill-governance/structure.rego`\n\n— structural rules: name format, description length, version, argument-hint`skill-governance/security.rego`\n\n— security rules: companion Rego required for tier ≥ 1All rules are `violation contains v if {...}`\n\n: the same OPA pattern as the plan linter. Adding a new governance rule is adding one Rego rule to an existing file or a new file in the directory; no Go code changes required.\n\nThe transition-debt report (`GET /debt_report`\n\n) currently tracks plan linter policies and smart tool translators. The same model applies to skills:\n\n`@deprecated`\n\nannotations reliably.Every compensatory skill should carry a `sunset_condition`\n\nin its companion Rego, making the retirement debt explicit and measurable. The governance rules do not enforce this today; it is the next natural extension of the structure rules once the organization has enough skills in production to make the debt visible.\n\nNothing in this architecture is specific to Claude Code. The governance rules, the Rego policy files, and the three-gate validation model apply to any skill runtime that:\n\nThe Claude Code specifics (the `SKILL.md`\n\nfront matter, the `/skill-name`\n\ninvocation, the `PreToolUse`\n\nhook) are the adapter layer. The governance model is the invariant.\n\nThis remains a proof of concept, and the same honesty that closed the previous article applies here. Keyword-based tier classification can be evaded by paraphrase: a body that says “run the migration from the terminal” without naming `Bash`\n\nclassifies as tier 0 today. The production posture is deny-by-default: any tool mention outside the known read-only allowlist (including unknown MCP tools) escalates the tier, and a body with no recognizable tool mention is treated as unclassifiable, not as safe. There is also a version-skew window at Gate 3: the agent executes the locally installed `SKILL.md`\n\nwhile the Plan Linter loads the companion `SKILL.rego`\n\nfrom the registry. The two must be pinned together (the registry serves the Rego of the *installed* version, identified by the content hash recorded at publication), or a stale skill would run under mismatched plan rules. Neither gap invalidates the architecture; both map the path from proof of concept to production.\n\nThe [Platform Planning Gateway](https://github.com/owulveryck/poc-agentic-platform) governs the execution plane. Skills governance closes the capability plane. Together they form a coherent answer to the question that opened the series in [See, Act, Correct](https://blog.owulveryck.info/2026/06/04/see-act-correct-three-levers-for-working-with-a-code-agent.html): how do we move from individual vibe coding to industrialized, at-scale software engineering?\n\nThe execution plane says: *every action the agent takes was planned, the plan was linted, and the scope is enforced in-tool.*\n\nThe capability plane says: *every workflow the agent can invoke was authored according to documented rules, validated by a deterministic policy engine, and published through a gated distribution channel.*\n\nNeither plane alone is sufficient. An ungoverned capability can produce a governed plan and still cause harm: the governance happened too late. A governed capability without execution governance produces a correctly packaged skill that an agent uses to take ungoverned actions: the governance stopped too early.\n\nThe guardrail is the loop. Skills governance and plan governance are two iterations of the same pattern applied to two consecutive moments in the agentic cycle. The next iteration (observation, the third pillar explicitly deferred from the previous article) closes the loop: structured, semantic feedback from execution back into planning, making each cycle smarter than the last.\n\nLet’s make AI work in your organization.", "url": "https://wpnews.pro/news/the-governed-skills-registry-policy-as-code-for-enterprise-agent-capabilities", "canonical_source": "https://blog.owulveryck.info/2026/07/08/governed-skills-registry.html", "published_at": "2026-07-08 08:00:00+00:00", "updated_at": "2026-07-10 09:17:17.986609+00:00", "lang": "en", "topics": ["ai-agents", "ai-policy", "ai-tools", "developer-tools"], "entities": ["Claude Code", "Platform Planning Gateway", "Rego", "OWulveryck"], "alternates": {"html": "https://wpnews.pro/news/the-governed-skills-registry-policy-as-code-for-enterprise-agent-capabilities", "markdown": "https://wpnews.pro/news/the-governed-skills-registry-policy-as-code-for-enterprise-agent-capabilities.md", "text": "https://wpnews.pro/news/the-governed-skills-registry-policy-as-code-for-enterprise-agent-capabilities.txt", "jsonld": "https://wpnews.pro/news/the-governed-skills-registry-policy-as-code-for-enterprise-agent-capabilities.jsonld"}}