Alter Vault Python SDK - OAuth token management with policy enforcement
Project description
Alter SDK for Python
Official Python SDK for Alter Vault - OAuth token management with policy enforcement.
Features
- Zero Token Exposure: Tokens are never exposed to developers - injected automatically
- Single Entry Point: One method (
vault.request()) for all provider APIs - Type-Safe Enums:
ProviderandHttpMethodenums with autocomplete - URL Templating: Path parameter substitution with automatic URL encoding
- Automatic Audit Logging: All API calls logged as fire-and-forget background tasks
- Real-time Policy Enforcement: Every token request checked against current policies
- Automatic Token Refresh: Tokens refreshed transparently by the backend
- Actor Tracking: First-class support for AI agent and MCP server observability
Installation
pip install alter-sdk
Quick Start
import asyncio
from alter_sdk import AlterVault, Provider, HttpMethod
async def main():
vault = AlterVault(api_key="alter_key_...")
# Make API request - token injected automatically, never exposed
response = await vault.request(
Provider.GOOGLE,
HttpMethod.GET,
"https://www.googleapis.com/calendar/v3/calendars/primary/events",
user={"user_id": "alice"},
query_params={"maxResults": "10"},
)
events = response.json()
print(events)
await vault.close()
asyncio.run(main())
Usage
Simple GET Request
response = await vault.request(
Provider.GOOGLE,
HttpMethod.GET,
"https://www.googleapis.com/calendar/v3/calendars/primary/events",
user={"user_id": "alice"},
)
POST with JSON Body
response = await vault.request(
Provider.SALESFORCE,
HttpMethod.POST,
"https://api.example.com/v1/items",
user={"user_id": "alice"},
json={"name": "New Item", "price": 99.99},
reason="Creating new item",
)
URL Path Templating
response = await vault.request(
Provider.SALESFORCE,
HttpMethod.PUT,
"https://api.example.com/v1/items/{item_id}",
user={"user_id": "alice"},
path_params={"item_id": "123"},
json={"price": 89.99},
)
Query Parameters and Extra Headers
response = await vault.request(
"notion",
HttpMethod.POST,
"https://api.notion.com/v1/databases/{db_id}/query",
user={"user_id": "alice"},
path_params={"db_id": "abc123"},
extra_headers={"Notion-Version": "2022-06-28"},
json={"page_size": 10},
)
Context Manager
async with AlterVault(api_key="alter_key_...") as vault:
response = await vault.request(
Provider.GOOGLE,
HttpMethod.GET,
"https://www.googleapis.com/calendar/v3/calendars/primary/events",
user={"user_id": "alice"},
)
# Automatically closed
Note: After
close()is called, subsequentrequest()calls raiseAlterSDKError.close()is idempotent — calling it multiple times is safe.
AI Agent Actor Tracking
vault = AlterVault(
api_key="alter_key_...",
actor_type="ai_agent",
actor_identifier="email-assistant-v2",
actor_name="Email Assistant",
actor_version="2.0.0",
framework="langgraph",
)
response = await vault.request(
Provider.GOOGLE,
HttpMethod.GET,
"https://www.googleapis.com/calendar/v3/calendars/primary/events",
user={"user_id": "alice"},
run_id="550e8400-e29b-41d4-a716-446655440000",
thread_id="thread-xyz",
tool_call_id="call_abc_123",
)
Multi-Agent Deployments
Each agent must create its own AlterVault instance with a unique actor identity. Do not share a single instance across agents.
# Each agent gets its own vault instance
email_agent = AlterVault(
api_key="alter_key_...",
actor_type="ai_agent",
actor_identifier="email-assistant-v2",
actor_name="Email Assistant",
)
calendar_agent = AlterVault(
api_key="alter_key_...",
actor_type="ai_agent",
actor_identifier="calendar-agent-v1",
actor_name="Calendar Agent",
)
# Audit logs and policies are tracked per agent
user = {"user_id": "alice"}
await email_agent.request(
Provider.GOOGLE, HttpMethod.GET,
"https://gmail.googleapis.com/gmail/v1/users/me/messages",
user=user,
)
await calendar_agent.request(
Provider.GOOGLE, HttpMethod.GET,
"https://www.googleapis.com/calendar/v3/calendars/primary/events",
user=user,
)
# Clean up each instance
await email_agent.close()
await calendar_agent.close()
Configuration
vault = AlterVault(
api_key="alter_key_...", # Required: Alter Vault API key
base_url="https://api.alter.com", # Optional: Custom API URL
timeout=30.0, # Optional: HTTP timeout in seconds
# Actor tracking (optional)
actor_type="ai_agent", # "ai_agent" or "mcp_server"
actor_identifier="my-agent", # Unique identifier
actor_name="My Agent", # Human-readable name
actor_version="1.0.0", # Version string
framework="langgraph", # AI framework
client_type="cursor", # MCP client type
)
Error Handling
from alter_sdk import AlterVault, Provider, HttpMethod
from alter_sdk.exceptions import (
AlterSDKError, # Base exception for all SDK errors (including validation: api_key, actor_type, URL scheme, path_params)
PolicyViolationError, # Policy denied access (403)
ConnectionNotFoundError, # No OAuth connection found (404)
TokenExpiredError, # Token refresh failed (400/502)
TokenRetrievalError, # Other backend errors
NetworkError, # Backend or provider unreachable
TimeoutError, # Request timed out (subclass of NetworkError)
ProviderAPIError, # Provider API returned error (4xx/5xx)
)
try:
response = await vault.request(
Provider.GOOGLE,
HttpMethod.GET,
"https://www.googleapis.com/calendar/v3/calendars/primary/events",
user={"user_id": "alice"},
)
except PolicyViolationError as e:
print(f"Policy denied: {e.message}")
print(f"Policy error: {e.policy_error}") # Detailed policy failure reason
except ConnectionNotFoundError:
print("No OAuth connection - user needs to authenticate")
except TokenExpiredError as e:
print(f"Token expired for connection: {e.connection_id}")
except TimeoutError as e:
print(f"Request timed out — safe to retry: {e.message}")
except NetworkError as e:
print(f"Network issue: {e.message}")
except ProviderAPIError as e:
print(f"Provider error {e.status_code}: {e.response_body}")
Supported Providers
from alter_sdk import Provider
Provider.GOOGLE # "google"
Provider.GITHUB # "github"
Provider.SLACK # "slack"
Provider.MICROSOFT # "microsoft"
Provider.SALESFORCE # "salesforce"
Provider.SENTRY # "sentry"
# Strings also work for any provider
await vault.request("notion", HttpMethod.GET, url, user=user)
Requirements
- Python 3.11+
- httpx[http2]
- pydantic
License
MIT License
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 alter_sdk-0.2.1.tar.gz.
File metadata
- Download URL: alter_sdk-0.2.1.tar.gz
- Upload date:
- Size: 17.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5dcdd7b382249972a847c29d84cce81aea2a5d6b082cc9b06c6e616289357044
|
|
| MD5 |
ec67b9e96b04e9d924fcbbfd1c77d5c7
|
|
| BLAKE2b-256 |
3968bb68b4593ce1482f3513f7447ca2b09e99c9417dead02b0eebd5f04e4ad6
|
Provenance
The following attestation bundles were made for alter_sdk-0.2.1.tar.gz:
Publisher:
python-sdk-release.yml on AlterAIDev/Alter-Vault
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
alter_sdk-0.2.1.tar.gz -
Subject digest:
5dcdd7b382249972a847c29d84cce81aea2a5d6b082cc9b06c6e616289357044 - Sigstore transparency entry: 967556922
- Sigstore integration time:
-
Permalink:
AlterAIDev/Alter-Vault@47297073fb9b68462c0cb24558c17d5988deb26c -
Branch / Tag:
refs/tags/python-sdk-v0.2.1 - Owner: https://github.com/AlterAIDev
-
Access:
internal
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-sdk-release.yml@47297073fb9b68462c0cb24558c17d5988deb26c -
Trigger Event:
push
-
Statement type:
File details
Details for the file alter_sdk-0.2.1-py3-none-any.whl.
File metadata
- Download URL: alter_sdk-0.2.1-py3-none-any.whl
- Upload date:
- Size: 18.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
846d5f1f30f20d513791e4abf1456f00be8240069c25ff66b715f227c42be1f0
|
|
| MD5 |
d39ba790753ef3a28786a892520c0cac
|
|
| BLAKE2b-256 |
c42ba64d527541273a71b0f975a81059a9aaf2c95b5ac0520a9bb03e5b06d657
|
Provenance
The following attestation bundles were made for alter_sdk-0.2.1-py3-none-any.whl:
Publisher:
python-sdk-release.yml on AlterAIDev/Alter-Vault
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
alter_sdk-0.2.1-py3-none-any.whl -
Subject digest:
846d5f1f30f20d513791e4abf1456f00be8240069c25ff66b715f227c42be1f0 - Sigstore transparency entry: 967556989
- Sigstore integration time:
-
Permalink:
AlterAIDev/Alter-Vault@47297073fb9b68462c0cb24558c17d5988deb26c -
Branch / Tag:
refs/tags/python-sdk-v0.2.1 - Owner: https://github.com/AlterAIDev
-
Access:
internal
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-sdk-release.yml@47297073fb9b68462c0cb24558c17d5988deb26c -
Trigger Event:
push
-
Statement type: