Skip to main content

Official Shield SDK for Python

Project description

Shield Python SDK

Official Python SDK for Shield ??tamper-evident session recording for online business transactions.

Installation

pip install shield-python==0.5.0

Quick Start

import shield

client = shield.Client(api_key="sk_live_your_api_key")

# Create a session
session = client.sessions.create(title="Contract Negotiation with Acme Corp")
session_id = session["id"]

# Record events
client.events.create(
    session_id=session_id,
    event_type="shield.party.joined",
    actor="agent@example.com",
    data={"role": "listing_agent", "name": "Jane Smith"},
)

client.events.create(
    session_id=session_id,
    event_type="shield.content.uploaded",
    actor="agent@example.com",
    data={"filename": "purchase_agreement.pdf"},
)

client.events.create(
    session_id=session_id,
    event_type="shield.agreement.signed",
    actor="buyer@example.com",
    data={"document": "purchase_agreement.pdf"},
)

# Verify session integrity
result = client.verify.session(session_id)
print(result["valid"])  # True

# Export session
pdf_bytes = client.sessions.export(session_id, format="pdf")
with open("audit_trail.pdf", "wb") as f:
    f.write(pdf_bytes)

Recording AI Agent Evidence

import hashlib

# Hash content locally — never send raw prompts or outputs to Shield
prompt_hash = hashlib.sha256(my_prompt.encode()).hexdigest()
output_hash = hashlib.sha256(agent_output.encode()).hexdigest()

event = client.agent.log_action(
    session_id,
    "shield.content.submitted",
    agent_id="agt-unique-identifier",
    agent_name="gpt-4o",
    agent_provider="OpenAI",
    principal_user_id="alice@example.com",
    prompt_hash=prompt_hash,   # bare 64-char lowercase hex
    output_hash=output_hash,
)

At least one of agent_id or agent_name is required. Hash fields (prompt_hash, input_hash, output_hash) must be bare 64-character lowercase SHA-256 hex digests (no prefix). Values of incorrect format or length raise ShieldError.

Recording Agent Action Evidence

For browser-automation and tool-call agents, use the typed action helpers. These record what the agent did — Shield does not judge whether the decision was correct.

import hashlib

# Hash screenshots/DOM locally — never upload raw images or HTML to Shield
screenshot_before_hash = hashlib.sha256(screenshot_bytes).hexdigest()
screenshot_after_hash  = hashlib.sha256(after_bytes).hexdigest()

# Record a click
client.agent.action_clicked(
    session_id,
    agent_id="agt-browser-001",
    principal_user_id="alice@example.com",
    target_url="https://app.example.com/checkout",
    element_selector="#confirm-order",
    element_text="Confirm Order",
    screenshot_before_hash=screenshot_before_hash,  # bare 64-char hex — do not include the sha256 prefix plus colon
    screenshot_after_hash=screenshot_after_hash,
    risk_level="medium",
)

# Record a tool call
client.agent.action_tool_called(
    session_id,
    agent_id="agt-001",
    tool_call_id="call_abc123",
    action_type="search_web",
    result="success",
)

# Record a confirmed payment (amount + currency + approval required)
client.agent.action_payment_confirmed(
    session_id,
    agent_id="agt-001",
    principal_user_id="alice@example.com",
    amount=299.99,
    currency="USD",
    human_approval_event_id="evt-approval-abc",  # or pass authority_scope=["payment:execute"]
)

Action helpers available:

Method Event type
agent.action_clicked shield.agent.action.clicked
agent.action_submitted shield.agent.action.submitted
agent.action_tool_called shield.agent.action.tool_called
agent.action_payment_confirmed shield.agent.action.payment_confirmed

All helpers accept keyword arguments that are passed as top-level request body fields. The SDK validates that screenshot_before_hash, screenshot_after_hash, dom_before_hash, and dom_after_hash are bare 64-character lowercase SHA-256 hex digests. Values beginning with the sha256 prefix plus colon are rejected before any request is made.

Payment actions additionally require amount (float), currency (str), and either human_approval_event_id or an authority_scope list containing a payment permission string ("payment" or "pay:"). Validation is enforced server-side.

For additional agent action types not covered by the helpers above, use agent.log_action directly:

client.agent.log_action(
    session_id,
    "shield.agent.action.navigated",
    agent_id="agt-001",
    target_url="https://app.example.com/dashboard",
)

Evidence Artifact References

When an AI agent captures screenshots, DOM snapshots, or I/O traces, you can record a tamper-evident reference to each artifact. Shield seals the uri + sha256 into the hash chain — proving the file was not changed later.

