Published on

Closing the Accountability Gap with Agentic Pipelines

Authors
  • avatar
    Name
    Parminder Singh
    Twitter

Teams are replacing static CI/CD pipelines with AI agents. The agent reads the repo state, decides what needs to happen, runs the build, and deploys it based on its own reasoning. If and when something breaks, the question

This post covers what breaks in your accountability model when you go agentic, and the controls that fix it — including where OPA alone isn't enough and what you need alongside it.

Section 1: What a Static Pipeline Gave You For Free

A static pipeline is deterministic. Every step is declared, the logs are complete, and every deployment traces back to a human — whoever merged the PR that triggered the run.

Three things you got automatically:

Authorization — the workflow was written, reviewed, and merged by people. Every run was implicitly sanctioned by whoever approved the change.

Attribution — there's a named human at the top of every deployment chain.

Reproducibility — same inputs, same steps, every time. You can reconstruct any deployment from logs.

None of these are defaults in an agentic pipeline.


Section 2: What the Agent Changes

The agent doesn't execute declared steps. It reasons about what to do based on context — repo state, test output, prior tool results — and acts. Two runs against similar inputs can take different paths.

The logs are a mix of LLM reasoning traces and tool call outputs. Verbose, unstructured, not queryable in any useful way.

More importantly: the agent acts when it has credentials. It doesn't wait for a human to merge a PR. The authorization model from your static pipeline doesn't carry over.

Three problems that follow directly from this:

Prompt injection at build time. An attacker embeds instructions in a dependency README, test fixture, or PR description. The agent reads it as context and acts on it. I covered this mechanism in the Clinejection post — same root cause, now operating at deployment scope rather than package scope.

Credential scope creep. The agent runs under a service account. Tasks expand over time. Non-human accounts rarely get the same audit scrutiny as human ones. The blast radius grows without anyone noticing.

Decision laundering. A human approves "deploy the auth service update." The agent makes a dozen implementation decisions along the way. The human approved the objective. The agent approved the implementation. In a regulated environment, that distinction matters.


Section 3: OPA Handles the Infrastructure Layer

OPA (Open Policy Agent) is the right tool for infrastructure-level policy. You write rules in Rego that evaluate before the agent executes any consequential action — which environments it can touch, what action types are permitted, what time windows are blocked.

package agent.deploy

default allow := false
default requires_human_approval := false

allow if {
    input.environment == "staging"
    input.artifact_signed == true
    input.tests_passed == true
}

requires_human_approval if {
    input.environment == "production"
}

deny if {
    input.action in ["iam:CreateRole", "secretsmanager:PutSecretValue"]
}

The agent calls OPA before every tool execution:

async def check_policy(action: dict) -> dict:
    response = await httpx.AsyncClient().post(
        "http://opa:8181/v1/data/agent/deploy",
        json={"input": action}
    )
    result = response.json()["result"]

    if result.get("deny"):
        raise PolicyViolationError(
            f"Blocked: {action['action']} on {action['environment']}"
        )
    if result.get("requires_human_approval"):
        approval = await request_human_approval(action)
        if not approval.approved:
            raise PolicyViolationError("Approval denied")

    return result

This covers the infrastructure layer well. OPA knows whether this action is permitted against this environment at this time.

What OPA doesn't know is anything about the agent session that produced the request.


Section 4: What OPA Can't See

OPA evaluates whatever JSON you pass it. It has no visibility into the session that preceded the deployment request.

Specifically, it can't answer:

  • Who initiated the workflow, and do they have the clearance for a production deployment given what the agent touched?
  • Did the agent access sensitive or regulated data during the run?
  • Did the agent's behavior during the session look normal, or were there anomalies — unexpected tool calls, prompt injection indicators, scope expansion attempts?

You can manually construct and pass some of this as input. Most teams don't. So OPA evaluates the deployment action in isolation from the session context that produced it.

