# Agent-Kit Setup Runbook for AI Coding Agents

URL: https://docs.nexart.io/docs/agent-kit-instructions

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:

- Click the Copy for LLM button above and paste it into your assistant as the first message of an integration task.
- Point your assistant at the raw markdown: "Follow the instructions at https://docs.nexart.io/agent-kit-instructions.md."
- 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):

- `@nexart/agent-kit@^0.5.2` and `@nexart/ai-execution@^0.22.0` are installed.
- At least one call site produces a CER bundle via `certifyDecision`, `wrapTool`, or `startWorkflow`.
- A verification call returns `status: 'VERIFIED'` / `ok: true`.
- 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.

| Pattern | Use when | What you get |
| --- | --- | --- |
| A. certifyDecision | One-off decision, single LLM call, single tool result | One CerAiExecutionBundle |
| B. wrapTool | A tool/function runs many times and every call should be certified | A wrapped function: each invocation produces a bundle |
| C. startWorkflow | Multi-step pipeline where the whole run is one auditable artifact | One 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

| Symptom | Cause | Fix |
| --- | --- | --- |
| ERR_REQUIRE_ESM | Project is CommonJS | Add "type": "module" to package.json OR use await import() from CJS |
| Cannot find module '@nexart/agent-kit' | Not installed | Re-run npm install @nexart/agent-kit @nexart/ai-execution |
| TS: Cannot find type declarations | Wrong moduleResolution | Set "moduleResolution": "NodeNext" in tsconfig.json |
| BUNDLE_TAMPERED or HASH_MISMATCH | Bundle was mutated after creation | Do not modify bundle between create and verify |
| step() called after finish() — workflow is sealed | Called wf.step(...) after wf.finish() | Move all step() before finish() |
| step() resolved after finish() — workflow was sealed mid-step | An async step() was pending when finish() ran | await every step() before finish() |
| TypeError: Cannot assign to read only property | Tried to mutate the deep-frozen bundle | Treat the bundle as immutable; build a new object |
| ProjectBundleRegistrationError | Node rejected the bundle | Check 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.

## Related

- Agent Kit: full API reference
- Quickstart: human walkthrough
- Verification: how CER verification works
- Project Bundles: multi-step workflow concept