Shield does not store raw artifact bytes in v1. Upload to your own storage first, then pass the URI and SHA-256 hash here.

import hashlib

# 1. Capture and hash the artifact locally
screenshot_bytes = page.screenshot()  # your browser/tool
sha256 = hashlib.sha256(screenshot_bytes).hexdigest()

# 2. Upload to your S3 bucket (your responsibility — Shield does not upload)
uri = "s3://my-company-evidence/session-123/screenshot-before.png"
# ... your upload code ...

# 3. Record the tamper-evident reference in Shield
shield.agent.action_clicked(
    session_id,
    agent_id="agt-browser-001",
    actor="agt-browser-001",
    element_selector="#confirm-order",
    evidence_artifacts=[{
        "artifact_type": "screenshot_before",  # required
        "sha256": sha256,            # required — bare 64-char lowercase hex, no "sha256:" prefix
        "uri": uri,                  # optional
        "storage_provider": "customer_s3",  # optional
        "content_type": "image/png",        # optional
        "size_bytes": len(screenshot_bytes), # optional
    }],
)

Allowed artifact_type values: screenshot_before, screenshot_after, dom_before, dom_after, input, output, trace, receipt, other

Allowed storage_provider values: customer_s3, customer_r2, customer_gcs, customer_azure_blob, shield_storage, external

Allowed uri schemes: http://, https://, s3://, gs://, azure://, r2://

Required per artifact: artifact_type (from allowlist) and sha256 (bare 64-char lowercase hex, no prefix)

HMAC Authentication

For enhanced security, provide an HMAC secret to sign every request:

client = shield.Client(
    api_key="sk_live_your_api_key",
    hmac_secret="your_hmac_secret",
)

When an HMAC secret is configured, the SDK computes a signature for each request:

  • X-Shield-Timestamp — Unix timestamp of the request
  • X-Shield-Nonce — unique single-use value, sealed into the signature
  • X-Shield-Signature — HMAC-SHA256 of {timestamp}.{nonce}.{METHOD}.{request_uri}.{SHA256(body)}

The server validates these headers to ensure requests have not been tampered with or replayed.

Flask Integration

from flask import Flask, request, jsonify
import shield

app = Flask(__name__)
client = shield.Client(api_key="sk_live_your_api_key")

@app.route("/sessions", methods=["POST"])
def create_session():
    data = request.get_json()
    session = client.sessions.create(title=data["title"])

    # Record who created the session
    client.events.create(
        session_id=session["id"],
        event_type="shield.session.created",
        actor=data["user_email"],
    )
    return jsonify(session), 201

@app.route("/sessions/<session_id>/upload", methods=["POST"])
def upload_document(session_id):
    file = request.files["file"]
    # ... save file logic ...

    client.events.create(
        session_id=session_id,
        event_type="shield.content.uploaded",
        actor=request.headers.get("X-User-Email"),
        data={"filename": file.filename},
    )
    return jsonify({"status": "uploaded"}), 200

@app.route("/sessions/<session_id>/sign", methods=["POST"])
def sign_agreement(session_id):
    data = request.get_json()

    client.events.create(
        session_id=session_id,
        event_type="shield.agreement.signed",
        actor=data["signer_email"],
        data={"document": data["document_name"]},
    )
    return jsonify({"status": "signed"}), 200

FastAPI Integration

from fastapi import FastAPI, UploadFile, Header
from pydantic import BaseModel
import shield

app = FastAPI()
client = shield.Client(
    api_key="sk_live_your_api_key",
    hmac_secret="your_hmac_secret",
)

class CreateSessionRequest(BaseModel):
    title: str
    user_email: str

class SignRequest(BaseModel):
    signer_email: str
    document_name: str

@app.post("/sessions")
async def create_session(body: CreateSessionRequest):
    session = client.sessions.create(title=body.title)
    client.events.create(
        session_id=session["id"],
        event_type="shield.session.created",
        actor=body.user_email,
    )
    return session

@app.post("/sessions/{session_id}/upload")
async def upload_document(
    session_id: str,
    file: UploadFile,
    x_user_email: str = Header(...),
):
    # ... save file logic ...

    client.events.create(
        session_id=session_id,
        event_type="shield.content.uploaded",
        actor=x_user_email,
        data={"filename": file.filename},
    )
    return {"status": "uploaded"}

@app.post("/sessions/{session_id}/sign")
async def sign_agreement(session_id: str, body: SignRequest):
    client.events.create(
        session_id=session_id,
        event_type="shield.agreement.signed",
        actor=body.signer_email,
        data={"document": body.document_name},
    )
    return {"status": "signed"}

@app.get("/sessions/{session_id}/verify")
async def verify_session(session_id: str):
    return client.verify.session(session_id)

