Skip to content

SDK Integration Guide — For SDK Authors

This page documents the current formal integration model for SDK repositories. If you are maintaining the suite itself, see Manifests Reference.

Integration Rules

When an SDK repository integrates conformance, these boundaries are mandatory:

  1. Conformance must run in a dedicated CI job, not inside the main unit-test or coverage job.
  2. Execution orchestration is owned by the run-conformance action provided by nnrp-conformance.
  3. The SDK repository provides a capability manifest and, when behavior validation is enabled, an adapter command.
  4. SDK-local pytest, xUnit, or other language-native tests must not replace the suite-owned execution plan and result schema.

Integration Contract

The suite owns baseline selection, canonical vector generation, execution-plan creation, and result validation. SDK repositories own only their implementation-specific adapter entrypoint and any evidence files they choose to attach.

SurfaceResponsibilityWhat the suite exchanges with the implementation repository
capability selectionDecide which public cases are selected for this implementationcapability manifest, conformance report
canonical vectorsProduce deterministic byte-level fixtures from readable recipessuite-generated vector manifest
adapter executionExecute selected dynamic behavior cases and return machine-readable resultsexecution plan, adapter command, case-result report

Step 1: Create your capability manifest

Create conformance/<protocol-version>.capabilities.json in your repository root, for example conformance/nnrp-1-preview3.capabilities.json. The path is conventional and is passed into the suite action via capabilities-path.

If you do not want to hand-write the JSON, start with the Capability Manifest Generator and then cross-check the selected tokens against the versioned capability catalog.

Capability Manifest Field Reference

FieldTypeRequiredValid valuesDescription
$schemastringnoURIJSON Schema reference.
implementation_namestringyesnon-empty stringCanonical short name for your implementation, e.g. nnrp-py or nnrp-cs.
protocol_versionstringyesnon-empty stringTarget protocol line. Must exactly match the suite action's protocol-version.
supportsarray of stringyesunique capability tokensCapabilities your implementation has completed and is willing to claim publicly. Unclaimed capabilities become not_claimed, not silently passed.

Find capability tokens by version

Capability tokens are now documented in the versioned capability catalog instead of being hard-coded inside the SDK integration page. That keeps preview2 and preview3 tokens from being mixed together, and it lets each version explain the exact semantics of the same token name independently.

Catalog Overview

Start here for the rules behind capability tokens, `supports`, and always-on cases with no token.

nnrp-1-preview2

Full preview2 token table with combination rules, related cases, and detailed explanations.

nnrp-1-preview3

Preview3 capability catalog covering the current mandatory core plus optional and experimental tokens.

Combination rules matter

Some cases are selected only when multiple tokens are claimed together. For example, the preview2 primary result path depends on result_push.partial, result_push.stale_reuse, and payload.tensor at the same time. Check the version page directly before editing supports.

Example capability manifest

json
{
  "$schema": "../../schemas/capability-manifest.schema.json",
  "implementation_name": "nnrp-py",
  "protocol_version": "nnrp-1-preview3",
  "supports": [
    "handshake.basic",
    "session.open_close",
    "frame_submit.tensor.inline",
    "result_push.basic"
  ]
}

Claim only what is complete

Claiming a capability means accepting a hard CI gate for every mandatory case mapped to that token.


Step 2: Implement the SDK adapter command

The suite action does not call your test framework directly. It calls an adapter command provided by your SDK repository. That command must consume the suite-owned execution plan and emit a case-result report in the shared schema.

Command contract

Your command must support at least these arguments:

Environment variableRequiredDescription
NNRP_CONFORMANCE_ADAPTER_PLANyesAbsolute path to the suite-generated execution plan JSON.
NNRP_CONFORMANCE_ADAPTER_RESULTSyesAbsolute path where the adapter must write the case-result report JSON.

The output file must satisfy all of the following:

  1. UTF-8 JSON, preferably without BOM.
  2. Top-level fields must include protocol_version, implementation_name, and results.
  3. Each result entry must include id and outcome.
  4. Result ids must match the execution-plan case ids exactly.

Python:

bash
python -m nnrp.tools.adapter_conformance

C#:

powershell
dotnet run --project tools/Nnrp.ConformanceAdapter/Nnrp.ConformanceAdapter.csproj

Do not add embedded conformance tests here

The formal integration contract is “suite-owned plan + adapter command + suite-validated results”. Local unit and integration tests still matter, but they are not the shared conformance surface.


Step 3: Use the suite runner for local debugging

