Skip to main content

Credential governance for AI agents - Python SDK

Project description

ID Wispera Python SDK

Credential governance for AI agents - Python edition.

Installation

pip install id-wispera

With Framework Integrations

# LangChain support
pip install id-wispera[langchain]

# CrewAI support
pip install id-wispera[crewai]

# All integrations
pip install id-wispera[all]

Quick Start

Initialize a Vault

idw-py init

Scan for Credentials

# Scan a directory
idw-py scan /path/to/project

# Scan system locations (OpenClaw format)
idw-py scan --system

Import Credentials

# Scan and import all
idw-py import ./project --all --owner dev@company.com -y

# Import high-confidence only
idw-py import ./project --min-confidence 0.9 --owner dev@company.com

# Import single file
idw-py import .env --owner dev@company.com

Import Options

Option Description
--all Import all detected credentials from scan
--min-confidence <level> Minimum confidence threshold (0-1)
--format <format> Import format (env, json, openclaw)
--owner <owner> Human owner email
--auto-name Auto-generate passport names
-y, --yes Import without confirmation
-p, --path <path> Custom vault path

Manage Passports

# List all passports
idw-py list

# Show passport details
idw-py show <passport-id>

# Revoke a passport
idw-py revoke <passport-id> --reason "Compromised"

Python API

Basic Usage

from id_wispera import Vault, create_passport, list_passports
from id_wispera.types import CreatePassportInput, CredentialType, VisaType, Platform

# Load vault
vault = Vault.load("~/.id-wispera/vault.json", passphrase="your-passphrase")

# Create a passport
passport = create_passport(vault, CreatePassportInput(
    name="openai-prod",
    agent_id="agent-001",
    credential_type=CredentialType.API_KEY,
    credential_value="sk-...",
    visa_type=VisaType.ACCESS,
    platforms=[Platform.OPENAI],
    scope=["chat", "embeddings"],
    human_owner="developer@example.com",
))

# List passports
passports = list_passports(vault, status="active")
for p in passports:
    print(f"{p.name}: {p.status}")

Credential Detection

from id_wispera.detection import detect_credentials, mask_credentials_in_text

# Detect credentials in text
text = "My API key is sk-abc123...xyz789"
results = detect_credentials(text)

for result in results:
    print(f"Found {result.type} at line {result.line}")
    print(f"  Value: {result.value[:10]}...")
    print(f"  Confidence: {result.confidence}")

# Mask credentials for safe logging
safe_text = mask_credentials_in_text(text)
print(safe_text)  # "My API key is [REDACTED]"

Policy Engine

from id_wispera.policy import evaluate_policy, validate_passport

# Evaluate whether a passport is allowed to perform an action
result = evaluate_policy(passport, action="access")
print(f"Allowed: {result.allowed}, Reason: {result.reason}")

# Validate a passport against all configured policies
validation = validate_passport(passport)
print(f"Valid: {validation.valid}, Violations: {validation.violations}")

Delegation Management

from id_wispera.delegation import add_delegation, get_delegation_depth

# Add a delegation hop to a passport
delegated = add_delegation(vault, passport_id, hop, issued_by="admin")
print(f"Delegated passport: {delegated.id}")

# Check delegation chain depth
depth = get_delegation_depth(vault, passport_id)
print(f"Delegation depth: {depth}")

Secure Sharing

from id_wispera.sharing import create_share_link, resolve_share_link

# Create a share link with expiry and view limits
link = create_share_link(vault, passport_id, expires_in=3600, max_views=1)
print(f"Share URL: {link.url}")

# Resolve a share link to retrieve the passport
shared = resolve_share_link(vault, link.token)
print(f"Shared passport: {shared.name}")

Locations Registry

from id_wispera.locations import detect_installed_providers, get_provider

# Detect which credential providers are available on the system
providers = detect_installed_providers()
for p in providers:
    print(f"Provider: {p.name} ({p.provider_type})")

# Get a specific provider by name
provider = get_provider("aws")
print(f"Provider: {provider.name}, Installed: {provider.installed}")

Provisioning

from id_wispera.provisioning import provision_and_create_passport, list_providers

# List available provisioning providers
providers = list_providers()
for p in providers:
    print(f"{p.name}: {p.description}")

# Provision a new credential and create a passport in one step
passport = provision_and_create_passport(vault, request, auth)
print(f"Provisioned: {passport.name} on {passport.platforms}")

Framework Integrations

LangChain

from id_wispera.integrations.langchain import WisperaCredentialProvider
from langchain_openai import ChatOpenAI

# Initialize provider (authenticates via session token or OS keychain automatically)
provider = WisperaCredentialProvider(vault_path="~/.id-wispera")

# Use with LangChain
llm = ChatOpenAI(api_key=provider.get("openai-prod"))

# Or use convenience methods
llm = ChatOpenAI(api_key=provider.get_openai_key())

Deprecated: The passphrase parameter in the WisperaCredentialProvider constructor is deprecated. Authentication is now resolved automatically via IDW_SESSION_TOKEN or OS keychain. Run idw auth login before first use.

CrewAI

from id_wispera.integrations.crewai import WisperaSecretManager, WisperaToolCredentials
from crewai import Agent, Task, Crew

# Initialize secret manager (authenticates via session token or OS keychain)
secrets = WisperaSecretManager()

# Create agent with governed credentials
researcher = Agent(
    role="Research Analyst",
    goal="Research and analyze information",
    llm_config=secrets.get_llm_config("anthropic-research", model="claude-3-5-sonnet-20241022"),
)

# Use tool credentials — retrieve via creds.get() instead of os.environ injection
from crewai_tools import SerperDevTool

