# AI Execution V2

URL: https://docs.nexart.io/docs/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 &quot;version&quot;:

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

There is no protocol version &quot;1.4.0&quot;. Do not describe protocolVersion &quot;1.3.1&quot; as &quot;AI Execution SDK version 1.3.1&quot; 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&#x27;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

- V1 / V2 Compatibility: which surfaces accept which schema.
- Migrating from V1 to V2: field mapping and code changes.
- AI Execution CER (V1): the unchanged, still-supported V1 schema.
- Verification Semantics: hash scope and verification results.
