Catalog PyPI
Back to packageRELEASE DETAILS

0.1.0

PyPI

agentplane-py

Runtime policy control plane for production AI agents. Block, degrade, escalate — without a redeploy.

agentscontrol-planeenterprisegovernanceguardrailsllmpolicyruntime
Published16 Jun 2026
Direct dependencies11
Transitive dependenciesNot calculated

README

Version 0.1.0 documentation
agentplane

CI PyPI Python License


agentplane is the runtime policy control plane for production AI agents.

OPA, Cedar, and Casbin answer "is this allowed?" at a point in time. agentplane answers "how should this agent behave right now, given everything that's happened" — and changes the answer without a redeploy.

wire-ai       → governance     (loops, HITL, SLA, audit)
agenthooks    → extensibility  (hookpoints, customer hooks)
agentplane    → control plane  (runtime policy, versioning, escalation)
AgentGuard    → safety         (injection, PII, toxic)
agent-gateway → routing        (protocol translation)

Why agentplane

OPA / Cedar / Casbinagentplane
Decision modelStatic yes/noStateful behavioral history
Runtime updateConfig reloadLive — no restart
VersioningExternalBuilt-in (diff, rollback, promote)
EscalationNoneChain: Alert → HITL → Degrade → Block
DegradationNoneModes with timed recovery
Agent-nativeNohookpoints, tenant_id, token/cost budgets
AuditExternalAppend-only JSONL, every evaluation

Install

pip install agentplane-py                     # zero-dependency core
pip install "agentplane-py[otel]"             # OpenTelemetry metrics + traces
pip install "agentplane-py[sqlite]"           # persistent SQLite store
pip install "agentplane-py[sync]"             # remote service sync
pip install "agentplane-py[all]"              # everything

Quickstart

import asyncio
from agentplane import (
    PolicyEngine, Policy, Selector, PolicyContext,
    AllowlistRule, RateRule, RedactRule, AuditRule,
)

async def main():
    engine = PolicyEngine()

    engine.add_policy(Policy(
        id="acme.data-access.v1",
        selector=Selector(tenants=["acme"], tools=["sql_run", "search"]),
        blocking=[
            AllowlistRule(tools=["sql_run", "search"]),
            RateRule(limit=100, window="1h", per="tenant"),
            RedactRule(fields=["ssn", "api_key", "password"]),
        ],
        non_blocking=[AuditRule()],
        priority=100,
    ))

    ctx = PolicyContext.new(
        agent_id="my-agent",
        tenant_id="acme",
        hookpoint="before_tool_call",
        tool_name="sql_run",
    )

    await engine.evaluate(ctx)   # raises PolicyBlocked or PolicyDegraded on enforcement

asyncio.run(main())

Blocking vs Non-Blocking Policies

Policy(
    id="prod.security",
    blocking=[
        # Agent waits. Raises PolicyBlocked or PolicyDegraded on failure.
        AllowlistRule(tools=["search", "read_file"]),
        RateRule(limit=50, window="1h"),
        RedactRule(fields=["ssn", "credit_card"]),
        InjectionScanRule(),
    ],
    non_blocking=[
        # Fire-and-forget. Agent never waits. Failures are silent.
        AuditRule(include_inputs=True),
        AlertRule(channel="slack", on="breach"),
        CostTrackingRule(track_per="tenant"),
        MetricsRule(emit_otel=True),
    ],
)

Escalation Chain

from agentplane import EscalationChain, EscalationLevel, Alert, Degrade, Block, HITL

escalation = EscalationChain([
    EscalationLevel(1, trigger="rate_breach",   action=Alert(channel="log")),
    EscalationLevel(2, trigger="rate_breach",   action=Degrade(mode="rate_throttle", recover_after="10m")),
    EscalationLevel(3, trigger="rate_breach",   action=Block(reason="Repeated violations")),
])

# Stateful — tracks history. 3 breaches in 10min escalates further than 1 breach a week ago.

Degradation Modes

from agentplane.degradation.modes import DegradationMode

engine.degrade("my-agent", DegradationMode.READ_ONLY,    recover_after="30m")
engine.degrade("my-agent", DegradationMode.NO_EXTERNAL,  recover_after="1h")
engine.degrade("my-agent", DegradationMode.SAFE_TOOLS_ONLY)
engine.degrade("my-agent", DegradationMode.FULL_BLOCK)
engine.recover("my-agent")  # manual recovery

Policy Versioning

from agentplane import VersionManager

vm = VersionManager()
vm.publish(policy_v1, changelog="Initial")
vm.publish(policy_v2, changelog="Tighten rate limit")

diff = vm.diff("acme.data-access", 1, 2)
# PolicyDiff(added_blocking=['RedactRule'], removed_blocking=[], ...)

restored = vm.rollback("acme.data-access", to_version=1)
# History is preserved — rollback creates v3, not a destructive reset

Decorators

from agentplane.engine.decorators import enforce, policy_guard, require_policy

@enforce(engine, hookpoint="before_tool_call", agent_id="my-agent", tenant_id="acme")
async def run_sql(query: str) -> str:
    ...