creds = WisperaToolCredentials(secrets, "serper")
search_tool = SerperDevTool(api_key=creds.get())

Deprecated: The passphrase parameter in the WisperaSecretManager constructor is deprecated. Authentication is now resolved automatically via IDW_SESSION_TOKEN or OS keychain.

Breaking change: WisperaToolCredentials no longer injects credentials into os.environ. Use creds.get() to retrieve the credential value directly.

OpenAI Agents SDK

from id_wispera.integrations.openai_agents import WisperaOpenAIAgentProvider

provider = WisperaOpenAIAgentProvider()

# Get API key for agent initialization
api_key = provider.get_agent_key("openai-prod")

# Get full agent config (api_key, model, provider)
config = provider.get_agent_config("openai-prod", model="gpt-4")

# Get tool authentication headers
tool_auth = provider.get_tool_auth("serper-api")
# Returns: {"tool": "serper-api", "credential": "...", "header_name": "Authorization", "header_template": "Bearer ..."}

# Scoped handoff credentials
cred = provider.get_handoff_credential("openai-prod", target_agent="research-agent", allowed_scopes=["read"])

# Batch tool credentials
creds = provider.get_tool_credentials({"search": "serper-api", "weather": "weather-api"})

Google A2A Protocol

from id_wispera.integrations.google_a2a import WisperaA2AProvider

provider = WisperaA2AProvider()

# Populate an Agent Card with credentials
creds = provider.get_agent_credentials("my-agent")
# Returns: {"auth_token": "...", "agent_id": "...", "scopes": [...], "expires_at": "..."}

# Validate incoming agent authentication
result = provider.validate_agent_auth(token="...", expected_agent_id="agent-123")
# Returns: {"valid": True, "agent_id": "agent-123"}

# Task-scoped credential access
task_creds = provider.get_task_credentials("task-456", required_scopes=["read"], passport_names=["my-agent"])

Slack

from id_wispera.integrations.slack import WisperaSlackProvider

provider = WisperaSlackProvider()

# Individual tokens
bot_token = provider.get_bot_token("slack-bot")       # xoxb-...
app_token = provider.get_app_token("slack-app")        # xapp-...
user_token = provider.get_user_token("slack-user")     # xoxp-...
webhook_url = provider.get_webhook_url("slack-webhook")

# Typed credential with auto-detection
cred = provider.get_slack_credential("slack-bot")
# Returns: {"value": "xoxb-...", "token_type": "bot", "team_id": "T12345"}

# Socket Mode (bot + app tokens together)
tokens = provider.get_socket_mode_tokens("slack-bot", "slack-app")
# Returns: {"bot_token": "xoxb-...", "app_token": "xapp-..."}

# List all Slack credentials in the vault
names = provider.list_slack_credentials()

Auth Module

The id_wispera.auth module provides the zero-plaintext credential architecture for Python:

from id_wispera.auth import PassphraseProvider, SessionTokenManager, KeychainProvider

# PassphraseProvider — derive vault key from passphrase (interactive login)
pp = PassphraseProvider()
vault_key = pp.derive_key(passphrase)

# KeychainProvider — cache/retrieve vault key from OS keychain
kc = KeychainProvider()
kc.store(vault_key)
cached = kc.retrieve()

# SessionTokenManager — create, validate, revoke scoped session tokens
stm = SessionTokenManager(vault)
token = stm.create(name="ci-deploy", scope=["read", "list"], ttl="24h")
session = stm.validate(token)
stm.revoke(token.id)
tokens = stm.list()
Class Purpose
PassphraseProvider Derive vault key from passphrase (interactive login)
SessionTokenManager Create / validate / revoke / list scoped session tokens
KeychainProvider Cache vault key in the OS keychain for session persistence

Environment Variables

Variable Description Default
IDW_SESSION_TOKEN Scoped session token (recommended for headless/CI)
IDW_VAULT_PATH Vault directory path ~/.id-wispera
IDW_PASSPHRASE Vault passphrase Deprecated -- use idw auth login or IDW_SESSION_TOKEN

Vault Compatibility

The Python SDK uses the same vault format as the TypeScript SDK. Vaults are interoperable:

  • AES-256-GCM encryption
  • Scrypt key derivation (N=16384, r=8, p=1)
  • JSON storage format

Development

# Install in development mode
pip install -e ".[dev]"

# Run tests
pytest

# Type checking
mypy id_wispera

License

MIT

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

id_wispera-0.1.0.tar.gz (69.3 kB view details)

Uploaded Source

Built Distribution

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

id_wispera-0.1.0-py3-none-any.whl (75.8 kB view details)

Uploaded Python 3

File details

Details for the file id_wispera-0.1.0.tar.gz.

File metadata

  • Download URL: id_wispera-0.1.0.tar.gz
  • Upload date:
  • Size: 69.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for id_wispera-0.1.0.tar.gz
Algorithm Hash digest
SHA256 bf714460b57dc87874b63ef5a9a0c7fb542f31df6cf866afaf38f7b99532e61a
MD5 025ee9c47939f3e429c5170cde75b656
BLAKE2b-256 80e1fcc5c5a4350de96e0eca08c14facf91655a47ef2c462b19029ffe3788d8c

See more details on using hashes here.

File details

Details for the file id_wispera-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: id_wispera-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 75.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for id_wispera-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 36356a9917b437109275bf2a1bf38ccf177ee18732535dce226710274e7500e1
MD5 00ca5a81c4eb5fd9a3ca326f0201e1bd
BLAKE2b-256 33ccd89685941ed0e08f33e362e58c3d731a1e50c50c9c0ed0974e225d5a59ca

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