Skip to content

Policy pack setup

This page walks you through setting up your first custom policy pack using the Arbitex API. It covers creating a pack, adding rules, configuring the org policy chain, and testing your configuration with the simulate endpoint.

A note on scope: the admin UI for policy management is not yet available. All configuration shown here uses the API directly. The same operations will be available in the UI when it ships — the data model is identical.

For a conceptual explanation of how packs, rules, chains, and evaluation work, read Policy Engine overview first. This page focuses on the mechanics of creating and configuring those objects.


A custom policy pack is a named container for your enforcement rules. You create it once, then add rules to it. The pack is not active until you add it to your org policy chain.

Terminal window
POST https://api.arbitex.ai/api/admin/orgs/{org_id}/policy/packs
Authorization: Bearer arb_live_your-api-key-here
Content-Type: application/json
{
"name": "Trading Desk Rules",
"description": "Enforcement rules for the trading desk group.",
"pack_type": "custom"
}
{
"pack_id": "pack_01HZ_TRADING_DESK",
"name": "Trading Desk Rules",
"description": "Enforcement rules for the trading desk group.",
"pack_type": "custom",
"created_at": "2026-03-08T14:00:00Z",
"rule_count": 0
}

Save the pack_id — you will use it when adding rules and when configuring the chain.


Adding a rule: block OpenAI for the no-openai group

Section titled “Adding a rule: block OpenAI for the no-openai group”

This rule blocks all requests to OpenAI for users in the no-openai group. It uses two conditions that both must match: the user must be in the group, and the request must be destined for the OpenAI provider.

Terminal window
POST https://api.arbitex.ai/api/admin/orgs/{org_id}/policy/packs/{pack_id}/rules
Authorization: Bearer arb_live_your-api-key-here
Content-Type: application/json
{
"name": "Block OpenAI for no-openai group",
"sequence": 10,
"applies_to": "input",
"conditions": {
"user_groups": ["no-openai"],
"providers": ["openai"]
},
"action": "BLOCK",
"message": "OpenAI access is not permitted for your group. Use the approved provider list instead."
}
{
"rule_id": "rule_01HZ_BLOCK_OPENAI",
"pack_id": "pack_01HZ_TRADING_DESK",
"name": "Block OpenAI for no-openai group",
"sequence": 10,
"applies_to": "input",
"conditions": {
"user_groups": ["no-openai"],
"providers": ["openai"]
},
"action": "BLOCK",
"message": "OpenAI access is not permitted for your group. Use the approved provider list instead.",
"created_at": "2026-03-08T14:01:00Z"
}

The sequence field controls evaluation order within the pack. Lower numbers evaluate first. Leave gaps between sequence numbers (10, 20, 30) so you can insert rules later without renumbering.

The message field is optional. When set, it appears in the 403 policy_block error response body that the caller receives. Write messages that tell the user what to do rather than just what was blocked — they may be shown in UI surfaces.


Adding a rule: redact credit cards globally

Section titled “Adding a rule: redact credit cards globally”

This rule applies to all users and all providers. It has no group condition — any request containing a credit card number gets the card number redacted before the prompt is forwarded. Unlike BLOCK, the REDACT action is non-terminal: other rules continue to evaluate after redaction runs.

Terminal window
POST https://api.arbitex.ai/api/admin/orgs/{org_id}/policy/packs/{pack_id}/rules
Authorization: Bearer arb_live_your-api-key-here
Content-Type: application/json
{
"name": "Redact credit cards globally",
"sequence": 20,
"applies_to": "both",
"conditions": {
"entity_types": ["credit_card"],
"entity_confidence_min": 0.85
},
"action": "REDACT",
"redact_replacement": "[CC-REMOVED]"
}
{
"rule_id": "rule_01HZ_REDACT_CC",
"pack_id": "pack_01HZ_TRADING_DESK",
"name": "Redact credit cards globally",
"sequence": 20,
"applies_to": "both",
"conditions": {
"entity_types": ["credit_card"],
"entity_confidence_min": 0.85
},
"action": "REDACT",
"redact_replacement": "[CC-REMOVED]",
"created_at": "2026-03-08T14:02:00Z"
}

Setting applies_to: "both" means this rule runs on both the user’s input prompt and the model’s output response. If the model echoes a credit card number in its reply, the rule fires on output as well.

Setting entity_confidence_min: 0.85 means only detections with a DLP confidence score of 0.85 or above trigger the rule. This reduces false positives from the NER tier on strings that look like card numbers but fail contextual validation.


Once your pack is ready, add it to your organization’s policy chain. The chain controls which packs are active and in what evaluation order. Sequence values determine precedence: lower sequences are evaluated first.

Terminal window
PUT https://api.arbitex.ai/api/admin/orgs/{org_id}/policy/chain
Authorization: Bearer arb_live_your-api-key-here
Content-Type: application/json
{
"combining_algorithm": "first_applicable",
"packs": [
{
"pack_id": "pack_01HZ_TRADING_DESK",
"sequence": 10
}
]
}
{
"org_id": "org_acme",
"combining_algorithm": "first_applicable",
"packs": [
{
"pack_id": "pack_01HZ_TRADING_DESK",
"sequence": 10,
"pack_name": "Trading Desk Rules",
"pack_type": "custom",
"rule_count": 2
}
],
"updated_at": "2026-03-08T14:05:00Z"
}

