TL;DR in plain English
- What changed: don't rely only on prompts to control an AI agent. Use an execution safety layer such as CTRLRun (the repo: https://github.com/CTRLRun/ctrlrun) to enforce runtime policies.
- Why it helps: it blocks disallowed external actions, creates a single audit trail for each run, and makes runs repeatable and reviewable for teams.
- Quick next steps: add a workflow (.github/workflows/ctrlrun.yml), drop a policy file (ctrlrun.yaml) in the repo, and run 3 sandbox tests before using protected branches.
Definitions (plain):
- CI = continuous integration (your automated build and test runner).
- API = application programming interface (how services and tools are called).
- MCP = registry pattern referenced on the project page (see: https://github.com/CTRLRun/ctrlrun).
Read time: ~30s. First-pass engineering time: ~120 minutes (2 hours).
Short scenario example:
- A small team wants a PR bot that can open pull requests but must never merge code without a human. You add ctrlrun.yaml to allow only create-branch and open-pr. You run 3 sandbox runs, review the audit file, then enable the workflow on protected branches with an approval gate.
What you will build and why it helps
You will add a CI step that runs an AI agent under an enforcement layer. That layer: only lets the agent call tools you allow, records each run in an audit file, and rejects forbidden actions at runtime.
Why this matters (concrete):
- Predictable tool use. The agent can only call connectors you map and permit.
- A single audit file per run. That file records decisions and tool calls for review.
- Safe rollout path. You can test in sandbox, then canary, then wider rollout with approvals.
Artifacts you will produce:
| Artifact | Purpose | Estimated time | |---|---:|---:| | .github/workflows/ctrlrun.yml | Runs the CTRLRun Action in CI | 15–30 minutes | | ctrlrun.yaml | Policy: tool allowlist and runtime limits | 10–20 minutes | | registry file | Maps logical tool names to connectors | 20–40 minutes | | connectivity script | Quick pre-flight check for secrets | 10–20 minutes |
Reference: CTRLRun project page and Action metadata: https://github.com/CTRLRun/ctrlrun
Before you start (time, cost, prerequisites)
Time and cost estimates:
- Initial setup: ~120 minutes (2 hours).
- Recommended test runs: 3 sandbox runs, then a 72-hour canary.
- CI minutes: budget ~500 CI minutes/month for modest usage (adjust to your plan).
Minimum prerequisites:
- A GitHub repo where you can add Actions and secrets.
- Repo admin or workflow-write permissions.
- A CI runner (GitHub-hosted or self-hosted).
- Familiarity with YAML and git.
- Short-lived API keys for external tools stored as secrets.
Permissions checklist to copy into your repo:
- [ ] Repo admin or workflow write access
- [ ] CI runner available and configured
- [ ] Secrets: TOOL_API_KEY, CTRL_RUN_TOKEN (or equivalent)
- [ ] Sandbox branch for the first 3 test runs
See the CTRLRun repo for the Action you will call: https://github.com/CTRLRun/ctrlrun
Step-by-step setup and implementation
Methodology note: this guide shows a minimal, safe path. Validate mappings and secrets in a sandbox before production.
Plain-language explanation (what happens when you run CTRLRun):
- The CI workflow checks out code and starts the CTRLRun Action.
- CTRLRun reads your policy (ctrlrun.yaml) and registry mappings.
- The agent runs inside this enforcement layer. Any tool call is checked against the allowlist. Allowed calls run through your configured connector. Disallowed calls are blocked and recorded in the audit file.
- Each run writes a structured audit (JSON) for review.
-
Inspect the CTRLRun repo and README to confirm an Action and example usage: https://github.com/CTRLRun/ctrlrun.
-
Add a policy file ctrlrun.yaml at the repo root. Keep it minimal at first.
# ctrlrun.yaml -- minimal example
tool_whitelist:
- create-branch
- open-pr
max_runtime_seconds: 300 # recommended starting value (300s = 5 minutes)
audit:
path: ./ctrlrun-audit.json
sample_rate: 0.10 # 10% verbose traces
- Add a GitHub Actions workflow that calls the CTRLRun Action. Keep the workflow timeout conservative.
name: ctrlrun-agent-check
on: [push, pull_request]
jobs:
run-agent:
runs-on: ubuntu-latest
timeout-minutes: 30 # fail fast during testing (30 minutes)
steps:
- uses: actions/checkout@v4
- name: Run CTRLRun agent
uses: CTRLRun/ctrlrun@main
with:
policy: ./ctrlrun.yaml
env:
CTRL_RUN_TOKEN: ${{ secrets.CTRL_RUN_TOKEN }}
TOOL_API_KEY: ${{ secrets.TOOL_API_KEY }}
- Add a short connectivity test to validate secrets before any real agent run.
#!/usr/bin/env bash
set -e
# connectivity-test.sh
curl -f -H "Authorization: Bearer $TOOL_API_KEY" https://api.example-tool.internal/v1/health || exit 1
echo "Connectivity OK"
- Run the workflow on a sandbox branch. Expect to iterate the policy based on audit output. Do 3 successful runs, then a 72-hour canary on a non-critical repo.
Reference for the Action and examples: https://github.com/CTRLRun/ctrlrun
Common problems and quick fixes
All fixes reference the repo for Action/usage examples: https://github.com/CTRLRun/ctrlrun
-
Problem: agent attempted a disallowed tool call.
- Fix: add the logical tool name to ctrlrun.yaml tool_whitelist and ensure your registry file maps that logical name. Block production runs until fixed.
- Threshold: unauthorized_tool_attempts > 0 => alert immediately.
-
Problem: workflow or agent times out.
- Fix: increase max_runtime_seconds (e.g., 300 → 600) and workflow timeout-minutes (30 → 60). Monitor avg_runtime_seconds and alert if > 2× baseline.
-
Problem: noisy audit logs or excessive storage.
- Fix: reduce audit.sample_rate from 0.10 to 0.02 (10% → 2%) and set a retention policy (retain 90 days).
-
Problem: authentication errors to external tools.
- Fix: re-check secrets (TOOL_API_KEY) in GitHub Settings, run connectivity-test.sh in CI, and replace expired credentials. Rotate keys every 30 days.
-
Problem: unexpected state change in production.
- Fix: immediately disable the workflow triggers, revoke tool credentials, and rollback. Use canary/approval gates next time.
Suggested alert thresholds to start with:
- failed_action_rate threshold: 1% (alert if >= 1%)
- unauthorized_tool_attempts: alert on > 0
- initial canary size: 5% of runs or 1 non-critical repo for 72 hours
See the CTRLRun repo for Action usage: https://github.com/CTRLRun/ctrlrun
First use case for a small team
Scenario: a solo founder or a small team (1–3 people) wants a safe PR-bot that opens PRs and triages issues but must never merge without human approval.
Concrete, low-friction advice (actionable):
- Minimal policy: start with two allowed actions: create-branch and open-pr. Deny merge and delete-branch explicitly in ctrlrun.yaml.
- Use a dedicated CI runner or a separate lightweight repo for testing. Run 3 sandbox executions, each under 5 minutes (max_runtime_seconds = 300), and inspect ./ctrlrun-audit.json after each run.
- Automate an approval gate: require 1 human approval for solo founders or 2 approvers for small teams before any run that targets protected branches.
- Limit credentials: use one short-lived API key per tool, rotate every 30 days, and store keys as secrets.
- Keep the initial registry tiny (<= 5 tools) and increase only after 72-hour canary success.
Team checklist (small teams / solo founders):
- [ ] Add ctrlrun.yaml with allowlist {create-branch, open-pr} and deny merge
- [ ] Add .github/workflows/ctrlrun.yml and connectivity-test.sh
- [ ] Run 3 successful sandbox executions (each <= 300s)
- [ ] Review ./ctrlrun-audit.json and confirm unauthorized_tool_attempts = 0
- [ ] Add an approval gate (1 approver for solo, 2 for teams) for protected branches
Rollout suggestion: 3 sandbox runs → 72-hour canary on a non-critical repo (5% traffic) → expand to 25% → full rollout if failed_action_rate < 1% and unauthorized_tool_attempts = 0.
Reference: CTRLRun repository and Action: https://github.com/CTRLRun/ctrlrun
Technical notes (optional)
Plain-language explanation before advanced details: the points below are for engineers who will tune production behavior. If you are following the minimal path, run the sandbox tests, read the audit file, and use the defaults until you need to change them.
Advanced topics and recommended thresholds. These assume you will read the project README and Action metadata: https://github.com/CTRLRun/ctrlrun
- Audit and retention: write structured JSON to ./ctrlrun-audit.json and retain logs for at least 90 days for incident investigation. Use sampling to limit storage (sample_rate 0.02–0.10).
- Registry mapping: use a short registry file (registry.yaml) that maps logical tool names to connectors. Start with <= 10 tools.
- Secrets and rotation: prefer short-lived keys, rotate every 30 days, and bind keys to least privilege.
- Runtime limits: set max_runtime_seconds per agent run (300s recommended initially). Increase to 600s only if necessary.
Example registry snippet (conceptual placement near ctrlrun.yaml):
# registry.yaml - minimal example
tools:
create-branch:
connector: git-connector-v1
open-pr:
connector: git-connector-v1
Metric examples to monitor:
- failed_action_rate target: < 1%
- unauthorized_tool_attempts: 0 (alert on >0)
- avg_runtime_seconds: baseline and alert if > 2× baseline
What to do next (production checklist)
Assumptions / Hypotheses
- CTRLRun provides a GitHub Action integration and documents usage on the project page: https://github.com/CTRLRun/ctrlrun.
- You will store policy (ctrlrun.yaml) in source control and use a registry mapping for tools.
- Hypothesis: 3 sandbox executions + a 72-hour canary will reduce unexpected production changes by a large fraction (>90%) for simple PR-bot workflows.
Risks / Mitigations
- Risk: Unauthorized tool call reaches production.
- Mitigation: require human approvals (1–2 approvers), disable workflows and revoke credentials on incident.
- Risk: Misconfiguration causes CI outages.
- Mitigation: run only in sandbox for 72 hours, then canary at 5% before full rollout.
- Risk: Audit logs grow too fast.
- Mitigation: use sampling (audit.sample_rate = 0.10 → 0.02) and keep 90-day retention; monitor log growth.
Enforced thresholds (examples):
- failed_action_rate < 1%
- unauthorized_tool_attempts = 0
- initial canary: 5% of runs or 1 non-critical repo for 72 hours
Next steps
- [ ] Add ctrlrun.yaml and .github/workflows/ctrlrun.yml to a sandbox branch (target time: 120 minutes)
- [ ] Run 3 successful test executions and inspect ./ctrlrun-audit.json
- [ ] Configure an approval gate requiring 1–2 approvers for protected branches
- [ ] Start a 72-hour canary on a non-critical repo (5% traffic) and track failed_action_rate and unauthorized_tool_attempts
- [ ] After canary success, roll policy to develop branches, then a small prod canary (25%) before full rollout
Useful reference and starting point: https://github.com/CTRLRun/ctrlrun