POLICY.md / Portable Agent Guardrails
You write the boundaries. Agents read them.
A portable, Markdown-native negative-capability manifest for AI agents.
$ git clone https://github.com/SidianLabs/POLICY.md.git
Not on npm yet. Run the CLI from a clone.
A manifest of rules in rows. Denied lines are struck out as solid bars; a reader passes down the file, the way an agent parses POLICY.md before it acts.
01 / What it is
A boundary you must respect.
POLICY.md is a portable way to tell an AI agent what it must not do, what it must ask before doing, and what is allowed. It is the negative-capability counterpart to SKILL.md.
Robots don't read README.md. They need deterministic rules of engagement, context boundaries, and executable constraints. POLICY.md is a working specification for declaring repository policies and constraints to autonomous agents.
- 1.1
SKILL.md= "here is an ability you can use" - 1.2
POLICY.md= "here is a boundary you must respect"
As agents gain tools that can write files, install packages, and call APIs, SKILL.md teaches abilities while POLICY.md enforces boundaries. It combines a human-readable Markdown body with machine-enforceable YAML frontmatter, supporting operators like 'eq', 'gt', and 'includes' across project, skill, or agent scopes.
The same file can be read by a human, understood by an LLM as system context, and enforced by a runtime engine.
Policy files are modular markdown documents that define operational constraints. They are stored in a .policy/ directory at the root of a project, or defined globally in your system directory (e.g., ~/.policy/) for cross-project rules. Agents parse these files before they are permitted to execute tools or propose changes.
- Title
- Machine-Readable Context
- Status
- Working Specification
- Format
- Markdown (.md)
- Version
- v0.2.0
---
version: 1.0
enforcement: strict
---
# Boundaries
- Agents MAY read any file in `src/`
- Agents MUST NOT modify files in `src/core/auth/` without human review
- Agents MUST NOT run `npm publish`
# Context
The system is built on Next.js App Router. Do not use the Pages router.
Always use Tailwind CSS for styling. Do not write custom CSS.
# Verification
Before proposing a PR, agents MUST run:
`npm run lint` and `npm test`A policy file in .policy/: frontmatter for the runtime, Markdown for people and models.
Capabilities
- 1.3Machine-enforceable YAML frontmatter + Markdown body
- 1.4allow / deny / require_approval actions
- 1.5Condition operators (eq, neq, gt, gte, lt, lte, includes, in, notIn, exists, notExists, wildcard)
- 1.6Scope targets: project, skill, agent, or department
- 1.7OpenAI Codex adapter (execpolicy + guardian prompt export)
- 1.8CLI for validate, check, read, init, install, sync, and list
02 / Three actions
Three words decide.
Every rule in the frontmatter names a capability and one of three actions. The Markdown body says the same thing for people, under three conventional headings.
- 2.1Most severe wins. When policies are combined, the runtime returns the most severe decision:
deny>require_approval>allow. - 2.2No match. If no rule matches, the default is
allow. The engine fails open.
| Rank | Decision | When combined |
|---|---|---|
| 1 | deny | Wins over both |
| 2 | require_approval | Wins over allow |
| 3 | allow | Least severe |
---
name: project-guardrails
description: Hard boundaries for this repo
version: 1.0.0
scope: project
appliesTo: [all]
rules:
- capability: file.write
action: deny
condition:
field: { path: 'payload.path', op: 'includes', value: '.env' }
reason: Never write .env or secret files
- capability: package.install
action: require_approval
reason: New dependencies need approval
- capability: npm.test
action: allow
reason: Tests can run without approval
---
## Forbidden
- Never commit `.env` files or any file containing secrets
- Never execute obfuscated shell commands
## Ask first
- Adding npm dependencies
- Modifying CI/CD pipelines
## Allowed
- Running `npm run typecheck` and `npm run test`
- Reading project documentationEach frontmatter rule has a twin in the body: deny under ## Forbidden, require_approval under ## Ask first, allow under ## Allowed.
Rules / From the docs example
| Action | Meaning | Body section | Example rule |
|---|---|---|---|
| deny | The agent must not do it. | ## Forbidden | file.write when payload.path includes .envNever write .env or secret files |
| require_approval | The agent must ask before doing it. | ## Ask first | package.installNew dependencies need approval |
| allow | The agent may do it. | ## Allowed | npm.testTests can run without approval |
03 / Condition operators
A rule applies when its condition holds.
A condition is exactly one of a field test, an and group, or an or group, and a field test uses one of twelve operators.
- 3.1Evidence. Twelve condition operators and
allow/deny/require_approvalare implemented inauthorizationEngine.ts(21 tests pass). See Claims & evidence. - 3.2Paths. Conditions read
payload.*,constraints.*,requester.*and built-ins such asrisk,capabilityandworkerId.
condition:
field: { path: payload.path, op: includes, value: .env }
condition:
and:
- field: { path: payload.amount, op: gt, value: 1000 }
- field: { path: constraints.environment, op: eq, value: production }
condition:
or:
- field: { path: workerId, op: eq, value: payment-bot }
- field: { path: specialist, op: in, values: [frontend, backend] }A field test, an and group and an or group.
| Group | Operators (12) |
|---|---|
| Comparison | eqneqgtgteltlte |
| Membership | includesinnotIn |
| Presence | existsnotExists |
| Pattern | wildcard |
04 / Scopes
Scopes stack. The most severe decision wins.
A policy targets one scope, set by scope in the frontmatter. Scopes stack: a skill policy can be stricter than its project policy, and the runtime combines them with the most severe decision winning.
A skill policy sits beside that skill's SKILL.md and holds its negative boundaries.
- 4.1Capability patterns.
file.writematches exactly,payment.*matches one segment,*matches every capability.
Frontmatter / Scope fields
| Field | Values | Default |
|---|---|---|
| scope | projectskillagentdepartment | project |
| appliesTo | Agent or skill ids; ["all"] means every agent. | ["all"] |
# .policy/POLICY.md (scope: project)
package.install require_approval
npm.test allow
# skills/deploy/POLICY.md (scope: skill)
package.install deny
# combined for package.install
denyIllustrative rules built from the docs example. The skill policy is stricter, so deny wins.
05 / Command reference
Ask the file before you act.
The policy CLI validates, checks, reads, scaffolds, installs, syncs and lists POLICY.md files. Everything it does is also available as a library.
The package is not published to npm yet. Until it is, run the CLI from a clone.
- 5.1Not on npm.
package.jsonexists at v0.2.0, but the package is not yet published. - 5.2
checkreturnsallow,denyorrequire_approvaland the rule that fired.
$ git clone https://github.com/SidianLabs/POLICY.md.git && cd POLICY.md
$ npm install && npm run build
$ node bin/policy.js --help$ node bin/policy.js check POLICY.md file.write --payload='{"path":".env"}'
deny rule file.write
Never write .env or secret files
$ node bin/policy.js check POLICY.md package.install
require_approval rule package.install
New dependencies need approval
$ node bin/policy.js check POLICY.md npm.test
allow rule npm.test
Tests can run without approvalChecking the docs example POLICY.md. The commands follow the reference below; the printed output is illustrative.
policy / 7 commands
| Command | Usage | What it does |
|---|---|---|
| validate | policy validate <path> [--strict] | Checks required fields, valid operators and YAML syntax. With --strict, unknown fields are rejected. |
| check | policy check <path> <capability> [--payload=<json>] [--agent=<id>] | Evaluates a capability against a policy without executing anything. Returns the decision and the rule that fired. |
| read | policy read <path> | Reads and prints the effective policy for a directory. |
| init | policy init <project> | Scaffolds a POLICY.md with default rules: no secret-file writes, approval for new dependencies, tests allowed. |
| install | policy install <owner/repo> [--dest=<dir>] | Pulls reusable guardrails from any GitHub repository. |
| sync | policy sync | Regenerates the AGENTS.md <policy_system> block so agent runtimes pick up current policies. |
| list | policy list | Lists every policy discovered in the working directory. |
06 / OpenAI Codex adapter
Export the boundaries to Codex.
The @sidianlabs/policy/adapters/codex module converts policies into OpenAI Codex-compatible formats.
- 6.1
toCodexExecpolicy(files)exports Starlarkexecpolicyrules. - 6.2
toCodexGuardianPrompt(files)exports Guardian LLM-judge prompt text. - 6.3Coverage. The adapter covers only
command.runandnetwork.*rules; other rule types are silently dropped.
import { toCodexExecpolicy, toCodexGuardianPrompt } from '@sidianlabs/policy/adapters/codex';
const execpolicy = toCodexExecpolicy(manager.list());
const guardianPrompt = toCodexGuardianPrompt(manager.list());Rules in, by capability / Illustrative
| Capability | In execpolicy and guardianPrompt |
|---|---|
| command.run | Exported |
| network.* | Exported |
| file.write | Silently dropped |
| package.install | Silently dropped |
07 / Use cases
Write it down once.
- 7.1Forbid agents from writing .env or secret filesdeny
- 7.2Require approval before adding new dependenciesrequire_approval
- 7.3Distribute reusable guardrails across teams and repos
- 7.4Inject policy context into agent system prompts
08 / Status and what it does not guarantee
It does not enforce itself.
POLICY.md is a Working Specification, version v0.2.0, with a working implementation and tests. The authorization engine is implemented in TypeScript with 21 vitest tests passing.
Read in full: the NON-GUARANTEES.md file in the repository, and the lab's non-guarantees and claims pages.
NON-GUARANTEES.md / Summary
Assumptions
- A.1A host runtime must call the authorization engine. POLICY.md does not enforce itself.
- A.2Write access to the policy file allows modification (no signature verification on installed policies).
Not guaranteed
- N.1Default behavior is fail-open (
allowwhen no rule matches). - N.2The OpenAI Codex adapter covers only
command.runandnetwork.*rules; other rule types are silently dropped. - N.3The specification is a working draft (v0.2.0), not a finalized industry standard.
- N.4The package is not yet published to npm.
09 / Evidence
Read the file.
No benchmark suite yet; the 21 tests reproduce with npm test in a clone. Status labels are never softened.