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.
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.2and@nexart/ai-execution@^0.22.0are installed.- At least one call site produces a CER bundle via
certifyDecision,wrapTool, orstartWorkflow. - 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.jsonMUST have"type": "module". Fallback: dynamicawait import('@nexart/agent-kit')from a CJS file. Do NOT attemptrequire('@nexart/agent-kit'), which throwsERR_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)
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 }.
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)
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 firstfinish(). Callingstep()afterfinish()throws. The workflow is sealed. finish()is deterministic and cached. Calling it twice returns the same bundle reference and the sameprojectHash. Options on the second call are silently ignored. Pass any options on the FIRST call.- The returned
projectBundleis deeply frozen. Do not attempt to mutate it, which throwsTypeError. 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:
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>.tsYou must observe one of:
Status: VERIFIED(Patterns A, B), orProject 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.jsondependencies - 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
bundleorprojectBundle
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