Skip to main content

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gim_sdk-1.0.0.tar.gz (8.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gim_sdk-1.0.0-py3-none-any.whl (7.5 kB view details)

Uploaded Python 3

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

Hashes for gim_sdk-1.0.0.tar.gz
Algorithm Hash digest
SHA256 75686664cd6781a0f50b9d8df53ea76014c75988ae70e5810df03b03c34b55da
MD5 29bb1956738ef239b41d8d1e56804d12
BLAKE2b-256 818439e5f04330343da20e4ff420fd0728a44e83c3dce5c41a3327268183bce7

See more details on using hashes here.

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

Hashes for gim_sdk-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7034d944864525319e54f725fad6235e4f0f5d4222dbe89c0170a60e7263a3d2
MD5 04a33cfdbb5a0d89e7f5d2adca583d0c
BLAKE2b-256 78aee1a8602d11a24d97a701f1cf7faac1b2ae77ef16add35bb46611e5fc16bc

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page