Skip to main content

Tinfoil Python Library

PyPI - Version SDK Test Documentation

A Python client for secure AI model inference through Tinfoil.

Installation

# With uv
uv add tinfoil

# With pip
pip install tinfoil

Usage

The Tinfoil SDK automatically selects a router enclave and verifies it against the official GitHub repository. You just need to provide your API key:

import os
from tinfoil import TinfoilAI

client = TinfoilAI(
    api_key=os.getenv("TINFOIL_API_KEY")
)

chat_completion = client.chat.completions.create(
    model="llama3-3-70b",
    messages=[
        {
            "role": "user",
            "content": "Hi",
        }
    ],
)
print(chat_completion.choices[0].message.content)

Inspecting verification

The verified release, measurements, attested keys, verifier version, and local verification completion time are available from the client:

document = client.get_verification_document()

print(document.release_tag)  # None for pinned or bundled verification
print(document.release_digest)
print(document.code_fingerprint)
print(document.enclave_fingerprint)
print(document.verifier)
print(document.verified_at)

verified_at is recorded from the local clock after every successful verification or re-verification. It is not an attested evidence timestamp or a freshness guarantee.

Audio Transcription with Whisper

You can transcribe audio files using OpenAI's Whisper model:

import os
from tinfoil import TinfoilAI

client = TinfoilAI(
    api_key=os.getenv("TINFOIL_API_KEY")
)

with open("audio.mp3", "rb") as audio_file:
    transcription = client.audio.transcriptions.create(
        file=audio_file,
        model="whisper-large-v3-turbo",
    )
print(transcription.text)

Async Usage

Simply import AsyncTinfoilAI instead of TinfoilAI and use await with each API call:

import os
import asyncio
from tinfoil import AsyncTinfoilAI

client = AsyncTinfoilAI(
    api_key=os.getenv("TINFOIL_API_KEY")
)

async def main() -> None:
    stream = await client.chat.completions.create(
        model="llama3-3-70b",
        messages=[{"role": "user", "content": "Say this is a test"}],
        stream=True,
    )
    async for chunk in stream:
        if chunk.choices and chunk.choices[0].delta.content is not None:
            print(chunk.choices[0].delta.content, end="", flush=True)
    print()

asyncio.run(main())

Functionality between the synchronous and asynchronous clients is otherwise identical.

Low-level HTTP Endpoints

You can also perform arbitrary GET/POST requests that are verified:

import os
from tinfoil import NewSecureClient

api_key = os.getenv("TINFOIL_API_KEY")
tfclient = NewSecureClient()

# GET example
resp = tfclient.get(
    "https://example.com/health",
    headers={"Authorization": f"Bearer {api_key}"},
    params={"query": "value"},
    timeout=30,
)
print(resp.status_code, resp.text)

# POST example
payload = {"key": "value"}
resp = tfclient.post(
    "https://example.com/analyze",
    headers={
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json",
    },
    json=payload,
    timeout=30,
)
print(resp.status_code, resp.text)

Prompt Cache Scoping

The inference router partitions prompt-prefix caches using both the authenticated API identity and user_cache_secret. Cache reuse requires the same identity, secret, model, and matching prompt prefix. Changing the identity or secret selects a different cache namespace, so those requests do not share cache entries or cache-hit timing.

user_cache_secret is sensitive application data used only for cache partitioning. It is not an API credential or encryption key. Do not log or expose it unnecessarily: a caller who can send requests with the same API identity and secret joins that cache namespace and can observe its cache-hit timing. The SDK adds it to eligible request bodies before they are protected for transport to the verified enclave.

By default, the SDK generates a random secret and persists it at ~/.tinfoil/user_cache_secret, requesting mode 0600 where supported. Tinfoil SDKs using the same home directory reuse this value. This default is suitable for a single-user application, but it does not separate end users who share one application process or home directory. You can control the scope explicitly:

from tinfoil import TinfoilAI

# Pin a stable, non-empty, opaque secret for this client.
client = TinfoilAI(api_key=api_key, user_cache_secret=secret)

# Or provision it via the environment
#   TINFOIL_USER_CACHE_SECRET=<secret>   use this value

# Multi-user services should scope every request to its end user;
# a non-empty string field set here wins over the client-level secret:
chat_completion = client.chat.completions.create(
    model="llama3-3-70b",
    messages=[{"role": "user", "content": "Hi"}],
    extra_body={"user_cache_secret": per_user_secret},
)

AsyncTinfoilAI and NewSecureClient accept the same user_cache_secret parameter. Resolution order is a non-empty per-request string, a non-empty client value, a non-empty TINFOIL_USER_CACHE_SECRET, then the generated default. Empty client or environment values are treated as unset, and an empty per-request string is replaced with the resolved client value. The SDK leaves non-string values unchanged, and applications should not use them for cache scoping.

Multi-user services must provide a stable, non-empty, opaque value for each user (or group whose members may share cache-hit timing) on every eligible request. Do not use a raw user identifier, API key, or encryption key. A single client, environment, or generated value groups all requests using it under the same API identity. If persistence is unavailable, the SDK uses an in-memory value and cache continuity ends when the process exits.

Security

Please report security vulnerabilities by emailing security@tinfoil.sh.

We aim to respond to (legitimate) security reports within 24 hours.

Development

Install uv before following these instructions.

# Set up the development environment and install the package
uv sync

# Run all tests (requires the TINFOIL_API_KEY environment variable)
export TINFOIL_API_KEY="..."
uv run pytest

# Run unit tests
uv run pytest -m "not integration"

# Run integration tests (requires the TINFOIL_API_KEY environment variable)
export TINFOIL_API_KEY="..."
uv run pytest -m integration

Metadata

Release files for tinfoil 0.14.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tinfoil 0.14.0
File Size Uploaded
tinfoil-0.14.0.tar.gz 682.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for tinfoil 0.14.0
File Interpreter ABI Platform
tinfoil-0.14.0-py3-none-any.whl Python 3 none any Details

Total release size: 784.8 kB

Release files / tinfoil-0.14.0.tar.gz

Download URL tinfoil-0.14.0.tar.gz
Size 682.8 kB
Tags Source
SHA-256 checksum
How to use checksums
b88838a80210582c7dd6b307cd83e581ea21b245fb0dad79ac57202b2e9f2968
BLAKE2b-256 checksum
How to use checksums
5f9c367219d98e901f7fd6597cbeb4954242e6751e0266943ceb6ec42ea9d118
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 4, 2026.

Transparency log

Release files / tinfoil-0.14.0-py3-none-any.whl

Download URL tinfoil-0.14.0-py3-none-any.whl
Size 102.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f04e1c0ed98e22619c03e6fc8b9a2cab60a4e9ed2001ffec58ab5cd848d77642
BLAKE2b-256 checksum
How to use checksums
91885e6e1e3ec922e2d6027d519e9ff2b7d7855dee179af607f546c30cdf38fb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 4, 2026.

Transparency log

Release history Release notifications | RSS feed

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page