Package Exports
- @tangle-network/tcloud
- @tangle-network/tcloud/shielded
Readme
tcloud
TypeScript SDK and CLI for Tangle AI Cloud — decentralized LLM inference with operator routing, reputation-based selection, and anonymous payments via ShieldedCredits.
Zero framework dependencies. Pure fetch + SSE. Works in Node.js, Deno, Bun, and edge runtimes.
Table of Contents
- Installation
- SDK
- CLI
- Configuration
- OpenAI SDK Compatibility
- Vercel AI SDK Compatibility
- Examples
- License
Installation
npm install tcloudOr run the CLI directly:
npx tcloud chat "What is Tangle?"SDK
Quick Start
import { TCloud } from 'tcloud'
// Set model at client creation — explicit and consistent.
const client = new TCloud({
apiKey: 'sk-tan-...',
model: 'gpt-4o-mini',
})
const answer = await client.ask('What is Tangle Network?')
console.log(answer)Model Selection
Model is set at client creation. Override per-request when needed:
// Default model for all requests
const client = new TCloud({ apiKey: '...', model: 'gpt-4o-mini' })
await client.ask('Hello') // uses gpt-4o-mini
// Full control per-request (OpenAI-compatible)
const completion = await client.chat({
model: 'claude-sonnet-4-6',
messages: [{ role: 'user', content: 'Hello' }],
temperature: 0.5,
maxTokens: 100,
})
// Get full response with usage stats
const full = await client.askFull('Hello')
console.log(full.model, full.usage?.total_tokens)
// Search available models
const llamas = await client.searchModels('llama')Streaming
for await (const chunk of client.askStream('Explain zero-knowledge proofs')) {
process.stdout.write(chunk)
}
// With model override
for await (const chunk of client.askStream('Hello', 'claude-sonnet-4-6')) {
process.stdout.write(chunk)
}Full Chat Completion
OpenAI-compatible request/response format:
const completion = await client.chat({
model: 'meta-llama/llama-4-maverick',
messages: [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'Hello' },
],
temperature: 0.7,
maxTokens: 1024,
})
console.log(completion.choices[0].message.content)Private Inference
Anonymous inference with no API key. Uses EIP-712 SpendAuth signatures — the operator verifies payment without learning your identity.
import { TCloud } from 'tcloud'
const client = TCloud.shielded()
const answer = await client.ask('Hello from the shadows')Under the hood: generates an ephemeral wallet, signs a SpendAuth payload, and sends it as an X-Payment-Signature header. The operator validates the cryptographic proof and serves inference without knowing who you are.
Operator Routing
Route requests to specific operators or use strategy-based selection:
const client = new TCloud({
apiKey: 'sk-tan-...',
routing: {
prefer: 'operator-slug', // specific operator
strategy: 'lowest-latency', // or 'lowest-price', 'highest-reputation'
region: 'us-east', // geographic preference
},
})The gateway selects the best operator based on a composite score (reputation 40%, latency 30%, price 30%) and returns the selection in response headers:
// After a request, check which operator served it:
// X-Tangle-Operator: <slug>
// X-Tangle-Price-Input: <per-token>
// X-Tangle-Price-Output: <per-token>Models and Operators
// List all available models
const models = await client.models()
models.forEach(m => console.log(m.id, m._provider))
// Search models by name, provider, or capability
const llamas = await client.searchModels('llama')
const anthropic = await client.searchModels('anthropic')
// List active operators with stats
const { operators, stats } = await client.operators()
console.log(`${stats.activeOperators} operators serving ${stats.totalModels} models`)
// Check credit balance
const credits = await client.credits()
console.log(`Balance: $${credits.balance}`)API Key Management
Create, list, and revoke API keys programmatically:
// Create a new key
const { key, id } = await client.createKey('my-app')
console.log(key) // sk-tan-... (shown once, store it)
// List all keys
const keys = await client.keys()
keys.forEach(k => console.log(k.name, k.prefix, k.lastUsedAt))
// Revoke a key
await client.revokeKey(id)Cost Estimation
Preview cost before sending a request:
const cost = await client.estimateCost({
model: 'gpt-4o',
inputTokens: 1000,
outputTokens: 500,
})
console.log(`Estimated: $${cost.total.toFixed(6)}`)
// { inputCost: 0.005, outputCost: 0.0075, total: 0.0125 }Spending Limits
Prevent runaway costs with per-request and total budget caps:
const client = new TCloud({
apiKey: 'sk-tan-...',
model: 'gpt-4o-mini',
limits: {
maxCostPerRequest: 0.01, // $0.01 max per request
maxTotalSpend: 1.00, // $1.00 lifetime budget
maxRequests: 100, // hard request cap
onLimitWarning: (info) => {
console.warn(`${info.type} at ${info.current}/${info.limit}`)
},
},
})
// Requests that would exceed limits are blocked with TCloudError (429)
await client.ask('Hello')
// Check metering
const { totalSpent, requestCount } = client.usageCLI
Authentication
tcloud auth login # Browser-based device flow
tcloud auth set-key sk-tan-... # Set key directly
tcloud auth status # Check current authChat
tcloud chat "Explain zero-knowledge proofs"
tcloud chat -m meta-llama/llama-4-maverick "Hello"
tcloud chat --private "Anonymous request" # ShieldedCredits mode
tcloud chat # Interactive modeBrowse
tcloud models # List available models
tcloud models -s llama # Search models
tcloud operators # List active operatorsCredits and Keys
tcloud credits balance # Check balance
tcloud credits add 10 # Add credits
tcloud keys create my-app # Create a new API key
tcloud keys list # List keysWallet Management
For private inference, manage ephemeral wallets:
tcloud wallet generate # Create wallet
tcloud wallet generate -l "research" # With label
tcloud wallet list # List walletsWallets use BIP-39 mnemonics with BIP-44 derivation. Private keys are encrypted at rest with AES-256-GCM (PBKDF2 210K iterations).
Configuration
Config stored in ~/.tcloud/config.json:
tcloud config --api-url https://router.tangle.tools
tcloud config --model gpt-4o-miniEnvironment variables:
TCLOUD_API_KEY— API key (primary)OPENAI_API_KEY— Fallback API key (works because the API is OpenAI-compatible)TCLOUD_BASE_URL— Override API base URL
OpenAI SDK Compatibility
tcloud's API is OpenAI-compatible. You can use the OpenAI SDK directly:
import OpenAI from 'openai'
const client = new OpenAI({
apiKey: 'sk-tan-...',
baseURL: 'https://router.tangle.tools/v1',
})
const completion = await client.chat.completions.create({
model: 'meta-llama/llama-4-maverick',
messages: [{ role: 'user', content: 'Hello' }],
})Vercel AI SDK Compatibility
Use with the Vercel AI SDK's OpenAI provider:
import { createOpenAI } from '@ai-sdk/openai'
import { generateText } from 'ai'
const tangle = createOpenAI({
apiKey: 'sk-tan-...',
baseURL: 'https://router.tangle.tools/v1',
})
const { text } = await generateText({
model: tangle('meta-llama/llama-4-maverick'),
prompt: 'What is decentralized AI?',
})Examples
See the examples/ directory — each is a self-contained script:
| # | Example | What it shows |
|---|---|---|
| 01 | Quick Start | Minimum viable setup |
| 02 | Model Selection | Three ways to pick a model, search, browse |
| 03 | Streaming | Real-time SSE output, text + chunk modes |
| 04 | Private Inference | ShieldedCredits, ephemeral wallets, auto-replenish |
| 05 | Operator Routing | Prefer operator, strategy, region, list operators |
| 06 | Cost & Usage | Estimate cost, track tokens, check balance |
| 07 | API Keys | Create, list, revoke keys programmatically |
| 08 | OpenAI SDK | Drop-in replacement via baseURL |
| 09 | Vercel AI SDK | generateText + streamText with Tangle |
| 10 | Spending Limits | Budget caps, request limits, warning callbacks |
Run any example:
TCLOUD_API_KEY=sk-tan-... npx tsx examples/01-quick-start.ts