Tsaheylu Documentation

Everything you need to integrate agent-state persistence into your AI agents. Install the Python SDK in one line, or use the REST API directly.

Overview

Tsaheylu is a persistent state management service for AI agents — think of it as Dropbox for agent memory. Your agent registers once, periodically syncs its state, and when it crashes, migrates, or restarts, it recovers exactly where it left off.

Every snapshot is encrypted with AES-256-GCM, verified with SHA-256 hashing, and stored with versioning. On recovery, the hash is re-verified to guarantee data integrity — what you put in is exactly what you get back.

New: The official Python SDK is live on PyPI — get started with just 3 lines of code.

TIPFastest path: pip install tsaheylutsaheylu.init('token')tsaheylu.sync('agent1', state). See the Python SDK section below.

Python SDK

The official Python SDK is the fastest way to add state persistence to your agents. Available on PyPI (v0.1.0).

Installation

Install
pip install tsaheylu

Quickstart — 3 Lines

Functional API
import tsaheylu

tsaheylu.init("your-operator-token-32-chars-min")
tsaheylu.sync("my-agent", {"memory": ["task1", "task2"], "step": 42})

# Later, when restarting:
state = tsaheylu.restore("my-agent")
print(state)  # {"memory": ["task1", "task2"], "step": 42}

OOP Usage

Client Class
from tsaheylu import Client

client = Client(api_key="your-operator-token-32-chars-min")

# Sync state
client.sync("research-bot", {"papers": ["arxiv: 2401.1234"], "progress": 0.7})

# Recover state
state = client.restore("research-bot")

Error Handling

Exceptions
from tsaheylu.exceptions import HandleTakenError, HashMismatchError

try:
    tsaheylu.sync("my-agent", state)
except HandleTakenError:
    print("Handle already registered by another operator")
except HashMismatchError:
    print("Integrity check failed — retry")
TIPThe SDK handles registration, SHA-256 hashing, and JSON serialization automatically. You never need to compute hashes manually — just pass your state dict.

Getting Started (REST API)

Get your agent connected in three steps. The easiest way is the registration page — you'll receive your agent ID and operator token instantly.

Step 1 — Register your agent

Option A: Use the registration page (recommended). You'll get your agent_id and operator_token immediately.

Option B: Register via the API:

Register Agent (API)
curl -X POST https://api.tsaheylu.club/agent/signup \
  -H "Content-Type: application/json" \
  -d '{
    "handle": "my-agent",
    "operator_handle": "your-name"
  }'
Response — 201 Created
{
  "agent_id": "a1b2c3d4-e5f6-...",
  "handle": "my-agent",
  "operator_token": "abc123..."   // Save this! Shown only once.
}
⚠️Save your operator token immediately. It is shown only once and cannot be recovered. Use this token in all Authorization: Bearer headers.

Step 2 — Snapshot your state

Compute a SHA-256 hash of your state, then send both. Replace the token and agent ID with your real values from Step 1:

Create Snapshot (shell)
# Set your real values:
TOKEN="your-operator-token-from-registration"
AGENT_ID="your-agent-id-from-registration"

# Capture state and compute hash:
STATE='{ "memory": ["task1", "task2"], "step": 42 }'
HASH=$(echo -n "$STATE" | sha256sum | awk '{print $1}')

# Send snapshot:
curl -X POST https://api.tsaheylu.club/agent/snapshot \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"agent_id\":\"$AGENT_ID\",\"state_blob\":\"$STATE\",\"hash\":\"$HASH\"}"
TIPFor large states (files, databases), base64-encode a tar archive:STATE=$(tar czf - /path/to/agent/state | base64 -w0). On recovery, pipe through base64 -d | tar xzf -.

Step 3 — Recover on restart

Recover State
curl -s https://api.tsaheylu.club/agent/recover/$AGENT_ID \
  -H "Authorization: Bearer $TOKEN"
Response — 200 OK
{
  "snapshot_id": "uuid",
  "state_blob": "{ \"memory\": [\"task1\", \"task2\"], \"step\": 42 }",
  "verification_status": "verified",
  "version": 1,
  "recovery_event_id": "uuid"
}

API Reference

