Framework-agnostic Python SDK for enforcing behavioral policies between agents in multi-agent pipelines
Project description
NormLayer
A framework-agnostic Python SDK that enforces behavioral policies between agents at runtime in multi-agent pipelines.
The Problem
When multiple agents work together (one planning, one executing, one reviewing) there is no standard way to enforce how they behave toward each other. Existing safety tools focus on agent-to-human behavior. NormLayer focuses on agent-to-agent behavior: detecting deception between agents, enforcing role boundaries, catching collusion, and escalating conflicts — all at runtime, across any framework.
Installation
# Core SDK (no heavy dependencies)
pip install normlayer
# With semantic scoring for NoDeception policy
pip install normlayer[embeddings]
# With AWS S3 logging + SageMaker audit
pip install normlayer[aws]
# Everything
pip install normlayer[all]
Quick Start
from normlayer import PolicyEngine, policies
engine = PolicyEngine(
policies=[
policies.NoDeception(threshold=0.8, handler="escalate"),
policies.RoleRespect(strict=True, handler="block"),
policies.EscalateOnConflict(to="supervisor_agent"),
policies.LoopDetection(max_repetitions=3, handler="warn"),
policies.NoUnsanctionedAction(
permissions={"worker": ["execute", "update"]},
handler="block",
),
],
)
# Use as a decorator
@engine.enforce
def my_agent(message, context):
return response
# Or wrap an existing agent inline
safe_agent = engine.wrap(existing_agent)
Built-in Policies
| Policy | Description | Default Handler |
|---|---|---|
NoDeception |
Detects when an agent misrepresents information to another agent using embedding similarity | warn |
RoleRespect |
Flags agents operating outside their defined role/scope | warn |
EscalateOnConflict |
Triggers escalation to a supervisor when agents disagree past a threshold | escalate |
LoopDetection |
Detects agents stuck in unproductive repetitive exchanges | warn |
ResponseProportionality |
Catches disproportionate responses relative to the triggering input | warn |
CoalitionConsistency |
Checks whether agents apply norms consistently across in-group vs. out-group | warn |
NormConflictResolution |
Detects contradictory directives given to an agent (e.g., "be brief" + "be thorough") | warn |
NoUnsanctionedAction |
Enforces action allowlists per agent — blocks unauthorized actions | block |
Framework Adapters
NormLayer works with any multi-agent framework through thin adapters.
LangGraph
from normlayer.adapters import LangGraphAdapter
adapter = LangGraphAdapter(engine)
safe_graph = adapter.wrap(compiled_graph)
result = safe_graph.invoke({"messages": [HumanMessage(content="Plan the task")]})
CrewAI
from normlayer.adapters import CrewAIAdapter
adapter = CrewAIAdapter(engine)
safe_crew = adapter.wrap(my_crew)
result = safe_crew.kickoff()
AutoGen
from normlayer.adapters import AutoGenAdapter
adapter = AutoGenAdapter(engine)
safe_agent = adapter.wrap(my_agent)
response = await safe_agent.on_messages(messages, cancellation_token)
AWS Integration
S3 Violation Logging
engine = PolicyEngine(
policies=[...],
aws_bucket="my-normlayer-logs",
aws_region="us-east-1",
)
# Violations are automatically shipped to S3
# Flush buffered violations manually if needed
engine.flush_violations()
SageMaker Batch Audit
from normlayer.logging import SageMakerAuditJob
job = SageMakerAuditJob(
role_arn="arn:aws:iam::123456789:role/SageMakerRole",
input_s3_uri="s3://my-normlayer-logs/violations/",
output_s3_uri="s3://my-normlayer-logs/audit-results/",
)
job.run()
print(job.status())
Handler Actions
Each policy can dispatch one of four handler actions on violation:
| Handler | Behavior |
|---|---|
block |
Raises EnforcementError, stopping the message |
warn |
Logs the violation but allows the message through |
escalate |
Routes to a designated supervisor agent |
log |
Records silently for audit; no visible action |
Examples
See the examples/ directory for demo notebooks:
langgraph_demo.ipynb— wrapping a LangGraph compiled graphcrewai_demo.ipynb— wrapping a CrewAI crewautogen_demo.ipynb— wrapping an AutoGen agent
Development
# Clone and install dev dependencies
git clone https://github.com/baekbyte/NormLayer.git
cd normlayer
pip install -e ".[dev]"
# Run tests
pytest --tb=short -q
# Type checking
mypy normlayer/
Contributing
Contributions are welcome! Please open an issue or pull request on GitHub.
- Fork the repository
- Create a feature branch (
git checkout -b feature/my-feature) - Write tests for your changes
- Ensure all tests pass (
pytest) - Submit a pull request
License
MIT License. See LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file normlayer-0.1.0.tar.gz.
File metadata
- Download URL: normlayer-0.1.0.tar.gz
- Upload date:
- Size: 28.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
583de373ae2a55ee44b2366b14c65fc48fe82aaa077d19aad4fceed6a72a45af
|
|
| MD5 |
55ee1a445de0bc881387a07dff3c5cfc
|
|
| BLAKE2b-256 |
b715bc0303cb8d0a0e4a21c248174b8044032c959a427f93008d74c385b5dbf6
|
Provenance
The following attestation bundles were made for normlayer-0.1.0.tar.gz:
Publisher:
ci.yml on baekbyte/NormLayer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
normlayer-0.1.0.tar.gz -
Subject digest:
583de373ae2a55ee44b2366b14c65fc48fe82aaa077d19aad4fceed6a72a45af - Sigstore transparency entry: 1023999783
- Sigstore integration time:
-
Permalink:
baekbyte/NormLayer@d9fa5b2a1a940712e068dab5da4a9b5f67c9a20b -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/baekbyte
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@d9fa5b2a1a940712e068dab5da4a9b5f67c9a20b -
Trigger Event:
release
-
Statement type:
File details
Details for the file normlayer-0.1.0-py3-none-any.whl.
File metadata
- Download URL: normlayer-0.1.0-py3-none-any.whl
- Upload date:
- Size: 35.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e3858485a815d0ce621816535d741d4f3c742a12eed96097ab73a153d831a933
|
|
| MD5 |
29bc155ae0661be812ad623af12253ff
|
|
| BLAKE2b-256 |
7240628c76f7560468f7d2cf7e1f229b6a3069cd4c039ac810ab17e134f948f9
|
Provenance
The following attestation bundles were made for normlayer-0.1.0-py3-none-any.whl:
Publisher:
ci.yml on baekbyte/NormLayer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
normlayer-0.1.0-py3-none-any.whl -
Subject digest:
e3858485a815d0ce621816535d741d4f3c742a12eed96097ab73a153d831a933 - Sigstore transparency entry: 1023999852
- Sigstore integration time:
-
Permalink:
baekbyte/NormLayer@d9fa5b2a1a940712e068dab5da4a9b5f67c9a20b -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/baekbyte
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@d9fa5b2a1a940712e068dab5da4a9b5f67c9a20b -
Trigger Event:
release
-
Statement type: