nexart.iodocs

    Agent-Kit Setup Runbook for AI Coding Agents

    A prescriptive runbook AI coding agents can follow to install @nexart/agent-kit, certify an AI decision, and verify the resulting bundle.

    How to use this page

    This page is unusual: it is written in the second person, addressed to an AI coding agent, not to you. AI assistants like Cursor, Claude Code, Lovable, Windsurf, and Cline can install and wire up @nexart/agent-kit correctly on the first try if given a single, prescriptive, constraint-aware runbook. This is that runbook.

    You have three ways to use it:

    1. Click the Copy for LLM button above and paste it into your assistant as the first message of an integration task.
    2. Point your assistant at the raw markdown: "Follow the instructions at https://docs.nexart.io/agent-kit-instructions.md."
    3. Read it yourself as the canonical setup reference.

    0. Goal

    Add NexArt certification to the user's Node.js / TypeScript project so that every AI decision produces a verifiable, tamper-evident bundle (a CerAiExecutionBundle). A "decision" is any output you would otherwise just log or return: an LLM completion, a tool call result, a routing choice, a generated artifact, etc.

    Success criteria (all must be true at the end):

    1. @nexart/agent-kit@^0.5.2 and @nexart/ai-execution@^0.22.0 are installed.
    2. At least one call site produces a CER bundle via certifyDecision, wrapTool, or startWorkflow.
    3. A verification call returns status: 'VERIFIED' / ok: true.
    4. You ran the project once and observed the verification pass.

    1. Prerequisites

    node --version   # must be >= 18.0.0
    cat package.json | grep '"type"'   # should be "module"
    • Node 18+ is required. If older, tell the user and stop.
    • The package is ESM-only. package.json MUST have "type": "module". Fallback: dynamic await import('@nexart/agent-kit') from a CJS file. Do NOT attempt require('@nexart/agent-kit'), which throws ERR_REQUIRE_ESM.
    • TypeScript recommended. Set "module": "NodeNext" and "moduleResolution": "NodeNext".

    2. Install

    npm install @nexart/agent-kit @nexart/ai-execution

    @nexart/ai-execution is a peer-style dep that @nexart/agent-kit re-exports verification helpers from. Install both.

    3. Pick the right pattern

    Pick one. If the user is vague, default to Pattern A.

    PatternUse whenWhat you get
    A. certifyDecisionOne-off decision, single LLM call, single tool resultOne CerAiExecutionBundle
    B. wrapToolA tool/function runs many times and every call should be certifiedA wrapped function: each invocation produces a bundle
    C. startWorkflowMulti-step pipeline where the whole run is one auditable artifactOne ProjectBundle with one CER per step

    Do not implement all three "to be safe". Ship the smallest correct change.

    4. Pattern A: certifyDecision (default)

    certify-example.ts
    import { certifyDecision, verifyAiCerBundleDetailed } from '@nexart/agent-kit';
    
    const { bundle } = await certifyDecision({
      decision: 'Recommend product X to user 123',
      output:   'product_x',
      provider: 'openai',
      model:    'gpt-4o',
    });
    
    const result = verifyAiCerBundleDetailed(bundle);
    if (result.status !== 'VERIFIED') {
      throw new Error(`CER verification failed: ${result.reasonCodes.join(', ')}`);
    }
    
    console.log('Certified:', bundle.certificateHash);
    console.log('Status:   ', result.status);

    Run it: node certify-example.js (or npx tsx certify-example.ts). Expected output: Status: VERIFIED. If you do not see VERIFIED, stop and report the actual reasonCodes.

    5. Pattern B: wrapTool

    wrapTool takes a SINGLE options object ({ name, run, provider?, source?, tags?, ... }), not positional arguments. The wrapped function returns { result, bundle, certificateHash }.

    wrapTool
    import { wrapTool, verifyAiCerBundleDetailed } from '@nexart/agent-kit';
    
    const lookupPrice = wrapTool({
      name:     'lookup-price',
      provider: 'agent-kit',
      run: async (args: { sku: string }) => {
        return { sku: args.sku, priceUsd: 19.99 };
      },
    });
    
    const { result, bundle, certificateHash } = await lookupPrice({ sku: 'SKU-42' });
    
    const v = verifyAiCerBundleDetailed(bundle);
    if (v.status !== 'VERIFIED') throw new Error(v.reasonCodes.join(', '));
    
    console.log('Tool returned:', result);
    console.log('Bundle hash: ', certificateHash);

    6. Pattern C: startWorkflow (multi-step project bundle)

    startWorkflow
    import { startWorkflow } from '@nexart/agent-kit';
    import { verifyProjectBundle } from '@nexart/ai-execution';
    
    const wf = startWorkflow({
      projectTitle: 'Daily report generation',
      projectGoal:  'Produce signed daily summary',
      // Recommended in v0.5.0+. Chains every step's CER to the previous one:
      enableSignals: true,
    });
    
    await wf.step('fetch-data',  async () => await fetchTodaysRows());
    await wf.step('summarize',   async () => await callLlmSummary());
    await wf.step('write-report', async () => await writeReportFile());
    
    const { projectBundle, projectHash } = wf.finish();
    
    const v = verifyProjectBundle(projectBundle);
    if (!v.ok) throw new Error(`Project bundle invalid: ${v.errors.join(', ')}`);
    
    console.log('Project hash:', projectHash);
    console.log('Steps:       ', projectBundle.totalSteps);

    Workflow rules (DO NOT VIOLATE)

    • Add all step() calls before the first finish(). Calling step() after finish() throws. The workflow is sealed.
    • finish() is deterministic and cached. Calling it twice returns the same bundle reference and the same projectHash. Options on the second call are silently ignored. Pass any options on the FIRST call.
    • The returned projectBundle is deeply frozen. Do not attempt to mutate it, which throws TypeError. Build new objects if you need a modified copy.

    7. (Optional) Register with a NexArt node

    If the user has a NexArt node URL and API key, replace wf.finish() with:

    finishAndRegister
    const { projectBundle, projectHash, registration } = await wf.finishAndRegister({
      register: {
        nodeUrl: process.env.NEXART_NODE_ENDPOINT!,
        apiKey:  process.env.NEXART_API_KEY!,
      },
    });
    
    console.log('Registered:', registration.registrationId);

    If the user does not have a node, skip this step entirely. Local verification is sufficient for most use cases.

    8. Run it and confirm

    node <your-file>.js          # or: npx tsx <your-file>.ts

    You must observe one of:

    • Status: VERIFIED (Patterns A, B), or
    • Project hash: sha256:... with no thrown error (Pattern C).

    If anything else happens, do not declare success. Fix it using the troubleshooting table below.

    9. Troubleshooting

    SymptomCauseFix
    ERR_REQUIRE_ESMProject is CommonJSAdd "type": "module" to package.json OR use await import() from CJS
    Cannot find module '@nexart/agent-kit'Not installedRe-run npm install @nexart/agent-kit @nexart/ai-execution
    TS: Cannot find type declarationsWrong moduleResolutionSet "moduleResolution": "NodeNext" in tsconfig.json
    BUNDLE_TAMPERED or HASH_MISMATCHBundle was mutated after creationDo not modify bundle between create and verify
    step() called after finish() — workflow is sealedCalled wf.step(...) after wf.finish()Move all step() before finish()
    step() resolved after finish() — workflow was sealed mid-stepAn async step() was pending when finish() ranawait every step() before finish()
    TypeError: Cannot assign to read only propertyTried to mutate the deep-frozen bundleTreat the bundle as immutable; build a new object
    ProjectBundleRegistrationErrorNode rejected the bundleCheck err.statusCode, err.details; usually wrong API key or node URL

    10. Public API surface

    The only symbols you should use:

    import {
      // Core certification
      certifyDecision,
      wrapTool,
      startWorkflow,
    
      // Project bundle helpers
      createProjectSession,
      exportProjectBundle,
      importProjectBundle,
    
      // Verification (re-exported from @nexart/ai-execution)
      verifyAiCerBundleDetailed,
      verifyProjectBundleDetailed,
      ReasonCode,
    
      // Context helpers
      getContextInfo,
      computeContextHash,
      summarizeContext,
      buildContextInfo,
    
      // Errors
      ProjectBundleRegistrationError,
    
      // Version constant
      AGENT_KIT_VERSION,
    } from '@nexart/agent-kit';
    
    import { verifyProjectBundle } from '@nexart/ai-execution';

    If you reach for any symbol not in this list, you are inventing API. Stop and re-read this document.

    11. Final checklist before declaring done

    • Both packages appear in package.json dependencies
    • One file imports from @nexart/agent-kit
    • That file calls one of: certifyDecision, wrapTool, startWorkflow
    • The same file calls a verification function on the produced bundle
    • You ran the file once and saw VERIFIED (A/B) or no errors (C)
    • You did not modify any returned bundle or projectBundle

    When all six boxes are checked, report success to the user with the bundle hash you observed.

    If you got stuck on a step not covered by the troubleshooting table, the canonical reference is the Agent Kit page.