Connect Your Agent to PRECINCT

You have an agent. You have PRECINCT running. Here is how to connect them in four steps: register identity, register tools, write a policy, and route traffic through the gateway.

Three Integration Paths

How you connect depends on what your agent already speaks. Pick the path that matches your situation.

Path A: MCP-Native Agent

Your agent already speaks the Model Context Protocol. Integration is a one-line URL change: point your MCP client at the PRECINCT gateway instead of directly at the MCP server.

Effort: 1 line of configuration

Path B: SDK Integration

Your agent makes tool calls over HTTP but does not use MCP natively. Use the Python or Go SDK to route calls through the gateway with automatic SPIFFE identity injection.

Effort: 5–10 lines of code

Path C: Adapter Pattern

Your agent uses a proprietary protocol or cannot be modified at all. Write a thin adapter that translates your protocol into MCP calls through the gateway, the same pattern used in the adapter case study.

Effort: ~800 lines of adapter code

Not Sure Which Path?

If your agent already uses an MCP client library, you are on Path A. If it makes direct HTTP calls to tools, Path B is your fastest route. If you cannot change the agent at all, Path C is always available. All three paths produce the same security outcome; the only difference is where the integration work happens.

Prerequisites

Before you begin, ensure:

  1. PRECINCT stack is running, either via Docker Compose or Kubernetes. Verify with curl http://localhost:9090/health.
  2. Your agent is running and making tool calls. You should be able to see it calling tools successfully in its current (ungoverned) configuration.
  3. agw CLI is available, the PRECINCT operations CLI. See the CLI Reference for installation.

Step 1: Register Your Agent's Identity

Every workload in PRECINCT is identified by a SPIFFE ID, a URI that cryptographically identifies who is making a request. Before your agent can talk to the gateway, it needs a registered identity.

Choose a SPIFFE ID

SPIFFE IDs follow the pattern spiffe://<trust-domain>/<path>. The path encodes the workload's role within your organization.

# Pattern
spiffe://<trust-domain>/agents/mcp-client/<agent-name>/<environment>

# Examples
spiffe://prod.example.com/agents/mcp-client/research-agent/prod
spiffe://poc.local/agents/mcp-client/my-agent/dev

Create the SPIRE registration entry

Docker Compose

In Docker Compose, registration entries are defined in the SPIRE configuration. Add your agent to the registration entries:

# Register your agent's workload identity
docker compose exec spire-server /opt/spire/bin/spire-server entry create \
  -spiffeID spiffe://poc.local/agents/mcp-client/my-agent/dev \
  -parentID spiffe://poc.local/spire-agent \
  -selector docker:label:app=my-agent

Kubernetes

In Kubernetes, use the SPIRE server CLI or a ClusterSPIFFEID CRD if you have the SPIFFE CSI driver installed:

# Via SPIRE server CLI
kubectl exec -n spire spire-server-0 -- /opt/spire/bin/spire-server entry create \
  -spiffeID spiffe://prod.example.com/agents/mcp-client/my-agent/prod \
  -parentID spiffe://prod.example.com/k8s-node \
  -selector k8s:pod-label:app=my-agent \
  -selector k8s:ns:default

Verify registration

agw identity list
# Should show your new SPIFFE ID in the output

Step 2: Register Your Tools

The PRECINCT gateway only forwards requests to tools that are registered in the capability registry. Each tool entry includes a name, description, upstream URL, and a SHA-256 hash of the tool's definition for integrity verification.

Compute the tool hash

The hash is computed over the tool's canonical JSON definition (name + description + input schema). This prevents tool poisoning attacks. If the tool's definition changes upstream, the hash will no longer match and the gateway will reject the request.

# Compute the SHA-256 hash of your tool's definition
echo -n '{"name":"my_tool","description":"Does something useful","inputSchema":{"type":"object","properties":{"query":{"type":"string"}}}}' \
  | shasum -a 256 | cut -d' ' -f1

Add to the capability registry

Add your tool to config/capability-registry-v2.yaml:

tools:
  - name: my_tool
    description: "Does something useful"
    upstream: "http://my-tool-server:8080"
    hash: "a1b2c3d4e5f6..."  # SHA-256 from the previous step
    risk_level: medium        # low | medium | high | critical
    input_schema:
      type: object
      properties:
        query:
          type: string

Verify registration

agw inspect tools
# Should list your tool with its hash and risk level
Risk Levels Matter

The risk_level field directly affects the session context engine (layer 8) and step-up gating (layer 9). Tools classified as critical (like shell execution) will trigger step-up authorization requirements. Choose the level that matches the tool's actual blast radius.

Step 3: Write a Policy

OPA policies (written in Rego) define what each agent identity is allowed to do. At minimum, you need a policy that permits your agent to call your registered tools.

Minimal policy

Create a new Rego file in config/opa/policies/:

# config/opa/policies/my_agent.rego
package precinct.authz

import rego.v1

# Allow my-agent to call my_tool
allow if {
    input.caller_spiffe_id == "spiffe://poc.local/agents/mcp-client/my-agent/dev"
    input.tool_name == "my_tool"
}

# Allow my-agent to list tools
allow if {
    input.caller_spiffe_id == "spiffe://poc.local/agents/mcp-client/my-agent/dev"
    input.method == "tools/list"
}

Test before deploying

# Evaluate the policy against a sample input
agw policy eval \
  --caller "spiffe://poc.local/agents/mcp-client/my-agent/dev" \
  --tool "my_tool" \
  --method "tools/call"