@policy_guard(engine, agent_id="my-agent", tenant_id="acme", on_block="skip")
async def delete_record(record_id: str) -> dict:
    ...  # returns None if blocked, never raises

@require_policy(engine, "prod.data-access")
async def export_data() -> bytes:
    ...  # raises PolicyBlocked if policy not active

Selectors — Fine-Grained Targeting

Selector(agents=["*"])                              # all agents
Selector(tenants=["acme", "siemens"])               # specific tenants
Selector(tools=["sql_run", "delete_*"])             # specific tools
Selector(hookpoints=["before_tool_call"])            # specific hookpoints
Selector(tags={"env": "prod", "tier": "premium"})   # tag-based
Selector(tenants=["acme"], tools=["sql_*"], tags={"env": "prod"})  # compound

Conflict Resolution

# Default: most restrictive wins (safe enterprise default)
Policy(id="p1", conflict_resolution=ConflictResolution.MOST_RESTRICTIVE, ...)

# Override: highest priority wins when it explicitly sets a value
Policy(id="p2", conflict_resolution=ConflictResolution.PRIORITY, priority=500, ...)

API Coverage

RuleTypeDescription
AllowlistRuleBlockingTool allowlist
DenylistRuleBlockingTool denylist
RedactRuleBlockingMark fields as redacted
RateRuleBlockingSliding-window rate limiter
RequireTenantRuleBlockingTenant allowlist
TokenBudgetRuleBlockingToken budget per window
CostBudgetRuleBlockingUSD cost budget per window
ApiAllowlistRuleBlockingAPI path/method allowlist
ApiDenylistRuleBlockingAPI path/method denylist
InjectionScanRuleBlockingPrompt injection detection
AuditRuleNon-blockingJSONL audit every evaluation
AlertRuleNon-blockingLog / webhook alerts
CostTrackingRuleNon-blockingCumulative cost tracking
MetricsRuleNon-blockingOTel metrics emission
PIIScanRuleNon-blockingPII detection

agenthooks Integration

from agenthooks import HookRegistry
from agentplane import PolicyEngine

engine = PolicyEngine()
engine.add_policy(my_policy)
engine.attach(registry)  # registers evaluation at before_tool_call + after_llm_response

Stack

agentplane-py  →  zero-dep core
├── [otel]     →  OpenTelemetry metrics + traces
├── [sqlite]   →  persistent policy store
├── [sync]     →  remote service sync (httpx)
└── [service]  →  REST API (FastAPI)

Apache 2.0 · Built for production enterprise agents

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Declared dependencies 16

Native requirements
11 direct targetsNot calculated transitive count
Package / targetRequirementRelationship
aiosqlite
Environment
{
  "extras": "",
  "marker": "extra == \"all\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
aiosqlite>=0.20; extra == "all"runtime
fastapi
Environment
{
  "extras": "",
  "marker": "extra == \"all\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
fastapi>=0.111; extra == "all"runtime
httpx
Environment
{
  "extras": "",
  "marker": "extra == \"all\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
httpx>=0.27; extra == "all"runtime
opentelemetry-api
Environment
{
  "extras": "",
  "marker": "extra == \"all\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
opentelemetry-api>=1.20; extra == "all"runtime
uvicorn
Environment
{
  "extras": "",
  "marker": "extra == \"all\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
uvicorn>=0.30; extra == "all"runtime
anyio
Environment
{
  "extras": "trio",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
anyio[trio]>=4.0; extra == "dev"runtime
mypy
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
mypy>=1.10; extra == "dev"runtime
pytest-asyncio
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
pytest-asyncio>=0.23; extra == "dev"runtime
pytest-cov
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
pytest-cov>=5.0; extra == "dev"runtime
pytest
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
pytest>=8.0; extra == "dev"runtime
ruff
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
ruff>=0.5; extra == "dev"runtime
opentelemetry-api
Environment
{
  "extras": "",
  "marker": "extra == \"otel\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
opentelemetry-api>=1.20; extra == "otel"runtime
fastapi
Environment
{
  "extras": "",
  "marker": "extra == \"service\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
fastapi>=0.111; extra == "service"runtime
uvicorn
Environment
{
  "extras": "",
  "marker": "extra == \"service\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
uvicorn>=0.30; extra == "service"runtime
aiosqlite
Environment
{
  "extras": "",
  "marker": "extra == \"sqlite\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
aiosqlite>=0.20; extra == "sqlite"runtime
httpx
Environment
{
  "extras": "",
  "marker": "extra == \"sync\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
httpx>=0.27; extra == "sync"runtime

Distribution files

2 collected
agentplane_py-0.1.0-py3-none-any.whl

bdist_wheel · 33.12 KB · Python py3

Source file
agentplane_py-0.1.0.tar.gz

sdist · 40.08 KB · Python source

Source file

Repository

PENDING
naveenkumarbaskaran/agentplane

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 22:54 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package_version:84769b6d07870ca6f28be8eaafac98f35e3d37a2da16d27d3264e51a06fd0146

Other collected versions

View all collected versions →