16. Client SDK, Community Skill, and Developer Experience
This chapter explains how the client layer provides different entry points for resource providers, callers, and node operators: oan-sdk-ts supports programmatic integration, the community skill package supports agent-assisted resource organization, registration, discovery, and verification, and the official website provides browser-based interaction. All three reuse the OpenAgenet (OAN) protocol and do not change the semantics of DID, control proofs, registration VCs, Root proof, or governance status. Subject private keys, resource-control private keys, and Local Identity backups remain on the client side; servers receive only public materials and necessary proofs.
| Entry point | Primary users | Core responsibilities | Responsibilities it does not assume |
|---|---|---|---|
| TypeScript SDK | Application developers and platform integrators | Types, request construction, registration and discovery calls, and verification assistance | Making trust decisions for users |
| Community skill package | Resource providers and agent operators | Organizing resources, assisting with registration and discovery, and explaining results | Holding governance keys or replacing node services |
| Official website | Browser users | Interactive registration, discovery, preview, and local download | Hosting user private keys or guaranteeing endpoint security |
| Operations assistance | Node operators | Building, configuration checks, deployment, and smoke testing | Automatically deciding production keys and rollback strategies |
16.1 TypeScript SDK Scope
The TypeScript SDK consists of protocol types, an HTTP client, governance reads, and workflow assistance. It is suitable for Node.js, browser build environments, and runtimes compatible with fetch. Callers can configure the Registrar node, Discovery node, Root platform, and content distribution platform addresses separately. The SDK handles serialization, requests, and response parsing; it does not decide whether a resource is trustworthy on behalf of the caller.
In terms of code organization, packages/protocol-types provides shared types such as ResourceRegistrationSubmission, ResourcePackage, discovery queries, and governance responses; packages/client-ts provides OanClient and HTTP calls to the various nodes; packages/sdk-ts provides DID Document drafts, resource-package binding, hash formatting, trust summaries, and lifecycle assistance; and packages/governance-ts targets governance reads from the off-chain trust indexer. This layering allows an application to depend only on the HTTP client or to combine resource validation and lifecycle assistance when needed, without duplicating protocol structures.
| Capability area | Provided by the SDK | Still the caller’s responsibility |
|---|---|---|
| DID and resource model | Types, parsing, and construction assistance | Confirming resource content and control relationships |
| Registration | Request construction, submission, and status reads | Safeguarding private keys and confirming the submission target |
| Discovery | Exact DID queries, semantic queries, and result parsing | Deciding whether relevance satisfies business requirements |
| Verification | Reading proof fields and verification assistance | Defining authorization policies and making final invocation decisions |
| Lifecycle | Aggregating registration, publication, distribution, and visibility status | Handling timeouts, retries, and business compensation |
The SDK supports two common endpoint-selection patterns. For the official website and community users, the caller can provide a baseUrl, from which the client derives service addresses under the official gateway. For multi-node or third-party-node testing, the caller can provide registrarEndpoint, discoveryEndpoint, rootEndpoint, and cdnEndpoint separately. Endpoint configuration determines where requests are sent; it does not perform node authorization, resource-control proof generation, or governance decisions for the caller.
16.2 DID Identity and Key Operations in the SDK
Identity and key operations take place on the client. The SDK generates subject identities, resource DIDs, and verification methods, uses private keys to sign control challenges, resource versions, or requests, and writes public keys into the DID Document. A backup may contain subject and resource-control materials, but it must not enter logs, HTTP requests, or indexes. During import, the implementation should validate the structure, the relationship between the DID and public key, and signing capability.
In a Node.js scenario, identity-store-node can be used to save subject, agent, and node identities in separate buckets in a local directory. In a browser scenario, the current session is held by page state or browser storage and is exported through a user operation. The common boundary of both implementations is that the DID Document may be publicly distributed, while private keys may only be used for client-side signing; the server receives signed control proofs or node request envelopes, not the original private keys.
- [x] Private-key generation, signing, and backup export occur on the client.
- [x] Registration requests carry only the public DID Document, resource information, and necessary control proofs.
- [x] Backup format, version, DID, public key, and signing capability are validated before import.
- [ ] Private keys must not be written to URLs, logs, telemetry, or server-side storage.
16.3 Registration Flow Example
A registration flow should first prepare the Local Identity, resource DID, DID Document, metadata, ResourcePackage, hashes, and control proof, and then call the Registrar node. The following example shows only the client-call boundary; submission should be constructed from data that has passed local validation and signing:
import { OanClient } from "@openagenet/oan-sdk-ts/client";
const client = new OanClient({
registrarEndpoint: "https://registrar.example.org",
});
const result = await client.registerResource(submission);
console.log({
resourceDid: result.resourceDid,
registrationVc: result.registrationVc ?? null,
});
The registration VC may temporarily be absent. The client should preserve the resource DID, request ID, and status; a network timeout cannot by itself prove that registration did not occur. The client should first confirm an explicit success or failure, then query the status by request ID or resource DID, and distinguish the three stages of Registrar node acceptance, Root platform publication, and Discovery node visibility.
The minimum pre-submission checks can be summarized as “object consistency, digest consistency, valid control, and explicit target”: didDocument.id must equal resourceDid; the resource type must match the DID subject encoding; the digests of the DID Document, metadata, and ResourcePackage must correspond to the actual materials; the control proof must be generated by the corresponding resource-control private key; and the registration endpoint must be a Registrar node explicitly selected by the user. The skill package can assist in identifying missing items, but the final submission must still be confirmed by the client or user.
Registration accepted -> Root accepted -> Content distribution completed -> Visible in discovery index
| | | |
Registrar Root CDN Discovery
16.4 Exact DID Discovery Example
Exact DID discovery uses the resource DID as the lookup key and does not depend on name similarity. After calling the discovery interface, the client should check the returned DID, version, ResourcePackage, and proof references, and then verify the DID Document, version hash, lifecycle, Root proof, and endpoint policy.
const resourceDid = "did:oan:SKDM:example";
const resource = await client.getDiscoveryResource(resourceDid);
if (resource.resourceDid !== resourceDid) {
throw new Error("discovery_did_mismatch");
}
An exact hit proves only that the Discovery node returned a record for the corresponding identifier. It does not by itself prove that the version is still valid, that the node remains authorized, or that the business endpoint can be safely called.
After obtaining candidate results, an application can first perform a consistency check using resourceDid, then select a candidate version according to the requested version policy, and finally load the ResourcePackage or DID Document to complete evidence verification. If the detail interface returns 404, this usually means that a candidate summary exists in the discovery index but the corresponding detail is not yet readable. The client should preserve this distinction and report it to the caller instead of treating the candidate result as a complete callable object.
16.5 Semantic Discovery Example
Semantic discovery can combine a natural-language task, capability tags, and structured conditions. The English query used on the official website, “I need a tool that can search code repositories and summarize the project structure.”, can serve as an example input:
const discovery = await client.discoverResources({
query: "I need a tool that can search code repositories and summarize the project structure.",
resourceType: "tool",
limit: 10,
});
for (const candidate of discovery.candidates) {
console.log(candidate.resourceDid, candidate.score);
}
The response should retain hit fields, tags, resource type, protocol, index version, source, and matching reasons. Semantic relevance answers “possibly applicable”; structured conditions answer “satisfies explicit filters”; and trusted evidence answers “whether the current version can be verified.” None of these can replace the others.
The SDK’s HTTP-response wrapper should preserve protocol stages rather than compressing every interface into one Boolean success value. A registration call should at least preserve the Registrar node’s status, resource DID, registration VC, and Root response. A discovery call should preserve discoveryDid, the candidate array, creation time, and any optional response proof. Dynamic status or explanation responses should preserve the original JSON so that the upper layer can process actual fields. This allows the SDK to distinguish “registration accepted,” “verified by the Root platform and queued,” “resource discovered,” and “evidence verification completed.”
Semantic-query result handling is best divided into two steps: first narrow candidates with query text, resource type, tags, or protocols; then check each candidate’s lifecycle, authorization domain, service binding, and proof status. A Discovery node may use a semantic index or fall back to keyword search when its backend is unavailable. Callers should focus on the returned candidates and explanation information, rather than hard-coding a particular search-backend name as a business dependency.
16.6 Verification and Trust Evidence Handling
Verification should first check the relationship between the DID Document and resource DID, the public key, and the control proof. It should then separately check the issuer, subject, version, signature, validity period, status, authorization domain, and capability scope of the registration VC, Root proof, and node authorization VC. When a critical proof is missing or expired, the client should mark the resource as unconfirmed or reject its use.
| Evidence | Main fact it proves | Fact it cannot prove |
|---|---|---|
| Control proof | The submitter can use the corresponding control private key | The Registrar node accepted the registration or the resource was published |
| Registration VC | The Registrar node’s statement about the registration fact | The Root platform published the resource or the endpoint is secure |
| Root proof | The specified resource version passed Root platform verification and entered the publication process | Every Discovery node has indexed the resource |
| Node authorization VC | The node has the corresponding qualification within the authorization domain and validity period | Every piece of business data returned by the node is correct |
| Governance status | A status fact recorded by the governance side at the current time | Resource functional quality or business suitability |
A reproducible verification fixture should at least contain the resource DID, DID Document, ResourcePackage, corresponding digests, a control proof or registration VC, and the node DID Document and authorization materials used to validate node eligibility. The test should first confirm success with untampered materials, then separately modify the DID, version, digest, issuer, or lifecycle status and confirm that the SDK returns a clear verification error. Whether a failure blocks use depends on the evidence type: control-proof or digest failure should normally block registration; insufficient semantic matching affects only candidate ranking; and uncertain governance status should block high-risk invocation or require human confirmation.
16.7 Community Skill Package Responsibilities
The community skill package uses scripts and documentation to assist with resource organization, tag recommendation, DID generation, registration requests, discovery queries, evidence verification, and result interpretation. It is not a Registrar node, Root platform, or Discovery node, and it must not hold governance keys. User confirmation, private-key use, sensitive paths, and the final publication decision remain under the control of the user or operator.
The typical interaction follows the sequence “read materials → form a draft → user confirmation → local signing → call the service → explain the result.” The skill package can identify missing fields, recommend semantic tags, and call the SDK, but it must not silently replace resource endpoints, expand authorization domains, or present recommendations as statements made by the resource provider.
The public workflow entry points of OanSkill include draftRegistrationFromResourceDescription(), registerFromResourceDescription(), registerBatchFromResourceDescriptions(), discover(), lifecycle(), and read-only governance assistance methods. A resource-description workflow returns candidate information, missing inputs, quality issues, and recommended actions. This allows batch onboarding to repair items individually instead of losing the diagnostics for the entire batch because one resource failed. The skill package uses the official public gateway by default; third-party nodes participate only when explicitly configured by the user.
16.8 Resource Authoring and Registration Assistance
Resource-authoring assistance should uniformly handle agent services, skill packages, MCP servers, and tool APIs, and guide the user in filling in the name, description, use cases, endpoints, protocols, version, capability tags, authorization domains, and ResourcePackage information. Recommended tags are not final declarations; before generation, the implementation should check the consistency of the DID Document, metadata, and ResourcePackage hashes.
| Input category | Minimum checks | Output purpose |
|---|---|---|
| Identity and control | Subject DID, resource DID, and verification methods | Generate the control proof |
| Capability semantics | Name, description, use cases, and capability tags | Semantic governance and discovery |
| Invocation information | Protocol, endpoint, and authentication hints | Filtering and negotiation before invocation |
| Version materials | Version, predecessor version, and ResourcePackage digest | Updates, idempotency, and integrity checks |
| Governance boundary | Resource type, authorization domain, and lifecycle | Admission and discovery filtering |
When organizing resources, authorizedDomains and capabilityTags should be processed separately. The former is a machine-readable domain used by the Registrar node for authorization-scope decisions; the latter is a semantic-discovery signal. The skill package may propose tags from the description, but it must not infer an authorization domain from the DID subject encoding, endpoint hostname, or natural-language description. When the fact cannot be determined, the missing information should be returned to the user for completion.
16.9 Node Operators and Deployment Assistance
Node-operations assistance can perform dependency checks, configuration checks, Rust compilation, service startup, health checks, and post-deployment registration and discovery smoke tests. The server, domain, keys, production configuration, and rollback plan require human confirmation.
- [x] Check processes, listening ports, and health endpoints.
- [x] Check database connectivity and required table structures.
- [x] Check the off-chain trust indexer status and whether its synchronization sequence continues to advance.
- [x] Verify the minimum path for structured registration responses, exact DID discovery, and semantic discovery.
- [ ] Do not treat the success of a single health endpoint as a substitute for a complete business smoke test.
The acceptance sequence for operations assistance should follow the business propagation sequence: first check processes and health endpoints, then check the database and node authorization status, next verify that a resource registration request receives a structured response, and finally confirm the discovery path using an exact DID query and a semantic query. When the Registrar node returns success but the Root platform, content distribution platform, or Discovery node is unavailable, the result should identify the corresponding stage rather than compressing the entire path into a single “deployment successful” conclusion.
16.10 Package Distribution and Compatibility Management
Published artifacts must include runtime entry points, built JavaScript, type declarations, scripts, necessary documentation, and dependencies. When the community skill package is published to npm, SKILL.md, scripts, or resource files must not be omitted. Before publishing the SDK, it should be installed from a clean directory and its imports, registration-request construction, and discovery-request construction should be verified.
Release acceptance should include:
- Preview the actual package file list and confirm that the presence of a file in the source repository does not mean that it is included in the published package.
- Install the package to an empty directory and verify the module entry points it declares as supported.
- Run minimum tests for registration, exact DID discovery, and semantic-discovery request construction.
- Check that the README, type declarations, scripts, and resource files are accessible from the installed package.
- Increase the major version for breaking interface or protocol-semantic changes and describe the migration boundary.
For the community skill package, the npm artifact must also retain SKILL.md, references, agents, src, and the built dist; checking only that TypeScript compilation succeeds is insufficient. For the SDK, verify that the root entry point and exports such as ./client, ./governance, ./protocol-types, and ./identity-store-node all point to actual JavaScript and declaration files. Release validation should run in an empty directory without using the source directory, so that omissions in package.json files, entry points, or dependency declarations can be detected.
16.11 Example Resources and Integration Templates
The minimum integration flow is: create or import a Local Identity; generate the resource DID, DID Document, metadata, ResourcePackage, and control proof; submit to a Registrar node; perform an exact DID query; perform natural-language, tag-based, and structured discovery; and, before invocation, verify the version, proofs, governance status, and endpoint.
The SDK is the programmatic entry point, the skill package is the operational assistant, and the official website is the interactive entry point. The four resource templates can share identity, version, semantic, and proof fields, but the protocol, endpoint, and ResourcePackage contents must reflect their individual differences.
The four resource types can reuse the same onboarding skeleton, but their invocation materials differ. An agent service normally needs a callable service endpoint; a skill package needs a manifest or download entry point; an MCP server needs an MCP protocol binding; and a tool API needs an API endpoint and input/output schema. The protocolBindings, service endpoints, resource descriptions, and package information in a template should be filled in according to the actual resource. The fact that all four types can be discovered does not justify copying one resource type’s protocol fields into another.
16.12 Client Security and Secret Handling
Private keys and Local Identity backups are generated, used, and stored only on the client. DID Documents, registration VCs, and ResourcePackages should be handled according to their respective disclosure policies; logs should record only the DID, version, request ID, status, and error code, and must not record private keys, complete Local Identity data, or unsanitized signature material.
Client security boundary: A Local Identity file that can be downloaded or exported is control-rights material. It does not become public merely because it was generated by the official website. Registration VCs, DID Documents, and ResourcePackages should also be handled according to their respective disclosure policies. Their being downloaded in one archive does not give them the same disclosure level.
SDK and skill-package tests must not write real private keys into fixed fixtures or commit records. Automated tests can use temporary directories, temporary keys, and placeholder DIDs. After a test, identity files should be cleaned up, and the request body, exception text, and logs should be checked to ensure that they contain no private-key fields. If an application needs to retain a Local Identity for a long period, the user should choose encrypted storage, an operating-system credential store, or an offline backup method; the SDK should not default to uploading it to a remote service.
16.13 Browser Registration and Local Identity Backup Behavior
The browser registration page treats the Local Identity as user-controlled material. The user can create and download a timestamped oan-registration-identity.bundle.<timestamp>.json, or import a backup; the browser sends only the public DID Document, resource data, and control proof to the Registrar node. The registration-result package must be generated only after submission succeeds and the resource DID has been confirmed.
| User action | Browser-side change | Server-side effect |
|---|---|---|
| Create and back up | Generate the identity, update the current subject, and trigger a download | None |
| Import from local | Validate and load the backup selected by the user | None |
| Preview DID Document | Generate or reuse a preview based on the current form and identity | No registration submission |
| Submit registration | Validate current input and send public materials and proofs | Creates a registration request |
| Download after success | Package the DID Document, registration VC, and existing Local Identity | Does not create a second registration |
16.13.1 Browser-Side Key Generation
The browser uses Web Crypto or the SDK to generate keys and establish the DID-to-public-key binding. The page must not place private keys in the DOM, URLs, public APIs, or error messages. Refreshing the page or clearing site data may lose an unbacked-up state, so the user should be prompted to back it up promptly.
16.13.2 Local Identity Import
The import operation reads the JSON file explicitly selected by the user, checks the structure of the version, subject configuration, resource configuration, and private-key materials, and verifies the relationship between the DID Document and public key. A failed import must not overwrite an existing valid identity. After a successful import, the preview and submission use the imported identity and recompute the control proof.
16.13.3 Local Backup Download
Local backup download uses the browser’s standard download capability. The filename contains oan-registration-identity.bundle and the generation time to avoid overwriting an older backup. The server does not participate in file generation; the user should keep the file as a sensitive key backup. Different browsers and mobile operating systems support automatic downloads differently. A failed download must not be marked as a valid backup, and an empty or incomplete file must not be treated as a valid backup.
16.13.4 Registration-Result Package Download
Registration-result packaging and download are triggered only after the server clearly returns success and the page confirms the resource DID. The archive name replaces the colons in the resource DID with hyphens. It contains the registration VC, DID Document, and existing Local Identity file. An empty VC may remain as an empty item, but no archive may be downloaded after failure, timeout, or a missing DID.
16.14 DID, VC, and ResourcePackage Download Formats
DID Documents, registration VCs, ResourcePackages, and Local Identity backups use recognizable JSON filenames and stable encodings. Public files must not contain private keys. Importers should verify the DID, version, and hashes from the content fields rather than trusting only the extension or filename.
| File | Suggested contents | Sensitivity | Minimum validation |
|---|---|---|---|
| DID Document | DID, public keys, services, and OAN metadata | Public | DID, verification methods, and structure version |
| Registration VC | Issuer, subject, claims, signature, and status references | According to issuer and disclosure policy | Issuer, subject, signature, and validity period |
| ResourcePackage | Resource description, endpoint, capabilities, and version materials | According to resource policy | Resource DID, version, and digest |
| Local Identity backup | Subject and resource-control private-key materials | Highly sensitive | Package version, DID, and public/private-key correspondence |
Unknown fields may be retained within a compatible version. Missing required fields, unrecognized structure versions, inconsistent digests, or private keys mixed into a public file must cause import or publication to be rejected.
The following is an example ResourcePackage used to explain field relationships. Its DID, digests, timestamps, and signature values are placeholders and do not represent an online resource. The example shows how a public ResourcePackage can reference the DID Document, metadata digest, ResourcePackage digest, and Root proof at the same time. An actual implementation may also retain extension fields allowed by the protocol type.
{
"packageVersion": "1.0.0",
"resourceDid": "did:oan:SKDM:ExampleResourceDid00000000000000000000",
"resourceType": "skill",
"didDocument": {
"@context": ["https://www.w3.org/ns/did/v1", "https://w3id.org/oan/v1"],
"id": "did:oan:SKDM:ExampleResourceDid00000000000000000000",
"verificationMethod": [
{
"id": "did:oan:SKDM:ExampleResourceDid00000000000000000000#key-1",
"type": "Ed25519VerificationKey2020",
"controller": "did:oan:SKDM:ExampleResourceDid00000000000000000000",
"publicKeyMultibase": "zExamplePublicKey"
}
],
"authentication": [
"did:oan:SKDM:ExampleResourceDid00000000000000000000#key-1"
],
"oanMetadata": {
"subjectType": "skill",
"resourceType": "skill",
"resourceDescription": {
"name": "Example repository structure skill",
"description": "Searches a code repository and summarizes its project structure.",
"capabilityTags": ["code-repository", "project-structure"]
},
"capabilityTags": ["code-repository", "project-structure"]
}
},
"didDocumentHash": "sha256:example-did-document-hash",
"metadataHash": "sha256:example-metadata-hash",
"packageHash": "sha256:example-package-hash",
"hashAlgorithm": "sha-256",
"metadata": {
"resourceDid": "did:oan:SKDM:ExampleResourceDid00000000000000000000",
"resourceType": "skill",
"subjectType": "skill",
"name": "Example repository structure skill",
"description": "Searches a code repository and summarizes its project structure.",
"capabilityTags": ["code-repository", "project-structure"],
"lifecycleState": "active",
"packageVersion": "1.0.0",
"packageHash": "sha256:example-package-hash",
"metadataHash": "sha256:example-metadata-hash",
"hashAlgorithm": "sha-256",
"updatedAt": "2026-01-01T00:00:00Z"
},
"rootProof": {
"rootDid": "did:oan:INPT:ExampleRootDid00000000000000000000",
"signature": "zExampleRootSignature",
"hashAlgorithm": "sha-256"
},
"createdAt": "2026-01-01T00:00:00Z"
}
The ResourcePackage above can serve as input for public publication and discovery, but it cannot replace the Local Identity backup. The latter also contains subject or resource-control private keys and must be exported, imported, and stored separately. Putting the Local Identity and ResourcePackage into the same registration-result archive only consolidates the download operation; it does not change their sensitivity levels or verification methods. Compatibility decisions for a download format should be based on the content structure. The timestamp and DID in a filename are only for human recognition and avoiding overwrites; they cannot prove authenticity, issuer, or control rights.
References
| Source | Type | Link |
|---|---|---|
oan-sdk-ts |
Code repository: DID, identity, ResourcePackage, registration, and discovery client capabilities | https://github.com/OpenAgenet/oan-sdk-ts |
oan-community-skill |
Code repository: community Skill, scripts, and developer workflows | https://github.com/OpenAgenet/oan-community-skill |
oan-protocol-common |
Code repository: protocol types and error contracts used by the SDK | https://github.com/wolfbrother/oan-protocol-common |
| OAN Yellow Paper | arXiv yellow paper: client, resource-publication, and verification flows | https://arxiv.org/abs/2606.03163 |
| OAN White Paper | arXiv white paper: developer ecosystem and open-infrastructure positioning | https://arxiv.org/abs/2606.03161 |