Skip to content

Agent Governance

AI coding agents ship code fast — and hold write access to your repository while they do it. Agent governance is Sentrik's answer to the questions that follow: who is this agent, what was it asked to do, what is it actually touching, and can you prove all of that to an auditor?

Every layer below is deterministic, runs locally, and writes to the same HMAC-signed audit log. Use one layer or all of them — each is independently useful and off by default.

Layer Question it answers CLI
Agent identity Who is acting? agent-register, agent-check
Task binding What was it asked to do, and is it staying in scope? task-bind, task-list
Blast radius Is it touching something dangerous? blast-check
Trust chains Who authorized this sub-agent? task-delegate, task-chain
JIT tool grants Does it hold elevated scopes right now? grants, request-grant
HITL approvals Did a human sign off? approvals, wait-approval
Rollback Can we undo everything it did? task-rollback
Anomaly detection Is it behaving unusually? anomaly-scan
Evidence report Can we prove all of the above? harness-report

Every capability is also exposed as an MCP tool (so the agent itself participates in governance) and a REST endpoint (so your dashboard and CI do too).

Quick start

# 1. Give your agent an identity (prints a sk_agent_... credential ONCE)
sentrik agent-register claude-code --scopes scan,findings:read,fix:write

# 2. The agent declares what it's about to do and where
export SENTRIK_AGENT_KEY=sk_agent_...
sentrik task-bind "Fix SQL injection in login" --path "src/auth/**" --path "tests/test_auth.py"

# 3. Work happens — scans, gates, and audit entries are attributed automatically

# 4. Close out and generate signed evidence
sentrik task-complete <session-id>
sentrik harness-report -o evidence.html

Agent identity

Named credentials

Register agents to get scoped, revocable sk_agent_ credentials (stored as SHA-256 hashes — the plaintext is shown once):

sentrik agent-register my-agent --scopes scan,findings:read --expires 90
sentrik agent-list
sentrik agent-revoke my-agent

Set SENTRIK_AGENT_KEY in the agent's environment and every CLI command, MCP call, and audit log entry is attributed to that name.

Ambient detection

Unregistered agents are still identified. Detection runs in confidence order:

  1. CredentialSENTRIK_AGENT_KEY (registered agent, highest confidence)
  2. Environment — session markers set by Claude Code, Cursor, CI runners, etc.
  3. Process — parent-process inspection (optional, requires psutil)
  4. Git — recent Co-authored-by: trailers

The detected agent, method, session ID, and trust level are recorded on every audit entry.

Trust levels

Six ordered levels gate what any agent may do:

Level Allows
none Nothing — blocked entirely
read Read findings, audit logs, metrics
scan Run scans and gate checks
fix:low Apply fixes for low/info severity (default for unknown agents)
fix:any Apply fixes for any severity, add dependencies, create PRs
admin Config and pack changes

Configure defaults and per-agent overrides in .sentrik/config.yaml:

governance:
  agent_defaults:
    default_trust_level: fix:low
    trust_by_agent:
      claude-code: fix:any
      ci: scan
    queue_action: block        # what to do when an action exceeds trust: allow | warn | block

Check before acting (this is also what pre-commit hooks and the MCP server call):

sentrik agent-check auto_fix_high            # human-readable decision
sentrik agent-check create_pr --quiet || exit 1   # exit-code only, for hooks

Task (intent) binding

The core primitive: before touching code, an agent declares what it intends to do and which paths that requires. Sentrik then knows the difference between "edited src/auth/login.py to fix the bug it was assigned" and "wandered into billing/."

sentrik task-bind "Patch CVE-2026-1234" --path "requirements.txt" --work-item "GH-42" --ttl 3600
sentrik task-list                        # active sessions
sentrik task-list --status violated      # sessions that went out of scope
sentrik task-complete <session-id>

Paths are glob patterns (** supported). Enforcement is configured per project:

governance:
  task_binding:
    enabled: true
    enforcement: warn        # warn | block | hitl
    require_binding: false   # true = agents may not act without an active session
    auto_expire_seconds: 7200

Out-of-scope file access is recorded on the session (visible in task-list --status violated, the dashboard Agents tab, and the harness report). With enforcement: block the action is refused; with hitl it creates an approval request and waits.

Agents integrate via the MCP tools bind_task, check_task_scope, and complete_task — a well-behaved agent checks scope before writing a file.

Blast radius zones

Some files are more dangerous than others. Blast radius gating classifies files into zones and applies per-zone enforcement, independent of what any task session declared. Six zones ship built in:

Zone Covers Default enforcement
auth Authentication, sessions, JWT, OAuth, passwords hitl
secrets .env, keys, certificates, vaults block
config App/infra config, Dockerfiles, CI workflows, IaC warn
billing Payments, subscriptions, invoicing hitl
database Migrations, models, raw SQL warn
crypto Cryptography, hashing, signatures hitl
sentrik blast-check --staged                 # pre-commit usage
sentrik blast-check src/auth/user.py --json

Override zones or enforcement in config (your zones replace the defaults):

governance:
  blast_radius:
    enabled: true
    default_enforcement: warn
    zones:
      - name: auth
        patterns: ["src/auth/**", "src/middleware/session*"]
        enforcement: hitl
      - name: payments
        patterns: ["src/billing/**"]
        enforcement: block

Findings that fall inside a zone are also escalated in scan results, so the gate feels the blast radius too.

Trust chains (delegation)

When an orchestrator agent spawns sub-agents, each delegation is recorded and trust can only stay level or go down — a fix:any orchestrator can hand a sub-agent scan, never admin. Chain depth is capped (default 4) and revoking a parent cascades to its children.

sentrik task-delegate --parent <session-id> "Run the test suite" --trust scan
sentrik task-chain <session-id>          # show the full delegation tree
governance:
  trust_chain:
    enabled: true
    max_depth: 4
    allow_same_level: true
    cascade_revocation: true

JIT tool grants

Instead of giving an agent broad standing permissions, grant elevated scopes just-in-time with a TTL:

sentrik request-grant fix:write --reason "Apply security patch" --wait   # agent side
sentrik grant fix:write my-agent --ttl 900                               # admin side
sentrik grants --active
sentrik revoke-grant <id>
governance:
  tool_grants:
    enabled: true
    auto_grant_scopes: [scan, findings:read, packs:read]   # approved instantly
    require_approval_scopes: [config:write, "*"]           # always require a human
    default_ttl_seconds: 1800
    max_ttl_seconds: 14400

Human-in-the-loop approvals

Any gated action — an out-of-scope write, an auto-patch above the severity ceiling, a config change, a grant request — becomes an approval request that a human resolves from the CLI or the dashboard Approvals tab:

sentrik approvals                          # pending requests
sentrik approve <id> --action approved --comment "Reviewed the diff"
sentrik wait-approval <id> --timeout 3600  # agents/CI block here; exit 0=approved, 1=rejected

Which events require review is part of your governance profile:

governance:
  profile: standard            # strict | standard | permissive
  human_review_required:
    on_critical_finding: true
    on_auto_patch_above: medium
    on_config_change: true
    on_dependency_add: true

Session rollback

Every task session records the git SHA at bind time. If a session goes wrong — scope violations, anomalous behavior, or a human just says no — roll the working tree back to where it started:

sentrik task-rollback <session-id> --dry-run   # show what would be reset
sentrik task-rollback <session-id>
governance:
  rollback:
    enabled: true
    require_approval_for_violations: true   # violated sessions need HITL sign-off to roll back
    dry_run_by_default: false

Anomaly detection

Completed sessions form a per-agent statistical baseline. New sessions are scored against it on four signals:

  • Scope violation rate — out-of-scope file accesses per file touched
  • File count multiplier — files touched vs. files declared at bind time
  • Finding rate — new findings introduced per file
  • New zone access — touching a blast-radius zone this agent has never touched

Each session gets a verdict — clean, suspicious, or anomalous — with a z-score per signal:

sentrik anomaly-scan
sentrik anomaly-scan --json
governance:
  anomaly_detection:
    enabled: true
    baseline_sessions: 50
    scope_violation_rate_threshold: 2.0   # std-devs above the mean
    file_count_multiplier_threshold: 3.0
    finding_rate_threshold: 2.5
    new_zone_flag: true

Detection is skipped until at least 3 baseline sessions exist — expect the first few runs to report an empty baseline rather than false positives.

The harness report (signed evidence)

sentrik harness-report assembles all of the above into one HMAC-SHA256-signed evidence document with seven sections: task binding, blast radius, trust chains, rollbacks, anomalies, human approvals, and the audit trail.

sentrik harness-report                                    # HTML to stdout/out/
sentrik harness-report --format json --since 2026-06-01 -o june.json
sentrik harness-report --verify june.json                 # signature check

This is the artifact to hand an auditor asking "how do you control your AI coding agents?" — it maps directly to EU AI Act human-oversight expectations and to the AI-governance questions now appearing in SOC 2 and ISO 27001 audits. Pair it with sentrik attest (scan attestation) and sentrik ai-attribution (EU AI Act Article 18 co-authorship reporting) for the full evidence set.

CI and pre-commit recipes

Block commits that leave the declared scope or touch a blocked zone:

# .pre-commit-config.yaml
repos:
  - repo: local
    hooks:
      - id: sentrik-blast-check
        name: Sentrik blast radius
        entry: sentrik blast-check --staged --quiet
        language: system
        pass_filenames: false
      - id: sentrik-agent-check
        name: Sentrik agent trust
        entry: sentrik agent-check auto_fix_high --quiet
        language: system
        pass_filenames: false

Gate a pipeline on human approval:

# GitHub Actions
- run: |
    id=$(sentrik request-approval auto_patch --title "Patch ${{ github.event.pull_request.title }}" --json | jq -r .id)
    sentrik wait-approval "$id" --timeout 3600

MCP and REST surface

Capability MCP tools REST
Task binding bind_task, complete_task, check_task_scope GET/POST /api/task-sessions, POST /api/task-sessions/{id}/complete
Delegation delegate_task, check_delegation POST /api/task-sessions/delegate, /api/task-sessions/chain
Rollback rollback_task POST /api/task-sessions/rollback
Blast radius check_blast_radius POST /api/blast-radius/check, GET /api/blast-radius/zones
Anomalies check_anomalies GET /api/anomalies
Grants request_tool_grant, release_tool_grant, check_tool_grant GET /api/tool-grants
Identity — (automatic via SENTRIK_AGENT_KEY) GET /api/agents, /api/agents/active, /api/agents/activity
Evidence generate_harness_report GET /api/harness-report

The dashboard Agents tab shows active sessions, pending approvals, blast-radius zones, anomaly verdicts, and the live activity feed in one place.

See also