# Expected: ALLOW

# Test a denial
agw policy eval \
  --caller "spiffe://poc.local/agents/mcp-client/my-agent/dev" \
  --tool "bash" \
  --method "tools/call"
# Expected: DENY (no policy permits this combination)

Hot-reload the policy

After writing or modifying a policy, reload it without restarting the gateway:

agw policy reload
# Policies are now active. No gateway restart required.
Policy as Code

Rego policies are version-controlled alongside your infrastructure. Every policy change is a git commit with a clear diff. This gives auditors a complete history of who was allowed to do what, and when those permissions changed.

Step 4: Route Traffic Through the Gateway

The final step depends on which integration path you chose.

Path A: MCP-Native Agent (1-line change)

If your agent already uses an MCP client, change the server URL to point at the PRECINCT gateway:

# Before: direct connection to MCP server
client = MCPClient(server_url="http://mcp-server:8080")

# After: routed through PRECINCT gateway
client = MCPClient(server_url="http://localhost:9090")

That is the entire change. The gateway speaks the same MCP protocol as the upstream server. Your agent does not know the difference.

Path B: SDK Integration (5–10 lines)

If your agent makes direct HTTP calls to tools, replace them with SDK calls through the gateway.

Python

# Before: direct HTTP to tool
import httpx
resp = httpx.post("http://my-tool:8080/search", json={"query": "AI security"})
result = resp.json()

# After: routed through PRECINCT gateway
from mcp_gateway_sdk import GatewayClient

client = GatewayClient(
    gateway_url="http://localhost:9090",
    spiffe_id="spiffe://poc.local/agents/mcp-client/my-agent/dev"
)
result = await client.call_tool("my_tool", {"query": "AI security"})

Go

// Before: direct HTTP to tool
resp, err := http.Post("http://my-tool:8080/search",
    "application/json", bytes.NewReader(payload))

// After: routed through PRECINCT gateway
client, _ := mcpgateway.NewClient(
    "http://localhost:9090",
    mcpgateway.WithSPIFFEID("spiffe://poc.local/agents/mcp-client/my-agent/dev"),
)
result, err := client.CallTool(ctx, "my_tool", map[string]any{
    "query": "AI security",
})

See the SDK documentation for the full API reference, error handling, and auto-discovery of SPIFFE identities.

Path C: Adapter Pattern

If your agent uses a proprietary protocol or cannot be modified, write an adapter that sits between the agent and the gateway. The adapter translates your application's native protocol into MCP JSON-RPC calls to the gateway.

The adapter contract is straightforward:

  1. Accept requests in the application's native protocol
  2. Map each request to an MCP tools/call or tools/list JSON-RPC call
  3. Forward to the PRECINCT gateway with the agent's SPIFFE ID
  4. Translate the gateway response back to the application's expected format

The adapter case study is a complete worked example of this pattern, including HTTP and WebSocket adapters totaling ~800 lines of Go.

Verify It Works

After completing the four steps above, verify that your agent is governed by PRECINCT.

1. Make a governed request

Have your agent call a registered tool. Verify the call succeeds and check the audit trail:

# Search the audit log for your agent's requests
agw audit search --caller "spiffe://poc.local/agents/mcp-client/my-agent/dev"
# Should show the request with decision=ALLOW and all 13 layers logged

2. Trigger a policy denial

Intentionally call a tool that your policy does not permit. Verify the request is denied:

curl -s http://localhost:9090/ \
  -H "Content-Type: application/json" \
  -H "X-SPIFFE-ID: spiffe://poc.local/agents/mcp-client/my-agent/dev" \
  -d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"bash","arguments":{"command":"whoami"}},"id":1}' \
  | jq .
# Expected: error with code "authz_policy_denied"

3. Inspect the audit record

Every request, whether allowed or denied, generates a structured audit event that traverses all 13 layers:

agw audit search --last 1 | jq .
# Shows: decision_id, trace_id, spiffe_id, tool, decision,
#         layers_traversed, timestamps, risk_score, hash chain
Your Agent Is Now Governed

If the allowed request succeeds with an audit trail, and the denied request returns a structured policy denial, your agent is fully integrated with PRECINCT.

What Happens Next

With your agent connected, every request now passes through the full PRECINCT enforcement chain. Here is what you get automatically:

  • Identity verification: SPIFFE-based mTLS authentication at layer 3
  • Tool integrity: SHA-256 hash verification at layer 5
  • Policy enforcement: fine-grained OPA authorization at layer 6
  • DLP scanning: credential and PII detection at layer 7
  • Session tracking: cumulative risk scoring at layer 8
  • Step-up gating: human-in-the-loop for critical operations at layer 9
  • Rate limiting: per-agent throughput control at layer 11
  • Audit trail: tamper-evident, hash-chained logging at layer 4
  • Dual observability: Phoenix for request-trace waterfalls and optional OpenSearch Dashboards for indexed audit/compliance investigations
  • Late-binding secrets: credential substitution at layer 13

For regulated environments, you can collect compliance evidence directly from the OpenSearch index using agw compliance collect --audit-source opensearch with HTTPS and mTLS certificate flags.

For Auditors

Generate compliance evidence mapped to SOC 2, NIST 800-53, ISO 27001, and more.

Compliance framework →

Architecture

Understand the full security model: five governed planes, 13-layer chain, and threat model.

Architecture deep dive →

Case Study

See how a real application was secured with PRECINCT using the adapter pattern, without changing its code.

Read the case study →