Skip to main content
Sign in →
API & SDK

Python SDK

The official shieldagent Python package provides a typed client for the ShieldAgent REST API. Requires Python 3.10+.

Installation

Not yet on PyPI

The shieldagent package has not been published to PyPI yet. Install from the source repository:

bash
git clone https://github.com/shieldagent-io/shieldagent.git
pip install -e ./shieldagent/backend/packages/sdk-python

Quick start

example.py
from shieldagent import ShieldAgentClient

client = ShieldAgentClient(
    api_key="{your-api-key}",
    base_url="https://api.shieldagent.io",
)

# List agents for a tenant
agents = client.agents.list(tenant_id="ten_abc123")
print(agents)

# Register a new agent
agent = client.agents.create(
    tenant_id="ten_abc123",
    name="my-assistant",
    description="Python-based coding agent",
)
print(agent.agent_key)  # sa_live_...

# Fetch recent audit events
events = client.audit.list(
    tenant_id="ten_abc123",
    limit=50,
    order="desc",
)
for event in events:
    print(event.tool, event.decision, event.risk_score)

Proxy-forwarding API calls

Use client.api_proxy() to route agent REST calls through ShieldAgent. Every request is authenticated, policy-checked, DLP-scanned, and audit-logged before being forwarded to the registered upstream.

proxy_examples.py
import asyncio
from shieldagent import ShieldAgentClient, ForbiddenError, RateLimitError, BadGatewayError

async def main():
    async with ShieldAgentClient(
        api_key="{your-agent-key}",
        base_url="https://proxy.shieldagent.io",
    ) as client:

        # ── POST through the proxy ────────────────────────────────────────
        charge = await client.api_proxy(
            "stripe", "POST", "/charges",
            json={"amount": 2000, "currency": "usd", "source": "tok_visa"},
        )

        # ── GET a specific resource ───────────────────────────────────────
        customer = await client.api_proxy(
            "stripe", "GET", "/customers/cus_abc123",
        )

        # ── Send a Slack message ──────────────────────────────────────────
        await client.api_proxy(
            "slack", "POST", "/chat.postMessage",
            json={"channel": "#alerts", "text": "Anomaly detected"},
        )

        # ── Call an internal microservice ─────────────────────────────────
        result = await client.api_proxy(
            "order-service", "POST", "/orders",
            json={"customer_id": "cust_42", "items": [{"sku": "ABC", "qty": 1}]},
        )

        # ── Error handling ────────────────────────────────────────────────
        try:
            await client.api_proxy("stripe", "DELETE", "/charges/ch_123")
        except ForbiddenError as e:
            print("Blocked by policy:", e.code, e.message)
        except RateLimitError as e:
            print("Rate limited. Retry after:", e.retry_after)
        except BadGatewayError as e:
            print("Upstream error:", e.message)

asyncio.run(main())

For the synchronous client, use SyncShieldAgentClient — same method signature without await:

proxy_sync.py
from shieldagent import SyncShieldAgentClient

with SyncShieldAgentClient(api_key="...", base_url="...") as client:
    charge = client.api_proxy(
        "stripe", "POST", "/charges",
        json={"amount": 2000, "currency": "usd", "source": "tok_visa"},
    )

Verdict API — scan & confirm

Use client.scan() to submit a tool call to ShieldAgent before executing it. The proxy returns a verdict (allow / block / human_review) but does not enforce it— your code must check the verdict and block execution when the action is "block". Call client.confirm_execution() afterwards to close the audit loop and support EU AI Act Art. 9 compliance claims.

When the proxy runs on a different host from the Management API, pass proxy_url to the client constructor.

verdict_api.py
import asyncio
from shieldagent import ShieldAgentClient

async def main():
    async with ShieldAgentClient(
        api_key="{your-agent-key}",
        base_url="https://api.shieldagent.io",
        proxy_url="https://proxy.shieldagent.io",
    ) as client:

        # ── 1. Scan before executing ──────────────────────────────────────
        verdict = await client.scan(
            tenant_id="ten_abc123",
            tool_name="read_file",
            params={"path": "/etc/passwd"},
            agent_id="agt_xyz789",       # optional — improves policy matching
            include_findings=True,        # optional — request detailed findings
        )

        # IMPORTANT: YOU must enforce the verdict. ShieldAgent does not block.
        if verdict.action == "block":
            raise RuntimeError(f"Tool call blocked: {verdict.reason}")
        if verdict.action == "human_review":
            raise RuntimeError(
                f"Tool call requires human review (review_id: {verdict.review_id})"
            )

        # ── 2. Execute the tool ───────────────────────────────────────────
        file_content = read_file("/etc/passwd")

        # ── 3. Confirm execution to close the audit loop ──────────────────
        await client.confirm_execution(
            "ten_abc123", verdict.audit_event_id, executed=True
        )

        # ── Verdict fields ────────────────────────────────────────────────
        # verdict.action         — 'allow' | 'block' | 'human_review'
        # verdict.reason         — human-readable explanation
        # verdict.risk_score     — 0–100 risk score at scan time
        # verdict.audit_event_id — use with confirm_execution()
        # verdict.review_id      — set when action is 'human_review', else None
        # verdict.findings       — list of findings (when include_findings=True)

