2026-02-22
Building Custom Domain Packs for Intended
Developer Relations · Developer Experience
Building Custom Domain Packs
Intended ships with domain packs for common operational domains: SaaS operations, FinTech, healthcare, infrastructure, software development, and security operations. These packs provide a strong baseline for governance in their respective domains. But every organization has unique operations, custom tools, and specific governance requirements that generic packs cannot fully address.
Custom domain packs let you encode your organization's specific governance knowledge into a package that the Intended authority engine evaluates against. This guide walks through creating a custom domain pack from scratch.
What Is in a Domain Pack
A domain pack is a JSON configuration package with four sections:
**Intents**: the mapping between raw actions and semantic intent categories. This is the classification layer that tells the authority engine what an agent is trying to do.
**Risk models**: the scoring functions that evaluate each intent against risk dimensions. This is the layer that tells the authority engine how risky an action is in context.
**Baselines**: the expected behavior profiles for agents operating in this domain. This is the layer that tells the authority engine what is normal.
**Thresholds**: the decision boundaries that determine when actions are auto-approved, escalated, or denied. This is the layer that tells the authority engine what to do about the risk.
Step 1: Define Your Intents
Start by mapping the tools your agents use to semantic intent categories. An intent has a hierarchical name (like "procurement.vendor.create"), a description, and a list of risk-relevant parameters that should be extracted from the tool call.
{
"intents": {
"procurement.vendor.create": {
"description": "Create a new vendor in the procurement system",
"tools": ["erp.createVendor", "procurement-api.vendors.create"],
"risk_params": [
{ "name": "vendor_country", "source": "params.country" },
{ "name": "vendor_category", "source": "params.category" },
{ "name": "payment_terms", "source": "params.paymentTerms" }
]
},
"procurement.po.create": {
"description": "Create a purchase order",
"tools": ["erp.createPurchaseOrder", "procurement-api.orders.create"],
"risk_params": [
{ "name": "amount", "source": "params.totalAmount" },
{ "name": "currency", "source": "params.currency" },
{ "name": "vendor_id", "source": "params.vendorId" },
{ "name": "line_items", "source": "params.items.length" }
]
},
"procurement.po.approve": {
"description": "Approve a pending purchase order",
"tools": ["erp.approvePurchaseOrder"],
"risk_params": [
{ "name": "amount", "source": "params.totalAmount" },
{ "name": "original_requester", "source": "params.requesterId" }
]
},
"procurement.invoice.process": {
"description": "Process a vendor invoice for payment",
"tools": ["erp.processInvoice", "ap-system.invoices.submit"],
"risk_params": [
{ "name": "amount", "source": "params.amount" },
{ "name": "vendor_id", "source": "params.vendorId" },
{ "name": "po_reference", "source": "params.purchaseOrderId" }
]
}
}
}The `tools` array maps raw tool names to this intent. When an agent calls "erp.createPurchaseOrder," the authority engine classifies it as "procurement.po.create" and extracts the risk-relevant parameters.
Be specific with your intent categories. "procurement.po.create" is better than "procurement.write" because it allows policies to distinguish between creating a PO and approving a PO, which are very different actions.
Step 2: Define Your Risk Models
Risk models define how to score each intent across the eight risk dimensions. Each dimension has a scoring function that takes the extracted risk parameters and returns a score between 0 and 1.
{
"risk_models": {
"procurement.po.create": {
"financial_impact": {
"type": "threshold",
"param": "amount",
"thresholds": [
{ "value": 1000, "score": 0.1 },
{ "value": 10000, "score": 0.4 },
{ "value": 50000, "score": 0.7 },
{ "value": 100000, "score": 0.9 }
],
"above_max": 1.0
},
"data_sensitivity": {
"type": "fixed",
"score": 0.2
},
"operational_risk": {
"type": "lookup",
"param": "vendor_id",
"known_values": { "score": 0.2 },
"unknown_values": { "score": 0.6 },
"description": "New vendors carry higher operational risk"
},
"compliance_exposure": {
"type": "threshold",
"param": "amount",
"thresholds": [
{ "value": 25000, "score": 0.2 },
{ "value": 75000, "score": 0.5 }
],
"above_max": 0.8,
"description": "Higher amounts trigger more compliance requirements"
},
"reversibility": {
"type": "fixed",
"score": 0.7,
"description": "POs can be cancelled before fulfillment"
},
"blast_radius": {
"type": "fixed",
"score": 0.2
},
"velocity": {
"type": "velocity_counter",
"window_seconds": 3600,
"thresholds": [
{ "count": 10, "score": 0.1 },
{ "count": 50, "score": 0.5 },
{ "count": 100, "score": 0.9 }
]
},
"privilege_level": {
"type": "fixed",
"score": 0.5
}
}
}
}The scoring types are:
- **fixed**: a constant score regardless of parameters
- **threshold**: a stepped score based on a numeric parameter
- **lookup**: a score based on whether a value is in a known set (e.g., known vendors vs. unknown vendors)
- **velocity_counter**: a score based on how many times this intent has been executed recently
- **time_window**: a score based on the current time (business hours vs. off-hours)
The composite risk score is a weighted average of the eight dimension scores. You define the weights in the risk model:
{
"composite_weights": {
"financial_impact": 0.25,
"data_sensitivity": 0.05,
"operational_risk": 0.15,
"compliance_exposure": 0.15,
"reversibility": 0.10,
"blast_radius": 0.05,
"velocity": 0.15,
"privilege_level": 0.10
}
}Different domains weight dimensions differently. A procurement domain pack weights financial impact and compliance exposure heavily. An infrastructure domain pack weights blast radius and reversibility heavily. The weights reflect what matters most in your domain.
Step 3: Define Baselines
Baselines establish what normal agent behavior looks like in your domain. They are used for anomaly detection: when an agent's behavior deviates significantly from its baseline, the risk scores increase.
{
"baselines": {
"procurement-agent": {
"daily_intent_counts": {
"procurement.po.create": { "mean": 25, "stddev": 8 },
"procurement.vendor.create": { "mean": 2, "stddev": 2 },
"procurement.invoice.process": { "mean": 40, "stddev": 12 }
},
"typical_amounts": {
"procurement.po.create": { "p50": 5000, "p95": 45000, "p99": 80000 },
"procurement.invoice.process": { "p50": 3000, "p95": 25000, "p99": 60000 }
},
"active_hours": { "start": "08:00", "end": "18:00", "timezone": "America/New_York" }
}
}
}Baselines can be seeded manually or computed from historical data. Intended provides a baseline computation API that analyzes the last 30 days of agent activity and generates baseline profiles. The baselines update continuously as the agent's behavior evolves.
Step 4: Define Thresholds
Thresholds map composite risk scores to decisions:
{
"thresholds": {
"default": {
"auto_approve_below": 0.4,
"escalate_between": [0.4, 0.8],
"deny_above": 0.8
},
"procurement.po.create": {
"auto_approve_below": 0.3,
"escalate_between": [0.3, 0.7],
"deny_above": 0.7
}
}
}Intent-specific thresholds override the default. You can be more restrictive for high-consequence intents and more permissive for routine intents.
Step 5: Package and Deploy
Combine the four sections into a single domain pack file and deploy it:
meritt domain-pack validate ./my-procurement-pack.json
meritt domain-pack deploy ./my-procurement-pack.json --org org_your_org_idThe validate command checks the pack for structural errors, referential integrity (every intent referenced in risk models exists in the intents section), and scoring function validity. The deploy command pushes the pack to Intended and activates it for your organization.
Versioning and Testing
Domain packs support versioning. You can deploy a new version without deactivating the current one, then switch traffic gradually:
meritt domain-pack deploy ./v2-pack.json --version 2.0
meritt domain-pack activate --version 2.0 --traffic-percent 10The traffic split lets you compare the behavior of the new pack against the old one in production. You can monitor the decision differences, identify unintended policy changes, and roll back if needed.
Best Practices
Start with a built-in domain pack and customize it rather than building from scratch. The built-in packs encode governance patterns that have been validated across many organizations.
Define intents at the right granularity. Too coarse (e.g., "procurement.write") and you lose the ability to distinguish between very different actions. Too fine (e.g., "procurement.po.create.domestic.under-1000.known-vendor") and your policy configuration becomes unmanageable.
Review your baselines monthly. Agent behavior evolves as the organization changes. Baselines that were accurate three months ago may be stale today.
Test threshold changes in staging before production. A threshold change that looks minor can shift hundreds of decisions from auto-approve to escalate, overwhelming your review team.
Custom domain packs are what turn Intended from a generic authority runtime into your organization's specific governance model. The built-in packs get you started. Custom packs get you to production.