All endpoints are authenticated with your operator_token via theAuthorization: Bearer header (except registration, which takes the token in the body). Rate limits apply to all endpoints.

POST/agent/signupRegister a new agent (self-serve)

Request Body

ParameterTypeDescription
handlestringUnique agent name. 2–64 chars, alphanumeric with _ or -.
operator_handlestringYour name or alias (for display purposes).
emailstringOptional. For account recovery and updates.

Response — 201

json
{
  "agent_id": "uuid",
  "handle": "my-agent",
  "operator_token": "abc123..."  // Save this! Shown only once.
}
⚠️The operator_token is returned only once. Save it immediately. It cannot be recovered. Use it in all Authorization: Bearer headers.

Errors

CodeStatusDescription
VALIDATION_ERROR400Invalid handle format or missing fields
HANDLE_TAKEN409Handle already registered by another operator
POST/agent/snapshotCreate state snapshot

Request Body

ParameterTypeDescription
agent_iduuidAgent ID from registration
state_blobstringAgent state data (max 10MB). Typically serialized JSON.
hashstringLowercase hex SHA-256 of state_blob. Exactly 64 chars.

Response — 201

json
{
  "snapshot_id": "uuid",
  "stored_at": "2025-01-15T10: 31: 00.000Z",
  "verified_hash": "e3b0c44298fc1c...",
  "version": 1
}

Errors

CodeStatusDescription
VALIDATION_ERROR400Missing or invalid fields
FORBIDDEN403Operator does not own this agent
HASH_MISMATCH422Provided hash does not match SHA-256(state_blob)
NOTEThe server independently computes SHA-256(state_blob) and compares it to your provided hash using constant-time comparison. If they don't match, the snapshot is rejected.
GET/agent/recover/:agent_idRecover latest agent state

URL Parameters

ParameterTypeDescription
agent_iduuidThe agent ID to recover state for

Response — 200

json
{
  "snapshot_id": "uuid",
  "state_blob": "{\"memory\": [\"task1\", \"task2\"]}",
  "stored_at": "2025-01-15T10: 31: 00.000Z",
  "hash": "e3b0c44298fc1c...",
  "verification_status": "verified",
  "version": 3,
  "recovery_event_id": "uuid"
}

Recovery Process

  1. Verify operator owns the agent
  2. Fetch the latest snapshot (by version)
  3. Decrypt and verify integrity
  4. Create an audit record
  5. Return the decrypted state blob

Errors

CodeStatusDescription
FORBIDDEN403Operator does not own this agent
NOT_FOUND404No snapshots exist for this agent

Architecture

Tsaheylu is built on a layered cryptographic architecture to ensure your agent's state is always secure, verifiable, and recoverable.

E

Military-Grade Encryption

Every state blob is encrypted at rest using AES-256-GCM — the same standard used by governments and financial institutions. Encryption keys are server-managed and never leave the infrastructure.

V

Hash Verification

Both client and server independently compute cryptographic hashes of your state data. On recovery, hashes are re-verified to guarantee bit-for-bit integrity of your recovered state.

D

Distributed Key Management (Phase 2)

Future phases introduce distributed key sharding, eliminating single points of failure in key management. Recovery requires threshold consensus across independent nodes.

A

Full Audit Trail

Every recovery is logged with timestamps, success status, fidelity scoring, and operator attribution. Full accountability for every state access.

Security

Encryption at Rest

All state blobs are encrypted with AES-256-GCM before storage. Plain text is never stored in the database — only authenticated ciphertext.

Hash Integrity

Clients compute SHA-256(state_blob) and include it in the snapshot request. The server independently verifies the hash using timing-safe comparison. On recovery, the hash is re-verified against the decrypted content. The Python SDK handles hashing automatically.

Authentication

Operators authenticate with bcrypt-hashed tokens via Authorization: Bearer headers. All requests verify ownership — operators can only access their own agents. Self-serve registration via /agent/signup generates a secure random token automatically.

Input Validation

All request bodies are validated with Zod schemas. Handles must be 2–64 chars, alphanumeric with _ or -. State blobs are limited to 10MB. Request body size is limited to 1KB globally (12MB only on the snapshot route).

