Registry Broker Client
The Registry Broker client in @hashgraphonline/standards-sdk provides a typed, batteries-included wrapper around the Hashgraph Online Registry Broker. It covers discovery, registration, chat relay, UAID utilities, metrics, and protocol detection in a single interface with rich Zod-backed response validation.
Getting Startedβ
Installationβ
pnpm add @hashgraphonline/standards-sdk
# or: npm install @hashgraphonline/standards-sdk
Credentials & Creditsβ
The production broker is pay-as-you-go. Before invoking any authenticated endpoints you must top up credits for your account at registry.hashgraphonline.com/billing. Without credits, registration, chat relays, vector search, and other metered APIs will fail with 402 responses.
Once credits are loaded you can generate an API key (or use session tokens) and create a client:
π‘ The Registry Broker production API is available at
https://registry.hashgraphonline.com/api/v1. OverridebaseUrlonly if youβve been provisioned a private deployment.
Creating a clientβ
import { RegistryBrokerClient } from '@hashgraphonline/standards-sdk';
const client = new RegistryBrokerClient({
// Optional: override the default https://registry.hashgraphonline.com/api/v1
baseUrl: process.env.REGISTRY_BROKER_API_URL,
// Optional: supply an API key issued by your Registry Broker instance
apiKey: process.env.REGISTRY_BROKER_API_KEY,
});
baseUrlβ defaults to the production broker (https://registry.hashgraphonline.com/api/v1). Trailing slashes and missing/api/v1segments are normalized automatically.apiKeyβ when provided, the client sets anx-api-keyheader on every request. You can update it later withclient.setApiKey(newKey).defaultHeadersβ useclient.setDefaultHeader(name, value)to add or remove headers after instantiation (values are trimmed; falsy values remove the header).fetchImplementationβ pass a custom fetch (for Cloudflare Workers, Node polyfills, testing, etc.).
const client = new RegistryBrokerClient({
fetchImplementation: (input, init) => myInstrumentationFetch(input, init),
defaultHeaders: {
'x-trace-id': crypto.randomUUID(),
},
});
You can inspect the current header set with client.getDefaultHeaders().
Quickstart: Paid OpenRouter chat relayβ
import { RegistryBrokerClient } from '@hashgraphonline/standards-sdk';
const client = new RegistryBrokerClient({
baseUrl: 'https://registry.hashgraphonline.com/api/v1',
apiKey: process.env.REGISTRY_BROKER_API_KEY,
});
const session = await client.chat.createSession({
agentUrl: 'openrouter://anthropic/claude-3.5-sonnet',
auth: { type: 'bearer', token: process.env.OPENROUTER_API_KEY! },
});
const reply = await client.chat.sendMessage({
sessionId: session.sessionId,
message: 'Give me a one-line summary of your pricing.',
auth: { type: 'bearer', token: process.env.OPENROUTER_API_KEY! },
});
console.log(reply.message);
If you omit the auth block for paid models, the broker returns a 401 from the adapter. Free-tier models do not require this step.
Architecture Overviewβ
The SDK mediates every request, ensuring headers and schemas are applied consistently.
β Free discovery: keyword search, vector search, adapter catalog, and public stats are available to everyone without credits or authentication.
Use the billing portal only when you need metered functionality such as agent registration, chat relay, UAID inscription, or history compaction. These endpoints require an active credit balance; otherwise the broker returns 402 responses.
Searching the Registryβ
Keyword searchβ
import type { SearchResult } from '@hashgraphonline/standards-sdk';
const result: SearchResult = await client.search({
q: 'custody agent',
registry: 'hol',
capabilities: ['messaging'],
minTrust: 70,
page: 1,
limit: 25,
});
console.log(`Found ${result.total} agents`);
for (const hit of result.hits) {
console.log(hit.name, hit.registry, hit.capabilities);
}
SearchParams supports q, page, limit, registry, minTrust, and capability filtering (capabilities can be AIAgentCapability enum values or arbitrary strings).
Vector searchβ
The broker also exposes embedding-powered search:
const vectorResult = await client.vectorSearch({
query: 'tax strategy assistant for small businesses',
limit: 10,
filter: {
capabilities: ['financial-services'],
registry: 'hol',
},
});
vectorResult.hits.forEach(hit => {
console.log(hit.agent.name, hit.score);
});
The optional filter can constrain results by capability, registry, agent type, or protocol.
Registry-specific namespace searchβ
const namespaceSearch = await client.registrySearchByNamespace('hol', 'fraud');
namespaceSearch.hits.forEach(hit => {
console.log(`${hit.registry}: ${hit.name}`);
});
This is useful when you want to query adapters that expose their own internal namespaces (for example, Hol or Virtuals).
Discovery Insightsβ
-
Registries & Popular Searches
const registries = await client.registries(); // { registries: string[] }
const popular = await client.popularSearches(); // { searches: string[] } -
Adapter catalog
const { adapters } = await client.adaptersDetailed();
adapters.forEach(adapter => {
console.log(adapter.id, adapter.chatProfile?.supportsChat, adapter.chatProfile?.requiresAuth);
});Adapter descriptors surface transport hints, chat support, and required credentials for every adapter the broker ships, which is useful when you do not have direct access to the server configuration.
-
Snapshot stats
const stats = await client.stats();
console.log(stats.totalAgents, stats.registries); -
Operational metrics
const metrics = await client.metricsSummary();
console.log(metrics.search.queriesTotal, metrics.websocket.connections);
const websocket = await client.websocketStats();
const dashboard = await client.dashboardStats();
These responses are strongly typed and validated, making them safe to expose in dashboards without additional schema definitions.
Working With UAIDsβ
The client includes helpers for dealing with agent UAIDs:
const resolved = await client.resolveUaid('uaid:aid:123...');
console.log(resolved.agent.name);
const validation = await client.validateUaid('uaid:aid:123...');
console.log(validation.valid, validation.formats);
const status = await client.getUaidConnectionStatus('uaid:aid:123...');
if (!status.connected) {
console.log('Agent offline');
}
await client.closeUaidConnection('uaid:aid:123...');
Each method returns the appropriate schema-backed response (UaidValidationResponse, UaidConnectionStatus).
Chat Sessionsβ
The chat namespace exposes a conversation relay with the brokerβs chat worker:
const session = await client.chat.createSession({ uaid: 'uaid:aid:123...' });
const reply = await client.chat.sendMessage({
sessionId: session.sessionId,
message: 'Hello from the SDK!',
streaming: false,
});
console.log(reply.content);
await client.chat.endSession(session.sessionId);
You can also seed the chat by agent URL instead of UAID ({ agentUrl: 'https://...' }). The streaming flag is passed through to the broker; if the backend supports streaming, you can adapt the response accordingly.
Passing downstream auth (paid OpenRouter models)β
Many adapters (notably OpenRouter) require user-provided credentials for paid tiers. Supply the downstream token with the auth block so the relay can authenticate on your behalf.
const session = await client.chat.createSession({
agentUrl: 'openrouter://anthropic/claude-3.5-sonnet',
auth: {
type: 'bearer',
token: process.env.OPENROUTER_API_KEY!, // the user's key, not the broker's
},
});
const response = await client.chat.sendMessage({
sessionId: session.sessionId,
message: 'Summarize your pricing in one sentence.',
auth: {
type: 'bearer',
token: process.env.OPENROUTER_API_KEY!,
},
});
AgentAuthConfig supports four schemes:
type | Fields used | Example |
|---|---|---|
bearer | token | { type: 'bearer', token: 'sk-or-...' } |
basic | username, password | { type: 'basic', username, password } |
apiKey | headerName, headerValue | { type: 'apiKey', headerName: 'x-api-key', headerValue: '...' } |
header | headerName, headerValue, optional headers map | Use for bespoke header names or multi-header payloads |
When you set auth, the broker caches the normalized header set and reuses it for the session (updating the downstream client if subsequent requests provide different credentials). Omit auth for free models or agents that do not require authentication.
Cross-protocol chat playbookβ
The Standards SDK ships end-to-end demos that bridge Registry Broker chat to both AgentVerse mailbox/proxy agents and ERC-8004 HTTP agents:
standards-sdk/demo/registry-broker-agentverse-demo.tsstandards-sdk/demo/registry-broker-erc8004-demo.ts
The following guidelines distill the patterns these demos implement so you can wire cross-protocol chat flows into your own services.
1. Discover and normalize UAIDsβ
-
Use
RegistryBrokerClient.searchto locate the remote agent. Filter byregistry/adaptersto narrow the result set (e.g.registry: 'agentverse'oradapters: ['erc8004-adapter']). -
Rebuild the UAID with the HCS-14 SDK so you own the nameplate. The AgentVerse demo calls
HCS14Client.createUaidwith the agentβsnativeIdto guarantee a deterministic identifier that survives registry refreshes. -
Inspect
hit.metadata.adapterto decide how the broker will deliver messages. The adapter determines the transport, authentication requirements, and whether the broker acts as a relay or simply points you at the agentβs native endpoint:agentverse-adapterβ AgentVerse mailbox/proxy envelopes (async mailbox, see below).openrouter-adapterβ OpenRouter/chat/completionsAPI (bearer token required).openconvai-adapterβ Hedera HCS-10 topics (requires broker-side operator keys).mcp-adapterβ JSON-RPC HTTP or SSE transports exposed by MCP servers.nanda-adapter,a2a-registry-adapter,a2a-protocol-adapterβ A2A JSON-RPC messaging (optionally backed by@a2a-jsclients).x402-bazaar-adapterβ Arbitrary HTTP requests defined by the agentβs X402 resource metadata.erc8004-adapterβ Discovery only; extract an HTTPS endpoint from the.well-known/agent-card.jsonmetadata (or IPFS token URI) and pass it asagentUrlwhen you create a session.virtuals-protocol-adapter/olas-protocol-adapterβ Discovery-only commerce/service metadata (no chat relay).
Use
const descriptors = await client.adaptersDetailed();to hydrate the adapter catalog in-process. EachAdapterDescriptorexposeschatProfile.requiresAuth, delivery mechanisms, and capability flags so you can branch without hard-coding knowledge of the broker deployment. The table below mirrors the fields returned byGET /api/v1/adapters/details:Adapter Supports chat Delivery Transport Streaming Requires auth Highlights agentverse-adapterYes Mailbox HTTPS envelope No Optional signer Broker submits signed envelopes and polls mailboxes for replies. openrouter-adapterYes Relay HTTPS No End-user OpenRouter bearer Requires the callerβs OpenRouter token for every message. openconvai-adapterYes Mailbox Hedera HCS No Hedera operator key Publishes to HCS-10 topics; replies arrive asynchronously. mcp-adapterYes Relay JSON-RPC HTTP/SSE Yes None Streams SSE for streamable_httptransports, plain JSON otherwise.nanda-adapterYes Relay A2A JSON-RPC No None Favors @a2a-jsconnections and falls back to JSON-RPC.a2a-registry-adapterYes Relay JSON-RPC No None Proxies records from the public A2A registry. a2a-protocol-adapterYes Relay JSON-RPC No None Crawls well-known A2A endpoints and relays JSON-RPC messages. x402-bazaar-adapterYes Relay HTTP No None Executes HTTP requests defined by Coinbase x402 resource metadata. erc8004-adapterNo Discovery N/A N/A None Emits discovery data; chat by supplying agentUrlderived from metadata.virtuals-protocol-adapterNo Discovery N/A N/A None Surfaces Virtuals commerce metadata without brokering chat. olas-protocol-adapterNo Discovery N/A N/A None Indexes OLAS services; integration is discovery-only today.
2. Launch your local agent (optional)β
The AgentVerse demo spins up a local A2A helper with startLocalA2AAgent so you can observe a full two-way conversation. Any local service that exposes the ASI chat protocol will workβjust pass its URL to client.chat.sendMessage({ agentUrl, ... }) when you forward the remote agentβs reply.
3. Handling AgentVerse mailbox and proxy agentsβ
- Always reuse a single
sessionIdwhen you bounce between the remote AgentVerse agent and your local participant. The broker stitches the history together for you. - Mailbox agents frequently acknowledge immediately and stream the real answer later. After each
sendMessagecall, pollclient.chat.getHistory(sessionId)for newagententries until you receive a non-empty body (the demoβswaitForNonEmptyHistoryhelper is a good template). - Proxy agents respond synchronously but may rate-limit bursts. Check for
429errors and back off before retrying.
4. Talking to ERC-8004 agentsβ
- Resolve an HTTP endpoint from the search hit. The ERC-8004 demo inspects
metadata.communicationEndpoints.primary,hit.endpoints.wellKnown, and on-chain registration data to derive a usable URL. - Create a chat session with
agentUrland send messages as usual. ERC-8004 agents typically respond immediately; you can still callgetHistoryto archive context. - When the agent publishes only an IPFS token URI, transform it to an HTTPS gateway (e.g.
ipfs://...βhttps://ipfs.io/ipfs/...).
5. Session hygieneβ
- Track the brokerβs history TTL (
session.historyTtlSeconds) so you know when to persist transcripts elsewhere. - Call
client.chat.endSession(sessionId)when the conversation is finishedβespecially important with proxy/mailbox agents to release upstream resources. - Log the resolved UAIDs alongside the remote
metadata.registry/metadata.protocolso you can debug adapter-specific behavior.
Adapter transport referenceβ
- AgentVerse (
agentverse-adapter) β Sends signed envelopes to/proxy/submitor/submit. Expect immediate acknowledgements followed by mailbox deliveries; pollchat.getHistory(sessionId)until a non-empty agent entry appears. Identity-based signatures are optional but recommended for production mailboxes. - OpenRouter (
openrouter-adapter) β Relays to OpenRouterβs REST API. Always supply the end-userβs OpenRouter API key in theauthblock. Responses are synchronous JSON documents; streaming is not exposed by the adapter yet. The history demo shows ledger-authenticated billing plus chat history compaction against an OpenRouter model. - OpenConvAI (
openconvai-adapter) β Publishes to Hedera HCS-10 topics using the brokerβs operator keys. Configure the broker withHCS10_*variables and budget a few seconds for replies to arrive on the outbound topic. Usechat.getHistoryto capture the eventual response. - MCP (
mcp-adapter) β Talks to Pulse MCP servers using JSON-RPC. Inspectagent.metadata.remoteTransportto differentiatehttp,streamable_http, andsse. For streaming transports the adapter parses SSE and surfaces incremental chunks in the chat response. - NANDA / A2A (
nanda-adapter,a2a-registry-adapter,a2a-protocol-adapter) β Wrap the A2A ecosystem. When an@a2a-jsclient can be established the adapter forwards prompts directly; otherwise it falls back to JSON-RPC requests against the agentβs declared endpoint. Consider running the local A2A helper from the AgentVerse demo when you need deterministic round-trips. - X402 Bazaar (
x402-bazaar-adapter) β Builds arbitrary HTTP requests from the message payload (method,target,headers,body). Use it when an agent exposes a REST interface via X402 metadata. - ERC-8004 (
erc8004-adapter) β Discovery-only. Extract a usable HTTPS endpoint from registration metadata (communication endpoints, token URI, IPFS link) and supply it asagentUrlwhen you create the session. The ERC-8004 demo illustrates this flow end-to-end. - Virtuals Protocol (
virtuals-protocol-adapter) & OLAS (olas-protocol-adapter) β Provide discovery metadata for ACP commerce and OLAS autonomous services respectively; the broker does not currently proxy chat for these registries.
Following these practices keeps cross-protocol conversations predictable and reproducible. Reference the demos for working code that combines discovery, UAID normalization, and chat relay in one script.
Chat history and compactionβ
The history demo (standards-sdk/demo/registry-broker-history-demo.ts) illustrates how to persist, audit, and eventually compact chat transcripts after a session concludes. The flow introduces a few extra broker capabilities:
- Authenticate with Hedera (optional but recommended on testnet) β run
client.createLedgerChallenge/client.verifyLedgerChallengeto mint a scoped API key tied to your Hedera account. The demo does this automatically, then callspurchaseCreditsWithHbarto top up testnet credits for history APIs. - Create a session with an explicit TTL β pass
historyTtlSecondstoclient.chat.createSessionso you know when the broker will evict entries. The demo defaults to 30 minutes. - Fetch transcripts on demand β call
client.chat.getHistory(sessionId)after each turn (or before you compact) to retrieve the orderedChatHistoryEntry[]. Each entry includesrole,timestamp, and the content the broker stored, matching what the UI shows. - Compact when the log gets large β invoke
client.chat.compactHistory({ sessionId, preserveEntries })to debit credits and replace older messages with a broker-generated summary. The demo preserves the most recent four entries, logs the summary text, and then re-fetches history to show the reduced footprint. - Handle billing responses β history compaction and long-lived storage consume metered credits. Inspect
result.creditsDebited(and catchRegistryBrokerErrorwith status402) so you can surface βinsufficient balanceβ to operators.
Following the demoβs pattern keeps history durable without letting sessions grow indefinitely, and it teaches your integration how to respond when credits are required for archival operations.
Agent Registrationβ
Registering an agent is a single call that expects a fully-formed HCS-11 profile:
import type { HCS11Profile } from '@hashgraphonline/standards-sdk';
const profile: HCS11Profile = {
version: '1.0.0',
type: 1,
display_name: 'Ledger Guard',
bio: 'Monitoring transactions for anomalies',
aiAgent: {
type: 'openai',
model: 'gpt-4o-mini',
capabilities: ['monitoring', 'compliance'],
},
};
const registration = await client.registerAgent({
profile,
registry: 'hol',
protocol: 'aid',
endpoint: 'https://ledger-guard.example.com',
metadata: {
trustScore: 92,
uptime: 99.95,
},
});
console.log(registration.uaid, registration.agent.nativeId);
End-to-end: register, poll progress, and inspect the resultβ
The snippet below illustrates a typical mainnet flow that:
- Authenticates with ledger credentials (auto top-up enabled).
- Registers a new agent targeting ERC-8004 networks.
- Waits for the asynchronous attempt to complete.
- Reads the UAID endpoint to confirm on-chain identifiers.
import 'dotenv/config';
import { PrivateKey } from '@hashgraph/sdk';
import {
RegistryBrokerClient,
isPendingRegisterAgentResponse,
} from '@hashgraphonline/standards-sdk';
const baseUrl = 'https://registry.hashgraphonline.com/api/v1';
const ledgerAccountId = process.env.MAINNET_HEDERA_ACCOUNT_ID!;
const ledgerPrivateKey = process.env.MAINNET_HEDERA_PRIVATE_KEY!;
const client = new RegistryBrokerClient({
baseUrl,
registrationAutoTopUp: {
accountId: ledgerAccountId,
privateKey: ledgerPrivateKey,
memo: 'demo:auto-topup',
},
});
// Authenticate via ledger challenge
const challenge = await client.createLedgerChallenge({
accountId: ledgerAccountId,
network: 'mainnet',
});
const key = PrivateKey.fromString(ledgerPrivateKey);
const signature = Buffer.from(
await key.sign(Buffer.from(challenge.message, 'utf8')),
).toString('base64');
const verification = await client.verifyLedgerChallenge({
challengeId: challenge.challengeId,
accountId: ledgerAccountId,
network: 'mainnet',
signature,
publicKey: key.publicKey.toString(),
});
client.setApiKey(verification.key);
client.setDefaultHeader('x-account-id', verification.accountId);
const profile = {
version: '1.0',
type: 1,
display_name: 'Async Demo Agent',
alias: 'async-demo-agent',
bio: 'Demonstrates registry-broker async registration.',
properties: {
agentFactsUrl: 'https://demo.example.com/.well-known/agent.json',
tags: ['demo', 'async'],
},
socials: [{ platform: 'x', handle: 'hashgraphonline' }],
aiAgent: {
type: 0,
model: 'demo-model',
capabilities: [0, 4, 18],
},
};
const registration = await client.registerAgent({
profile,
registry: 'hol',
communicationProtocol: 'a2a',
endpoint: 'https://demo.example.com/a2a',
additionalRegistries: [
'erc-8004:ethereum-sepolia',
'erc-8004:base-sepolia',
],
metadata: {
provider: 'sdk-demo',
},
});
let progress = null;
if (isPendingRegisterAgentResponse(registration) && registration.attemptId) {
progress = await client.waitForRegistrationCompletion(
registration.attemptId,
{
throwOnFailure: false,
intervalMs: 2000,
onProgress: latest => {
const summary = Object.values(latest.additionalRegistries)
.map(entry => `${entry.registryKey}:${entry.status}`)
.join(', ');
console.log(`[progress] ${latest.status} ${summary}`);
},
},
);
}
if (progress?.status === 'failed') {
console.error('Registration failed', progress.errors);
process.exit(1);
}
console.log('UAID:', registration.uaid);
console.log('Attempt status:', progress?.status ?? registration.status);
const uaidResponse = await fetch(
`${baseUrl}/agents/${encodeURIComponent(registration.uaid)}`,
{
headers: {
accept: 'application/json',
'x-api-key': verification.key,
'x-account-id': verification.accountId,
},
},
).then(res => {
if (!res.ok) {
throw new Error(`UAID fetch failed: ${res.status} ${res.statusText}`);
}
return res.json();
});
console.log(
'Additional registries:',
uaidResponse.metadata.additionalRegistries,
);
π Save this script as
register-erc8004-demo.tsand run it withpnpm tsx register-erc8004-demo.ts. Ledger credentials are read fromMAINNET_HEDERA_ACCOUNT_ID/MAINNET_HEDERA_PRIVATE_KEY, so export them in your shell or.env.
The response supplies UAID, agent metadata, optional HCS-10 registry results, and OpenConvAI compatibility data when available.
Handling asynchronous responses & progress trackingβ
When a registration includes additional registries (for example ERC-8004) the broker returns 202 Accepted with a status: "pending" payload. The primary Hashgraph inscription is committed immediately, while downstream registrars are processed in the background via a work queue. The SDK exposes helpers to wait on the attempt or poll progress manually:
import {
isPendingRegisterAgentResponse,
type RegistrationProgressRecord,
} from '@hashgraphonline/standards-sdk';
const response = await client.registerAgent({
profile,
registry: 'hol',
communicationProtocol: 'a2a',
endpoint: 'https://ledger-guard.example.com',
additionalRegistries: ['erc-8004:ethereum-sepolia'],
});
let progress: RegistrationProgressRecord | undefined;
if (isPendingRegisterAgentResponse(response) && response.attemptId) {
progress = await client.waitForRegistrationCompletion(response.attemptId, {
intervalMs: 2000,
timeoutMs: 5 * 60_000,
throwOnFailure: false, // let the caller inspect partial failures
onProgress: latest => {
console.log(
`Attempt ${latest.attemptId} status β ${latest.status}`,
Object.values(latest.additionalRegistries).map(
entry => `${entry.registryKey}:${entry.status}`,
),
);
},
});
}
if (progress?.status === 'failed') {
throw new Error(`Registration failed: ${progress.errors?.join(', ')}`);
}
All progress tracking endpoints are protected by account ownership checks. Using the SDK automatically attaches the x-account-id header returned during ledger authentication (or the API key context) so authorized callers can retrieve the current state later via client.getRegistrationProgress(attemptId).
Updating agents & publishing to ERC-8004β
Updates reuse the same asynchronous pipeline. When you call updateAgent the broker:
- Re-validates UAID invariants (display name, native ID, primary endpoint, etc.).
- Inscribes an updated profile (only if the fingerprint changed).
- Queues any additional registries for gas-only updates. Existing ERC-8004 agent IDs are reused; only the metadata file is re-pinned and
setAgentUriis invoked on-chain.
Assuming you stored the original registration payload (or fetched the profile from search/UAID endpoints), the SDK update flow looks like this:
import type { AgentRegistrationRequest } from '@hashgraphonline/standards-sdk';
const existingProfile = registration.agent.profile; // reuse the profile you stored earlier
const updatePayload: AgentRegistrationRequest = {
profile: existingProfile,
communicationProtocol: 'a2a',
registry: registration.registry ?? 'hol',
endpoint: registration.agent.endpoint ?? registration.agent.nativeId ?? undefined,
additionalRegistries: [
'erc-8004:ethereum-sepolia',
'erc-8004:base-sepolia',
],
};
const updateResponse = await client.updateAgent(registration.uaid, updatePayload);
if (isPendingRegisterAgentResponse(updateResponse) && updateResponse.attemptId) {
const updateProgress = await client.waitForRegistrationCompletion(
updateResponse.attemptId,
{ throwOnFailure: false },
);
console.log('Additional registries β', updateProgress?.additionalRegistries);
}
- Credits: profile updates charge the base credit fee only when the profile actually changes. ERC-8004 updates consume gas credits only; the SDKβs auto top-up helpers can cover any shortfall by purchasing credits before retrying.
- Progress entries: each additional registry tracks
status,credits,agentId, andagentUri. Successful ERC-8004 updates return the canonical on-chain identifier (<chainId>:<agentId>) and the IPFS URI that was pinned during the run. - Polling manually: if you prefer not to block, store the attempt ID and poll
client.getRegistrationProgress(attemptId)from another process. Responses include both the global attempt status and per-network details so UI layers can render live progress.
Protocol Discoveryβ
const protocols = await client.listProtocols(); // { protocols: string[] }
const detected = await client.detectProtocol({
message: {
headers: { 'content-type': 'application/json' },
body: '{"hello":"world"}',
},
});
console.log(detected.protocol); // e.g. "aid"
Use this to guess which adapter or protocol an incoming payload belongs to before routing it.
Handling Errorsβ
All HTTP failures throw RegistryBrokerError; schema validation issues throw RegistryBrokerParseError.
try {
await client.search({ registry: 'unknown' });
} catch (error) {
if (error instanceof RegistryBrokerError) {
console.error('Broker rejected the request', error.status, error.body);
} else if (error instanceof RegistryBrokerParseError) {
console.error('Unexpected response shape', error.cause);
} else {
throw error;
}
}
Both error classes expose contextual data so you can log or retry intelligently.
Advanced: Custom Fetch Pipelinesβ
The client is fetch-agnostic. You can instrument every request (for retries, auth rotation, tracing) by wrapping a fetch implementation:
const client = new RegistryBrokerClient({
fetchImplementation: async (input, init) => {
const start = performance.now();
const response = await fetch(input, init);
console.log(`[registry-broker] ${new URL(input as string).pathname} -> ${response.status} in ${performance.now() - start}ms`);
return response;
},
});
Example: Discover and Chatβ
const client = new RegistryBrokerClient({ apiKey: process.env.RB_API_KEY });
// 1. Find high-trust audit agents
const auditAgents = await client.search({ q: 'audit', minTrust: 80, limit: 5 });
// 2. Ask the top result a question
const topAgent = auditAgents.hits[0];
const session = await client.chat.createSession({ uaid: topAgent.uaid });
await client.chat.sendMessage({ sessionId: session.sessionId, message: 'Summarize your capabilities.' });
This flow demonstrates how the SDK threads the brokerβs discovery, chat, and UAID utilities into a single toolkit.
Referenceβ
All return types are exported from @hashgraphonline/standards-sdk/services/registry-broker:
SearchResult,RegistryStatsResponse,PopularSearchesResponseCreateSessionResponse,SendMessageResponseRegisterAgentResponse,ProtocolsResponse,DetectProtocolResponseRegistrySearchByNamespaceResponse,VectorSearchResponseWebsocketStatsResponse,MetricsSummaryResponse,DashboardStatsResponseUaidValidationResponse,UaidConnectionStatus
Check the source for the latest schemas and helper utilities.
With the Registry Broker client you can wire up agent discovery, registration, chat, and monitoring in a handful of lines while relying on the Standards SDK to validate every response.