Runtime governance for AI agents. Evaluate, enforce, and audit every action your agent takes — before it executes.
pip install edonEDON sits between your agent's decision and execution. Before a tool runs, EDON evaluates it against your policy and returns a verdict:
- ALLOW → proceed
- BLOCK → action stopped, reason logged
- HUMAN_REQUIRED → escalate to a human before continuing
- DEGRADE → automatically substitute a safer alternative
Every decision is written to a tamper-evident audit trail. Compliance reports map to EU AI Act, NIST AI RMF, ISO 42001, and SOC2.
Sign up at edoncore.com → copy your API key.
pip install edonimport edon
edon.configure(api_key="your-key")
@edon.govern(action_type="email.send")
def send_email(to: str, subject: str, body: str) -> None:
# This only runs if EDON allows it
smtp_send(to, subject, body)
# If policy blocks this action, EdonBlockedError is raised
# and the function never executes
send_email("all@company.com", "Announcement", "...")from edon import EdonClient
client = EdonClient(api_key="your-key")
decision = client.evaluate(
action_type="email.send",
action_payload={"to": "user@example.com", "subject": "Hello"},
agent_id="my-agent",
)
if decision.allowed:
send_email(...)
elif decision.blocked:
print(f"Blocked: {decision.decision_reason}")
elif decision.needs_human:
print(f"Human approval required: {decision.escalation_question}")pip install 'edon[langchain]'from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain_community.tools import DuckDuckGoSearchRun, GmailSendMessage
from edon.integrations.langchain import EdonGuard
# Wrap your tools — same interface, now governed
tools = EdonGuard.wrap_tools(
tools=[DuckDuckGoSearchRun(), GmailSendMessage()],
api_key="your-edon-key",
agent_id="research-agent",
)
agent = create_tool_calling_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools)
executor.invoke({"input": "Search for AI news and email the summary to the team"})
# DuckDuckGo search → ALLOW ✓
# Gmail send → evaluated against policy before sendingAudit-only mode (non-blocking, pure observability):
from edon.integrations.langchain import EdonCallbackHandler
handler = EdonCallbackHandler(api_key="your-key", agent_id="my-agent", verbose=True)
executor = AgentExecutor(agent=agent, tools=tools, callbacks=[handler])
# All tool calls logged to EDON — no blockingpip install 'edon[openai]'from agents import Agent, Runner, function_tool
from edon.integrations.openai_agents import EdonToolGuard
@function_tool
def send_email(to: str, subject: str, body: str) -> str:
"""Send an email."""
...
@function_tool
def delete_records(table: str, condition: str) -> str:
"""Delete database records."""
...
# Govern before passing to Agent
governed = EdonToolGuard.wrap(
tools=[send_email, delete_records],
api_key="your-edon-key",
agent_id="my-openai-agent",
)
agent = Agent(name="Assistant", tools=governed)
result = Runner.run_sync(agent, "Delete all test records and notify the team")
# delete_records → likely BLOCKED (database.delete outside policy scope)
# send_email → evaluated by policypip install 'edon[crewai]'from crewai import Agent, Task, Crew
from crewai.tools import tool
from edon.integrations.crewai import EdonCrewGuard
@tool("Search the web")
def web_search(query: str) -> str:
"""Search for current information."""
...
@tool("Send email report")
def send_report(to: str, content: str) -> str:
"""Send a research report via email."""
...
# Govern all crew tools
governed = EdonCrewGuard.wrap_tools(
tools=[web_search, send_report],
api_key="your-edon-key",
agent_id="research-crew",
)
researcher = Agent(
role="Research Analyst",
goal="Find and summarize key information",
tools=governed,
)
crew = Crew(agents=[researcher], tasks=[...])
crew.kickoff()curl -X POST https://edon-gateway.fly.dev/v1/action \
-H "X-EDON-TOKEN: your-key" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "my-agent",
"action_type": "email.send",
"action_payload": {"to": "user@example.com", "subject": "Hello"},
"timestamp": "2026-03-10T12:00:00Z",
"context": {}
}'Response:
{
"action_id": "dec-abc123",
"decision": "ALLOW",
"decision_reason": "Action approved: email.send within scope, constraints satisfied.",
"policy_version": "1.0.0",
"processing_latency_ms": 12,
"reason_code": "APPROVED"
}# Install
pip install edon
export EDON_API_KEY=your-key
# Check gateway health
edon ping
# Evaluate an action
edon evaluate email.send --payload '{"to": "user@example.com", "subject": "Hello"}'
# View recent audit events
edon audit --limit 20
# View your policy rules
edon policy
# View available policy packs
edon packs| Verdict | Meaning | Agent action |
|---|---|---|
ALLOW |
Action is within policy | Proceed normally |
BLOCK |
Action violates policy | Do not execute — log reason |
HUMAN_REQUIRED |
Needs human approval | Pause and escalate |
DEGRADE |
Use safer alternative | Execute safe_alternative instead |
PAUSE |
Temporarily halted | Retry after delay |
Pre-built governance presets for common agent types:
| Pack | Use Case | Risk Level |
|---|---|---|
casual_user |
Everyday personal agents | LOW |
market_analyst |
Financial research agents | LOW |
founder_mode |
Power users, startup ops | MEDIUM |
ops_commander |
Workflow automation | MEDIUM |
helpdesk |
Customer support agents | LOW |
autonomy_mode |
Fully autonomous co-pilots | HIGH |
Apply a pack in the EDON console or via API — your agents pick up the new policy instantly.
from edon import EdonClient, EdonBlockedError, EdonEscalatedError
client = EdonClient(api_key="your-key", raise_on_block=True)
try:
decision = client.evaluate("shell.exec", {"command": "rm -rf /"})
except EdonBlockedError as e:
print(f"Blocked: {e.reason}")
print(f"Code: {e.reason_code}") # e.g. "OUT_OF_SCOPE"
print(f"Audit ID: {e.action_id}") # for the audit trail
except EdonEscalatedError as e:
print(f"Needs approval: {e.question}")
# Send e.question to your human review queue
# Resolve via EDON console or APIimport asyncio
from edon import AsyncEdonClient
async def main():
async with AsyncEdonClient(api_key="your-key") as client:
decision = await client.evaluate(
"email.send",
{"to": "user@example.com", "subject": "Hello"},
agent_id="async-agent",
)
print(decision.decision)
asyncio.run(main())| Variable | Description |
|---|---|
EDON_API_KEY |
Your EDON API key |
EDON_BASE_URL |
Gateway URL (default: https://edon-gateway.fly.dev) |
EDON_AGENT_ID |
Default agent identifier |
EDON_INTENT_ID |
Default intent contract ID |
EDON Gateway is open for self-deployment:
docker run -p 8000:8000 \
-e EDON_API_TOKEN=your-token \
ghcr.io/edoncore/edon-gateway:latestThen point the SDK at your instance:
client = EdonClient(api_key="your-token", base_url="http://localhost:8000")- Console: edoncore.com/console
- Docs: docs.edoncore.com
- Issues: github.com/edoncore/edon-python/issues
- Email: sdk@edoncore.com
MIT © EDON Core