Writing Policies
A step-by-step guide to authoring MAPL policies for your organization. Learn how to design policy hierarchies and implement real-world access patterns.
Plan Your Hierarchy
Before writing policies, map your organization's structure to policy levels:
Organization ├── company:acme ← Company-wide defaults │ ├── bu:engineering ← Engineering business unit │ │ ├── team:backend ← Backend team │ │ │ ├── user:alice ← Individual user │ │ │ └── user:bob │ │ └── team:frontend │ └── bu:finance │ └── team:analysts
Questions to Answer
- • What resources should everyone access?
- • What's different between business units?
- • What team-specific restrictions exist?
- • Do any users need special permissions?
Best Practices
- • Start broad at the top, restrict going down
- • Keep organization policies minimal
- • Don't over-specialize at the user level
- • Use teams to group similar users
Write the Root Policy
Start with your organization's root policy. This defines the broadest permissions that all child policies inherit from:
{
"policy_id": "company:acme",
"version": "1.0",
"description": "Acme Corp - Company-wide base policy",
"scope": "org",
"resources": [
"llm:openai/*",
"llm:anthropic/*",
"tool:calculator/*"
],
"denied_resources": [
"*.secret",
"*.password",
"admin:**"
],
"constraints": {
"rate_limit": 1000,
"parameters": {
"llm:**": {
"max_tokens": {"max": 8000}
}
}
}
}Key Points
- • resources: Define what everyone CAN potentially access
- • denied_resources: Block dangerous patterns for all users
- • constraints: Set upper bounds that children cannot exceed
Add Business Unit Policies
Business unit policies inherit from the company policy and add BU-specific restrictions:
{
"policy_id": "bu:engineering",
"extends": "company:acme",
"description": "Engineering BU - Code and tools access",
"scope": "bu",
"resources": [
"tool:github/*",
"tool:database/query"
],
"constraints": {
"rate_limit": 500,
"parameters": {
"llm:**": {
"max_tokens": {"max": 4000}
}
}
}
}Notice: Engineering adds GitHub and database access (domain-aware inheritance), but restricts token limits from 8000 to 4000.
Define Team Policies
Team policies specialize further based on team responsibilities:
{
"policy_id": "team:backend",
"extends": "bu:engineering",
"description": "Backend team - Database and API access",
"scope": "team",
"resources": [
"tool:database/*",
"tool:api/*"
],
"constraints": {
"rate_limit": 200,
"parameters": {
"llm:**": {
"model": ["gpt-4", "claude-3-sonnet"],
"max_tokens": {"max": 2000}
},
"tool:database/*": {
"tables": {
"allowed_values": ["users", "orders", "products", "logs"]
}
}
}
}
}Optional: User-Specific Policies
Most users should inherit from their team policy without customization. Only create user policies when truly necessary:
Good Reasons for User Policies
- • Special project access (time-limited)
- • Additional restrictions (probation, compliance)
- • Role-specific tools (tech lead, on-call)
Bad Reasons for User Policies
- • Granting more permissions (use group instead)
- • One-off exceptions (creates maintenance burden)
- • Personal preference (not a security concern)
Deploy and Test
Create and test your policies using the Console:
1. Create Policies
- Go to Console → Policies
- Click Create Policy
- Paste your policy JSON and click Save
- The Console validates syntax automatically on save
2. View Inheritance Chain
- Click on any policy to open the detail view
- The Inheritance section shows the full policy chain
- Click Show Effective Policy to see the merged result
3. Test with Real Requests
Write a simple test script to verify your policies work as expected:
from macaw_adapters.openai import SecureOpenAI
# Test as a specific user
client = SecureOpenAI(
app_name="policy-test",
jwt_token=alice_jwt # Alice's token
)
# This should succeed if alice has access
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": "Hello"}],
max_tokens=1000
)4. Check Audit Logs
- Go to Console → Logs
- Find your test requests
- Verify
ALLOWEDorDENIEDmatches expectations - Click events to see which policy was applied
Common Policy Patterns
Read-Only Access
"resources": [ "tool:database/query", // Allow reads "tool:reports/view" ], "denied_resources": [ "tool:database/insert", // Block writes "tool:database/update", "tool:database/delete" ]
Cost Control (Token Limits)
"constraints": {
"parameters": {
"llm:**": {
"model": ["gpt-3.5-turbo"], // Cheaper model only
"max_tokens": {"max": 500} // Limited output
}
}
}Human Approval for High-Value Operations
"attestations": [
"manager_approval::{params.amount > 10000}"
],
"constraints": {
"attestations": {
"manager_approval": {
"approval_criteria": "role:manager",
"timeout": 300,
"time_to_live": 3600
}
}
}