{"id":"d32ab9d2-e556-49fb-8865-5ef537fab0a8","slug":"idevsec-creduent-js","kind":"mcp","name":"creduent-js","summary":"Official JavaScript/TypeScript SDK for the Creduent Protocol: resolve, verify, and register secure AI agent identities in Node.js and MCP hosts.","owner":"Idevsec","repoUrl":"https://github.com/Idevsec/creduent-js","license":"Apache-2.0","licenseTier":"permissive","trust":"community","stars":0,"match":null,"fewStars":true,"format":"mcp","createdAt":"2026-05-29T22:51:43.000Z","addedAt":"2026-10-28T21:29:54.289Z","logoUrl":"https://avatars.githubusercontent.com/u/165232919?v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["developer-tools"],"tags":["creduent"],"runtime":"node","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-28T21:30:21.104Z","sample":false,"url":"https://conduits.dev/tools/idevsec-creduent-js","language":"TypeScript","transports":["stdio"],"install":{"npm":"@idevsec/creduent"},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# Creduent JS/TS SDK\n\n[![npm version](https://img.shields.io/npm/v/@idevsec/creduent.svg?color=blue)](https://www.npmjs.com/package/@idevsec/creduent)\n[![License](https://img.shields.io/github/license/idevsec/creduent-js.svg)](https://github.com/idevsec/creduent-js/blob/main/LICENSE)\n[![Node Compatibility](https://img.shields.io/node/v/@idevsec/creduent.svg)](https://nodejs.org/)\n[![Downloads](https://img.shields.io/npm/dm/@idevsec/creduent.svg)](https://www.npmjs.com/package/@idevsec/creduent)\n\nThe official JavaScript/TypeScript SDK for the **[Creduent Protocol](https://idevsec.com/creduent)**, the open standard for cryptographic AI agent identity, Ed25519 signing, and attestation.\n\n### What is Creduent?\n\n**Creduent** is an open application-layer protocol for cryptographic identity and trust verification of autonomous AI agents, originally created by Kashish Kanojia and stewarded by IDevSec. The official JavaScript/TypeScript SDK is developed and maintained by IDevSec.\n\nPerforms fully **decentralized, local Ed25519 signature verification** using the Web Crypto API (`globalThis.crypto.subtle`). Zero runtime dependencies, as it works natively on Node.js 18+, Vercel Edge, Cloudflare Workers, Deno, and modern browsers.\n\n> **Protocol**: [idevsec.com/creduent](https://idevsec.com/creduent) | **Docs**: [idevsec.com/creduent/docs](https://idevsec.com/creduent/docs) | **Registry**: [creduent.idevsec.com](https://creduent.idevsec.com)\n\n---\n\n## Key Features\n\n- **Zero Runtime Dependencies**: No third-party cryptography libraries. Uses only the built-in Web Crypto API.\n- **Edge-Compatible**: Runs anywhere `globalThis.crypto.subtle` is available, including Vercel Edge, Cloudflare Workers, Deno, and Node.js 18+.\n- **Decentralized Verification**: Validates Ed25519 signatures locally. No registry trust required for `verify()`.\n- **Path Traversal Mitigation**: Pre-resolution security guards in `resolveTarget()` rejecting directory traversal URI sequences (`../`, `..\\`).\n- **Owner Metadata Scheme Validation**: Hardened `identity.owner` validation strictly enforcing `mailto:` or `https://` schemes.\n- **Client-Side DNSSEC Verification**: Exported `verifyDnssec()` DoH helper appending `dnssec_verified?: boolean` property to `VerifyResult`.\n- **Dynamic Cache TTL Tuning**: Automatically parses HTTP `Cache-Control: max-age=N` headers to dynamically optimize local resolution cache TTLs.\n- **RFC 8785 JCS Canonicalization**: Native TypeScript implementation for deterministic JSON serialization before signing.\n- **Dual CJS & ESM Support**: Ships with full ESM and CommonJS exports alongside built-in TypeScript declarations.\n- **Registry Operations**: Built-in support for webhook management, attestation renewals, and authenticated capability discovery.\n- **Provenance & Reversibility Guard**: Fail-closed `ProvenanceGuard` ensuring un-bound tool self-assertions resolve to `IRREVERSIBLE` (OWASP AISVS v1.0 C9.2.3 canonicalization).\n- **Ledger Chain Verification**: Independent `LedgerChainVerifier` querying `/ledger/chain/{chainId}` to prevent self-referential payload truncation during reduction.\n- **Agent Framework Integrations**: First-class adapters for Vercel AI SDK, LangGraph JS, LangChain JS, and LlamaIndex TS.\n- **Identity-Based Rate Limiting (IBRL)**: Express and Hono middleware for identity throttling (`IdentityRateLimiter`) per cryptographically verified `agent_id`.\n\n---\n\n## Installation\n\n```bash\nnpm install @idevsec/creduent\n```\n\n---\n\n## Quickstart\n\n### Verify an Agent (Decentralized)\n\nThe primary use case is to fetch an agent document and validate its Ed25519 signature locally:\n\n```typescript\nimport { verify } from \"@idevsec/creduent\";\n\nconst result = await verify(\"agent://idevsec/steward\");\n\nif (result.valid) {\n    console.log(\"Agent ID:\", result.agent_id);\n    console.log(\"Owner:\", result.document?.owner);\n    console.log(\"Capabilities:\", result.document?.capabilities);\n} else {\n    console.error(\"Verification failed:\", result.reason);\n}\n```\n\n### Verify from a Raw Document\n\nIf you already have the `agent.json` document in memory:\n\n```typescript\nimport { verify } from \"@idevsec/creduent\";\nimport type { AgentDocument } from \"@idevsec/creduent\";\n\nconst doc: AgentDocument = {/* your agent.json object */};\nconst result = await verify(doc);\n\nconsole.log(result.valid); // true | false\n```\n\n### Resolve a Target\n\nResolve an `agent://` URI, a domain, or a direct HTTPS URL to its `agent.json` document:\n\n```typescript\nimport { resolveTarget } from \"@idevsec/creduent\";\n\n// Resolves via registry: https://creduent.idevsec.com/attest/<uri>\nconst doc = await resolveTarget(\"agent://idevsec/steward\");\n\n// Resolves via .well-known: https://example.com/.well-known/agent.json\nconst doc2 = await resolveTarget(\"example.com\");\n```\n\n### Register an Agent\n\n```typescript\nimport { registerAgent } from \"@idevsec/creduent\";\n\nconst record = await registerAgent({\n    agent_id: \"agent://myorg/mybot\",\n    domain: \"myorg.com\",\n    agent_json_url: \"https://myorg.com/.well-known/agent.json\",\n    metadata: { env: \"production\" },\n});\n\nconsole.log(\"Registered:\", record.agent_id);\n```\n\n### CommonJS\n\n```javascript\nconst { verify } = require(\"@idevsec/creduent\");\n\nverify(\"agent://idevsec/steward\")\n    .then((result) => {\n        console.log(result.valid);\n    })\n    .catch(console.error);\n```\n\n### Framework Integrations\n\n#### Vercel AI SDK\n\nIntegrate agent verification as a tool within the Vercel AI SDK:\n\n```typescript\nimport { creduentVerifyToolDefinition } from \"@idevsec/creduent\";\nimport { tool } from \"ai\"; // Vercel AI SDK\n\nexport const creduentVerifyTool = tool({\n    description: creduentVerifyToolDefinition.description,\n    parameters: creduentVerifyToolDefinition.parameters,\n    execute: creduentVerifyToolDefinition.execute,\n});\n```\n\n#### LangGraph JS\n\nEnsure agent-to-agent interactions are secure using the LangGraph node middleware:\n\n```typescript\nimport { verifyAgentNode } from \"@idevsec/creduent\";\nimport { StateGraph } from \"@langchain/langgraph\";\n\ninterface State {\n    agentUri?: string;\n    verificationResult?: any;\n}\n\nconst workflow = new StateGraph<State>({\n    channels: {\n        agentUri: null,\n        verificationResult: null,\n    },\n}).addNode(\"verify\", (state) => verifyAgentNode(state, { strict: true }));\n```\n\n#### LangChain JS\n\n```typescript\nimport { verifyCreduentAgent } from \"@idevsec/creduent\";\n\nconst result = await verifyCreduentAgent(\"agent://idevsec/steward\", { strict: true });\nconsole.log(\"Verified:\", result.verified);\n```\n\n#### LlamaIndex TS\n\n```typescript\nimport { verifyLlamaIndexAgent } from \"@idevsec/creduent\";\n\nconst result = await verifyLlamaIndexAgent(\"agent://idevsec/steward\");\nconsole.log(\"LlamaIndex Verified:\", result.verified);\n```\n\n---\n\n## How Verification Works\n\n`verify()` performs a 4-step cryptographic check locally:\n\n1. **Resolve**: Fetches the `agent.json` document from the registry or `.well-known` endpoint.\n2. **Schema check**: Validates required fields (`version`, `agent_id`, `capabilities`, `signature`).\n3. **Canonicalize**: Removes the `signature` field and applies RFC 8785 JCS serialization.\n4. **Verify**: Validates the Ed25519 signature against all declared active public keys using `globalThis.crypto.subtle`.\n\nIf any active key produces a valid signature, the result is `valid: true`. The registry does not need to be live for step 4 to succeed.\n\n---\n\n## API Reference\n\n### `verify(target)`\n\nPerforms full cryptographic verification of an agent document.\n\n- **Parameters**:\n    - `target` (`string | AgentDocument`): An `agent://` URI, domain, HTTPS URL, or a pre-fetched document object.\n- **Returns**: `Promise<VerifyResult>`\n\n---\n\n### `resolveTarget(target)`\n\nResolves a target string to an `AgentDocument` without verifying the signature.\n\n- **Parameters**:\n    - `target` (`string`): `agent://` URI, domain, or HTTPS URL.\n- **Returns**: `Promise<AgentDocument>`\n\nSet the `CREDUENT_REGISTRY_URL` environment variable to override the default registry (`https://creduent.idevsec.com`).\n\n---\n\n### `resolveAgent(uri, options)`\n\nResolves the complete registry attestation record for the given agent URI.\n\n- **Parameters**:\n    - `uri` (`string`): The canonical `agent://` URI.\n    - `options` (`ClientOptions`, optional): Configuration options.\n- **Returns**: `Promise<AgentRecord>`\n\n---\n\n### `registerAgent(payload, options)`\n\nRegisters an AI agent's identity with the Creduent registry.\n\n- **Parameters**:\n    - `payload` (`RegisterPayload`): `agent_id`, `domain`, `agent_json_url`, optional `metadata`.\n    - `options` (`ClientOptions`, optional): Configuration options.\n- **Returns**: `Promise<AgentRecord>`\n\n---\n\n### `verifyAgent(uri, options)`\n\nChecks whether an agent's attestation status is active and valid (`verified` or `trusted`). Cleanly returns `false` on HTTP 404 and HTTP 410 (revoked) instead of throwing, allowing hosts to fail-closed gracefully.\n\n- **Parameters**:\n    - `uri` (`string`): The canonical `agent://` URI.\n    - `options` (`ClientOptions`, optional)\n- **Returns**: `Promise<boolean>`\n\n---\n\n### `renewAgent(payload, options)`\n\nRenews an agent's cryptographic registry attestation.\n\n- **Parameters**:\n    - `payload` (`RenewPayload`): Contains `agent_id`, `new_expires_at`, and signature.\n    - `options` (`ClientOptions`, optional)\n- **Returns**: `Promise<RenewResult>`\n\n---\n\n### `registerWebhook(payload, options)`\n\nRegisters a webhook URL for status change notifications.\n\n- **Parameters**:\n    - `payload` (`WebhookPayload`): Contains `agent_id`, `webhook_url`, and signature.\n    - `options` (`ClientOptions`, optional)\n- **Returns**: `Promise<WebhookResult>`\n\n---\n\n### `queryWebhook(agentId, options)`\n\nRetrieves the currently registered webhook URL for the specified agent.\n\n- **Parameters**:\n    - `agentId` (`string`): The agent URI.\n    - `options` (`ClientOptions`, optional)\n- **Returns**: `Promise<WebhookResult>`\n\n---\n\n### `createExpressIBRLMiddleware(limiter?)`\n\nCreates Express middleware for Identity-Based Rate Limiting (IBRL).\n\n```typescript\nimport express from \"express\";\nimport { createExpressIBRLMiddleware } from \"@idevsec/creduent\";\n\nconst app = express();\napp.use(createExpressIBRLMiddleware());\n```\n\n---\n\n### `discoverAgent(targetUri, myAgentId, privateKeyPem, options)`\n\nPerforms authenticated capability discovery by querying the target agent's `/discover` endpoint with challenge-response validation.\n\n- **Parameters**:\n    - `targetUri` (`string`): Target agent URI.\n    - `myAgentId` (`string`, optional): Your agent URI.\n    - `privateKeyPem` (`string`, optional): Your private key PEM.\n    - `options` (`ClientOptions`, optional)\n- **Returns**: `Promise<DiscoveryResult>`\n\n> **Security**: Authenticated discovery only contacts endpoints using `https:`. If the agent document's endpoint field uses any other scheme, the function returns `authenticated: false` with an error instead of making the request. This prevents SSRF in Node.js server-side deployments.\n\n---\n\n### `signPayload(payload, privateKeyPem)`\n\nUtility to sign an arbitrary JSON payload using JCS canonicalization + Ed25519.\n\n- **Parameters**:\n    - `payload` (`any`): The payload to sign.\n    - `privateKeyPem` (`string`): Private key in PEM format.\n- **Returns**: `string` (Base64-encoded signature)\n\n---\n\n### `canonicalize(obj)`\n\nDeterministic RFC 8785 JSON Canonicalization Scheme (JCS) serialization.\n\n- **Returns**: `string`\n\n```typescript\nimport { canonicalize } from \"@idevsec/creduent\";\n\nconst canonical = canonicalize({ b: 2, a: 1 });\n// => '{\"a\":1,\"b\":2}'\n```\n\n---\n\n### `verifySignature(publicKey, signature, data)`\n\nLow-level Ed25519 signature verification using the Web Crypto API.\n\n```typescript\nimport { verifySignature } from \"@idevsec/creduent\";\n\nconst valid = await verifySignature(\n    \"ed25519:V43yNaTrpqQj9YJnjYVL2HdOrqUDcnflhzNGuHTaFD8=\",\n    \"<base64-signature>\",\n    \"<canonical-json-string>\"\n);\n```\n\n---\n\n### `agentToDid(agentUri, scheme?)`\n\nConverts an `agent://` URI into a standard Decentralized Identifier string (`did:creduent` or `did:web`).\n\n- **Parameters**:\n    - `agentUri` (`string`): The canonical `agent://` URI.\n    - `scheme` (`\"creduent\" | \"web\"`, optional): Target DID scheme. Defaults to `\"creduent\"`.\n- **Returns**: `string`\n\n---\n\n### `didToAgent(didUri)`\n\nConverts a `did:creduent` or `did:web` identifier string back to an `agent://` URI.\n\n- **Parameters**:\n    - `didUri` (`string`): The DID identifier.\n- **Returns**: `string`\n\n---\n\n### `agentToDidDocument(doc, scheme?)`\n\nGenerates a standard W3C DID Document (JSON-LD compliant) from an `AgentDocument`.\n\n- **Parameters**:\n    - `doc` (`AgentDocument`): The agent document object.\n    - `scheme` (`\"creduent\" | \"web\"`, optional): Target DID scheme. Defaults to `\"creduent\"`.\n- **Returns**: `any` (W3C DID Document object)\n\n---\n\n## Types\n\n```typescript\ninterface AgentDocument {\n    version: string;\n    agent_id?: string;\n    owner?: string;\n    public_key?: string;\n    keys?: KeyRecord[];\n    endpoint?: string;\n    capabilities?: string[];\n    issued_at?: string;\n    signature?: string;\n\n    // v2.0 decoupled fields\n    identity?: {\n        agent_id: string;\n        owner: string;\n        keys: KeyRecord[];\n        endpoint: string;\n        delegated_from?: string;\n    };\n    policy?: {\n        capabilities: string[];\n    };\n\n    [key: string]: any;\n}\n\ninterface KeyRecord {\n    public_key: string;\n    status: \"active\" | \"revoked\";\n    expires_at?: string;\n    revoked_at?: string;\n}\n\ninterface VerifyResult {\n    valid: boolean;\n    agent_id?: string;\n    reason?: string;\n    document?: AgentDocument;\n}\n\ninterface RegisterPayload {\n    agent_id: string;\n    domain: string;\n    agent_json_url: string;\n    metadata?: Record<string, string>;\n}\n\ninterface ClientOptions {\n    baseUrl?: string;\n    headers?: Record<string, string>;\n}\n\ninterface RenewPayload {\n    agent_id: string;\n    new_expires_at: string;\n    signature: string;\n}\n\ninterface RenewResult {\n    agent_id: string;\n    issuer: string;\n    level: \"verified\" | \"trusted\" | \"unverified\" | \"revoked\";\n    domain: string;\n    public_key: string;\n    registered_at: string;\n    issued_at: string;\n    expires_at: string;\n}\n\ninterface WebhookPayload {\n    agent_id: string;\n    webhook_url: string;\n    signature: string;\n}\n\ninterface WebhookResult {\n    agent_id: string;\n    webhook_url: string;\n}\n\ninterface DiscoveryResult {\n    target_agent_id: string;\n    endpoint?: string;\n    capabilities?: string[];\n    authenticated: boolean;\n    error?: string;\n}\n```\n\n---\n\n## Environment Variables\n\n| Variable                | Default                        | Description                                               |\n| :---------------------- | :----------------------------- | :-------------------------------------------------------- |\n| `CREDUENT_REGISTRY_URL` | `https://creduent.idevsec.com` | Override the registry used for `agent://` URI resolution. |\n\n---\n\n## Protocol Specification\n\n- **Protocol overview**: [idevsec.com/creduent](https://idevsec.com/creduent)\n- **Technical reference**: [idevsec.com/creduent/docs](https://idevsec.com/creduent/docs)\n- **CLI**: [github.com/idevsec/creduent-cli](https://github.com/idevsec/creduent-cli)\n- **Standards documents**: [github.com/idevsec/creduent](https://github.com/idevsec/creduent) (CREDUENT-001 through CREDUENT-008)\n\n---\n\n## License\n\nLicensed under the **[Apache License 2.0](LICENSE)**. See the [LICENSE](LICENSE) file for the full legal text.\n"}