nexart.iodocs

    Getting Started with NexArt

    Start with NexArt in a few steps: install the SDK, certify an execution, read the certificate hash and verify that record locally or via the node API.

    Start here: choose your path

    Both paths produce Certified Execution Records that anyone can verify. Pick the one that fits how your system works.

    I write code
    Use the SDK
    Add a few lines to your application. Records are sealed in your own process, can be verified offline, and can optionally be attested by the Node.
    1. Install the SDK
    2. Seal a record locally
    3. Verify it locally
    4. Optionally attest it
    5. Check the result
    Start the SDK Quickstart →
    I already have events or logs
    Use the Evidence Bridge
    Send existing JSON or OpenTelemetry events to bridge.nexart.io. A mapping profile turns each event into a record without changing your application code.
    1. Sign in and create an API key
    2. Check readiness
    3. Create a mapping profile
    4. Send one event
    5. Verify, then optionally attest
    Start with the Evidence Bridge →
    SDKEvidence Bridge
    Code changesYes, a few linesNo, send events you already have
    Where the hash is createdIn your process, by the SDKBy the Bridge, from your mapped event
    Works offlineYes (sealing and verification)No, events are sent to the Bridge
    Node attestationOptional, separate callOptional, separate step

    Not sure? Read Architecture for how records are built, or Integration Surfaces for every option.

    Quick Implementation Flow

    Four steps. Each has a single responsibility. Following them in order produces a record anyone can verify without trusting your infrastructure.

    Quick Implementation Flow
    The four steps required to integrate NexArt correctly. Each step has a single responsibility.
    1. Step 1Capture execution
      What: Record provider, model, prompt, input, parameters, and output. All six are required on CertifyDecisionParams.
      Why: The certificateHash is computed from this data. Capture must happen before sealing.
      @nexart/signals · createContext() (optional) → passed into certifyDecision(...)
    2. Step 2Create CER
      What: Seal a CER bundle and compute certificateHash over the strict whitelist (JCS).
      Why: The hash is the canonical identity of the record. It binds the bundle to its content.
      certifyDecision(params) · or sealCer(snapshot) for the lower-level path
    3. Step 3Certify via node
      What: Submit the bundle to the attestation node. Receive a signed receipt and verification envelope.
      Why: The node signs an attestation of the submitted record, separate from the producer integration, and can serve a public verification surface.
      certifyAndAttestDecision(params, options) · or attest(bundle, options) · POST /v1/cer/ai/certify
    4. Step 4Verify independently
      What: Anyone can re-derive certificateHash, validate the receipt signature, and validate the envelope.
      Why: Verification requires no trust in your infrastructure or the node beyond its published key.
      verifyAiCerBundleDetailed(bundle) · or https://verify.nexart.io/c/{bundle.certificateHash}
    Deeper reference: Verification · Verification Layers · Hashes

    Minimal working example

    One execution, one CER, one certification, one verification. This is the canonical example reused across the docs.

    How the SDK is split
    • Creation is local and deterministic (certifyDecision). It produces a sealed bundle and a certificateHash. No network call.
    • Certification is node-based (certifyAndAttestDecision or attest(bundle, options)). It returns an AttestationReceipt and the bundle gains a verification envelope.
    • Attestation and public publication are separate. A URL such as https://verify.nexart.io/c/{certificateHash} resolves only when a public record or public reseal exists; attestation alone does not publish the record.
    • prompt and parameters are REQUIRED fields on CertifyDecisionParams, alongside provider, model, input, and output.
    Flow A - Certified execution (recommended)
    import {
      certifyAndAttestDecision,
      verifyAiCerBundleDetailed,
    } from "@nexart/ai-execution";
    
    // Steps 1-3: capture execution, seal the CER, attest via the node.
    // certifyAndAttestDecision is async because it contacts the attestation node.
    const { bundle, receipt } = await certifyAndAttestDecision(
      {
        provider:   "openai",
        model:      "gpt-4o-mini",
        prompt:     "Should this refund be approved?",
        input:      { messages: [{ role: "user", content: "Should this refund be approved?" }] },
        parameters: { temperature: 0, maxTokens: 1024, topP: null, seed: null },
        output:     { decision: "approve", reason: "policy_passed" },
      },
      {
        nodeUrl: process.env.NEXART_NODE_ENDPOINT!,
        apiKey:  process.env.NEXART_API_KEY!,
      },
    );
    
    const certificateHash = bundle.certificateHash;
    const verificationUrl = `https://verify.nexart.io/c/${certificateHash}`;
    
    console.log(certificateHash);         // sha256:...
    console.log(receipt.attestationId);   // node-issued id
    console.log(verificationUrl);         // https://verify.nexart.io/c/sha256:...
    
    // Step 4: independent verification. No trust in your infrastructure required.
    const report = await verifyAiCerBundleDetailed(bundle);
    // report.checks.bundleIntegrity    -> PASS  (Layer 1)
    // report.checks.nodeSignature      -> PASS  (Layer 2)
    // report.checks.receiptConsistency -> PASS  (Layer 3)
    
    Flow B - Local-only execution (no node interaction)
    import { certifyDecision, verifyAiCerBundleDetailed } from "@nexart/ai-execution";
    
    // certifyDecision is synchronous and deterministic.
    // It produces a sealed CER bundle and certificateHash WITHOUT contacting the node.
    // There is no receipt, no envelope, and no public verificationUrl in this flow.
    const bundle = certifyDecision({
      provider:   "openai",
      model:      "gpt-4o-mini",
      prompt:     "Should this refund be approved?",
      input:      { messages: [{ role: "user", content: "Should this refund be approved?" }] },
      parameters: { temperature: 0, maxTokens: 1024, topP: null, seed: null },
      output:     { decision: "approve", reason: "policy_passed" },
    });
    
    const certificateHash = bundle.certificateHash;
    console.log(certificateHash);   // sha256:...
    
    // Local verification: Layer 1 PASS, Layers 2 & 3 SKIPPED.
    const report = await verifyAiCerBundleDetailed(bundle);
    
    // To obtain a signed receipt, attest the bundle. Public lookup is a separate publication step.
    // via certifyAndAttestDecision(...) or attest(bundle, options).
    

    Using LangChain? See the dedicated LangChain integration page for the optional adapters createLangChainCer / certifyLangChainRun imported from @nexart/ai-execution/langchain.

    What NexArt Does

    NexArt is the AI Evidence Layer: verifiable execution infrastructure that produces cryptographic evidence about what was executed. NexArt creates Certified Execution Records (CERs), cryptographically bound records of AI or deterministic execution that can be independently verified.

    Every CER carries a certificateHash, computed with the canonicalization profile bound to its protocolVersion (for example jcs-v1 for AI Execution V2). That hash is the canonical identity of the record. Optional node attestation produces a signed receipt so anyone can verify the record without trusting your infrastructure.

    What NexArt is not

    NexArt is not an observability dashboard, and it does not judge whether a model output was correct, truthful, fair, or compliant with any regulation. It proves canonical artifact integrity, hash equality, signed node attestation, and (for confidential fields) commitment consistency. See the Glossary for precise definitions of these terms.

    Multi-step or multi-agent workflow? Follow Path A first, then see Path B: Project Bundle.

    Step 1 of 4: Install the SDK

    npm install @nexart/ai-execution

    Current version: @nexart/ai-execution@1.4.0. See AI Execution V2 for the full V2 schema reference.

    Steps 2 and 3 of 4: Seal and verify locally, then attest (Path A, V2)

    The primary happy path. One execution produces one verifiable V2 record. Sealing is fully offline (no API key, no network call); attestation is a single call to the node. Every V2 record declares an executionRole ('advisory' | 'operative' | 'unspecified'), and, when an instruction is present, a matching instructionKind ('system' | 'derived' | 'label'). Both are producer-declared; NexArt never infers them.

    Seal and attest a V2 CER
    import { certifyDecisionV2, attest, verifyCerV2 } from "@nexart/ai-execution";
    
    // certifyDecisionV2 is synchronous. No network call.
    const bundle = certifyDecisionV2({
      provider:       "openai",
      model:          "gpt-4o-mini",
      instruction:    "Answer the user's arithmetic question.",
      instructionKind: "system",
      input:          { messages: [{ role: "user", content: "What is 2 + 2?" }] },
      parameters:     { temperature: 0, maxTokens: 1024, topP: null, seed: null },
      output:         { text: "4" },
      executionRole:  "advisory",
    });
    
    const certificateHash = bundle.certificateHash;
    console.log(certificateHash);
    
    // Local verification, no node call. Re-derives protectedSet and re-checks hashes.
    const local = verifyCerV2(bundle);
    // local.code === "OK", local.verdict === "VERIFIED"
    
    // Attest to the node. The certificateHash already exists; attest() never
    // creates or replaces it.
    const attestation = await attest(bundle, {
      nodeUrl: process.env.NEXART_NODE_ENDPOINT!,
      apiKey:  process.env.NEXART_API_KEY!,
    });
    // attestation.ok === true

    The certificateHash is the canonical identity of the record and does not change between sealing and attestation. attest() POSTs the already-sealed bundle to the node's /api/attest route, which dispatches on bundleType and accepts both cer.ai.execution.v1 and cer.ai.execution.v2.

    Note: executionId is not a unique artifact identifier. Always look up records by certificateHash.

    V1 integrations (existing, still supported)

    cer.ai.execution.v1 is unchanged and remains fully supported. New integrations SHOULD use V2. If you already have a V1 integration, keep using certifyDecision / sealCer from @nexart/ai-execution. For upgrading, see Migration: V1 to V2 and V1/V2 Compatibility.

    V1 (legacy, still supported): Seal a Single CER (offline)
    import { certifyDecision, verifyAiCerBundleDetailed } from "@nexart/ai-execution";
    
    // certifyDecision (V1, from @nexart/ai-execution) is synchronous. No network call.
    const bundle = certifyDecision({
      provider:   "openai",
      model:      "gpt-4o-mini",
      prompt:     "What is 2 + 2?",
      input:      { messages: [{ role: "user", content: "What is 2 + 2?" }] },
      parameters: { temperature: 0, maxTokens: 1024, topP: null, seed: null },
      output:     { text: "4" },
    });
    
    const certificateHash = bundle.certificateHash;
    
    const report = await verifyAiCerBundleDetailed(bundle);
    // report.checks.bundleIntegrity    === "PASS"
    // report.checks.nodeSignature      === "SKIPPED"  (no node attestation yet)
    // report.checks.receiptConsistency === "SKIPPED"  (no envelope yet)

    Path B: Workflow with a Project Bundle

    For multi-step or multi-agent workflows, certify each step as its own CER and group them into a Project Bundle. The bundle has its own projectHash covering all step certificateHash values.

    Linear workflow with @nexart/agent-kit
    import { startWorkflow } from "@nexart/agent-kit";
    
    const workflow = startWorkflow({ projectTitle: "Contract review" });
    
    const clauses = await workflow.step("Extract clauses", async () => {
      return await llm.call("Extract key clauses...");
    });
    
    const risks = await workflow.step("Summarize risks", async () => {
      return await llm.call("Summarize risks from: " + clauses);
    });
    
    const bundle = workflow.finish();
    // bundle.integrity.projectHash is the verifiable hash

    For public verification on verify.nexart.io, the bundle must be registered on the node. See End-to-End Verification for the full registration flow.

    Step 4 of 4: Verify the record

    Verification can be performed independently. Open https://verify.nexart.io and paste the certificateHash, or open the URL directly:

    https://verify.nexart.io/c/{certificateHash}

    Official Example Repos

    Common mistakes

    Common Mistakes
    Verified failure patterns observed in real integrations. Avoid these to prevent verification errors.
    • Wrong: Setting version: "1.0" on the bundle
      Right: Use version: "0.1" (matches cer.ai.execution.v1).
      Why: An incorrect version changes the canonical projection and breaks certificateHash recomputation.
    • Wrong: Hashing the full bundle (including meta.attestation, signature, receipt)
      Right: Hash only the strict whitelist: bundleType, version, createdAt, snapshot, context, contextSummary (JCS).
      Why: meta and attestation are added after sealing. Hashing them produces a different, non-verifiable hash.
    • Wrong: Trying to verify the Verification Envelope from a publicly redacted record
      Right: Layer 3 envelope verification requires the full attestation projection. Redacted public payloads support Layer 1 and Layer 2 only.
      Why: Envelope signature covers a 5-field projection that may be removed by redaction.
    • Wrong: Mutating the bundle after certification (re-ordering keys, adding fields, normalizing dates)
      Right: Treat the certified bundle as immutable. Persist it byte-for-byte.
      Why: Any mutation invalidates certificateHash and the receipt. The node enforces EXECUTION_MUTATION_DETECTED (409) on resubmit.
    • Wrong: Looking up records by executionId
      Right: Always look up by certificateHash. executionId is not a unique artifact identity.
      Why: Two attempts of the same execution can share an executionId but produce different certificateHashes.

    What happens if it fails

    What happens if verification fails
    Each verification layer fails for a different, specific reason. Isolating the failed layer tells you exactly what went wrong.
    LayerFailureMeaningAction
    Layer 1: IntegritycertificateHash mismatchThe bundle was modified after sealing, or the wrong projection was hashed.Re-derive certificateHash with sealCer(...) over the strict whitelist. If it still differs, the stored bundle is no longer authentic.
    Layer 2: Signed ReceiptReceipt signature invalidThe receipt was not produced by the published node key, or the receipt payload was modified.Refetch the node key set from /.well-known/nexart-node.json. If signature still fails, the receipt is not trustworthy.
    Layer 3: Verification EnvelopeEnvelope signature invalid or projection mismatchThe envelope payload (5-field attestation projection) does not match what was signed, or the kid is wrong.Confirm the bundle includes meta.verificationEnvelope and meta.verificationEnvelopeSignature. Public/redacted payloads cannot satisfy Layer 3.
    NodeEXECUTION_MUTATION_DETECTED (409)An execution_id already maps to a different certificateHash. The node rejects mutation by design.Do not re-submit modified bundles under the same execution_id. Create a new execution.

    Next Steps