Audio Version

Every engineering team using GitHub Copilot, Claude Code, or Cursor has hit the same wall: the AI agent can do too much. It can commit directly to main. It can push without review. It can call tools you didn't intend it to have access to. And the providers — Anthropic, OpenAI — give you no mechanism to restrict what their models are allowed to do inside your codebase.

The problem isn't the model. The problem is the absence of a policy layer between the harness (your IDE) and the LLM provider. Prompts can suggest safe behavior, but they don't enforce it. If your agent can call tools, write files, run shell commands, or trigger git operations, you need a runtime enforcement layer — not a set of instructions in a system prompt.

This is the harness engineering problem: how do you introduce a controllable, auditable, policy-enforced boundary between where developers interact with AI and where that AI executes actions against your infrastructure?

The Architecture Gap

Right now, the flow looks like this:

Developer → VS Code → GitHub Copilot → OpenAI / Anthropic API ↓ (no policy layer) ↓ Tool execution (git, shell, files, API)

GitHub Copilot serves as the aggregator of AI capabilities — routing to Claude, GPT, or custom BYOK models. But between Copilot and the model's tool execution, there is nothing. No policy engine. No approval gate. No allowlist of permitted actions.

The desired architecture inserts a policy enforcement layer:

Developer → VS Code → GitHub Copilot → POLICY GATEWAY → OpenAI / Anthropic API ↓ Policy evaluation (OPA, Rego, allowlists) ↓ Approved tool calls only

This gateway intercepts every tool call the model attempts. It evaluates the call against policy rules — can this agent commit to main? Can it run destructive shell commands? Can it access this API? — and blocks, transforms, or routes to human approval before execution.

Why Prompts Are Not Enough

The standard approach is to bake safety into the system prompt:

"Never commit directly to the main branch. Always create a pull request first."

This fails for three reasons:

  1. LLMs don't obey prompts under pressure. When a model is optimizing for task completion, it will rationalize around instructions — especially when the instruction conflicts with what it perceives as the user's intent.
  2. Prompt injection bypasses instructions. Content in the codebase, in terminal output, or in fetched URLs can override system prompts. Every major 2025-2026 agent incident exploited the tool-use loop, and none of them tripped a content filter.
  3. There's no audit trail. When a prompt-based guardrail fails, you have no log of what was attempted, what was blocked, and why. You can't retroactively answer "what did the agent try to do at 3 PM on Tuesday?"

Core principle

Prompts are advisory. Policy is mandatory. The harness layer must enforce rules that the model cannot override, regardless of prompt injection, context manipulation, or provider behavior changes.

The Policy Enforcement Landscape

Several approaches have emerged for inserting policy between the harness and the LLM. They operate at different layers and with different trade-offs.

1. LLM Gateway Proxies (LiteLLM, Grepture)

LiteLLM Proxy [Link] sits between your application and any LLM provider, exposing a unified OpenAI-compatible API. Its guardrails system supports three enforcement modes:

The key insight: LiteLLM's guardrails can strip tool definitions from the request. If your policy says "this agent cannot call git-commit," the gateway removes that tool definition before forwarding to the provider. The model literally cannot call what it doesn't know about.

Grepture [Link] takes this further with a tool allowlist gateway. You declare which tools each agent is permitted to call. Everything else is denied at two points: on the request side (tool definitions are stripped) and on the response side (tool calls are intercepted and validated against the allowlist). This works across providers — OpenAI Chat Completions, Anthropic Messages, and the OpenAI Responses API.

2. Policy-as-Code (Open Policy Agent)

Open Policy Agent (OPA) [Link] is a general-purpose policy engine using Rego, a declarative policy language. It's been used for Kubernetes admission control, Terraform plan validation, and API gateway policies. Now it's being applied to AI agent tool calls.

The pattern: when the agent decides to call a tool, the harness intercepts the call and evaluates it against an OPA policy before execution:

# policies/git.rego
package git

default allow = false

allow {
    input.tool == "git-commit"
    input.branch != "main"
    input.branch != "master"
}

allow {
    input.tool == "git-commit"
    input.branch == "main"
    input.has_approval == true
}

This is the critical distinction: OPA evaluates structured data (the tool name, its arguments, the current branch, whether a human approved it) — not natural language. The policy is deterministic, testable, and version-controlled. You can write unit tests for your policies.

The ai-sdk [Link] from Vercel wires OPA directly into agent tool calls. Every tool invocation is gated by Rego policies in policies/decision.rego, editable without touching application code. Policies can enforce read-only command allowlists for shell tools, domain-scoped web searches, city allowlists for weather tools — and yes, branch-protection rules for git operations.

Strata's Maverics AI Identity Gateway embeds OPA to evaluate fine-grained policies on MCP tool calls at request time, positioning OPA as the containment boundary where every tool invocation must pass policy evaluation before reaching any upstream service.

3. MCP Gateways (Speakeasy, NeuralTrust)

The Model Context Protocol (MCP) has become the standard for how agents connect to tools. Speakeasy [Link] operates an MCP gateway that sits between AI agents and MCP servers. Every tool call routes through the gateway, where:

Speakeasy's model: policies are written once at the control plane, scoped to the person or agent, the target system, and the specific action. An agent used by a junior developer gets different permissions than one used by a senior engineer, even if they're running the same model.

