When running AI agents in CI pipelines, automated workflows, or other headless environments, interactive approval prompts are impossible. Rampart provides the ci.yaml policy preset to convert all approval-required operations into hard denies.
# Use the CI preset instead of standard
rampart init --profile ci
# Or copy to your policies directory
cp ~/.rampart/policies/ci.yaml ~/.rampart/policies/active.yaml
The ci.yaml preset is a strict variant of the standard policy:
| Standard Policy | CI Policy |
|---|---|
action: ask → native prompt |
action: deny |
action: ask (with audit: true) → dashboard |
action: deny |
| Package installs → approval | Package installs → blocked |
| Cloud uploads → approval | Cloud uploads → blocked |
| Persistence changes → approval | Persistence changes → blocked |
Problem: In CI, there’s no human to click “Allow” on Claude Code’s permission prompt. Without the CI preset:
action: ask rules hang forever waiting for inputaction: ask (with audit: true) rules poll the dashboard indefinitelySolution: The CI preset converts all interactive rules to denies. The agent completes (or fails fast) with no human intervention needed.
headless_only FlagFor fine-grained control, use headless_only: true in your ask rules:
policies:
- name: production-deploys
match:
tool: ["exec"]
rules:
- action: ask
ask:
audit: true
headless_only: true # ← blocks in CI, prompts interactively
when:
command_matches:
- "kubectl apply *"
message: "Production deployment requires approval"
How it works:
rampart serve, no TTY): Blocks with a denyThis lets you write one policy that works both locally (with prompts) and in CI (with denies).
Rampart considers a session “headless” when:
rampart serve is not running, ORYou can force headless mode with RAMPART_HEADLESS=1.
# .github/workflows/ai-agent.yml
jobs:
agent:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rampart
run: curl -fsSL https://rampart.sh/install | bash
- name: Configure CI policy
run: rampart init --profile ci
- name: Run agent
run: |
rampart wrap -- python agent.py
env:
RAMPART_HEADLESS: "1"
The built-in ci.yaml is intentionally strict. To customize:
# Create a custom CI policy based on the preset
cp ~/.rampart/policies/ci.yaml ~/.rampart/policies/ci-custom.yaml
Then edit ci-custom.yaml to allow specific operations:
# Allow npm install in CI (after the built-in deny rule)
policies:
- name: ci-allow-npm
priority: 0 # Higher priority than default rules
match:
tool: ["exec"]
rules:
- action: allow
when:
command_matches:
- "npm ci" # Deterministic installs only
- "npm install --frozen-lockfile"
Project policies (.rampart/policy.yaml in your repo) are loaded on top of the global policy. In CI:
ci.yaml) provides the strict baselineRAMPART_NO_PROJECT_POLICY=1 disables project policies if needed# .rampart/policy.yaml in your repo
version: "1"
policies:
- name: project-allow-specific-deploy
match:
tool: ["exec"]
rules:
- action: allow
when:
command_matches:
- "kubectl apply -f k8s/staging/" # Allow staging only
Even with denies, you want visibility. Run rampart serve in the background for audit collection:
- name: Start Rampart audit
run: |
rampart serve --background
- name: Run agent
run: rampart wrap -- python agent.py
- name: Upload audit
if: always()
uses: actions/upload-artifact@v4
with:
name: rampart-audit
path: ~/.rampart/audit/*.jsonl