Skip to main content

Official Python SDK for Tether.name - AI agent identity verification

Project description

Tether.name Python SDK

PyPI Python versions License: MIT

Official Python SDK for Tether.name โ€” cryptographic identity verification for AI agents.

Tether lets AI agents prove their identity using RSA-2048 digital signatures, providing a secure, verifiable way to establish trust in AI-to-AI and AI-to-human interactions.

๐Ÿš€ Quick Start

Installation

pip install tether-name

Basic Usage

from tether_name import TetherClient

# Initialize with your agents
client = TetherClient(
    agent_id="your-agent-id",
    private_key_path="/path/to/your/private-key.pem"
)

# Verify your agent's identity
result = client.verify()

if result.verified:
    print(f"โœ… Verified as: {result.agent_name}")
    print(f"๐Ÿ“ง Email: {result.email}")
    print(f"๐Ÿ”— Verification URL: {result.verify_url}")
else:
    print(f"โŒ Verification failed: {result.error}")

Agent Management

One line to start managing agents programmatically:

from tether_name import TetherClient

client = TetherClient(api_key="sk-tether-name-...")

# Create, list, and delete agents
agent = client.create_agent("my-bot", domain_id="verified-domain-id")
agents = client.list_agents()
domains = client.list_domains()
client.delete_agent(agent.id)

๐Ÿ“– How Tether Works

Tether.name provides cryptographic identity verification for AI agents through a simple 3-step process:

  1. Register: Create an agent identity at tether.name and get your agent ID and RSA-2048 private key
  2. Sign: Your agent signs a cryptographic challenge using its private key
  3. Verify: The signature proves your agent's identity to others

This creates unforgeable digital identity that anyone can verify.

๐Ÿ”ง Configuration

Authentication

The SDK supports two authentication modes:

API Key โ€” for agent management (create, list, delete):

client = TetherClient(api_key="sk-tether-name-...")

Private Key โ€” for identity verification (sign, verify):

client = TetherClient(
    agent_id="your-agent-id",
    private_key_path="/path/to/key.pem"
)

Both โ€” for full access:

client = TetherClient(
    api_key="sk-tether-name-...",
    agent_id="your-agent-id",
    private_key_path="/path/to/key.pem"
)

Environment Variables

Set these environment variables to avoid hardcoding secrets:

export TETHER_API_KEY="sk-tether-name-..."
export TETHER_AGENT_ID="your-agent-id"
export TETHER_PRIVATE_KEY_PATH="/path/to/your/key.pem"

Then initialize without parameters:

client = TetherClient()  # Uses environment variables

Key Formats

The SDK supports multiple private key formats:

# From file path (PEM or DER)
client = TetherClient(
    agent_id="...",
    private_key_path="/path/to/key.pem"
)

# From PEM string
client = TetherClient(
    agent_id="...",
    private_key_pem="-----BEGIN PRIVATE KEY-----\n..."
)

# From DER bytes  
with open("key.der", "rb") as f:
    key_bytes = f.read()

client = TetherClient(
    agent_id="...",
    private_key_der=key_bytes
)

๐Ÿ“š API Reference

TetherClient

Main client for Tether.name API interactions.

Constructor

TetherClient(
    agent_id: Optional[str] = None,
    private_key_path: Optional[Union[str, Path]] = None,
    private_key_pem: Optional[Union[str, bytes]] = None,
    private_key_der: Optional[bytes] = None,
    timeout: float = 30.0,
    api_key: Optional[str] = None
)
Parameter Env var Description
api_key TETHER_API_KEY API key for agent management operations
agent_id TETHER_AGENT_ID Agent ID for identity verification
private_key_path TETHER_PRIVATE_KEY_PATH Path to RSA-2048 private key (PEM or DER)
private_key_pem โ€” PEM-encoded private key string
private_key_der โ€” DER-encoded private key bytes

When api_key is set, agent_id and private key parameters become optional (only needed for verify/sign operations).

Methods

verify() -> VerificationResult

Perform complete identity verification in one call.

result = client.verify()
print(result.verified)      # bool: True if verified
print(result.agent_name)    # str: Your agent's display name
print(result.verify_url)    # str: Public verification URL
print(result.email)         # str: Registered email address
request_challenge() -> str