NeuralTrust TrustGate [Link] applies a similar architecture but with a focus on sovereign AI — the data plane runs inside your VPC or on-prem, enforcing policies locally so data never leaves your environment. TrustGate applies one policy model to both LLM traffic and MCP traffic, with threat detection handled in-engine.

4. Human-in-the-Loop (OpenAI Agents SDK, Anthropic MCP)

Not every tool call needs to be blocked — some need human approval. Both major providers now support this natively:

OpenAI Agents SDK [Link] supports approval workflows for hosted MCP tools. You configure require_approval per tool with policies of "always", "never", or a dict mapping specific tool names to policies. The SDK pauses execution, surfaces the tool call to the human, and resumes only after approval.

Anthropic's MCP implementation requires explicit user approval for tool access from the start of the protocol. The caveat: a one-time approval covers a tool that can materially change later — the tool's description, capabilities, or behavior can update without re-prompting the user. This is a known gap in the shared responsibility model.

5. IDE-Level Controls (GitHub Copilot BYOK)

GitHub Copilot's BYOK (Bring Your Own Key) mode [Link] lets organizations route Copilot through their own LLM providers. Enterprise owners can enable custom model policies, assign minimum necessary scopes to API keys, and choose providers that comply with governance requirements.

This doesn't solve the tool-call policy problem directly — it solves the provider governance problem. But it's a prerequisite: you need BYOK to insert your own gateway between Copilot and the model.

The Copilot LLM Gateway extension [Link] registers as a language model provider inside Copilot Chat and adds a resilience layer for self-hosted models. It demonstrates that the extension point exists — you can intercept Copilot's model calls and route them through your own infrastructure.

Designing the Policy Layer

Here's what a practical policy layer looks like for the problem we started with: preventing AI agents from committing directly to main branches.

Policy Rules (Rego)

package agent_policy

# Block commits to protected branches without approval
deny {
    input.tool == "git-commit"
    input.args.branch == "main"
    not input.context.approved_by_human
}

# Block destructive shell commands entirely
deny {
    input.tool == "shell"
    regex.match("^rm\\s+-rf\\s+/", input.args.command)
}

# Allow read-only git operations
allow {
    input.tool == "git-log"
}

allow {
    input.tool == "git-diff"
}

# Require approval for any file write outside the agent's workspace
deny {
    input.tool == "write-file"
    not string.startswith(input.args.path, input.context.workspace)
}

Gateway Configuration (LiteLLM)

# config.yaml
model_list:
  - model_name: claude-sonnet-4-20250514
    litellm_params:
      model: anthropic/claude-sonnet-4-20250514
      api_key: os.environ/ANTHROPIC_API_KEY

guardrails:
  - pre_call_guardrails:
      - name: tool_allowlist
        uuid: tool-allowlist-001
        litellm_params:
          allowed_tools:
            - "read-file"
            - "search-files"
            - "git-log"
            - "git-diff"
            - "create-branch"
            - "create-pr"
          # git-commit is NOT in the allowlist
          # The model will never see it as an option

  - post_call_guardrails:
      - name: opa_policy_check
        uuid: opa-check-001
        litellm_params:
          opa_url: http://opa-sidecar:8181
          policy_path: agent_policy

Enforcement Points

A robust policy layer enforces at multiple points:

  1. Request time (pre_call): Strip disallowed tool definitions. The model cannot call what it doesn't know about. This is the cheapest enforcement — it prevents the problem before the model even thinks about it.
  2. Response time (post_call): Validate tool calls against policy. Even if a model hallucinates a tool call to a stripped tool, the gateway catches it. Evaluate the call's arguments against OPA policies — is the branch protected? Is the path outside the workspace?
  3. Execution time: For tools that pass policy but still need oversight, route to human approval. The agent pauses, the developer reviews, and execution resumes only after confirmation.
  4. Audit log: Every tool call — allowed, blocked, or approved — is logged with the agent identity, the tool, the arguments, the policy decision, and the timestamp. This is your forensic trail.

What's Missing Today

The infrastructure pieces exist, but they're fragmented. Here's what's not yet solved:

The Path Forward

The immediate path for teams wanting to enforce policy today:

  1. Deploy LiteLLM Proxy as your LLM gateway. Configure it with BYOK mode in Copilot. This gives you the interception point.
  2. Define tool allowlists per agent role. Junior developers get read-only tools. Senior developers get write tools with branch protection. Maintainers get everything.
  3. Add OPA as the policy engine for argument-level enforcement. Branch protection, path scoping, command allowlists — all in Rego.
  4. Wire human-in-the-loop for high-risk operations. Git commits to release branches, database operations, external API calls — anything that crosses the "point of no return" threshold.
  5. Log everything. Every tool call, every policy decision, every approval. This becomes your dataset for refining policies and your evidence for audits.

The longer-term trajectory: as MCP matures and the Agentic AI Foundation standardizes protocols, we'll see policy enforcement become a first-class concern in the agent stack. The harness layer — between the IDE and the model — will evolve from a routing layer into a governance layer. The teams that build their policy infrastructure now will have the advantage when the standard emerges.

"Prompts can suggest safe behavior, but they do not enforce it. If your agent can call tools, write records, send emails, run SQL, trigger workflows, or spend money, you need a runtime policy engine — not a system prompt."

— Jack M. Singularity, AI Agent Runtime Policy: Stop Dangerous Tool Calls Before They Execute [Link]

Key Players and Resources