nexart.iodocs

    AI Execution V2

    The normative reference for the AI Execution V2 record schema (ai.execution.v2), the current recommended schema for new integrations built on @nexart/ai-execution 1.4.0.

    Overview

    AI Execution V2 is a record schema, identified by snapshot.type "ai.execution.v2" and bundle type cer.ai.execution.v2. It is the current recommended schema for new integrations. V1 remains fully supported and unchanged; see V1 / V2 Compatibility and, for migrating existing integrations, Migrating from V1 to V2. For the V1 schema, see AI Execution CER.

    Version Axes

    Four different numbers appear around a V2 record. They MUST be presented as distinct axes, never collapsed into one "version":

    AxisValueMeaning
    npm package version@nexart/ai-execution 1.4.0SDK release, ships both V1 and V2 APIs
    Record schemaV1 (ai.execution.v1) or V2 (ai.execution.v2)Snapshot shape and field set
    Canonicalisation protocolVersion"1.3.1" (jcs-v1) for V2Canonical JSON scheme used to hash the bundle
    Container version"0.1"Bundle envelope format, same for V1 and V2

    There is no protocol version "1.4.0". Do not describe protocolVersion "1.3.1" as "AI Execution SDK version 1.3.1" or vice versa; they are unrelated numbers.

    Snapshot Field Reference

    The V2 snapshot type (AiExecutionSnapshotV2) uses a strict top-level keyset. Absent optional fields MUST be omitted from the object entirely; they MUST NOT be present with a null value.

    Required

    • type, protocolVersion ("1.3.1"), executionSurface: "ai"
    • executionId, timestamp
    • provider, model
    • input, inputHash, parameters
    • output, outputHash
    • executionRole

    Optional

    • instruction, instructionKind
    • decisionRefs, modelEvidence
    • identity, toolCalls
    • runId, stepId, stepIndex, workflowId, conversationId, prevStepHash
    • sdkVersion, appId, ext
    • confidential declaration

    ext keys MUST be namespaced, either <ns>:<name> or reverse-DNS style. A NexArt-reserved namespace is rejected by schema validation. Related exports: validateSnapshotV2Schema, V2_REQUIRED_FIELDS, V2_OPTIONAL_FIELDS.

    executionRole

    executionRole is REQUIRED and MUST be declared by the producer. It MUST NOT be inferred by NexArt, by the node, or by any provider wrapper.

    • advisory: the output informs a later human or system decision.
    • operative: the output directly determines downstream automated behaviour.
    • unspecified: neither stronger declaration applies.

    Provider wrappers default executionRole to "unspecified" when the caller does not supply one. They never guess "advisory" or "operative"from the call shape.

    instruction and instructionKind

    instructionKind is REQUIRED if and only if instruction is present, and FORBIDDEN when instruction is absent.

    • system: verbatim system/task text supplied to the provider.
    • derived: a human-readable representation derived from the input.
    • label: a short label, such as a tool or step name, not provider text.

    modelEvidence

    modelEvidence is optional, has a strict keyset, and is producer-transcribed only: { responseDeclaredModel?, transactionRef?, providerEvidence?: Record<string,string> }. It is never provider-signed proof of what model ran.

    The top-level model field always holds the requested/producer-declared model. It MUST NOT be overwritten with response.model from the provider call; that value, if captured, belongs in modelEvidence.responseDeclaredModel. V2 has no modelVersion field.

    decisionRefs and refForm

    decisionRefs?: { ref: string | ConfidentialEnvelope; refForm: 'public' | 'commitment'; category? }[]. When refForm is "commitment", the commitment domain binds the array index (decisionRef:<index>), so reordering the array changes the commitment domain for each entry.

    Opacity is not confidentiality. A commitment-form ref hides the underlying value from readers of the bundle, but that is a one-way cryptographic commitment, not encryption, and it makes no confidentiality guarantee on its own.

    protectedSet

    protectedSet is sealed inside certificateHash. It is SDK-derived and MUST NOT be supplied by the caller.

    protectedSet shape
    {
      stabilitySchemeId: "jcs-v1",
      protectedSetId: "nexart.ai.execution.v2.protected-set.v1",
      protectedFields: string[] // sorted snapshot field paths + present bundle-level evidence
    }

    protectedSet never lists itself or certificateHash among protectedFields. verifyCerV2 re-derives protectedSet from the bundle (via deriveProtectedSetV2) and compares it to the sealed value. A mismatch produces PROTECTED_SET_MISMATCH; a protected field expected by the scheme but missing from the bundle produces PROTECTED_FIELD_MISSING.

    What certificateHash Covers in V2

    • meta is excluded from certificateHash.
    • context, contextSummary, and policyEvaluation are included when present.

    See Verification Semantics for how hash scope interacts with reseal and public verification.

    Working Examples

    createSnapshotV2 + sealCerV2
    import { createSnapshotV2, sealCerV2 } from "@nexart/ai-execution";
    
    const snapshot = createSnapshotV2({
      executionId: "exec_123",
      provider: "openai",
      model: "gpt-4o-mini",
      input: { messages: [{ role: "user", content: "Summarize this ticket." }] },
      parameters: { temperature: 0.2, maxTokens: 500 },
      output: { summary: "Customer requests a refund." },
      executionRole: "advisory",
      instruction: "Summarize the support ticket in one sentence.",
      instructionKind: "system",
    });
    
    const bundle = sealCerV2(snapshot);
    // bundle.certificateHash is the canonical identifier
    certifyDecisionV2
    import { certifyDecisionV2 } from "@nexart/ai-execution";
    
    const { bundle, certificateHash } = await certifyDecisionV2({
      provider: "openai",
      model: "gpt-4o-mini",
      input: { messages: [{ role: "user", content: "Approve refund?" }] },
      parameters: { temperature: 0 },
      output: { decision: "approve" },
      executionRole: "operative",
    });
    verifyCerV2
    import { verifyCerV2 } from "@nexart/ai-execution";
    
    const result = verifyCerV2(bundle);
    if (!result.ok) {
      // result.code: e.g. PROTECTED_SET_MISMATCH, PROTECTED_FIELD_MISSING,
      // CERTIFICATE_HASH_MISMATCH, SCHEMA_ERROR, ...
      throw new Error(`verification failed: ${result.code}`);
    }
    // result.verdict: 'VERIFIED' | 'VERIFIED_CONFIDENTIAL'
    Provider wrappers: OpenAI and Anthropic
    import { runOpenAIChatExecutionV2 } from "@nexart/ai-execution/providers/openaiV2";
    import { runAnthropicExecutionV2 } from "@nexart/ai-execution/providers/anthropicV2";
    
    const { output, snapshot, bundle } = await runOpenAIChatExecutionV2({
      instruction: "You are a support ticket summarizer.",
      input: { messages: [{ role: "user", content: "My order is late." }] },
      model: "gpt-4o-mini",
      executionRole: "advisory",
      apiKey: process.env.OPENAI_API_KEY,
    });
    // instruction is sent as the provider system message -> instructionKind "system"
    // executionRole defaults to "unspecified" if omitted; it is never inferred
    
    const anthropicResult = await runAnthropicExecutionV2({
      instruction: "You are a support ticket summarizer.",
      input: { messages: [{ role: "user", content: "My order is late." }] },
      model: "claude-3-5-sonnet-latest",
      executionRole: "advisory",
      apiKey: process.env.ANTHROPIC_API_KEY,
    });
    Attesting the sealed bundle to the node
    import { attest } from "@nexart/ai-execution";
    
    // certificateHash already exists before this call; the node never creates
    // or replaces it, it only witnesses the already-sealed bundle.
    const receipt = await attest(bundle, {
      nodeUrl: "https://node.nexart.io",
      apiKey: process.env.NEXART_API_KEY,
    });

    V2 bundles must not be created through the V1 producer endpoint /v1/cer/ai/certify; the node's /api/attest route dispatches by bundleType and accepts both cer.ai.execution.v1 and cer.ai.execution.v2. See Attestation Node.

    Claim Boundaries

    NexArt proves:

    • Canonical artifact integrity and hash equality
    • Signed node attestation
    • Workflow structure integrity
    • Timestamp evidence
    • Commitment consistency

    NexArt does not prove:

    • Model output correctness, truthfulness, fairness, or regulatory compliance
    • That a producer-declared field (including executionRole and modelEvidence) is factually true
    • That a self-asserted identity is real
    • That a provider actually ran the model, absent provider-signed evidence
    • Legal admissibility

    Cryptographic binding is not identity assurance: a bound identity claim can still have verified: false. See Trust Model.

    Next