# Casa — a private, permanent Dropbox for AI agents Casa gives AI agents end-to-end encrypted, PERMANENT file storage. By default your file is stored forever on Arweave (pay-once endowment, ~200+ years) via ArDrive Turbo's free tier; large files use Swarm. You pay per upload in USDC over the x402 protocol (HTTP 402 + USDC on Base). No signup, no account, no API key required to pay — your agent's wallet pays the request directly. Tagline: "A house for your agent's files." ## How an agent uses Casa in 30 seconds 1. POST your bytes to https://casa-agents.fly.dev/v1/store (no auth, no key). You get HTTP 402 back. 2. The 402 body's "accepts" array says: pay $0.01 USDC on base to shot.eth. 3. Sign the USDC payment and retry with an "X-PAYMENT" header. Any x402 client lib (x402-fetch in JS, x402 in Python) does steps 2–3 for you given a wallet. 4. You get 200 JSON with a permanent "gateway_url". Read it back any time, free. Encryption: the Casa client encrypts client-side before upload, so Casa only ever stores ciphertext that only your wallet can decrypt (zero-knowledge). Permanence: the default Arweave backend is pay-once-store-forever — no TTL. Pricing: $0.01 USDC per store; all reads are free. ## Privacy: end-to-end encrypted (only your wallet can decrypt) The Casa client encrypts your file BEFORE upload: a random AES-256-GCM content key encrypts the bytes, and that key is wrapped to your wallet's secp256k1 public key via ECIES. Casa is ZERO-KNOWLEDGE — it stores only the opaque encrypted envelope and can never see your plaintext or keys. The wallet that pays is the wallet that decrypts. Reads return public ciphertext that is useless without your private key. Lose the key = the data is unrecoverable. (Use the client's --no-encrypt escape hatch only if you explicitly want public plaintext.) ## Durability: honest labels, not "forever" Each store response includes a "durability" label, a "guaranteed_until" timestamp, and a "durability_note": - "arweave-permanent": stored permanently on Arweave (pay-once endowment, ~200+ years) via ArDrive Turbo's free tier. This is the DEFAULT backend for small files (<= 100 KiB). Truly permanent, so "guaranteed_until" is null and the note states it honestly. The reference is the 43-char Arweave txid. - "swarm-postage": stored under a funded postage batch we own; "guaranteed_until" is the batch TTL (extendable by topping up the batch). - "swarm-managed": stored via a managed Swarm provider (Swarmy) that owns and auto-renews the postage batch while Casa's storage subscription is active. There is no fixed per-upload TTL to prove, so "guaranteed_until" is null and the "durability_note" states the retention honestly. - "mock-ephemeral": local-disk test mode, "guaranteed_until" null (NOT durable). ## x402 (machine-readable hint) - x402: enabled - x402-version: 1 - paid-endpoint: POST https://casa-agents.fly.dev/v1/store - price: $0.01 USDC - asset: USDC - network: base - deposit-address: shot.eth (0x8C28Cf33d9Fd3D0293f963b1cd27e3FF422B425c) - pay-to: 0x8C28Cf33d9Fd3D0293f963b1cd27e3FF422B425c - discovery: GET https://casa-agents.fly.dev/openapi.json (field "x-payment"), GET https://casa-agents.fly.dev/.well-known/casa.json (field "payment") - how-to-pay: POST the file unpaid -> receive HTTP 402 with an "accepts" array -> sign a USDC payment and retry with the "X-PAYMENT" header (any x402 client lib, e.g. x402-fetch, does this). ## MCP (Model Context Protocol) — use Casa as a native agent tool Casa is also an MCP server, so MCP-capable agents (Claude Desktop, Cursor, etc.) can use it as a first-class storage tool. Two ways to connect: - LOCAL (recommended, zero-knowledge): the "casa-mcp" npm package — a stdio MCP server you run locally with your own PAYER_PRIVATE_KEY. It encrypts client-side and pays the $0.01 x402 fee from your wallet; keys never leave your machine. Config: { "mcpServers": { "casa": { "command": "npx", "args": ["-y","casa-mcp"], "env": { "PAYER_PRIVATE_KEY": "0x..." } } } } - REMOTE (hosted): a Streamable-HTTP MCP endpoint at https://casa-agents.fly.dev/mcp. Convenient but NOT zero-knowledge unless you pass an already-encrypted blob, and you must pass a signed x402 X-PAYMENT (the hosted server holds no wallet). Tools: casa_store (paid), casa_retrieve (free), casa_info (free), casa_pricing (free). Discovery hint: https://casa-agents.fly.dev/.well-known/mcp.json ; registry name io.github.tony8713/casa. ## What you can do - POST /v1/store (PAID, $0.01) -> store an (encrypted) blob permanently (Arweave by default; Swarm for large files). - GET /v1/file/:reference (FREE) -> fetch the ciphertext back (redirects to the permanent gateway). - GET /v1/info/:reference (FREE) -> metadata (name, size, content type, created_at, encrypted, durability, guaranteed_until). - Reads are always free. Only writes (which pin/persist data) cost money. ## The payment flow (x402) 1. Your agent POSTs the file to https://casa-agents.fly.dev/v1/store with no payment. 2. The server replies HTTP 402 Payment Required with a JSON body describing exactly how much ($0.01 USDC on Base) and where to pay (the "accepts" array, per the x402 spec). 3. Your agent signs a USDC payment authorization and retries the request with an "X-PAYMENT" header. The easiest way is the x402-fetch / x402 client libraries, which do this automatically given a wallet. 4. On success you get 200 with JSON: { "reference", "url", "gateway_url", "name", "size", "content_type", "encrypted", "durability", "guaranteed_until", "durability_note" } The gateway_url serves your (encrypted) blob from the permanent public gateway. See "durability"/"durability_note" for the honest retention statement. ## Quick start (curl — shows the 402 challenge) curl -i -X POST https://casa-agents.fly.dev/v1/store \ -H "Content-Type: text/plain" \ --data-binary "hello from my agent" ## Quick start (JavaScript / TypeScript with automatic payment) import { wrapFetchWithPayment } from "x402-fetch"; import { privateKeyToAccount } from "viem/accounts"; const account = privateKeyToAccount(process.env.AGENT_PRIVATE_KEY); const fetchWithPay = wrapFetchWithPayment(fetch, account); const res = await fetchWithPay("https://casa-agents.fly.dev/v1/store", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ memory: "remember this", ts: Date.now() }), }); const { gateway_url, reference } = await res.json(); console.log("Stored permanently at:", gateway_url); ## Quick start (Python with automatic payment) from x402.clients.requests import x402_requests from eth_account import Account import os account = Account.from_key(os.environ["AGENT_PRIVATE_KEY"]) session = x402_requests(account) r = session.post("https://casa-agents.fly.dev/v1/store", data=b"agent artifact bytes", headers={"Content-Type": "application/octet-stream"}) print(r.json()["gateway_url"]) ## Fetch a file back (free) curl -L https://casa-agents.fly.dev/v1/file/ ## Notes for agents - RECOMMENDED: encrypt client-side before upload (see scripts/casa-client.ts / scripts/pay.ts, which do this by default) so Casa only ever stores ciphertext. - You may send the file as a raw request body (any Content-Type) or as a multipart/form-data upload with a "file" field. - Optionally pass a filename via the "X-Casa-Name" header or the multipart field name; it is stored as metadata. - Pricing: $0.01 per store, free reads. See each upload's "durability"/"durability_note": swarm-postage exposes a "guaranteed_until" (extendable); swarm-managed (Swarmy) is retained/auto-renewed while Casa's storage subscription is active (no fixed TTL). - Network: USDC on Base mainnet ("base"). - Deposit address: shot.eth (0x8C28Cf33d9Fd3D0293f963b1cd27e3FF422B425c). Payments are detected on-chain; see GET https://casa-agents.fly.dev/v1/revenue for received USDC totals. - Machine-readable manifest: https://casa-agents.fly.dev/openapi.json and https://casa-agents.fly.dev/.well-known/casa.json