Event Types Reference

Shield Standard Event Taxonomy v1.0 — 40 event types across 8 categories:

Party Events

Event Type Description
shield.party.joined A party joined the session
shield.party.left A party left the session
shield.party.identity.verified Party identity was verified
shield.party.identity.failed Party identity verification failed
shield.party.role.assigned A role was assigned to a party

Session Events

Event Type Description
shield.session.created Session was created
shield.session.opened Session was opened
shield.session.closed Session was closed
shield.session.expired Session expired
shield.session.archived Session was archived

Content Events

Event Type Description
shield.content.uploaded Content was uploaded
shield.content.viewed Content was viewed
shield.content.downloaded Content was downloaded
shield.content.deleted Content was deleted
shield.content.hash.verified Content hash was verified
shield.content.submitted Content or analysis was submitted by an AI agent

Negotiation Events

Event Type Description
shield.negotiation.terms.proposed Terms were proposed
shield.negotiation.terms.accepted Terms were accepted
shield.negotiation.terms.rejected Terms were rejected
shield.negotiation.terms.modified Terms were modified
shield.negotiation.terms.expired Terms expired
shield.negotiation.message.sent Negotiation message sent
shield.negotiation.message.read Negotiation message read

Agreement Events

Event Type Description
shield.agreement.drafted Agreement was drafted
shield.agreement.reviewed Agreement was reviewed
shield.agreement.approved Agreement was approved
shield.agreement.signed Agreement was signed
shield.agreement.countersigned Agreement was countersigned
shield.agreement.voided Agreement was voided
shield.agreement.reached Agreement was reached

Access Events

Event Type Description
shield.access.granted Access was granted
shield.access.revoked Access was revoked
shield.access.attempted Access was attempted
shield.access.denied Access was denied

Disclosure Events

Event Type Description
shield.disclosure.presented Disclosure was presented
shield.disclosure.acknowledged Disclosure was acknowledged
shield.disclosure.declined Disclosure was declined

Evidence Events

Event Type Description
shield.evidence.exported Evidence was exported
shield.evidence.verified Evidence was verified
shield.evidence.tampered_detected Evidence tampering was detected

Agent Action Events (use with agent.log_action or action helpers)

Event Type Description
shield.agent.action.navigated Agent navigated to a URL
shield.agent.action.clicked Agent clicked a UI element
shield.agent.action.input_filled Agent filled a form input
shield.agent.action.submitted Agent submitted a form
shield.agent.action.confirmed Agent confirmed an action
shield.agent.action.payment_initiated Agent initiated a payment — requires amount, currency, and approval/scope
shield.agent.action.payment_confirmed Agent confirmed a payment — requires amount, currency, and approval/scope
shield.agent.action.tool_called Agent called a tool or function
shield.agent.action.human_approval_requested Agent requested human approval
shield.agent.action.human_approval_granted Human approved the agent's pending action

Versioning & API compatibility

This SDK follows Semantic Versioning.

  • Pre-1.0 (current): minor-version bumps may ship breaking changes. Pin the full version in requirements.txt.
  • 1.0 and later: the public API is stable within a major version. Breaking changes require a major-version bump.

The Shield HTTP API is versioned at the URL path (/api/v1). This SDK targets /api/v1 and will not transparently follow a server-side version bump — a new server major version will be delivered as a new SDK major version so callers opt in explicitly.

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

shield_python-0.5.0.tar.gz (19.3 kB view details)

Uploaded Source

Built Distribution

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

shield_python-0.5.0-py3-none-any.whl (15.5 kB view details)

Uploaded Python 3

File details

Details for the file shield_python-0.5.0.tar.gz.

File metadata

  • Download URL: shield_python-0.5.0.tar.gz
  • Upload date:
  • Size: 19.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for shield_python-0.5.0.tar.gz
Algorithm Hash digest
SHA256 e2378d2984c0acc26d9abc8993eac55281a2538b31c0b71bd8af8f02bedb28ae
MD5 ef0e2b73d8491a9069ea20f198431389
BLAKE2b-256 ec1e333d9e7fb50420b6bb82cd665078d6f7b51858a61c1938abbffb5de5cd99

See more details on using hashes here.

File details

Details for the file shield_python-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: shield_python-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 15.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for shield_python-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4c99dfd4aa9fe09c8ae1df15f881f9aef7826f6fc20fd6ff5ef340c8a6cad69a
MD5 d7dec1de4212b4f23f74cb250b0cfbfc
BLAKE2b-256 929cf4ca69c86d4c52a2c8f851c45254fa3763a838d8b506bb4b306cdeda341e

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