Securing Agents with Policies
This tutorial walks through securing a customer service agent step by step. You’ll restrict tool access, propagate user identity, enforce business rules with CEL, and validate everything in audit mode before going live.
Scenario
Section titled “Scenario”You have a customer service agent (support-agent) with access to a customer-tools ToolRegistry containing:
lookup_order— look up order detailscheck_status— check order statusprocess_refund— issue refundsdelete_account— delete a customer account
The agent should be able to look up orders and process refunds, but not delete accounts. Refunds should be capped at $500 and require a reason. The user’s team identity must flow through to downstream services.
Prerequisites
Section titled “Prerequisites”- A running Omnia cluster with Istio enabled
- JWT authentication configured (see Configure Agent Authentication)
- The
support-agentAgentRuntime andcustomer-toolsToolRegistry deployed
Step 1: Restrict Tool Access with AgentPolicy
Section titled “Step 1: Restrict Tool Access with AgentPolicy”Start by limiting which tools the agent can call. Create an AgentPolicy with a tool allowlist:
apiVersion: omnia.altairalabs.ai/v1alpha1kind: AgentPolicymetadata: name: support-agent-policy namespace: productionspec: selector: agents: - support-agent
toolAccess: mode: allowlist rules: - registry: customer-tools tools: - lookup_order - check_status - process_refund # delete_account is deliberately excludedApply it:
kubectl apply -f support-agent-policy.yamlVerify the policy is active:
kubectl get agentpolicies -n productionNAME MODE PHASE MATCHED AGEsupport-agent-policy enforce Active 1 10sThe agent can now only call lookup_order, check_status, and process_refund. Any attempt to call delete_account is blocked at the Istio network level.
Step 2: Map JWT Claims for User Identity
Section titled “Step 2: Map JWT Claims for User Identity”Add claim mapping so the user’s team and customer ID flow through to tool services:
apiVersion: omnia.altairalabs.ai/v1alpha1kind: AgentPolicymetadata: name: support-agent-policy namespace: productionspec: selector: agents: - support-agent
toolAccess: mode: allowlist rules: - registry: customer-tools tools: - lookup_order - check_status - process_refund
claimMapping: forwardClaims: - claim: team header: X-Omnia-Claim-Team - claim: customer_id header: X-Omnia-Claim-Customer-IdApply the update:
kubectl apply -f support-agent-policy.yamlNow every tool call includes X-Omnia-Claim-Team and X-Omnia-Claim-Customer-Id headers, extracted from the user’s JWT.
Step 3: Add Business Rules with ToolPolicy
Section titled “Step 3: Add Business Rules with ToolPolicy”Create a ToolPolicy with CEL rules to enforce refund limits and require a reason:
apiVersion: omnia.altairalabs.ai/v1alpha1kind: ToolPolicymetadata: name: refund-guardrails namespace: productionspec: selector: registry: customer-tools tools: - process_refund
requiredClaims: - claim: Team message: "Team claim is required for refund operations" - claim: Customer-Id message: "Customer ID is required for refund operations"
rules: - name: max-refund-amount description: "Cap refunds at $500" deny: cel: 'has(body.amount) && double(body.amount) > 500.0' message: "Refund amount exceeds the $500 limit"
- name: require-reason description: "All refunds must include a reason" deny: cel: '!has(body.reason) || body.reason == ""' message: "A reason is required for refund requests"
headerInjection: - header: X-Processed-By cel: 'headers["X-Omnia-Claim-Team"]'
mode: audit # Start in audit mode onFailure: deny
audit: logDecisions: trueApply it:
kubectl apply -f refund-guardrails.yamlVerify:
kubectl get toolpolicies -n productionNAME REGISTRY MODE PHASE RULES AGErefund-guardrails customer-tools audit Active 2 10sStep 4: Validate in Audit Mode
Section titled “Step 4: Validate in Audit Mode”With mode: audit, the policy logs violations but does not block requests. This lets you verify the rules are matching correctly before enforcement.
Test the agent by making a refund call that violates the rules (e.g., amount > $500). Then check the policy proxy logs:
kubectl logs -n production -l app=customer-tools -c policy-proxy | grep policy_decisionYou should see audit entries like:
{ "msg": "policy_decision", "decision": "deny", "wouldDeny": true, "mode": "audit", "policy": "refund-guardrails", "rule": "max-refund-amount", "message": "Refund amount exceeds the $500 limit", "path": "/v1/refund", "method": "POST"}The wouldDeny: true field confirms the rule would deny in enforce mode, but the request was allowed through.
Step 5: Switch to Enforce Mode
Section titled “Step 5: Switch to Enforce Mode”Once audit logs confirm the policy is working correctly, switch to enforce mode:
spec: mode: enforcekubectl apply -f refund-guardrails.yamlVerify the mode changed:
kubectl get toolpolicies -n productionNAME REGISTRY MODE PHASE RULES AGErefund-guardrails customer-tools enforce Active 2 1hNow any refund over $500 or without a reason returns a 403 response:
{ "error": "policy_denied", "rule": "max-refund-amount", "message": "Refund amount exceeds the $500 limit"}What You’ve Built
Section titled “What You’ve Built”Here’s the complete security architecture for your agent:
graph TB CLIENT[Client + JWT] --> ISTIO[Istio Sidecar]
subgraph "AgentPolicy Enforcement" ISTIO -->|Tool allowlist check| FACADE[Facade] ISTIO -->|Extract team, customer_id| FACADE end
FACADE --> RUNTIME[Runtime]
subgraph "ToolPolicy Enforcement" RUNTIME -->|HTTP + X-Omnia-* headers| PROXY[Policy Proxy] PROXY -->|Check required claims| PROXY PROXY -->|Evaluate CEL rules| PROXY PROXY -->|Inject X-Processed-By| TOOL[Tool Service] end
PROXY -->|403 if denied| RUNTIMEAgentPolicy provides:
- Tool allowlist —
delete_accountblocked at the network level - Claim mapping —
teamandcustomer_idpropagated as headers
ToolPolicy provides:
- Required claims — team and customer ID must be present
- CEL rules — refund amount cap and reason requirement
- Header injection — team identity forwarded to the tool service
- Audit logging — full decision trail
Next Steps
Section titled “Next Steps”- Add more CEL rules for other tools in the registry
- Configure
audit.redactFieldsto mask sensitive data in logs - Create policies for other agents in the namespace
- Review the AgentPolicy Reference and ToolPolicy Reference for all available fields
Related Resources
Section titled “Related Resources”- Policy Engine Architecture — how the policy engine works
- AgentPolicy CRD Reference — field-by-field specification
- ToolPolicy CRD Reference — field-by-field specification
- Configure Agent Policies — operational guide
- Configure Tool Policies — operational guide