Skip to main content

ODIN HEL Policy Engine

Lightweight, embeddable policy engine for governing AI egress (URLs/hosts/methods) with:

  • Profiles: strict, medium, open
  • Allowlist: per-tenant overrides
  • Optional Rego (OPA) evaluation when rego_path provided and the opa binary is available

Install:

pip install odin-hel

Quick Start

from odin_hel import PolicyEngine, Decision

# Create a PolicyEngine with the default 'medium' profile
engine = PolicyEngine(profile="medium")

# Prepare a context for evaluation (simulate an API call)
ctx = {
  "tenant_id": "acme",
  "forward_url": "https://api.openai.com/v1/chat/completions",
  "method": "POST",
  "headers": {"authorization": "Bearer ..."},
  "payload_cid": "sha256:...",
  "attrs": {"user": "alice"}
}

# Evaluate the context
decision = engine.evaluate(ctx)
print(decision)
assert decision.allow

# Use a strict profile (deny by default)
engine_strict = PolicyEngine(profile="strict")
decision_strict = engine_strict.evaluate(ctx)
print(decision_strict)

# Use a custom allowlist
engine_custom = PolicyEngine(profile="strict", allowlist=["api.openai.com"])
decision_custom = engine_custom.evaluate(ctx)
print(decision_custom)

FAQ: Common Errors

Q: I get ModuleNotFoundError: No module named 'odin_hel' when running tests. A: Make sure your PYTHONPATH includes the src/ directory, e.g.:

export PYTHONPATH=./data/odin-hel/src
pytest

Or on Windows PowerShell:

$env:PYTHONPATH = 'data/odin-hel/src'; python -m pytest

Q: Why does my context get rejected with reason='no_host'? A: The context must include either a host or a valid forward_url field. If both are missing or invalid, the engine cannot determine the target host.

Q: How do I add a custom allowlist? A: Pass the allowlist argument to PolicyEngine, e.g. PolicyEngine(profile="strict", allowlist=["api.example.com"]).

Profiles

  • strict: deny by default, only explicit allowlist permits
  • medium: curated defaults for common AI API hosts + allowlist
  • open: allow all (useful for local/dev)

Rego (OPA) optional

If you pass rego_path="policies/egress.rego" and an opa binary is on PATH, the engine will evaluate data.odin.allow against the provided context and return that decision. If OPA or the policy is unavailable, the engine falls back to the profile/allowlist result (fail-closed when explicitly configured).


VS Code + Copilot

Recommended tasks:

  • Run tests: pytest
  • Add or refine allowlist defaults under profiles.py

Copilot prompts:

“Extend domain matching to support wildcards like *.example.com and add unit tests.”

“Add reason codes and structured details when a host is rejected (e.g., policy=profile_denied, match=none).”

“Implement a sample Rego policy and a smoke-test that is skipped when opa is not installed.”


Publishing

Use the included GitHub Actions workflow to publish on tag push (set PYPI_API_TOKEN in repo secrets).


License

Apache-2.0

Metadata

Release files for odin-hel 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for odin-hel 0.5.0
File Size Uploaded
odin_hel-0.5.0.tar.gz 7.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for odin-hel 0.5.0
File Interpreter ABI Platform
odin_hel-0.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 13.4 kB

Release files / odin_hel-0.5.0.tar.gz

Download URL odin_hel-0.5.0.tar.gz
Size 7.5 kB
Tags Source
SHA-256 checksum
How to use checksums
2e22390bf4d7178796d79cd1a313eeb33177a25f1151e3a1c195576b411f2176
BLAKE2b-256 checksum
How to use checksums
8bcaa904098472a717776e552b6a79b8e228672939f887c21e92c4a6eb385b7c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.7

Release files / odin_hel-0.5.0-py3-none-any.whl

Download URL odin_hel-0.5.0-py3-none-any.whl
Size 5.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0fe9cc3b5dd4cf498947da5c6b07fe8bfce8b328b060113b03a312bdbe471930
BLAKE2b-256 checksum
How to use checksums
a890143743e2651403412161ba9bf9213ac29afa9a2da710e3ecf388c0792f82
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.7

Release history Release notifications | RSS feed

This release

0.5.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page