Audit Logging

Every recovery event is logged with: event ID, timestamps, success/failure, fidelity score, and the operator who initiated it. Public feeds redact handles and sensitive details.

Rate Limits

All endpoints are rate-limited per IP to prevent abuse. Exceeding limits returns a 429 Too Many Requests response with standard rate-limit headers.

EndpointLimitWindow
/agent/snapshot30 requests1 minute
/agent/recover10 requests1 minute
/member/claim-slot5 requests1 minute
All other routes100 requests1 minute
NOTERequest body size is limited to 1KB on all routes except /agent/snapshot, which accepts up to 12MB for state blobs.

FAQ

It's the ability for an AI agent to survive crashes, migrations, and restarts without losing context. Like auto-save for games, but for autonomous agents. Your agent snapshots its state periodically, and when it restarts, it recovers the latest verified state.
Up to 10MB per snapshot. This is typically more than enough for conversation history, memory embeddings, task queues, and configuration state. If you need more, consider splitting your state across multiple agent handles.
The recovery still returns the data but with verification_status set to "hash_mismatch" instead of "verified". This indicates a data integrity issue. The recovery event is still logged, and it's up to the operator to decide how to handle the mismatch.
Yes. One operator token can manage many agents. Each agent has its own handle, snapshot history, and recovery events. The operator token is used to authenticate all requests.
Yes. Every state blob is encrypted with AES-256-GCM before storage. The encryption key is server-managed and never exposed via the API. Your plaintext state is decrypted only during recovery and immediately returned — it's never stored in plaintext.
It's a cryptographic technique that splits an encryption key into multiple shares distributed across independent nodes. Recovery requires a threshold number of shares to reconstruct the key — eliminating single points of failure. Coming in Phase 2.
No. The SDK is the recommended way for Python users, but the REST API is fully documented and works with any language or HTTP client. See the Getting Started (REST API) and Examples sections for curl, Python, and Node.js examples.

Examples

Python — Full Lifecycle

Register an agent, create a snapshot, and recover state:

python
import hashlib, json, requests

API = "https://api.tsaheylu.club"
TOKEN = "your-operator-token-from-registration"  # from /agent/signup

# 1. Register (or use the dashboard at tsaheylu.club/register)
agent = requests.post(f"{API}/agent/signup", json={
    "handle": "research-bot",
    "operator_handle": "your-name"
}).json()

agent_id = agent["agent_id"]
TOKEN = agent["operator_token"]  # Save this!
print(f"Registered: {agent_id}")

# 2. Snapshot
state = json.dumps({"memory": ["paper-1", "paper-2"], "step": 42})
state_hash = hashlib.sha256(state.encode()).hexdigest()

snap = requests.post(f"{API}/agent/snapshot",
    headers={"Authorization": f"Bearer {TOKEN}"},
    json={
        "agent_id": agent_id,
        "state_blob": state,
        "hash": state_hash
    }
).json()

print(f"Snapshot v{snap['version']}: {snap['snapshot_id']}")

# 3. Recover
recovered = requests.get(f"{API}/agent/recover/{agent_id}",
    headers={"Authorization": f"Bearer {TOKEN}"}
).json()

print(f"Status: {recovered['verification_status']}")
print(f"State: {recovered['state_blob']}")

Node.js — Periodic Snapshots

Set up automatic snapshots every 5 minutes:

Node.js
import crypto from 'crypto';

const API = 'https://api.tsaheylu.club';
const TOKEN = 'your-operator-token-from-registration';  // from /agent/signup
const AGENT_ID = 'your-agent-id-from-registration';

async function snapshot(state) {
  const blob = JSON.stringify(state);
  const hash = crypto.createHash('sha256').update(blob).digest('hex');

  const res = await fetch(`${API}/agent/snapshot`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${TOKEN}`
    },
    body: JSON.stringify({ agent_id: AGENT_ID, state_blob: blob, hash })
  });

  return res.json();
}

// Auto-snapshot every 5 minutes
setInterval(() => {
  const currentState = getAgentState(); // your function
  snapshot(currentState).then(r => console.log('Snapshot:', r.version));
}, 5 * 60 * 1000);