The formal CI path should use the suite action. The commands below are for local debugging and manual inspection only.

Replace these with your target baseline

Substitute <protocol-version>, <path-to-protocol-manifest>, and <path-to-recipe> with the version line you are currently integrating.

summary — inspect the execution plan

bash
cargo run \
  --manifest-path <path-to-nnrp-conformance>/Cargo.toml \
  -p nnrp-conformance-runner \
  -- \
  summary \
  --protocol <path-to-protocol-manifest> \
  --capabilities conformance/<protocol-version>.capabilities.json

generate-vectors — produce the canonical vector manifest

bash
cargo run \
  --manifest-path <path-to-nnrp-conformance>/Cargo.toml \
  -p nnrp-conformance-runner \
  -- \
  generate-vectors \
  --recipe <path-to-nnrp-conformance>/protocol/<protocol-version>/vectors/semantic-vectors.json \
  --output /tmp/canonical-vectors.json

verify-vectors — confirm canonical determinism

bash
cargo run \
  --manifest-path <path-to-nnrp-conformance>/Cargo.toml \
  -p nnrp-conformance-runner \
  -- \
  verify-vectors \
  --recipe <path-to-nnrp-conformance>/protocol/<protocol-version>/vectors/semantic-vectors.json \
  --manifest /tmp/canonical-vectors.json

validate-adapter-results — validate adapter output

bash
cargo run \
  --manifest-path <path-to-nnrp-conformance>/Cargo.toml \
  -p nnrp-conformance-runner \
  -- \
  validate-adapter-results \
  --plan /tmp/adapter-plan.json \
  --results /tmp/adapter-results.json

Step 4: Wire CI through the suite-owned action

  1. Keep your language-native test or coverage job focused on repository-local validation.
  2. Add a separate conformance job.
  3. In that job, checkout the suite repository and call run-conformance.
  4. Pass your adapter command through adapter-command.

Key run-conformance inputs

InputDescription
protocol-versionTarget protocol line, e.g. nnrp-1-preview3.
capabilities-pathPath to your capability manifest.
working-directoryDirectory in which the adapter command should run.
artifact-nameArtifact name used for reports and generated manifests. The default recommendation is a generic name such as <repo>-conformance; only append the version when one workflow intentionally publishes multiple protocol lines side by side.
adapter-commandCommand that consumes NNRP_CONFORMANCE_ADAPTER_PLAN and writes NNRP_CONFORMANCE_ADAPTER_RESULTS.

GitHub Actions example

yaml
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Run tests
        run: <your language-native test command>

  conformance:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Checkout nnrp-conformance action
        uses: actions/checkout@v4
        with:
          repository: <your-org>/nnrp-conformance
          path: nnrp-conformance-action

      - name: Setup language runtime
        run: <install the runtime your SDK adapter needs>

      - name: Resolve conformance baseline
        id: conformance-baseline
        shell: bash
        run: |
          capabilities_path="$(find conformance -maxdepth 1 -name '*.capabilities.json' | head -n 1)"
          test -n "$capabilities_path"
          protocol_version="$(basename "$capabilities_path" .capabilities.json)"
          echo "protocol_version=$protocol_version" >> "$GITHUB_OUTPUT"
          echo "capabilities_path=$capabilities_path" >> "$GITHUB_OUTPUT"

      - name: Run suite-owned conformance action
        uses: ./nnrp-conformance-action/.github/actions/run-conformance
        with:
          protocol-version: ${{ steps.conformance-baseline.outputs.protocol_version }}
          capabilities-path: ${{ steps.conformance-baseline.outputs.capabilities_path }}
          working-directory: .
          artifact-name: <repo>-conformance
          adapter-command: <your adapter command>

Common errors and resolutions

ErrorCauseResolution
protocol version mismatchCapability manifest, suite action input, and adapter result use different version strings.Align protocol-version, the capability manifest's protocol_version, and the result report.
adapter-command exits successfully but no output file existsThe adapter did not write the expected result path.Ensure the command writes exactly to NNRP_CONFORMANCE_ADAPTER_RESULTS.
JSON parse fails at column 1The output file contains a BOM or is not valid JSON.Emit UTF-8 JSON without BOM and return a non-zero exit code on adapter failure.
Result ids do not matchThe adapter returned local private ids instead of plan case ids.Copy the exact id values from the execution plan.
All cases are not_claimedThe capability manifest's supports list is empty or mismatched for the chosen protocol version.Verify supports and protocol_version.

NNRP Documentation