Request a cryptographic challenge from Tether.

challenge = client.request_challenge()
print(challenge)  # "550e8400-e29b-41d4-a716-446655440000"
sign(challenge: str) -> str

Sign a challenge with your private key.

challenge = client.request_challenge()
signature = client.sign(challenge)
print(signature)  # URL-safe base64 signature (no padding)
submit_proof(challenge: str, proof: str) -> VerificationResult

Submit signed challenge for verification.

challenge = client.request_challenge()
signature = client.sign(challenge)
result = client.submit_proof(challenge, signature)
create_agent(agent_name: str, description: str = "", domain_id: str = "") -> Agent

Create a new agent. Requires API key authentication. domain_id is optional and assigns this agent to a verified domain.

agent = client.create_agent("my-bot", description="My automated agent", domain_id="verified-domain-id")
print(agent.id)                # Agent ID
print(agent.agent_name)        # "my-bot"
print(agent.registration_token) # Token for agent registration
list_agents() -> list[Agent]

List all agents. Requires API key authentication.

agents = client.list_agents()
for agent in agents:
    print(f"{agent.agent_name} (created {agent.created_at})")
list_domains() -> list[Domain]

List all registered domains for the account. Requires API key authentication.

domains = client.list_domains()
for domain in domains:
    print(domain.domain, domain.verified)
delete_agent(agent_id: str) -> bool

Delete an agent. Requires API key authentication.

client.delete_agent("agent-id-here")

Agent

Agent object returned by management operations.

@dataclass
class Agent:
    id: str                        # Unique agent ID
    agent_name: str                # Agent display name
    description: str               # Agent description
    domain_id: str = ""            # Optional assigned domain ID
    domain: Optional[str] = None   # Resolved domain name
    created_at: int                # Creation time (epoch ms)
    registration_token: str = ""   # Token for agent registration
    last_verified_at: int = 0      # Last verification time (epoch ms)
@dataclass
class Domain:
    id: str
    domain: str
    verified: bool
    verified_at: int = 0
    last_checked_at: int = 0
    created_at: int = 0

VerificationResult

Result object returned by verification operations.

@dataclass
class VerificationResult:
    verified: bool                           # True if verification succeeded
    agent_name: Optional[str] = None         # Agent's display name
    verify_url: Optional[str] = None         # Public verification URL
    email: Optional[str] = None              # Registered email
    domain: Optional[str] = None             # Verified domain (if assigned)
    registered_since: Optional[datetime] = None  # Registration date
    error: Optional[str] = None              # Error message if failed
    challenge: Optional[str] = None          # Original challenge

๐Ÿ” Step-by-Step Example

For more control, you can break down the verification process:

from tether_name import TetherClient, TetherAPIError, TetherVerificationError

try:
    client = TetherClient(
        agent_id="your-agent-id",
        private_key_path="/path/to/key.pem"
    )
    
    # Step 1: Request a challenge
    print("๐Ÿ“ก Requesting challenge...")
    challenge = client.request_challenge()
    print(f"๐Ÿ”ข Challenge: {challenge}")
    
    # Step 2: Sign the challenge  
    print("โœ๏ธ  Signing challenge...")
    signature = client.sign(challenge)
    print(f"๐Ÿ“ Signature: {signature[:32]}...")
    
    # Step 3: Submit proof
    print("๐Ÿ“ค Submitting proof...")
    result = client.submit_proof(challenge, signature)
    
    if result.verified:
        print(f"โœ… Successfully verified as {result.agent_name}")
        print(f"๐Ÿ”— Share this verification: {result.verify_url}")
    else:
        print(f"โŒ Verification failed: {result.error}")
        
except TetherAPIError as e:
    print(f"๐ŸŒ API Error: {e.message}")
    if e.status_code:
        print(f"๐Ÿ“Š Status: {e.status_code}")
        
except TetherVerificationError as e:
    print(f"๐Ÿ”’ Verification Error: {e.message}")
    
finally:
    client.close()  # Clean up HTTP connections

๐Ÿงช Testing

The SDK includes comprehensive unit tests that don't hit the live API:

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

# Run tests
pytest

# Run with coverage
pytest --cov=tether_name

๐Ÿ”— Context Manager Support

Use TetherClient as a context manager for automatic cleanup:

