Skip to main content

Python SDK for Sphyr Agent Guard

Project description

sphyr-sdk

Python SDK for Sphyr Agent Guard. Adds verifiable, auditable security checks to every outbound agent request.

Quick-Start

1. Install

pip install sphyr-sdk

2. Sign in (no key copy-paste)

npx @sphyr/cli login

Opens your browser, signs you in via the device flow, and writes your credential to ~/.sphyr/config.json (owner-only 0600). After this, the SDK picks it up automatically.

No Node/npx on your machine? Run python -m sphyr_sdk login for the same device-flow sign-in.

Setting up an IDE-based agent (Claude Desktop, Cursor, etc.) instead? Use npx @sphyr/cli guard init — it signs you in and writes the MCP server config for each detected IDE.

3. Protect every outbound call (recommended — install and forget)

from sphyr_sdk import auto_instrument

# One line at startup. After this, every requests / httpx call is signed, scanned,
# and audited through Sphyr automatically — no per-call wrapping.
report = auto_instrument()
print(report.requests.status)  # 'patched' or 'not_installed'
print(report.httpx.status)     # 'patched' or 'not_installed'

Breaking change (v0.27.0): auto_instrument() now returns a PatchReport (per-lib instrumentation status) instead of a SphyrClient. Callers that did client = auto_instrument(...) must update — use SphyrClient(...).instrument() directly if you need a client reference for later teardown.

The SDK does nothing until you call auto_instrument() — importing the package alone is not protective.

Fail-closed by default: if the Sphyr gateway is unreachable, instrumented requests raise SphyrNetworkError rather than leaving unscreened. Pass auto_instrument(fail_closed=False) to prioritize app uptime over strict enforcement.

Credentials resolve in order: explicit args → SPHYR_CREDENTIAL env var → ~/.sphyr/config.json. So auto_instrument() with no arguments works after npx @sphyr/cli login.

Works with your agent framework — automatically

auto_instrument() patches the underlying HTTP layer (requests and httpx), so any library or framework that makes outbound calls through them is signed, scanned, and audited the moment you call it — no adapters, no per-framework wiring. That includes the OpenAI SDK, the Anthropic SDK, LangChain / LangGraph, CrewAI, AutoGen, and LlamaIndex (all of which use requests/httpx under the hood). Call auto_instrument() once at process start, before your agent makes its first request.

Manual / advanced — wrap calls yourself

import asyncio

from sphyr_sdk.client import AsyncSphyrClient
from sphyr_sdk.errors import SphyrError


async def main() -> None:
    client = AsyncSphyrClient()  # resolves creds from env / ~/.sphyr/config.json
    try:
        result = await client.call({"url": "https://api.example.com/data", "mthd": "GET"})
        print(result)
    except SphyrError as err:
        print(err.code, err.retryable, err.docs_url)


asyncio.run(main())

4. Add the MCP Server (Claude Desktop, Cursor, etc.)

Recommended — one command:

npx @sphyr/cli guard init

This opens your browser, signs you in, and writes per-IDE configs automatically — including the SPHYR_CREDENTIAL env var. MCP server setup uses the Node-based sphyr-mcp binary from @sphyr/sdk.

See sphyr.io/docs/mcp for per-client setup (Claude Desktop, Claude Code CLI, Cursor, Antigravity, OpenAI Codex).

Full reference (retry policy, custom transport, timeout config, error catalog): sphyr.io/docs

What traffic is intercepted (and what is not)

instrument() / auto_instrument() work by patching specific HTTP client libraries. Traffic from anything else flows directly to the network, unguarded — there is no OS-level interception.

Transport Intercepted?
requests (Session-based and module-level) ✅ yes
httpx (Client and AsyncClient) ✅ yes
aiohttp ❌ no — flows unguarded
urllib / urllib.request / http.client ❌ no — flows unguarded
urllib3 (used directly, not via requests) ❌ no — flows unguarded
pycurl / subprocess curl ❌ no — flows unguarded

If your agent uses an unsupported transport, route those calls through SphyrClient.call() explicitly, or switch the agent's HTTP layer to requests/httpx.

Local/private traffic exclusions. To prevent gateway loops and keep local development working, intercepted clients pass traffic to localhost, RFC 1918 ranges (10/8, 172.16/12, 192.168/16), generic link-local (169.254/16), and IPv6 ULA/link-local directly to the real transport, unguarded. One deliberate exception: the cloud metadata endpoints (169.254.169.254, fd00:ec2::254) are always routed through the gateway, which blocks and audits the attempt — these are the primary SSRF targets a prompt-injected agent probes.

Tool Schema Drift Detection

When SphyrClient.instrument() is active, the SDK automatically detects changes to an MCP server's tools/list response between sessions. The first response per origin sets the baseline; subsequent changes raise SphyrDriftError (in BLOCK mode) or emit a telemetry event and continue (in LOG mode, the default).

from sphyr_sdk import SphyrClient, SphyrDriftError

try:
    result = await client.call({"url": "https://mcp.example.com/...", "mthd": "GET"})
except SphyrDriftError as err:
    # Tool schema changed unexpectedly — halt and alert
    print(err.code)  # "TOOL_SCHEMA_DRIFT"

SphyrDriftError is also importable from sdk.agent_guard_utils for legacy integrations. The enforcement mode (LOG or BLOCK) is set per API key via key_flags.tool_drift_mode in the admin console.

User-Agent header (custom integrations)

This SDK sends User-Agent: sphyr-sdk-python/<version> on every request to the Sphyr gateway. You do not need to do anything to enable this — it is set automatically.

If you are building a custom MCP client that talks to the Sphyr gateway directly (i.e. not using this SDK), you must set a User-Agent header on your requests. Cloudflare's WAF blocks Python urllib's default Python-urllib/3.X User-Agent as a bot — requests fail with HTTP 403 / Error 1010 (browser_signature_banned) before they reach the Worker. Any non-empty descriptive value (e.g. your-app/1.0) is sufficient.

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

sphyr_sdk-2.0.0b1.tar.gz (71.7 kB view details)

Uploaded Source

Built Distribution

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

sphyr_sdk-2.0.0b1-py3-none-any.whl (41.7 kB view details)

Uploaded Python 3

File details

Details for the file sphyr_sdk-2.0.0b1.tar.gz.

File metadata

  • Download URL: sphyr_sdk-2.0.0b1.tar.gz
  • Upload date:
  • Size: 71.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for sphyr_sdk-2.0.0b1.tar.gz
Algorithm Hash digest
SHA256 bbc6c24c4b074688485a9b21150039da2e739c7c4f9be6977e093a316186a63d
MD5 ae5bfa0305b8beb58bf9b830b48b01f9
BLAKE2b-256 556a5d20eac8b1029b8f1a8403945d920bd9e942332a5240e224f30a396f6ba4

See more details on using hashes here.

File details

Details for the file sphyr_sdk-2.0.0b1-py3-none-any.whl.

File metadata

  • Download URL: sphyr_sdk-2.0.0b1-py3-none-any.whl
  • Upload date:
  • Size: 41.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for sphyr_sdk-2.0.0b1-py3-none-any.whl
Algorithm Hash digest
SHA256 fdae944854cd9a5102946d9628d39b3a4f91d1da523d2848361b9ac3a4f61343
MD5 9de9264564799a73bb00a2a005c61e88
BLAKE2b-256 40a91c49ac508877f145bfe6453b48f7dffb175f09c28a6681f73feefca43d62

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