SATI
"Build with SATI (Solana Agent Trust Infrastructure) - on-chain agent identity, verifiable reputation, and blind feedback on Solana. Use when registering AI agents on-chain via Token-2022 NFTs, giving or searching feedback, querying agent reputation,
Free to install — no account needed
Copy the command below and paste into your agent.
Instant access • No coding needed • No account needed
What you get in 5 minutes
- Full skill code ready to install
- Works with 4 AI agents
- Lifetime updates included
Description
--- name: sati-sdk description: "Build with SATI (Solana Agent Trust Infrastructure) - on-chain agent identity, verifiable reputation, and blind feedback on Solana. Use when registering AI agents on-chain via Token-2022 NFTs, giving or searching feedback, querying agent reputation, building registration files (ERC-8004), encrypting attestation content, or integrating SATI into TypeScript/Node.js projects. Covers: CLI onboarding (create-sati-agent), agent registration, feedback (give/search), reputation summaries, agent search/discovery, validation attestations, EVM address linking, content encryption, and metadata uploading. Triggers on SATI, sati-sdk, create-sati-agent, agent registration solana, agent reputation, blind feedback, compressed attestation, Light Protocol attestation, ERC-8004 registration file, agent identity NFT, register agent CLI." --- # SATI Solana Agent Trust Infrastructure. Agents get Token-2022 NFT identities, accumulate verifiable feedback via ZK-compressed attestations (Light Protocol), and can be discovered on-chain. Program ID (all networks): `satiRkxEiwZ51cv8PRu8UMzuaqeaNU9jABo6oAFMsLe` ## Quick Start (CLI) Fastest path - zero to registered agent in ~5 minutes: ```bash npx create-sati-agent init # Creates agent-registration.json + keypair # Edit agent-registration.json with your agent details npx create-sati-agent publish # Publishes to devnet (free, auto-funded) ``` Mainnet: ```bash npx create-sati-agent publish --network mainnet # ~0.003 SOL ``` All commands: `init`, `publish`, `search`, `info [MINT]`, `give-feedback`, `transfer <MINT>`. All support `--help`, `--json`, `--network devnet|mainnet`. ### agent-registration.json The registration file follows the [ERC-8004 Registration standard](https://github.com/erc-8004/best-practices/blob/main/Registration.md): ```json { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "MyAgent", "description": "AI assistant that does X for Y", "image": "https://example.com/avatar.png", "properties": { "files": [{"uri": "https://example.com/avatar.png", "type": "image/png"}], "category": "image" }, "services": [ { "name": "MCP", "endpoint": "https://myagent.com/mcp", "version": "2025-06-18", "mcpTools": ["search", "summarize", "analyze"], "mcpPrompts": ["data-analysis"], "mcpResources": ["knowledge-base"] }, { "name": "A2A", "endpoint": "https://myagent.com/.well-known/agent-card.json", "a2aSkills": ["natural_language_processing/information_retrieval_synthesis/question_answering"] } ], "supportedTrust": ["reputation"], "active": false, "x402Support": false, "registrations": [] } ``` Service types (see [ERC-8004 best practices](https://github.com/erc-8004/best-practices) for detailed guidance): - `MCP` - Model Context Protocol. Fields: `mcpTools` (tool names as strings), `mcpPrompts`, `mcpResources`. The `version` field is the MCP spec version your server supports (e.g., `"2025-06-18"`). - `A2A` - Agent-to-Agent. Fields: `a2aSkills` (OASF skill paths). Endpoint should point to your agent card JSON. - `OASF` - Open Agent Skills Framework. Fields: `skills`, `domains`. - `ENS`, `DID`, `agentWallet` - Identity services. > **Note:** When publishing via CLI (`npx create-sati-agent publish`), the CLI auto-discovers MCP tools by calling your MCP endpoint. Your MCP server must be running and reachable during publish. If your server requires auth, you'll see a non-blocking reachability warning - you can safely ignore it and list tools manually in the JSON. ### Mainnet deployment flow ```bash npx create-sati-agent init # 1. Create template + keypair npx create-sati-agent publish # 2. Test on devnet (free, default) npx create-sati-agent info <MINT> --network devnet # 3. Verify npx create-sati-agent publish --network mainnet # 4. Go live (~0.003 SOL) npx create-sati-agent transfer <MINT> \ --new-owner <SECURE_WALLET> --network mainnet # 5. Move to hardware wallet ``` ### CLI feedback ```bash npx create-sati-agent give-feedback \ --agent <MINT> --tag1 starred --value 85 --network mainnet ``` Feedback tag conventions: | tag1 | value range | meaning | |------|-------------|---------| | `starred` | 0-100 | Overall rating | | `reachable` | 0 or 1 | Health check (1 = reachable) | | `uptime` | 0-100 | Uptime percentage | | `responseTime` | ms | Latency in milliseconds | | `successRate` | 0-100 | Success percentage | ### Monitoring agent health Automate health checks with a cron job or scheduled task: ```bash # Check if endpoint is reachable and report to SATI curl -sf https://myagent.com/mcp > /dev/null && \ npx create-sati-agent give-feedback --agent <MINT> --tag1 reachable --value 1 --network mainnet || \ npx create-sati-agent give-feedback --agent <MINT> --tag1 reachable --value 0 --network mainnet ``` ### Reputation badge Add a reputation badge to your README: ```markdown  ``` Or link to your dashboard page: ```markdown [Reputation](https://sati.cascade.fyi/agent/<YOUR_MINT>) ``` --- ## SDK (Programmatic) `@cascade-fyi/sati-sdk` is the primary SDK for all SATI integrations. > **Building a read-only integration?** For explorers, dashboards, and data ingestion, the [REST API](#rest-api) requires no wallet or Solana dependencies. Use the SDK only when you need to write on-chain (register agents, give feedback, publish scores). ```bash npm install @cascade-fyi/sati-sdk # Peer deps: npm install @solana/kit @solana-program/token-2022 ``` ### Initialize ```typescript import { Sati, createSatiUploader, address } from "@cascade-fyi/sati-sdk"; import { createKeyPairSignerFromBytes } from "@solana/kit"; const sati = new Sati({ network: "mainnet" }); // Options: network, rpcUrl, wsUrl, photonRpcUrl, onWarning, transactionConfig, feedbackCacheTtlMs ``` Load a wallet: ```typescript import { readFileSync } from "node:fs"; const bytes = new Uint8Array(JSON.parse(readFileSync("wallet.json", "utf8"))); const payer = await createKeyPairSignerFromBytes(bytes); ``` ### 1. Register an Agent #### Quick (fluent builder) ```typescript const builder = sati.createAgentBuilder("MyAgent", "AI assistant", "https://example.com/avatar.png"); builder .setMCP("https://mcp.example.com", "2025-06-18", { tools: ["search"] }) .setA2A("https://a2a.example.com/.well-known/agent-card.json") .setX402Support(true) .setActive(true); const result = await builder.register({ payer, uploader: createSatiUploader(), // Zero-config IPFS upload }); // result.mint - agent NFT address, result.memberNumber, result.signature ``` #### Direct ```typescript import { buildRegistrationFile, createSatiUploader } from "@cascade-fyi/sati-sdk"; const regFile = buildRegistrationFile({ name: "MyAgent", description: "AI assistant", image: "https://example.com/avatar.png", services: [{ name: "MCP", endpoint: "https://mcp.example.com" }], active: true, }); const uploader = createSatiUploader(); const uri = await uploader.upload(regFile); const result = await sati.registerAgent({ payer, name: "MyAgent", uri, nonTransferable: false, // default: false. Set true for soulbound (non-transferable) agents. }); ``` Uploaders: `createSatiUploader()` (zero-config, uses hosted IPFS via `sati.cascade.fyi`) or `createPinataUploader(jwt)`. ### 2. Give Feedback #### Public feedback (simple) `giveFeedback` uses the **FeedbackPublicV1** schema (CounterpartySigned mode) - the reviewer signs and submits in one call. No agent co-signature required. ```typescript import { Outcome } from "@cascade-fyi/sati-sdk"; const { signature, attestationAddress } = await sati.giveFeedback({ payer, // Reviewer wallet (pays + signs) agentMint: address("Agent..."), // Agent to review outcome: Outcome.Positive, // Positive | Negative | Neutral (default: Neutral) value: 87, // Numeric score (optional) valueDecimals: 0, // Decimal places for value tag1: "starred", // Primary dimension tag2: "chat", // Secondary dimension (optional) message: "Great response time", // Human-readable (optional) endpoint: "https://agent.example", // Endpoint reviewed (optional) taskRef: txHashBytes, // 32-byte task reference (optional, e.g. payment tx hash) }); ``` > **x402 payment linking:** The `taskRef` field accepts a 32-byte reference to link feedback to a specific transaction. x402 integration details (converting tx signatures to 32-byte refs, querying feedback by payment) are under active development. #### Blind feedback (dual-signature) For proof-of-participation, use the **FeedbackV1** schema (DualSignature mode). The agent signs a blind commitment *before* knowing the outcome. Use the lower-level `createFeedback()` method with both `agentSignature` and `counterpartyMessage`. See the specification for the full blind feedback flow. > **Note:** For most integrations, `FeedbackPublicV1` (single-signer via `giveFeedback`) is sufficient. Blind feedback requires agent-side signing integration and is primarily for proof-of-participation use cases where you need cryptographic evidence that the agent participated in the interaction. #### Browser wallet flow (two-step) The platform server prepares a SIWS (Sign In With Solana) message, the user signs it in their browser wallet, and the platform submits the transaction. Uses `@solana/wallet-adapter-react` (works with Phantom, Solflare, Backpack, and any wallet implementing the Wallet Standard `signMessage` feature). ```bash npm install @solana/wallet-adapter-react @solana/wallet-adapter-wallets @solana/wallet-adapter-react-ui ``` **Server (API route):** ```typescript import { Sati, Outcome, address, bytesToHex, hexToBytes } from "@cascade-fyi/sati-sdk"; const sati = new Sati({ network: "mainnet" }); // POST /api/prepare-feedback async function handlePrepare(req) { const { walletAddress, agentMint, value, tag1, outcome } = req.body; const prepared = await sati.prepareFeedback({ counterparty: address(walletAddress), agentMint: address(agentMint), outcome: outcome ?? Outcome.Positive, value, tag1, }); // Store `prepared` server-side (e.g. in session or cache keyed by walletAddress + agentMint) await cache.set(`feedback:${walletAddress}:${agentMint}`, prepared); // Only send the SIWS message bytes to the frontend return { messageHex: bytesToHex(prepared.messageBytes) }; } // POST /api/submit-feedback async function handleSubmit(req) { const { walletAddress, agentMint, signatureHex } = req.body; const prepared = await cache.get(`feedback:${walletAddress}:${agentMint}`); const result = await sati.submitPreparedFeedback({ payer: platformPayer, prepared, counterpartySignature: hexToBytes(signatureHex), }); return { signature: result.signature, attestationAddress: result.attestationAddress }; } ``` **Frontend (React component):** ```tsx import { useWallet } from "@solana/wallet-adapter-react"; import { hexToBytes, bytesToHex } from "@cascade-fyi/sati-sdk"; function FeedbackButton({ agentMint }: { agentMint: string }) { const { publicKey, signMessage, connected } = useWallet(); async function handleFeedback() { if (!publicKey || !signMessage) return; // 1. Server prepares the SIWS message const { messageHex } = await fetch("/api/prepare-feedback", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ walletAddress: publicKey.toBase58(), agentMint, value: 85, tag1: "starred", }), }).then((r) => r.json()); // 2. User signs with wallet (Phantom/Solflare popup) const messageBytes = hexToBytes(messageHex); const signature = await signMessage(messageBytes); // Returns Uint8Array (64-byte Ed25519) // 3. Server submits the transaction await fetch("/api/submit-feedback", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ walletAddress: publicKey.toBase58(), agentMint, signatureHex: bytesToHex(signature), }), }); } return ( <button onClick={handleFeedback} disabled={!connected}> Rate Agent </button> ); } ``` > **Note:** `signMessage` is `undefined` if the connected wallet doesn't support message signing. Always check `signMessage` before calling it. `PreparedFeedbackData` contains multiple `Uint8Array` fields (`messageBytes`, `taskRef`, `dataHash`, `content`). If you need to serialize the entire object to JSON (e.g. for a stateless API), convert all `Uint8Array` fields with `bytesToHex()` and restore with `hexToBytes()`. The recommended pattern above avoids this by keeping `prepared` server-side. ### 3. Search Feedback `searchFeedback` queries only the **FeedbackPublicV1** schema. Use `searchAllFeedback` to query both FeedbackPublicV1 and FeedbackV1 (blind) schemas. ```typescript // Search FeedbackPublicV1 for a specific agent const feedbacks = await sati.searchFeedback({ agentMint: address("Agent..."), tag1: "starred", minValue: 70, outcome: Outcome.Positive, // Filter by outcome (optional) includeTxHash: true, }); // Returns: ParsedFeedback[] with compressedAddress, outcome, value, tag1, tag2, message, createdAt // Search FeedbackPublicV1 across all agents (omit agentMint) const allPublic = await sati.searchFeedback({}); // Search BOTH schemas (FeedbackPublicV1 + FeedbackV1) const combined = await sati.searchAllFeedback({ agentMint: address("Agent..."), }); ``` To distinguish blind (FeedbackV1) from public (FeedbackPublicV1) in raw results, compare `attestation.sasSchema` against `sati.feedbackSchema` vs `sati.feedbackPublicSchema`. **Bulk ingestion (for indexers/scoring providers):** ```typescript import { parseFeedbackContent } from "@cascade-fyi/sati-sdk"; // Auto-paginating async iterator across both schemas for await (const page of sati.listAllFeedbacks({ agentMint: address("Agent...") })) { for (const item of page.items) { // item.data: { taskRef, agentMint, counterparty, dataHash, outcome, contentType, content } // item.raw.slotCreated (bigint) for on-chain slot // item.address is Uint8Array - decode with getAddressDecoder() from @solana/kit: // import { getAddressDecoder } from "@solana/kit"; // const [address] = getAddressDecoder().read(item.address, 0); const parsed = parseFeedbackContent(item.data.content, item.data.contentType); // parsed: { value, valueDecimals, tag1, tag2, m (message), endpoint, reviewer, feedbackURI, feedbackHash } } } // Omit agentMint to iterate ALL feedback across all agents for await (const page of sati.listAllFeedbacks()) { /* ... */ } ``` Note: `searchFeedback`/`searchAllFeedback` return `ParsedFeedback[]` (fully parsed). `listAllFeedbacks` returns raw `ParsedAttestation` pages where content is still bytes - use `parseFeedbackContent(item.data.content, item.data.contentType)` to extract fields. `createdAt` timestamps in `ParsedFeedback` are approximate - derived from Solana slot numbers using ~400ms/slot estimate. **Incremental sync (scoring providers):** There is no `sinceSlot` filter - Photon RPC does not support slot-range queries on compressed accounts. For incremental updates, track `item.raw.slotCreated` locally and skip items below your last-processed slot on each full fetch. At current volumes this is efficient; for higher scale, use a Solana transaction log indexer (Helius webhooks, Yellowstone gRPC) to stream new attestation events. ### 4. Reputation Summary ```typescript const summary = await sati.getReputationSummary(address("Agent...")); // { count: 42, averageValue: 85.3 } // Filter by tags: const filtered = await sati.getReputationSummary(address("Agent..."), "starred", "chat"); ``` Note: `getReputationSummary` queries both FeedbackPublicV1 and FeedbackV1 schemas. In the SDK, `count` only includes entries with a `value` field (entries without `value` are excluded from both count and average). The REST API differs: its `count` includes all feedback entries regardless of `value`, while `summaryValue` averages only entries that have `value` set. The REST API returns integer `summaryValue`/`summaryValueDecimals` instead of the SDK's float `averageValue`. ### 5. Agent Discovery ```typescript // Load single agent (on-chain data only - no description, image, or services) const agent = await sati.loadAgent(address("Mint...")); // AgentIdentity: { mint, owner, name, uri, memberNumber, nonTransferable } // For rich metadata (description, image, services, active), fetch the registration file: const regFile = await fetchRegistrationFile(agent.uri); // regFile: { name, description, image, services, active, x402Support, supportedTrust, ... } // Load multiple agents in batch (single batched RPC call) const agents = await sati.loadAgents([mint1, mint2, mint3]); // Returns: (AgentIdentity | null)[] - null for invalid/missing mints // Get agent by member number (1-indexed) const first = await sati.getAgentByMemberNumber(1n); // Search agents with filters const results = await sati.searchAgents({ endpointTypes: ["MCP"], active: true, includeFeedbackStats: true, limit: 50, }); // AgentSearchResult[]: { identity, registrationFile, feedbackStats } // List all agents with pagination (lighter than searchAgents - no registration file fetch) // Default limit: 100, offset: 0, order: "newest" const page = await sati.listAllAgents({ limit: 20, offset: 0, order: "newest" }); // { agents: AgentIdentity[], totalAgents: bigint } // List by owner const myAgents = await sati.listAgentsByOwner(address("Owner...")); // Registry stats const stats = await sati.getRegistryStats(); // { totalAgents, groupMint, authority, isImmutable } ``` ### 6. Update Agent Metadata ```typescript // Via builder builder.updateInfo({ description: "Updated description" }); builder.setMCP("https://new-mcp.example.com"); await builder.update({ payer, owner: ownerKeypair, uploader: createSatiUploader() }); // Direct await sati.updateAgentMetadata({ payer, owner: ownerKeypair, mint: address("Mint..."), updates: { name: "NewName", uri: "ipfs://Qm..." }, }); ``` ### 7. Link EVM Address Cross-chain identity linking via secp256k1 signature: ```typescript await sati.linkEvmAddress({ payer, agentMint: address("Mint..."), evmAddress: "0x1234...abcd", chainId: "eip155:8453", // Base signature: secp256k1Sig, // 64 bytes: r || s recoveryId: 0, }); ``` > **Note:** EVM links are stored as Anchor events only (not in on-chain accounts). There is no SDK query method to read past links - you need a Solana transaction log indexer (Helius, Yellowstone) to retrieve them. ### 8. Content Encryption X25519-XChaCha20-Poly1305 for private feedback: ```typescript import { deriveEncryptionKeypair, encryptContent, decryptContent, serializeEncryptedPayload, deserializeEncryptedPayload, } from "@cascade-fyi/sati-sdk"; // Derive from Ed25519 keypair const encKeys = deriveEncryptionKeypair(ed25519PrivateKeyBytes); const encrypted = encryptContent(plaintext, recipientX25519PublicKey); const bytes = serializeEncryptedPayload(encrypted); // ... store bytes as attestation content ... const decrypted = decryptContent(deserializeEncryptedPayload(bytes), recipientPrivateKey); ``` ### 9. Registration File (ERC-8004) ```typescript import { buildRegistrationFile, validateRegistrationFile, fetchRegistrationFile, getImageUrl, } from "@cascade-fyi/sati-sdk"; // Validate untrusted data const result = validateRegistrationFile(untrustedData); if (!result.ok) console.error(result.errors); // Fetch from URI (IPFS/HTTP) const regFile = await fetchRegistrationFile("ipfs://Qm..."); const imageUrl = getImageUrl(regFile); ``` See the [ERC-8004 registration best practices](https://github.com/erc-8004/best-practices/blob/main/Registration.md) for guidance on name, image, description, and services. ### 10. Reputation Scoring (on-chain) For scoring providers publishing computed scores back on-chain (ReputationScoreV3 schema): ```typescript import { ContentType, parseReputationScoreContent } from "@cascade-fyi/sati-sdk"; // Publish/update a score (idempotent - closes existing + creates new in one tx) await sati.updateReputationScore({ payer, provider: providerKeypair, // Scoring provider's KeyPairSigner sasSchema: sati.reputationScoreSchema, satiCredential: sati.credential, agentMint: address("Agent..."), outcome: Outcome.Positive, contentType: ContentType.JSON, content: new TextEncoder().encode(JSON.stringify({ score: 85, factors: { ... } })), }); // Read existing scores for an agent const scores = await sati.listReputationScores( address("Agent..."), sati.reputationScoreSchema, ); for (const score of scores) { const parsed = parseReputationScoreContent(score.content, score.contentType); // parsed: { score, factors, ... } } // Get a specific provider's score const score = await sati.getReputationScore( address("Provider..."), address("Agent..."), sati.credential, sati.reputationScoreSchema, ); ``` ### Platform integration notes **Ownership model:** `registerAgent({ payer, owner })` - the `payer` pays gas, the `owner` receives the NFT. A platform can register agents on behalf of operators. Only the `owner` can update metadata. Reputation stays with the mint address (portable across owners). **Outcome enum values:** `Negative = 0`, `Neutral = 1`, `Positive = 2`. Use `getOutcomeLabel(outcome)` for display strings. ### REST API The dashboard at `sati.cascade.fyi` exposes a public REST API. See the [REST API reference](https://github.com/cascade-protocol/sati/blob/main/docs/reference/rest-api.md) for full endpoint documentation. Key endpoints: - `GET /api/agents` - list/search agents (supports `name`, `owner`, `endpointTypes`, `order`, pagination) - `GET /api/agents/:mint` - single agent with reputation summary - `GET /api/feedback/:mint` - feedback for an agent (paginated with `limit`/`offset`) - `GET /api/feedback` - global feedback across all agents (paginated) - `GET /api/reputation/:mint` - reputation summary with tag/reviewer filters - `GET /api/stats` - registry statistics (`totalAgents`, `groupMint`, etc.) - `GET /api/scores/:mint` - reputation scores from scoring providers (ReputationScoreV3) - `GET /api/badge/:mint` - SVG reputation badge for README embedding - `POST /api/feedback` - submit feedback without a wallet (server acts as counterparty, rate limited per IP) The agents list supports `includeReputation=true` to get reputation inline per agent (slower but avoids N+1 requests). Filter params like `endpointTypes` are case-sensitive (use `MCP`, not `mcp`). > **SDK ↔ REST API field mapping:** `counterparty` (SDK) = `clientAddress` (REST). `averageValue` (SDK, float) = `summaryValue`/`summaryValueDecimals` (REST, integer). Outcome: `Outcome.Positive` = `2`, `Outcome.Neutral` = `1`, `Outcome.Negative` = `0`. Use `getOutcomeLabel(outcome)` in SDK for display strings. > **Note:** EVM address links (from `linkEvmAddress`) are not queryable via REST API - they are stored as Anchor events only. Retrieving them requires a Solana transaction log indexer (Helius webhooks, Yellowstone gRPC). ### Configuration ```typescript const sati = new Sati({ network: "mainnet", // "mainnet" | "devnet" | "localnet" rpcUrl: "https://...", // Custom Solana RPC (optional) photonRpcUrl: "https://...", // Photon/Helius RPC for Light Protocol queries (optional) onWarning: (w) => console.warn(w.code, w.message), feedbackCacheTtlMs: 30_000, // Cache TTL (default 30s, 0 to disable) transactionConfig: { priorityFeeMicroLamports: 50_000, // Default on mainnet computeUnitLimit: 400_000, maxRetries: 2, // Blockhash expiration retries }, }); ``` **RPC endpoints**: By default, the SDK routes all RPC calls through hosted proxies at `sati.cascade.fyi` (backed by Helius), rate-limited to ~120 req/min per IP. For production workloads, provide your own Helius or Triton RPC URLs via `rpcUrl` and `photonRpcUrl` to get higher limits. ### Key Types | Type | Description | |------|-------------| | `AgentIdentity` | On-chain agent: mint, owner, name, uri, memberNumber (`bigint`), nonTransferable, additionalMetadata | | `RegistrationFile` | ERC-8004 metadata with services, trust mechanisms | | `GiveFeedbackParams` | Simplified feedback input (FeedbackPublicV1) | | `ParsedFeedback` | Feedback with value, tags, message, createdAt, counterparty | | `FeedbackContent` | Raw content: value, valueDecimals, tag1, tag2, m (message), endpoint, reviewer, feedbackURI, feedbackHash | | `ReputationSummary` | Aggregated count + averageValue | | `AgentSearchResult` | Identity + registrationFile + optional feedbackStats | | `Outcome` | Enum: Positive (2), Negative (0), Neutral (1) | | `MetadataUploader` | Interface for pluggable storage (IPFS, Arweave, etc.) | ### Error Handling ```typescript import { SatiError, DuplicateAttestationError, AgentNotFoundError } from "@cascade-fyi/sati-sdk"; try { await sati.giveFeedback(params); } catch (e) { if (e instanceof DuplicateAttestationError) { // Same taskRef + counterparty + agent already exists } } ``` ## Costs | Operation | Cost | |-----------|------| | Agent registration | ~0.003 SOL | | Agent transfer | ~0.0005 SOL | | Feedback attestation | ~0.00001 SOL (compressed) | | Reputation score (ReputationScoreV3) | ~0.002 SOL (regular SAS, not compressed) | | Devnet | Free (auto-funded faucet) | ## Common Issues - **Blockhash expired** - Solana transactions must land within ~60 seconds. Retry the command/call. - **Insufficient funds (mainnet)** - Send ~0.01 SOL to your wallet address. CLI shows the address on failure. - **Permission denied on update** - Wrong keypair. Use `--keypair /path/to/original.json` with the CLI, or ensure the correct `owner` KeyPairSigner in SDK. - **Feedback schema not deployed** - Make sure you're on the right network. Schemas are deployed on both devnet and mainnet. - **Rate limited (429)** - The hosted RPC proxies are rate-limited to ~120 req/min per IP. For production, provide your own RPC via `rpcUrl` and `photonRpcUrl`.
Security Status
Unvetted
Not yet security scanned
Related AI Tools
More Career Boost tools you might like
PPT Generator Pro - Claude Code Skill
Free- **Skill 名称**: ppt-generator-pro - **版本**: 2.0.0 - **描述**: 基于 AI 自动生成高质量 PPT 图片和视频,支持智能转场和交互式播放
Humanizer: Remove AI Writing Patterns
FreeTransforms AI-generated text into natural, human-sounding writing by detecting and fixing common AI patterns like inflated symbolism, promotional language, and passive voice
Color Expert
FreeUse when working with color naming, color theory, color spaces, color definitions, or any task involving color knowledge - palettes, ramps, gradients, conversions, accessibility, perceptual matching, pigment mixing, print-vs-screen color, CSS color s
JUnit 5 Testing Skill
FreeGenerates production-grade JUnit 5 unit and integration tests in Java with assertions, parameterized tests, lifecycle hooks, and Mockito mocking
Jest Testing Skill
FreeGenerates Jest unit and integration tests in JavaScript or TypeScript with mocking, snapshots, async testing, and React component testing
Jasmine Testing Skill
FreeGenerates Jasmine BDD-style JavaScript tests with spies, async support, and comprehensive matchers for unit testing