checkrd

Recipes

Real-world workflows — kill switch on alert, CI key rotation, GitOps policy publish, scripted org provisioning.

Recipes

Real workflows people actually run. Each recipe is independent and copy-pasteable.

Kill an agent from a PagerDuty alert

PagerDuty webhook handler that trips the kill switch as soon as an alert fires:

bash
#!/usr/bin/env bash
# /etc/pagerduty/scripts/kill-checkrd-agent.sh

set -euo pipefail
AGENT_ID="${1:?usage: $0 <agent-id>}"

export CHECKRD_API_KEY="$(cat /etc/checkrd/api-key)"
checkrd agents kill "$AGENT_ID"

# Post to Slack so the on-call sees what happened.
curl -X POST "$SLACK_WEBHOOK_URL" \
  -H 'Content-Type: application/json' \
  -d "{\"text\":\":octagonal_sign: Killed Checkrd agent \`$AGENT_ID\`.\"}"

Wire the script as a PagerDuty webhook target. The kill takes effect within ~1 second via the agent's SSE control stream — no SDK restart needed.

Rotate API keys in CI

Keep CI credentials short-lived. Mint a fresh key per workflow run, then revoke at the end:

yaml
# .github/workflows/ci.yml
jobs:
  smoke:
    steps:
      - name: Mint ephemeral key
        id: mint
        run: |
          KEY_JSON=$(checkrd keys create \
            --name "ci-${{ github.run_id }}" \
            --output json)
          echo "key=$(echo $KEY_JSON | jq -r '.secret')" >> $GITHUB_OUTPUT
          echo "id=$(echo $KEY_JSON  | jq -r '.id')"     >> $GITHUB_OUTPUT
        env:
          CHECKRD_API_KEY: ${{ secrets.CHECKRD_ADMIN_KEY }}

      - name: Run smoke tests
        run: pytest tests/smoke
        env:
          CHECKRD_API_KEY: ${{ steps.mint.outputs.key }}

      - name: Revoke ephemeral key
        if: always()
        run: checkrd keys revoke "${{ steps.mint.outputs.id }}"
        env:
          CHECKRD_API_KEY: ${{ secrets.CHECKRD_ADMIN_KEY }}

The admin key (CHECKRD_ADMIN_KEY) is long-lived and only used to mint/revoke. The short-lived key is what your test code actually uses, so a leaked CI log only exposes a credential that's already been revoked.

GitOps: publish policies from a Git PR merge

policies/ directory in your infra repo, one YAML per agent. Merge to main triggers a publish:

yaml
# .github/workflows/policies.yml
on:
  push:
    branches: [main]
    paths: [policies/**]

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: |
          curl -fsSL https://checkrd.io/install.sh | sh
          echo "$HOME/.checkrd/bin" >> $GITHUB_PATH

      - name: Diff + publish each changed policy
        env:
          CHECKRD_API_KEY: ${{ secrets.CHECKRD_KEY }}
        run: |
          for file in policies/*.yaml; do
            agent=$(basename "$file" .yaml)
            echo "::group::$agent"
            checkrd policies diff "$agent" "$file"
            checkrd policies publish "$agent" "$file" \
              --message "Merged: ${{ github.sha }}"
            echo "::endgroup::"
          done

Run checkrd policies diff in the PR check (without publish) so reviewers see the change set in PR comments before merge.

Tail events into structured logs

Pipe live events into Vector or any log shipper. NDJSON output makes this trivial:

bash
checkrd events tail --agent sales-bot --output json | \
  vector --config /etc/vector/checkrd.toml

Vector config snippet:

toml
[sources.checkrd]
type = "stdin"

[transforms.parse]
type = "remap"
inputs = ["checkrd"]
source = '''
  . = parse_json!(.message)
  .source = "checkrd"
'''

[sinks.datadog]
type = "datadog_logs"
inputs = ["parse"]
default_api_key = "$DD_API_KEY"

For a quick local watch, just pipe through jq:

bash
checkrd events tail --agent sales-bot --output json | \
  jq -c 'select(.event == "kill_switch" or .event == "policy_decision")'

Audit-log export for SOC 2

Quarterly export of every administrative action for compliance:

bash
#!/usr/bin/env bash
# scripts/quarterly-audit-export.sh

quarter_start=$(date -u -d "$(date +%Y-%m-01) -3 months" +%Y-%m-%d)
out="audit-${quarter_start}.jsonl"

checkrd audit list --limit 10000 --output json | \
  jq -c '.data[] | select(.created_at >= "'"$quarter_start"'")' \
  > "$out"

# Sign + upload to your evidence vault.
gpg --armor --detach-sign "$out"
aws s3 cp "$out"      "s3://compliance-evidence/audit/$out"
aws s3 cp "$out.asc"  "s3://compliance-evidence/audit/$out.asc"

The CLI's audit list --limit matches the API's pagination; for full-scale exports past 10K rows, paginate with --cursor (use --output json | jq '.next_cursor' to thread the cursor between calls).

Scripted workspace provisioning

When you onboard a new customer, spin up their workspace + first agent + starter policy in one shot:

bash
#!/usr/bin/env bash
# scripts/provision-customer.sh

customer_name="${1:?usage: $0 <customer-name>}"

# 1. Create the workspace.
org_json=$(checkrd org create --name "$customer_name" --output json)
org_id=$(echo "$org_json" | jq -r '.id')

# 2. Switch into it (re-mint a key scoped to the new org via dashboard,
#    or pass the new key here in real automation).

# 3. Create the customer's first agent.
agent_json=$(checkrd agents create \
  --name "${customer_name}-bot" \
  --description "Auto-provisioned for $customer_name" \
  --output json)
agent_id=$(echo "$agent_json" | jq -r '.id')

# 4. Render the read-only starter template.
checkrd templates render read-only \
  --param domain="api.${customer_name}.example.com" \
  --out /tmp/policy.yaml

# 5. Publish it.
checkrd policies publish "$agent_id" /tmp/policy.yaml \
  --message "Initial policy for $customer_name"

echo "✓ Provisioned org=$org_id agent=$agent_id"

Run as part of your post-Stripe-checkout webhook to give new paying customers a working state before they even log in.

Shell aliases for muscle memory

If you spend a lot of time switching workspaces:

bash
# ~/.zshrc
alias ck='checkrd'
alias ckp='checkrd --profile production'
alias ckd='checkrd --profile development'

# Drop into events tail for any agent by name fragment
ckt() {
  local match=$(checkrd agents list --output json | \
    jq -r ".data[] | select(.name | contains(\"$1\")) | .id" | head -1)
  [[ -z "$match" ]] && { echo "no agent matched '$1'"; return 1; }
  checkrd events tail --agent "$match"
}

Now ckt sales tails whatever agent has "sales" in the name.

What's missing?

Got a workflow you'd like documented? Open an issue — recipes are merged from real-world patterns we see in the wild.