Anthropic Integration
The Glacis Anthropic integration wraps the official Anthropic client to automatically create attestations for every API call.
Installation
pip install glacis[anthropic]Quick Start
from glacis.integrations.anthropic import attested_anthropic, get_last_receipt
client = attested_anthropic( glacis_api_key="glsk_live_...", anthropic_api_key="sk-ant-...")
# Make a normal Anthropic call - attestation happens automaticallyresponse = client.messages.create( model="claude-3-opus-20240229", max_tokens=1024, messages=[{"role": "user", "content": "Hello, Claude!"}])
print(response.content[0].text)
# Get the attestation receiptreceipt = get_last_receipt()print(f"Attested: {receipt.badge_url}")What Gets Attested
For each message, Glacis captures:
| Field | Attested | Details |
|---|---|---|
| Request messages | Hash only | SHA-256, never sent |
| Response content | Hash only | SHA-256, never sent |
| Model | Metadata | Sent as-is |
| Max tokens | Metadata | Sent as-is |
| System prompt | Hash only | SHA-256, never sent |
| Timestamp | Metadata | ISO 8601 |
Environment Variables
export GLACIS_API_KEY=glsk_live_...export ANTHROPIC_API_KEY=sk-ant-...from glacis.integrations.anthropic import attested_anthropic
# Keys read from environment automaticallyclient = attested_anthropic()from glacis.integrations.anthropic import attested_anthropic
client = attested_anthropic( glacis_api_key="glsk_live_...", anthropic_api_key="sk-ant-...")Streaming Support
Streaming messages are automatically attested when the stream completes:
with client.messages.stream( model="claude-3-opus-20240229", max_tokens=1024, messages=[{"role": "user", "content": "Tell me a story"}]) as stream: for text in stream.text_stream: print(text, end="", flush=True)
# Receipt available after stream completesreceipt = get_last_receipt()print(f"\n\nAttested: {receipt.badge_url}")System Prompts
System prompts are hashed but never transmitted:
response = client.messages.create( model="claude-3-opus-20240229", max_tokens=1024, system="You are a helpful AI assistant specialized in compliance.", messages=[{"role": "user", "content": "What is GDPR?"}])
# System prompt is included in the attestation hashreceipt = get_last_receipt()Multi-Turn Conversations
Each API call creates a separate attestation:
messages = []
# First turnmessages.append({"role": "user", "content": "Hello!"})response = client.messages.create( model="claude-3-opus-20240229", max_tokens=1024, messages=messages)receipt1 = get_last_receipt()messages.append({"role": "assistant", "content": response.content[0].text})
# Second turnmessages.append({"role": "user", "content": "How are you?"})response = client.messages.create( model="claude-3-opus-20240229", max_tokens=1024, messages=messages)receipt2 = get_last_receipt()
# Each turn has its own attestationprint(f"Turn 1: {receipt1.attestation_id}")print(f"Turn 2: {receipt2.attestation_id}")Offline Mode
For development without an API key:
from glacis.integrations.anthropic import attested_anthropic
client = attested_anthropic( glacis_mode="offline", anthropic_api_key="sk-ant-...")
response = client.messages.create( model="claude-3-opus-20240229", max_tokens=1024, messages=[{"role": "user", "content": "Hello!"}])
receipt = get_last_receipt()print(f"Status: {receipt.witness_status}") # "UNVERIFIED"Full Example
#!/usr/bin/env python3"""Complete example: Anthropic Claude with attestation"""import osfrom glacis.integrations.anthropic import attested_anthropic, get_last_receipt
def main(): client = attested_anthropic( glacis_api_key=os.environ.get("GLACIS_API_KEY"), anthropic_api_key=os.environ.get("ANTHROPIC_API_KEY"), )
response = client.messages.create( model="claude-3-opus-20240229", max_tokens=1024, system="You are a compliance expert.", messages=[ {"role": "user", "content": "What is ISO 42001?"} ] )
print("Response:", response.content[0].text) print()
receipt = get_last_receipt() print("Attestation Details:") print(f" Receipt ID: {receipt.attestation_id}") print(f" Timestamp: {receipt.timestamp}") print(f" Badge URL: {receipt.badge_url}")
if __name__ == "__main__": main()