asyncio.run(main())

For the synchronous client, use the same methods without await:

verdict_api_sync.py
from shieldagent import SyncShieldAgentClient

with SyncShieldAgentClient(api_key="...", base_url="...", proxy_url="...") as client:
    verdict = client.scan("ten_abc123", "read_file", {"path": "/etc/passwd"})
    if verdict.action == "block":
        raise RuntimeError(verdict.reason)
    # ... execute tool ...
    client.confirm_execution("ten_abc123", verdict.audit_event_id, executed=True)

Policy management

policies.py
async with ShieldAgentClient(api_key="...", base_url="...") as client:
    # Apply a built-in template to the tenant
    result = await client.policy_templates.apply("ten_abc123", "pii-protection")
    print(f"Created {result.policies_created} policies from '{result.template_name}'")

    # Block DELETE on the Stripe endpoint for a specific agent
    await client.policies.create(
        "ten_abc123",
        agent_id=agent.id,
        tool_name="rest:stripe",
        action="deny",
        conditions={"method": "DELETE"},
    )

    # List active policies for an agent
    policies = await client.policies.list("ten_abc123", agent_id=agent.id)
    for p in policies.data:
        print(p.tool_name, p.action)

Risk monitoring & anomaly detection

risk.py
async with ShieldAgentClient(api_key="...", base_url="...") as client:
    # Get current risk scores
    scores = await client.risk.list("ten_abc123")
    high_risk = [s for s in scores.data if s.risk_tier in ("high", "critical")]
    print("High-risk agents:", [s.agent_name for s in high_risk])

    # Drill into a specific agent's risk trend
    detail = await client.risk.get_detail("ten_abc123", agent.id)
    print(f"Risk: {detail.score} ({detail.trend}) — delta 24h: {detail.delta_vs_24h}")

    # Batch anomaly analysis over the last 24 hours
    anomalies = await client.anomalies.analyze_batch(
        "ten_abc123", agent_id=agent.id, window_hours=24
    )
    if anomalies.anomalies_detected:
        for a in anomalies.results:
            print(f"Anomaly [{a.anomaly_type}] score={a.anomaly_score:.2f} — {a.explanation}")

Incident & review workflows

incidents.py
async with ShieldAgentClient(api_key="...", base_url="...") as client:
    # Open an incident for a detected threat
    incident = await client.incidents.create(
        "ten_abc123",
        agent_id=agent.id,
        title="Prompt injection detected in session ses_xyz",
        severity="critical",
        type="injection",
        data={"session_id": "ses_xyz"},
    )

    # Move to investigating
    await client.incidents.update(incident.id, status="investigating")

    # Process the human-review queue
    pending = await client.reviews.list("ten_abc123", status="pending")
    for review in pending.data:
        decision = "denied" if "stripe" in review.tool_name else "approved"
        await client.reviews.decide(
            review.id, decision=decision, comment="Reviewed by on-call"
        )

Async support

Async vs sync — which client to use?

ShieldAgentClientasync/awaitFastAPI, asyncio applications, async agent frameworks (LangChain async, LlamaIndex).
SyncShieldAgentClientblockingScripts, CLI tools, Django, Flask, synchronous agent loops, Celery workers.

Both clients expose identical method signatures — switch by changing the import.

python
from shieldagent import ShieldAgentClient
import asyncio

async def main():
    async with ShieldAgentClient(api_key="...") as client:
        agents = await client.agents.list(tenant_id="ten_abc123")
        print(agents)

asyncio.run(main())

Error handling

python
from shieldagent import ShieldAgentError

try:
    client.agents.create(tenant_id="bad-id", name="x")
except ShieldAgentError as e:
    print(e.status, e.code, e.message)

Available resources

client.tenantslist, create, update, delete
client.agentslist, create, update, delete, rotate_key
client.policieslist, create, update, delete
client.policy_templateslist, apply
client.auditlist, verify
client.risklist, get_detail, calculate
client.compliancelist_reports, generate_report
client.incidentslist, create, update, get_counts
client.alertslist, create, update, delete, list_events
client.anomaliesanalyze, analyze_batch, list_events
client.reviewslist, decide, get_counts
client.api_proxy()GET, POST, PUT, PATCH, DELETE → upstream
client.scan()submit tool call for security verdict
client.confirm_execution()close audit loop after verdict
Python SDK