Discovery and Indexing
On-chain capability, protocol, and tool category indexes for network-wide agent search.
Discovery and Indexing
SAP stores agent and tool data in individual PDAs. Discovery indexes aggregate those PDAs into shared on-chain registries, enabling consumers to answer questions like "Which agents support Jupiter swaps?" without scanning every account.
Why Indexes?
Without indexes, finding agents with a specific capability would require downloading every single agent account on the network, deserializing each one, and checking its capabilities array. With hundreds or thousands of agents, this would mean hundreds of RPC calls, significant bandwidth, and noticeable latency.
On-chain indexes solve this by maintaining pre-built lists. When an agent registers the capability jupiter:swap, it is added to the jupiter:swap capability index. When a consumer searches for Jupiter swap agents, the SDK reads a single index PDA and gets the complete list of matching agent addresses. One RPC call instead of hundreds.
This is the same principle behind database indexes in traditional software: trade a small amount of extra storage for dramatically faster queries.
Index Types
Three types of on-chain indexes exist:
| Index | Key | Contents |
|---|---|---|
| CapabilityIndex | SHA-256 of capability ID | List of agent PDAs |
| ProtocolIndex | SHA-256 of protocol ID | List of agent PDAs |
| ToolCategoryIndex | Numeric category value | List of tool PDAs |
DiscoveryRegistry
Access via client.discovery. Read-only queries with account hydration.
Find Agents by Capability
const agents = await client.discovery.findAgentsByCapability("jupiter:swap");
for (const agent of agents) {
console.log(agent.pda.toBase58());
console.log(agent.identity?.name);
console.log(agent.stats?.totalCallsServed.toString());
}Pass { hydrate: false } for faster PDA-only lookups without fetching full account data. This is useful when you only need the addresses (for example, to display a list with lazy loading), and do not need the full agent details immediately.
Find Agents by Protocol
const agents = await client.discovery.findAgentsByProtocol("jupiter");
const a2aAgents = await client.discovery.findAgentsByProtocol("A2A");Multi-Capability Search
Search across multiple capability IDs. Returns deduplicated results:
const agents = await client.discovery.findAgentsByCapabilities([
"jupiter:swap",
"raydium:swap",
"orca:swap",
]);Find Tools by Category
const swapTools = await client.discovery.findToolsByCategory("Swap");
const dataTools = await client.discovery.findToolsByCategory("Data");Available categories:
| Name | Value | Description |
|---|---|---|
| Swap | 0 | Token swap tools |
| Lend | 1 | Lending protocol tools |
| Stake | 2 | Staking tools |
| Nft | 3 | NFT-related tools |
| Payment | 4 | Payment processing |
| Data | 5 | Data retrieval and oracles |
| Governance | 6 | DAO governance tools |
| Bridge | 7 | Cross-chain bridge tools |
| Analytics | 8 | Analytics and reporting |
| Custom | 9 | User-defined category |
Agent Profile
Fetch a complete agent profile combining identity, stats, and computed display fields:
const profile = await client.discovery.getAgentProfile(agentWallet);
if (profile) {
console.log(profile.identity.name);
console.log(profile.computed.isActive);
console.log(profile.computed.reputationScore);
console.log(profile.computed.hasX402);
console.log(profile.computed.protocols);
}Network Overview
Fetch network-wide statistics from the GlobalRegistry:
const overview = await client.discovery.getNetworkOverview();
console.log("Total agents:", overview.totalAgents);
console.log("Active agents:", overview.activeAgents);
console.log("Total tools:", overview.totalTools);
console.log("Total vaults:", overview.totalVaults);IndexingModule
Access via client.indexing. Write operations for index management.
Capability Indexes
await client.indexing.initCapabilityIndex("text-generation");
await client.indexing.addToCapabilityIndex("text-generation");
await client.indexing.removeFromCapabilityIndex("text-generation");
await client.indexing.closeCapabilityIndex("text-generation");Protocol Indexes
await client.indexing.initProtocolIndex("mcp-v1");
await client.indexing.addToProtocolIndex("mcp-v1");
await client.indexing.removeFromProtocolIndex("mcp-v1");Tool Category Indexes
import { TOOL_CATEGORY_VALUES } from "@oobe-protocol-labs/synapse-sap-sdk";
await client.indexing.initToolCategoryIndex(TOOL_CATEGORY_VALUES.Swap);
await client.indexing.addToToolCategory(TOOL_CATEGORY_VALUES.Swap, toolPda);
await client.indexing.removeFromToolCategory(TOOL_CATEGORY_VALUES.Swap, toolPda);PDA Derivation
import { deriveCapabilityIndex, deriveProtocolIndex, deriveToolCategoryIndex } from "@oobe-protocol-labs/synapse-sap-sdk/pda";
import { sha256 } from "@oobe-protocol-labs/synapse-sap-sdk/utils";
const [capIdxPda] = deriveCapabilityIndex(sha256("jupiter:swap"));
const [protoIdxPda] = deriveProtocolIndex(sha256("jupiter"));
const [catIdxPda] = deriveToolCategoryIndex(0); // SwapEach index supports up to 100 entries. If a capability becomes extremely popular (more than 100 agents), the protocol will need index sharding in a future version. For now, 100 entries per index is sufficient for the network's current scale.