# Migrating from V1 to V2

URL: https://docs.nexart.io/docs/migration-v1-to-v2

A practical, optional migration guide from the AI Execution V1 schema to V2: field mapping, before/after code for each integration path, and common mistakes to avoid.

## Migration Is Optional and Additive

Migrating to AI Execution V2 is optional. V1 remains fully supported; see V1 / V2 Compatibility. Adopting V2 means certifying new executions with the V2 APIs going forward.

Do not rewrite existing records
Existing sealed V1 records MUST NOT be rewritten or re-sealed into V2. Re-sealing changes `certificateHash`, producing a different record rather than migrating the existing one. There is no supported &quot;upgrade in place&quot; operation for a sealed CER.

## Field Mapping

| V1 field | V2 field | Notes |
| --- | --- | --- |
| prompt | instruction + instructionKind | instructionKind required iff instruction present |
| modelVersion | modelEvidence.responseDeclaredModel | Producer-transcribed, never provider-signed proof |
| model | model | Unchanged: stays the requested/producer-declared model |
| (none) | executionRole | New required field, producer-declared, never inferred |

## Direct SDK Path

Before: V1

```
import { createSnapshot, sealCer } from "@nexart/ai-execution";

const snapshot = createSnapshot({
  model: "gpt-4o-mini",
  prompt: "Summarize this ticket.",
  input: { messages },
  output: { summary },
  modelVersion: "gpt-4o-mini-2024-07-18",
});
const bundle = sealCer(snapshot);
```

After: V2

```
import { createSnapshotV2, sealCerV2 } from "@nexart/ai-execution";

const snapshot = createSnapshotV2({
  executionId: "exec_123",
  provider: "openai",
  model: "gpt-4o-mini",
  instruction: "Summarize this ticket.",
  instructionKind: "system",
  input: { messages },
  parameters: { temperature: 0.2, maxTokens: 500 },
  output: { summary },
  executionRole: "advisory",
  modelEvidence: { responseDeclaredModel: "gpt-4o-mini-2024-07-18" },
});
const bundle = sealCerV2(snapshot);
```

## Provider Wrapper Path

Before: V1 provider helper

```
import { runOpenAIChatExecution } from "@nexart/ai-execution/providers/openai";

const result = await runOpenAIChatExecution({
  prompt: "You are a support summarizer.",
  input: { messages },
  model: "gpt-4o-mini",
  apiKey: process.env.OPENAI_API_KEY,
});
```

After: V2 provider wrapper

```
import { runOpenAIChatExecutionV2 } from "@nexart/ai-execution/providers/openaiV2";

const result = await runOpenAIChatExecutionV2({
  instruction: "You are a support summarizer.",
  input: { messages },
  model: "gpt-4o-mini",
  executionRole: "advisory",
  apiKey: process.env.OPENAI_API_KEY,
});
// instruction is sent as the system message -> instructionKind "system"
// executionRole defaults to "unspecified" if omitted; declare it explicitly
```

## LangChain Path

Before: V1

```
import { createLangChainCer } from "@nexart/ai-execution";

const cer = await createLangChainCer({ chain, input, model: "gpt-4o-mini" });
```

After: V2

```
import { createLangChainCerV2 } from "@nexart/ai-execution";

const cer = await createLangChainCerV2({
  chain,
  input,
  model: "gpt-4o-mini",
  executionRole: "advisory",
});
```

## Agent Kit Path

Before: V1

```
import { certifyDecision } from "@nexart/agent-kit";

const { bundle, certificateHash } = await certifyDecision({
  model: "gpt-4o-mini",
  input,
  output,
});
```

After: V2

```
import { certifyAiExecutionV2 } from "@nexart/agent-kit";

const { bundle, certificateHash, executionId } = await certifyAiExecutionV2({
  provider: "openai",
  model: "gpt-4o-mini",
  input,
  output,
  executionRole: "advisory",
});
```

Agent Kit&#x27;s `wrapTool` and `startWorkflow` step bookkeeping stay V1 forever; they are not AI executions and have no V2 counterpart. Do not emit synthetic V2 records for them. See V1 / V2 Compatibility.

## Migration Checklist

- Confirm the change is additive: new executions use V2, existing V1 records are left untouched.
- Map `prompt` to `instruction` + a correctly chosen `instructionKind`.
- Move `modelVersion` to `modelEvidence.responseDeclaredModel`, keeping `model` as the requested model.
- Add an explicit, producer-declared `executionRole` to every call site.
- Update verification code to call `verifyCerV2` for V2 bundles (`verifyCer` remains for V1).
- If attesting, confirm the node call still targets `/api/attest`, never `/v1/cer/ai/certify` for V2.
- Re-run `nexart ai verify --aief` against sample V2 output to confirm AIEF v0.2.5 checks pass.

## Common Mistakes

- Inferring executionRole. executionRole is producer-declared and MUST NOT be inferred by NexArt or by a wrapper. Set it explicitly at the call site instead of defaulting or guessing from context.
- Reusing agent-kit run IDs as transactionRef. `modelEvidence.transactionRef` is producer-transcribed provider transaction evidence, not an internal Agent Kit run identifier. Do not substitute one for the other.
- Copying response.model into model. The top-level `model` field must stay the requested/producer-declared model. If you want to record what the provider reported back, put it in `modelEvidence.responseDeclaredModel`.
- Sending V2 to /v1/cer/ai/certify. That endpoint is the V1 producer certify flow. V2 bundles must not be created through it; use the V2 SDK functions and attest the resulting bundle through `/api/attest`.

## Next

- AI Execution V2: the full V2 schema reference.
- AI Execution CER (V1): the unchanged V1 schema.
- V1 / V2 Compatibility: the full surface matrix.
- Attestation Node: how the node dispatches attestation requests by schema.
- Trust Model: what changes and what stays constant across schemas.
