Project Bundles
Structured, cryptographically linked collections of CERs for multi-step and multi-agent workflows, verified as a single bundle.
Overview
A Project Bundle is a structured collection of Certified Execution Records representing a multi-step workflow. Where a single CER proves one execution, a Project Bundle proves an entire sequence of executions and their relationships.
Why Project Bundles Exist
Single CERs work well for isolated executions. But many real-world systems involve multiple steps:
- An agent that reasons, calls tools, then summarizes
- A pipeline that transforms data across several stages
- A workflow where each step depends on a previous output
Project Bundles give these multi-step processes a single verifiable artifact with one hash.
What a Project Bundle Contains
- stepRegistry: ordered step metadata. Each entry contains a
stepId,sequencenumber,stepLabel, and the step'scertificateHash. - embeddedBundles: the actual CERs, keyed by
stepId. Each embedded bundle is a full CER with its owncertificateHash. - integrity: contains the
projectHashand the algorithm used (sha256-canonical-json). Any change to any embedded CER, step metadata, or ordering produces a differentprojectHash. - Project-level metadata:
projectBundleId,projectTitle, timestamps (startedAt,completedAt), and optional fields likeprojectGoal,projectSummary,appName, andtags.
Canonical Structure
This is the real stored shape of a Project Bundle artifact.
{
"bundleType": "cer.project.bundle.v1",
"projectBundleId": "pb_a1b2c3d4",
"projectTitle": "Contract review pipeline",
"protocolVersion": "1.2.0",
"version": "0.1",
"startedAt": "2026-04-01T10:00:00.000Z",
"completedAt": "2026-04-01T10:02:30.000Z",
"totalSteps": 2,
"stepRegistry": [
{
"stepId": "step_1",
"sequence": 0,
"stepLabel": "Extract clauses",
"certificateHash": "sha256:1111..."
},
{
"stepId": "step_2",
"sequence": 1,
"stepLabel": "Summarize risks",
"certificateHash": "sha256:2222..."
}
],
"embeddedBundles": {
"step_1": {
"bundleType": "cer.ai.execution.v1",
"certificateHash": "sha256:1111...",
"snapshot": { "model": "gpt-4", "inputHash": "sha256:...", "outputHash": "sha256:..." }
},
"step_2": {
"bundleType": "cer.ai.execution.v1",
"certificateHash": "sha256:2222...",
"snapshot": { "model": "gpt-4", "inputHash": "sha256:...", "outputHash": "sha256:..." }
}
},
"integrity": {
"algorithm": "sha256-canonical-json",
"projectHash": "sha256:ab12cd34ef56..."
}
}projectHash
The projectHash is computed using sha256-canonical-json over the canonical content of the Project Bundle. It covers all embedded CERs, the step registry, ordering, and project metadata. Modifying any embedded CER, reordering steps, or changing metadata produces a different hash.
This is different from a certificateHash, which covers a single CER. See Certificate Hash vs Project Hash for a detailed comparison.
Relationship to CERs
A Project Bundle does not replace CERs. Each entry in embeddedBundles contains a full CER that remains independently verifiable by its certificateHash. The Project Bundle adds:
- Step ordering and sequence via
stepRegistry - Step identity and labeling (
stepId,stepLabel) - A single project-level hash covering the entire workflow
- Optional project-level node receipt
Defining Workflow Boundaries
NexArt does not automatically detect workflows. The developer explicitly defines the start and end of a workflow and decides which steps are included.
- A workflow starts when you begin recording CERs for a given process.
- Each meaningful step must create its own CER.
- The developer keeps the workflow context consistent and then collects the relevant CERs into a Project Bundle.
- The workflow ends when you build the Project Bundle from those CERs.
Developers often track a shared workflow or conversation identifier in their own system to group related steps. This is a developer-side concern, not a Project Bundle protocol requirement.
Conceptual builder example
This is a simplified conceptual example showing the general flow. Refer to the AI Execution SDK docs for the exact current helper signatures.
import { certify, createProjectBundle } from "@nexart/ai-execution";
// Step 1: create CER
const cer1 = await certify({
model: "gpt-4",
input: "Extract key clauses from the contract.",
output: "Clause 1: ..., Clause 2: ..."
});
// Step 2: create CER
const cer2 = await certify({
model: "gpt-4",
input: "Summarize risks from: Clause 1: ..., Clause 2: ...",
output: "Risk summary: ..."
});
// Build Project Bundle from collected CERs
// Step metadata (stepId, sequence, stepLabel) is included when building
const projectBundle = await createProjectBundle({
projectTitle: "Contract review pipeline",
steps: [
{ stepId: "step_1", stepLabel: "Extract clauses", cer: cer1 },
{ stepId: "step_2", stepLabel: "Summarize risks", cer: cer2 }
]
});
// projectBundle.integrity.projectHash is the verifiable hashImportant
NexArt guarantees integrity of what is recorded. It does not guarantee that all steps were recorded. Completeness is controlled by the developer.
Best practices
- Record every meaningful step (LLM call, tool call, transformation).
- Keep step ordering explicit using
sequencevalues. - Keep workflow context consistent across steps in your application.
- Build the Project Bundle immediately after execution completes.
- Register it on the node if you want public lookup by
projectHash.
Using agent-kit (recommended)
For linear workflows, @nexart/agent-kit removes manual step tracking. Instead of creating CERs individually and assembling them, you use the workflow helpers:
startWorkflow()begins a new workflow and generates aworkflowIdstep()creates a CER per step. Each step gets its ownexecutionId. TheworkflowIdlinks them together.finish()builds the Project Bundle synchronously
step() records the step name as input and the function return value as output. Implicit closure state is NOT recorded.
import { startWorkflow } from "@nexart/agent-kit";
const workflow = startWorkflow({ projectTitle: "Contract review" });
const clauses = await workflow.step("Extract clauses", async () => {
return await llm.call("Extract key clauses...");
});
const risks = await workflow.step("Summarize risks", async () => {
return await llm.call("Summarize risks from: " + clauses);
});
const bundle = workflow.finish();
// bundle.integrity.projectHash is the verifiable hashLimitation
agent-kit v0.3.0 is designed for linear workflows. For complex DAGs or non-linear execution graphs, use the lower-level SDK helpers (certify + createProjectBundle).
Verification
Project Bundles can be verified in two ways:
- On verify.nexart.io via
/p/:projectHash. The site fetches the Project Bundle from the node-backed trust surface and runs verification independently in the browser. - With the SDK:
verifyProjectBundle()for Node/server environments, orverifyProjectBundleAsync()for browser-safe verification.
Verification checks:
projectHashintegrity- Each embedded CER's
certificateHash - Optional node receipt at the project level
The node is not required for verification. It provides discovery and independent attestation. Integrity is proven by the hashes alone.
See How Verification Works and AI Execution SDK for details.