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
passphraseparameter in theWisperaCredentialProviderconstructor is deprecated. Authentication is now resolved automatically viaIDW_SESSION_TOKENor OS keychain. Runidw auth loginbefore 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
passphraseparameter in theWisperaSecretManagerconstructor is deprecated. Authentication is now resolved automatically viaIDW_SESSION_TOKENor OS keychain.Breaking change:
WisperaToolCredentialsno longer injects credentials intoos.environ. Usecreds.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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bf714460b57dc87874b63ef5a9a0c7fb542f31df6cf866afaf38f7b99532e61a
|
|
| MD5 |
025ee9c47939f3e429c5170cde75b656
|
|
| BLAKE2b-256 |
80e1fcc5c5a4350de96e0eca08c14facf91655a47ef2c462b19029ffe3788d8c
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
36356a9917b437109275bf2a1bf38ccf177ee18732535dce226710274e7500e1
|
|
| MD5 |
00ca5a81c4eb5fd9a3ca326f0201e1bd
|
|
| BLAKE2b-256 |
33ccd89685941ed0e08f33e362e58c3d731a1e50c50c9c0ed0974e225d5a59ca
|