The PUT /policy/chain endpoint replaces the full chain. If you have existing packs in the chain, include them all in the request body — omitting a pack removes it from the chain.

combining_algorithm: "first_applicable" is the recommended setting for most organizations. The first terminal match wins. See Policy Engine overview — Combining algorithm for when to use deny_overrides instead.

To add a compliance bundle alongside your custom pack, include its pack_id in the same packs array. Compliance bundle pack IDs are retrievable from GET /api/admin/orgs/{org_id}/policy/bundles.


Before your policy changes affect live traffic, use the simulate endpoint to verify rule behavior. The simulate endpoint runs a synthetic request through the full policy evaluation pipeline without forwarding the request to any model provider.

Terminal window
POST https://api.arbitex.ai/api/admin/orgs/{org_id}/policy/simulate
Authorization: Bearer arb_live_your-api-key-here
Content-Type: application/json
{
"user_id": "usr_test_trader",
"user_groups": ["no-openai"],
"provider": "openai",
"model": "gpt-4o",
"prompt": "Explain the mechanics of a credit default swap."
}
{
"outcome": "BLOCK",
"matched_pack_id": "pack_01HZ_TRADING_DESK",
"matched_rule_id": "rule_01HZ_BLOCK_OPENAI",
"matched_rule_name": "Block OpenAI for no-openai group",
"matched_sequence": 10,
"match_reason": "user_groups matched ['no-openai']; providers matched ['openai']",
"action_taken": "BLOCK",
"message": "OpenAI access is not permitted for your group. Use the approved provider list instead.",
"dlp_findings": []
}

The response shows exactly which pack and rule matched, at which sequence position, and why. This is the same information that appears in a real audit log entry.

Simulate a request that should be redacted

Section titled “Simulate a request that should be redacted”
Terminal window
POST https://api.arbitex.ai/api/admin/orgs/{org_id}/policy/simulate
Authorization: Bearer arb_live_your-api-key-here
Content-Type: application/json
{
"user_id": "usr_test_analyst",
"user_groups": ["finance"],
"provider": "anthropic",
"model": "claude-sonnet-4-20250514",
"prompt": "The cardholder's Visa number is 4111111111111111 — is this valid?"
}
{
"outcome": "REDACT",
"matched_pack_id": "pack_01HZ_TRADING_DESK",
"matched_rule_id": "rule_01HZ_REDACT_CC",
"matched_rule_name": "Redact credit cards globally",
"matched_sequence": 20,
"match_reason": "entity_types detected: credit_card (confidence 0.98)",
"action_taken": "REDACT",
"redacted_prompt": "The cardholder's Visa number is [CC-REMOVED] — is this valid?",
"dlp_findings": [
{
"entity_type": "credit_card",
"tier": 1,
"confidence": 0.98,
"offset": 34,
"length": 16
}
]
}

The redacted_prompt field in the simulate response shows you exactly what would be forwarded to the upstream provider after redaction. Use this to verify that your entity_confidence_min threshold is set appropriately and that the replacement string looks correct in context.

Simulate a request that should pass through

Section titled “Simulate a request that should pass through”
Terminal window
POST https://api.arbitex.ai/api/admin/orgs/{org_id}/policy/simulate
Authorization: Bearer arb_live_your-api-key-here
Content-Type: application/json
{
"user_id": "usr_test_analyst",
"user_groups": ["finance"],
"provider": "anthropic",
"model": "claude-sonnet-4-20250514",
"prompt": "Summarize the key provisions of SOX Section 404."
}
{
"outcome": "ALLOW",
"matched_pack_id": null,
"matched_rule_id": null,
"match_reason": "No rule matched. Default action: ALLOW.",
"action_taken": "ALLOW",
"dlp_findings": []
}

A null match result means no rule in the chain matched this request. The default terminal action is ALLOW. If your posture requires that anything not explicitly permitted is denied, add a catch-all BLOCK rule with no conditions at a high sequence number (for example, sequence=999) as described in Policy Engine overview — Default terminal action.


PATCH a rule to change specific fields without replacing the whole object:

Terminal window
PATCH https://api.arbitex.ai/api/admin/orgs/{org_id}/policy/packs/{pack_id}/rules/{rule_id}
Authorization: Bearer arb_live_your-api-key-here
Content-Type: application/json
{
"entity_confidence_min": 0.90,
"message": "Updated block message."
}

Only the fields you include are updated. Fields you omit retain their current values.

Terminal window
DELETE https://api.arbitex.ai/api/admin/orgs/{org_id}/policy/packs/{pack_id}/rules/{rule_id}
Authorization: Bearer arb_live_your-api-key-here

Returns 204 No Content on success. The deletion takes effect immediately for new requests. In-flight requests that are already mid-evaluation are not affected.