with TetherClient(agent_id="...", private_key_path="...") as client:
    result = client.verify()
    print(f"Verified: {result.verified}")
# HTTP client automatically closed

๐Ÿ›ก๏ธ Security Notes

  • Private Key Security: Never commit private keys to version control or share them publicly
  • API Key Security: API keys are hashed before storage. The sk-tether-name- prefix enables leak detection. Revoke compromised keys immediately
  • Key Format: Tether requires RSA-2048 keys. Other key sizes will be rejected
  • Challenge Uniqueness: Each verification uses a unique challenge to prevent replay attacks
  • Signature Algorithm: Uses SHA256withRSA (PKCS#1 v1.5 padding) as specified by Tether

๐Ÿ› Error Handling

The SDK provides specific exception types for different error conditions:

from tether_name import (
    TetherError,           # Base exception
    TetherAPIError,        # API request failures  
    TetherVerificationError,  # Verification failures
    TetherKeyError,        # Private key issues
)

try:
    result = client.verify()
except TetherAPIError as e:
    # Handle API connectivity or server errors
    print(f"API Error {e.status_code}: {e.message}")
except TetherVerificationError as e:
    # Handle verification failures (invalid signature, etc.)
    print(f"Verification failed: {e.message}")
except TetherKeyError as e:
    # Handle private key loading or format errors
    print(f"Key error: {e.message}")
except TetherError as e:
    # Handle any other Tether-related errors
    print(f"Tether error: {e.message}")

๐Ÿ“‹ Requirements

  • Python: 3.8+
  • Dependencies: httpx>=0.20.0, cryptography>=3.4.0
  • Key Format: RSA-2048 private key (PEM or DER)

๐Ÿ“ฆ Publishing

Published to PyPI automatically via GitHub Actions when a release is created (uses trusted publishing).

Version checklist

Update the version in:

  1. pyproject.toml โ†’ version
  2. src/tether_name/__init__.py โ†’ __version__

Steps

  1. Update version numbers above (they must match)
  2. Commit and push to main
  3. Create a GitHub release with a matching tag (e.g. v1.0.0)
  4. CI builds and publishes to PyPI automatically

Manual publish (if needed)

pip install build twine
python -m build
twine upload dist/*

๐Ÿ“„ License

MIT License - see LICENSE file for details.

๐Ÿค Contributing

Contributions welcome! Please see the GitHub repository for details.

๐Ÿ”— Links


Ready to get started? Register your AI agent at tether.name and start building with cryptographic identity verification! ๐Ÿš€

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

tether_name-2.0.1.tar.gz (16.0 kB view details)

Uploaded Source

Built Distribution

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

tether_name-2.0.1-py3-none-any.whl (13.2 kB view details)

Uploaded Python 3

File details

Details for the file tether_name-2.0.1.tar.gz.

File metadata

  • Download URL: tether_name-2.0.1.tar.gz
  • Upload date:
  • Size: 16.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for tether_name-2.0.1.tar.gz
Algorithm Hash digest
SHA256 2fb201861f45d5d6344e15aca5258ca9dbe6caaa24e0c5c74afc1b65f7e9a355
MD5 b3421011d35fd35a4b39de626f060ff8
BLAKE2b-256 9ed328b9b062d5df0df9928ca8c9fb44e3873ce7bf69d5d7d35f166d23f9a8f8

See more details on using hashes here.

Provenance

The following attestation bundles were made for tether_name-2.0.1.tar.gz:

Publisher: publish.yml on tether-name/tether-name-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tether_name-2.0.1-py3-none-any.whl.

File metadata

  • Download URL: tether_name-2.0.1-py3-none-any.whl
  • Upload date:
  • Size: 13.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for tether_name-2.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 4ef2db1cf6866fa4c0c2cb9c9a9ba40311d6955f39a6d75f7a363199472ab2aa
MD5 52c1267ceecdf44a7bbf3a08c1fcdc2e
BLAKE2b-256 3440ce58bac2c94cd8282af815c112ea4352a2285aea987478c813e1b39d644c

See more details on using hashes here.

Provenance

The following attestation bundles were made for tether_name-2.0.1-py3-none-any.whl:

Publisher: publish.yml on tether-name/tether-name-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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