This is the gap. OPA can tell you whether the action is structurally permitted. It can't tell you whether the session that led to it was clean.


Section 5: The Session Attestation Pattern

The fix is to make session context available to OPA as a signed, verifiable input before the deployment decision is evaluated.

The pattern: before the agent reaches a deployment decision, an AI governance layer has been observing the session in real time — who initiated it, what role they hold, what data the agent accessed, whether the agent's behavior was consistent with the task. At deployment time, it produces a session attestation that OPA can evaluate against.

{
  "session_attestation": {
    "session_id": "abc-123",
    "workflow_run_id": "gh-run-98765",
    "initiated_by": "parminder@company.com",
    "role": "platform-engineer",
    "clearance": "tier-2",
    "data_classification": ["config", "non-pii"],
    "anomalies_detected": false,
    "session_integrity": "clean",
    "signed_at": "2026-03-01T14:22:00Z",
    "signature": "sha256:..."
  }
}

OPA now evaluates the full picture:

import future.keywords.in

allow if {
    input.environment == "production"
    input.session_attestation.anomalies_detected == false
    input.session_attestation.session_integrity == "clean"
    input.session_attestation.role in {"senior-engineer", "platform-lead"}
    verify_signature(input.session_attestation)
}

# Block prod deploy if agent touched PII during the session
# and the initiating role isn't cleared for that
deny if {
    input.environment == "production"
    "pii" in input.session_attestation.data_classification
    not input.session_attestation.clearance == "tier-1"
}

The second rule is the important one. Without session attestation, OPA has no way to write it. The deployment action looks identical regardless of whether the agent accessed PII or not. With attestation, the policy can reflect what actually happened during the run.

This is what DeepInspect provides in this architecture. It sits on the AI traffic layer, enforces policy in real time based on user identity, role, and data classification, and produces signed audit-ready evidence per session. That evidence feeds into OPA's input bundle, giving your infrastructure policy layer visibility into the AI layer.

OPA handles the infrastructure boundary. DeepInspect handles the AI session boundary. Neither replaces the other.


Section 6: The Audit Trail

With these controls in place, every production deployment has a complete record:

  • The OIDC token for the agent session, scoped and TTL-bound
  • The OPA decision log — what policy evaluated, what it returned
  • The session attestation — who initiated it, what data was touched, whether the session was clean
  • The human approval record — who approved the prod push and when
@dataclass
class DeployAuditRecord:
    deployment_id: str
    workflow_run_id: str       # links to the triggering human action in CI
    agent_model: str
    environment: str
    service: str
    image_tag: str
    opa_decision: dict         # full OPA input and result
    session_attestation: dict  # DeepInspect attestation
    human_approval: dict       # approver, timestamp, approval ID
    outcome: str
    timestamp: datetime
    signature: str             # HMAC over the full record

Written to S3 with Object Lock in COMPLIANCE mode. Queryable. Tamper-evident.


What You Can Answer

QuestionStatic pipelineAgentic, no controlsAgentic, with controls
What was deployed?✅ Pipeline log⚠️ Maybe a trace✅ Signed audit record
Who authorized it?✅ PR approver❌ The agent✅ Named human on record
Was it within policy?⚠️ Implicit❌ Unknown✅ OPA decision captured
Did the agent behave normally?N/A❌ No visibility✅ Session attestation
Did it touch sensitive data?N/A❌ No visibility✅ Data classification in record

Closing

The static pipeline enforced accountability through structure. You couldn't deploy without going through declared steps, and those steps were defined by people. The agentic pipeline removes that structure. You have to rebuild it explicitly.

OPA closes the infrastructure policy gap. But a deployment policy that can't see what the agent did during the session is evaluating in partial context. The session attestation pattern closes that gap — and gives your auditors something they can actually use.

DeepInspect is built for this layer — real-time policy enforcement on AI sessions with signed, audit-ready output you can feed into your existing policy infrastructure.