Concepts
Policy Management
Control agent execution with policies
Policy Management
Policies define what actions an agent can execute, providing fine-grained control over agent behavior. Think of policies as execution guardrails that work alongside intent verification.
What are Policies?
A policy is a set of rules that determines:
- Which MCPs and actions are allowed/denied
- Time-based access restrictions
- Rate limits
- IP whitelisting
- Tool-level permissions
Policy Structure
{
"allow": ["analytics-mcp/*", "data-mcp/fetch_*"],
"deny": ["data-mcp/delete_*", "admin-mcp/*"],
"allowed_tools": ["read_file", "analyze", "aggregate"],
"rate_limit": 100,
"ip_whitelist": ["10.0.0.0/8", "192.168.1.0/24"],
"time_restrictions": {
"allowed_hours": [9, 10, 11, 12, 13, 14, 15, 16, 17],
"allowed_days": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
},
"priority": 50
}Policy Fields
| Field | Type | Description | Example |
|---|---|---|---|
allow | list[str] | Allowed MCP/action patterns (glob) | ["data-mcp/*"] |
deny | list[str] | Denied MCP/action patterns (glob) | ["data-mcp/delete_*"] |
allowed_tools | list[str] | Whitelisted tool names | ["read_file", "analyze"] |
rate_limit | int | Max requests per hour | 100 |
ip_whitelist | list[str] | Allowed IPs/CIDR ranges | ["10.0.0.0/8"] |
time_restrictions | object | Time-based access control | See below |
priority | int | Policy priority (0-100, higher wins) | 50 |
Time Restrictions
{
"allowed_hours": [9, 10, 11, 12, 13, 14, 15, 16, 17], // 0-23
"allowed_days": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
}Creating Policies
Method 1: Programmatic (SDK)
Define policies directly in your code:
# Restrictive policy for production agent
policy = {
"allow": ["analytics-mcp/*", "data-mcp/fetch_*"],
"deny": ["data-mcp/delete_*"],
"allowed_tools": ["read_file", "analyze", "aggregate"],
"rate_limit": 100,
"ip_whitelist": ["10.0.0.0/8"],
"time_restrictions": {
"allowed_hours": [9, 10, 11, 12, 13, 14, 15, 16, 17],
"allowed_days": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
}
}
token = client.get_intent_token(
plan_capture=plan,
policy=policy,
validity_seconds=3600
)Method 2: Visual Policy Builder (ArmorIQ Canvas)
Create policies using the drag-and-drop interface at platform.armoriq.ai/dashboard/policies:
Steps:
- Click "Canvas" button to open visual builder
- Drag users, MCPs, and agents onto canvas
- Connect entities with edges (connections)
- Click edge to configure permissions visually
- Use "Browse Tools" to select allowed tools from MCP
- Set IP restrictions, time windows, rate limits
- Save policy with name and priority
Use the policy ID in SDK:
# Use policy created in Canvas
token = client.get_intent_token(
plan_capture=plan,
policy_id="f88cf4c7-732d-44ff-901b-fd3d882c2ecf", # From Canvas
validity_seconds=3600
)Or fetch policy JSON from API:
import requests
# Fetch policy from ArmorIQ API
policy_response = requests.get(
f"https://customer-api.armoriq.ai/policies/f88cf4c7-732d-44ff-901b-fd3d882c2ecf",
headers={"Authorization": f"Bearer {user_jwt}"}
)
policy = policy_response.json()["data"]["permissions"]
# Use fetched policy
token = client.get_intent_token(
plan_capture=plan,
policy=policy,
validity_seconds=3600
)Policy Evaluation
How Policies are Applied
When you request an intent token, ArmorIQ:
- Loads applicable policies (user, agent, organization level)
- Merges policies by priority (higher priority wins)
- Evaluates plan actions against merged policy
- Rejects token if any action violates policy
- Embeds policy hash in token
At invocation time, ArmorIQ:
- Extracts policy from token
- Checks if action matches allow/deny patterns
- Verifies time restrictions (if any)
- Checks rate limits
- Validates IP address (if whitelist exists)
- Allows or denies request
Allow/Deny Pattern Matching
Policies use glob patterns for flexible matching:
policy = {
"allow": [
"data-mcp/*", # All data-mcp actions
"analytics-mcp/fetch_*" # Only fetch actions in analytics-mcp
],
"deny": [
"data-mcp/delete_*", # No delete actions
"admin-mcp/*" # No admin actions at all
]
}Matching Rules:
*matches any stringdata-mcp/*matchesdata-mcp/fetch,data-mcp/analyze, etc.data-mcp/fetch_*matchesdata-mcp/fetch_users,data-mcp/fetch_orders, etc.- Deny takes precedence over allow
Priority Resolution
When multiple policies apply:
# User-level policy (priority 30)
user_policy = {
"allow": ["data-mcp/*"],
"priority": 30
}
# Agent-level policy (priority 60)
agent_policy = {
"deny": ["data-mcp/delete_*"],
"priority": 60
}
# Organization-level policy (priority 90)
org_policy = {
"allow": ["analytics-mcp/*"],
"priority": 90
}
# Merged result:
# - data-mcp/* allowed (user policy)
# - data-mcp/delete_* denied (agent policy, higher priority)
# - analytics-mcp/* allowed (org policy, highest priority)Policy Examples
Example 1: Read-Only Agent
# Agent can only read data, no writes
readonly_policy = {
"allow": [
"data-mcp/fetch_*",
"data-mcp/query_*",
"analytics-mcp/analyze_*"
],
"deny": [
"data-mcp/insert_*",
"data-mcp/update_*",
"data-mcp/delete_*"
],
"rate_limit": 1000
}Example 2: Business Hours Only
# Agent only works during business hours
business_hours_policy = {
"allow": ["*"],
"time_restrictions": {
"allowed_hours": [9, 10, 11, 12, 13, 14, 15, 16, 17],
"allowed_days": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
}
}Example 3: High-Security Agent
# Agent with strict security constraints
secure_policy = {
"allow": ["finance-mcp/fetch_balance", "finance-mcp/calculate_*"],
"deny": ["finance-mcp/transfer_*", "finance-mcp/withdraw_*"],
"ip_whitelist": ["10.0.0.0/8"], # Internal network only
"rate_limit": 50,
"time_restrictions": {
"allowed_hours": [9, 10, 11, 12, 13, 14, 15, 16, 17],
"allowed_days": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
}
}Example 4: Development Agent
# Permissive policy for development
dev_policy = {
"allow": ["*"],
"deny": ["production-mcp/*"], # No production access
"rate_limit": 10000
}Policy Composition
You can compose policies for different scenarios:
def get_policy(environment: str, role: str) -> dict:
"""Get policy based on environment and role."""
base_policy = {
"rate_limit": 100,
"priority": 50
}
# Environment-specific
if environment == "production":
base_policy["ip_whitelist"] = ["10.0.0.0/8"]
base_policy["time_restrictions"] = {
"allowed_hours": list(range(9, 18)),
"allowed_days": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
}
# Role-specific
if role == "admin":
base_policy["allow"] = ["*"]
base_policy["rate_limit"] = 1000
elif role == "analyst":
base_policy["allow"] = ["data-mcp/fetch_*", "analytics-mcp/*"]
base_policy["deny"] = ["data-mcp/delete_*"]
elif role == "viewer":
base_policy["allow"] = ["data-mcp/fetch_*"]
base_policy["deny"] = ["*"]
return base_policy
# Usage
policy = get_policy(environment="production", role="analyst")
token = client.get_intent_token(plan_capture=plan, policy=policy)Testing Policies
1. Dry Run Validation
# Validate policy without executing
try:
token = client.get_intent_token(
plan_capture=plan,
policy=test_policy,
dry_run=True # Don't create token, just validate
)
print("✓ Policy is valid")
except PolicyViolationError as e:
print(f"✗ Policy violation: {e}")2. Policy Simulation
# Test if action would be allowed
def simulate_policy(policy: dict, mcp: str, action: str) -> bool:
"""Check if action would be allowed by policy."""
full_action = f"{mcp}/{action}"
# Check deny patterns
for pattern in policy.get("deny", []):
if fnmatch.fnmatch(full_action, pattern):
return False
# Check allow patterns
for pattern in policy.get("allow", []):
if fnmatch.fnmatch(full_action, pattern):
return True
return False
# Usage
policy = {"allow": ["data-mcp/*"], "deny": ["data-mcp/delete_*"]}
print(simulate_policy(policy, "data-mcp", "fetch_data")) # True
print(simulate_policy(policy, "data-mcp", "delete_all")) # FalsePolicy Management Best Practices
1. Start Restrictive, Then Relax
# Start with minimal permissions
initial_policy = {
"allow": ["data-mcp/fetch_data"],
"deny": ["*"]
}
# Add permissions as needed
expanded_policy = {
"allow": ["data-mcp/fetch_*", "analytics-mcp/analyze"],
"deny": ["data-mcp/delete_*"]
}2. Use Environment-Specific Policies
policies = {
"development": {
"allow": ["*"],
"deny": ["production-mcp/*"],
"rate_limit": 10000
},
"staging": {
"allow": ["*"],
"deny": ["production-mcp/*"],
"rate_limit": 1000
},
"production": {
"allow": ["data-mcp/fetch_*", "analytics-mcp/*"],
"deny": ["data-mcp/delete_*"],
"rate_limit": 100,
"ip_whitelist": ["10.0.0.0/8"]
}
}
env = os.getenv("ENVIRONMENT", "development")
policy = policies[env]3. Version Your Policies
policy_v1 = {
"version": "1.0.0",
"allow": ["data-mcp/*"],
"deny": []
}
policy_v2 = {
"version": "2.0.0",
"allow": ["data-mcp/*", "analytics-mcp/*"],
"deny": ["data-mcp/delete_*"]
}
# Use version in metadata
token = client.get_intent_token(
plan_capture=plan,
policy=policy_v2,
metadata={"policy_version": "2.0.0"}
)4. Monitor Policy Violations
# Log policy violations for security monitoring
try:
token = client.get_intent_token(plan_capture=plan, policy=policy)
except PolicyViolationError as e:
logger.error(f"Policy violation: {e}", extra={
"user_id": user_id,
"agent_id": agent_id,
"violated_action": e.action,
"policy": policy
})
raiseCommon Policy Patterns
Pattern 1: Separation of Concerns
# Data team: Read-only access to data
data_team_policy = {
"allow": ["data-mcp/fetch_*", "data-mcp/query_*"],
"deny": ["data-mcp/insert_*", "data-mcp/delete_*"]
}
# Analytics team: Read + compute
analytics_team_policy = {
"allow": ["data-mcp/fetch_*", "analytics-mcp/*"],
"deny": ["data-mcp/insert_*", "data-mcp/delete_*"]
}
# Admin team: Full access
admin_team_policy = {
"allow": ["*"],
"deny": []
}Pattern 2: Progressive Permissions
# Level 1: Basic access
level1_policy = {
"allow": ["data-mcp/fetch_public_*"],
"rate_limit": 100
}
# Level 2: Intermediate access
level2_policy = {
"allow": ["data-mcp/fetch_*", "analytics-mcp/basic_*"],
"rate_limit": 500
}
# Level 3: Advanced access
level3_policy = {
"allow": ["data-mcp/*", "analytics-mcp/*"],
"deny": ["data-mcp/delete_*"],
"rate_limit": 1000
}Next Steps
- get_intent_token() - Apply policies to tokens
- Security Model - Understand verification
- Token Lifecycle - How tokens work