Runtime Engine
Policies are Markdown files, but enforcement happens in code. The runtime loads every POLICY.md in scope, evaluates intents against all of them, and returns the most severe decision.
Note: the
@sidianlabs/policypackage is not on npm yet — run the CLI from a clone (npm install && npm run build, thennode bin/policy.js).
The pieces
| Module | File | Job |
|---|---|---|
PolicyManager | src/policyManager.ts | Discovers, loads, and lists policies |
AuthorizationEngine | src/authorizationEngine.ts | Evaluates one intent against one policy set |
PolicyValidator | src/validate.ts | Schema, operator, and YAML checking |
Installer | src/installer.ts | Pulls policies from GitHub repos |
AgentsMd | src/agentsmd.ts | Regenerates the AGENTS.md policy block |
Parser | src/parser.ts | Frontmatter + Markdown body parsing |
Codex adapters | src/adapters/codex.ts | Exports to OpenAI Codex formats |
Load and evaluate
import { createPolicyManager } from '@sidianlabs/policy';
const manager = createPolicyManager();
manager.load(); // searches working dir for POLICY.md files
const engine = manager.createAuthorizationEngine();
const decision = engine.evaluate({
id: '1',
workRunId: 'run-1',
workerId: 'agent-1',
specialist: 'frontend',
actionType: 'tool',
capability: 'file.write',
riskLevel: 'medium',
payload: { path: 'src/.env' },
requester: { type: 'user', id: 'user-1' },
createdAt: Date.now(),
});
// decision.action === 'deny'
// decision.reason === 'Never write .env or secret files'Inject into system prompts
Policies double as LLM context - the agent reads the same rules the engine enforces:
import { buildPoliciesContext } from '@sidianlabs/policy';
const prompt = buildPoliciesContext(manager);
// prepend to the agent system promptComposite engines
Stack an org policy over a repo policy. The composite returns the most severe decision across every engine:
deny > require_approval > allowimport { createCompositeAuthorizationEngine, createAuthorizationEngine } from '@sidianlabs/policy';
const filePolicyEngine = manager.createAuthorizationEngine();
const orgPolicyEngine = createAuthorizationEngine({ document: orgPolicy });
const final = createCompositeAuthorizationEngine([orgPolicyEngine, filePolicyEngine]);
const result = final.evaluate(intent);Validation
PolicyValidator checks required fields, valid operators, and YAML syntax. With --strict, unknown fields are rejected:
npx @sidianlabs/policy validate POLICY.md --strictDistribution: install and sync
# Pull a team's guardrails into .policies/
npx @sidianlabs/policy install SidianLabs/payment-guardrails
# Regenerate the AGENTS.md <policy_system> block
npx @sidianlabs/policy sync
# See every discovered policy
npx @sidianlabs/policy listOpenAI Codex adapters
Export policies to the formats Codex understands:
import { toCodexExecpolicy, toCodexGuardianPrompt } from '@sidianlabs/policy/adapters/codex';
// Starlark execpolicy for the Codex runtime
const execpolicy = toCodexExecpolicy(manager.list());
// Guardian prompt text for the Codex harness
const guardianPrompt = toCodexGuardianPrompt(manager.list());Scope stacking
Discovery order is project, then named directories (.policies/payment/), then skill-local files (.devin/skills/<skill>/POLICY.md). A skill policy can be stricter than its project policy; evaluation combines all in-scope policies with most-severe-wins, so a skill-local deny always beats a project-level allow.