Governance in Motion SDK -- runtime governance for AI agents
Project description
Governance in Motion SDK
Runtime governance enforcement for AI agents. Every tool call your agent makes is checked against your governance policies and delegation contracts before it executes.
Installation
pip install gim-sdk
With LangChain support:
pip install gim-sdk[langchain]
Quick Start
from gim_sdk import GIMAgent
agent = GIMAgent(
gateway_url="http://localhost:8001",
agent_id="my-agent-001",
tenant_id="00000000-0000-0000-0000-000000000001",
)
# Check before acting
decision = agent.check("http_request", domain="api.example.com", method="GET")
if decision.allowed:
response = requests.get("https://api.example.com/data")
elif decision.denied:
print(f"Blocked: {decision.explanation}")
elif decision.requires_approval:
print(f"Waiting for approval: {decision.approval_id}")
Environment Variables
Set these instead of passing constructor args:
export GIM_GATEWAY_URL="http://localhost:8001"
export GIM_AGENT_ID="my-agent-001"
export GIM_TENANT_ID="00000000-0000-0000-0000-000000000001"
export GIM_ENVIRONMENT="prod"
Then just:
from gim_sdk import GIMAgent
agent = GIMAgent() # reads from env
Action Types
HTTP Request
decision = agent.check(
action_type="http_request",
domain="api.stripe.com",
method="POST",
body={"amount": 1000},
)
Send Message
decision = agent.check(
action_type="send_message",
recipient="customer@example.com",
data_class="internal",
)
Database Query
decision = agent.check(
action_type="query_db",
db="production",
table="users",
)
Decision Object
decision.allowed # bool — True if ALLOW
decision.denied # bool — True if DENY
decision.requires_approval # bool — True if REQUIRE_APPROVAL
decision.redacted # bool — True if REDACT
decision.explanation # str — human-readable reason
decision.policy_id # str — which policy matched
decision.approval_id # str — approval request ID (if pending)
decision.redacted_fields # list — fields that were masked
# Raise exception instead of checking manually
decision.raise_if_denied() # raises GovernanceError on DENY
decision.raise_if_not_allowed() # raises GovernanceError on anything except ALLOW
Error Handling
from gim_sdk import GIMAgent, GovernanceError
agent = GIMAgent(...)
try:
decision = agent.check("http_request", domain="api.example.com")
decision.raise_if_denied()
# safe to proceed
except GovernanceError as e:
print(f"Governance blocked: {e}")
print(f"Decision was: {e.decision.decision}")
Gateway Unreachable
If the gateway is down, the SDK returns DENY by default (fail-closed):
decision = agent.check("http_request", domain="api.example.com")
# If gateway is unreachable:
# decision.denied == True
# decision.explanation == "Gateway unreachable — action blocked by default"
LangChain Integration
Wrap a tool
from langchain.tools import tool
from gim_sdk import GIMAgent
agent = GIMAgent(...)
@tool
def search_web(query: str) -> str:
"""Search the web for information."""
return requests.get(f"https://api.search.com?q={query}").text
# Wrap with governance
governed_search = agent.as_langchain_tool(
search_web,
action_type="http_request",
domain="api.search.com",
)
# Use in your agent as normal — governance runs automatically
Callback handler (intercepts all tools)
from langchain.agents import AgentExecutor
executor = AgentExecutor(
agent=llm_agent,
tools=tools,
callbacks=[agent.as_langchain_callback()],
)
# Every tool call now goes through governance before executing
Full ActionEvent (advanced)
from gim_sdk import GIMAgent, ActionEvent
agent = GIMAgent(...)
event = ActionEvent(
tenant_id = "00000000-...",
agent_id = "my-agent-001",
action_type = "http_request",
tool_name = "stripe_charge",
target = {"domain": "api.stripe.com", "method": "POST"},
request = {"body": {"amount": 5000, "currency": "usd"}},
context = {
"data_class": "confidential",
"tags": ["verified", "production-ready"],
"user_id": "user-123",
},
environment = "prod",
)
decision = agent.invoke(event)
Demo (works with local dev stack)
from gim_sdk import GIMAgent
agent = GIMAgent(
gateway_url = "http://localhost:8001",
agent_id = "demo-agent-001",
tenant_id = "00000000-0000-0000-0000-000000000001",
environment = "dev",
)
# Should ALLOW (if policy permits)
d = agent.check("http_request", domain="api.example.com")
print(d) # Decision(ALLOW: Permitted by policy)
# Should DENY (if blocklist policy active)
d = agent.check("http_request", domain="evil.com")
print(d) # Decision(DENY: Domain blocked by policy)
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 gim_sdk-1.0.0.tar.gz.
File metadata
- Download URL: gim_sdk-1.0.0.tar.gz
- Upload date:
- Size: 8.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
75686664cd6781a0f50b9d8df53ea76014c75988ae70e5810df03b03c34b55da
|
|
| MD5 |
29bb1956738ef239b41d8d1e56804d12
|
|
| BLAKE2b-256 |
818439e5f04330343da20e4ff420fd0728a44e83c3dce5c41a3327268183bce7
|
File details
Details for the file gim_sdk-1.0.0-py3-none-any.whl.
File metadata
- Download URL: gim_sdk-1.0.0-py3-none-any.whl
- Upload date:
- Size: 7.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7034d944864525319e54f725fad6235e4f0f5d4222dbe89c0170a60e7263a3d2
|
|
| MD5 |
04a33cfdbb5a0d89e7f5d2adca583d0c
|
|
| BLAKE2b-256 |
78aee1a8602d11a24d97a701f1cf7faac1b2ae77ef16add35bb46611e5fc16bc
|