The .ajutant bundle format
This page describes the on-disk format of an .ajutant bundle: the signed file
produced when you export an assistant and
consumed when you import one. It’s the single source of truth for moving assistants
between environments. If you only want to move an assistant through the UI, the
export/import how-to is all you need. This
reference is for maintainers and integrators who build, validate, or inspect bundles
directly.
The signed envelope
Section titled “The signed envelope”A bundle is a JSON object with a signature and a payload. The signature protects the payload’s integrity; import rejects any bundle whose signature doesn’t verify against a trusted public key.
{ "signature": { "algorithm": "RS256", "signedAt": "2026-08-18T10:00:00.000Z", "signedBy": "platform@ajutant.ai", "publicKeyId": "ajutant-signing-2026", "value": "<base64url RS256 signature>" }, "payload": { "...": "see below" }}| Signature field | Meaning |
|---|---|
algorithm | Always RS256 (RSASSA-PKCS1-v1_5 over SHA-256). |
signedAt | ISO 8601 timestamp the payload was signed. |
signedBy | Identifier (email or system name) of the signer. |
publicKeyId | Which public key to verify against, see Signing keys. |
value | The base64url-encoded signature. |
Two on-disk shapes
Section titled “Two on-disk shapes”The signature is computed over the base64url encoding of the payload’s JSON. Because of that, a bundle can be written in either of two equivalent shapes, and import accepts both:
- Inline:
{ signature, payload }, with the payload as a normal JSON object. This is the shape the JSON Schema validates. - Compact (JWT-style):
{ signature, payloadBase64 }, with the payload carried as a single base64url string. Import decodespayloadBase64back to the payload before validating it.
Verification always checks the signature against the base64url payload, so a bundle that was re-serialised (for example, pretty-printed) still verifies as long as the payload’s content is unchanged.
The payload
Section titled “The payload”Every payload carries provenance plus exactly one of three bundle bodies, chosen by
exportType.
{ "schemaVersion": "1.2.0", "exportType": "single", "exportedAt": "2026-08-18T10:00:00.000Z", "exportedBy": { "email": "admin@example.com", "name": "Admin User" }, "source": { "tenantName": "acme-staging", "platformVersion": "0.4.60" }, "assistant": { "...": "an AssistantExport" }}| Payload field | Required | Meaning |
|---|---|---|
schemaVersion | ✓ | Bundle format version, see Versioning. |
exportType | ✓ | single, batch, or module. |
exportedAt | ✓ | ISO 8601 timestamp of the export. |
exportedBy | ✓ | { email, name } of the exporting user. |
source | ✓ | { tenantName, platformVersion }, where the export came from. |
assistant | when single | One AssistantExport. |
assistants | when batch | An array of AssistantExport. |
module | when module | A ModuleExport (name, description, its assistants, and any shared knowledge base / collections). |
What an assistant bundle contains
Section titled “What an assistant bundle contains”An AssistantExport groups everything needed to reconstruct one assistant:
assistant: the assistant configuration:name,description,systemPrompt, model settings (modelName,modelType,temperature,maxTokens, reasoning options),capabilities(RAG, web search, structured output, function calling, image generation, …),guardrails(content filtering, PII detection, blocked topics), routingkeywords,suggestedPrompts, and portability fields (requiredCategory,preferredModel,testedModels,requiredCapabilities).endpoints: the assistant’s API endpoints:name,slug,userPromptTemplate(a Handlebars template), optionalparametersSchema/outputSchema,allowedMethods,fileUploadConfig, per-endpointconfiguration(timeout, token/temperature overrides, citations), andinputSources, the input-source bindings (e.g. a liveurlfetch that grounds the prompt) added in schema 1.2.0.knowledgeBaseItems: knowledge base entries as references, not content (see below).collections: the collection names the assistant belongs to.promptSections: optional structured prompt-builder sections (context,persona,instructions, …) with order and enabled state.guardConfigs: optional per-assistant guard-chain overrides (e.g. Presidio PII thresholds and actions).
What does not travel
Section titled “What does not travel”- API keys and connection credentials are never exported. Each environment keeps its own, so you mint endpoint keys and bind connections again after import. (See Getting a key.)
- Knowledge base document content does not travel. A
knowledgeBaseItemsentry of typedocumentcarries only a reference (filename, a SHA-256contentHash, andfileSizeBytes), not the file’s bytes. Typeurlentries carry theaddressand arefreshSchedule. On import the assistant is wired up with these references, but the actual documents are not re-embedded and won’t ground answers until you supply and process them in the target environment. Don’t expect an imported assistant to arrive with a populated, grounded knowledge base. - Environment-specific bindings (concrete model deployments, resource names, and other per-tenant infrastructure) do not travel. Portability is by tier instead (next).
Model portability by tier
Section titled “Model portability by tier”A bundle records a model tier (requiredCategory: economy, value, performance,
or frontier) rather than pinning a concrete deployment. On import, the target
environment’s category map resolves the tier to one of its own approved deployments, so
the same bundle runs on different environments without edits. modelName and
preferredModel are also carried, but they’re advisory, used for “running on X, tested on
Y” hints, not for resolution. A null requiredCategory is allowed and resolves as
value at runtime.
Versioning and migration
Section titled “Versioning and migration”The format uses semantic versioning in schemaVersion. The current version is
1.2.0, and the accepted set is enumerated in the schema (1.1.0, 1.2.0). Import
validates a bundle against the schema for the version it declares, then applies migrations
as needed:
- Same version: accepted as-is.
- Older version: migrated forward through a registry of sequential steps
(
1.0.0 → 1.1.0 → 1.2.0) before validation. For example,1.1.0 → 1.2.0is a pure version stamp because the addedinputSourcesfield is optional. - Newer minor/patch, same major: accepted (forward-compatible); fields the platform doesn’t recognise are ignored.
- Newer major: rejected with a “please upgrade the platform” message.
Because minor bumps are additive and backward-compatible, older bundles keep validating:
1.2.0 added the optional endpoint inputSources field, and 1.1.0 bundles remain valid.
Authoring and validating a bundle
Section titled “Authoring and validating a bundle”The signing CLI generates a key pair, signs an unsigned payload JSON into a .ajutant
file, and validates an existing bundle against the schema:
# 1. Generate an RSA key pair (private stays secret; register the public key).npx tsx scripts/sign-export.ts --generate-keys --output-dir ~/.ajutant-keys/
# 2. Sign an unsigned payload into a bundle.npx tsx scripts/sign-export.ts \ --input my-assistant.json \ --key ~/.ajutant-keys/private.pem \ --output my-assistant.ajutant
# 3. Validate a bundle against the schema (no key needed).npx tsx scripts/sign-export.ts --input my-assistant.ajutant --validateThe public key must be registered in the target environment for import to trust the bundle, see Signing keys.
Reference pointers
Section titled “Reference pointers”- Authoritative schema:
lib/export-import/export-schema-v1.2.0.json - Format code:
lib/export-import/{schema,types,migration,validator,signature}.ts - Signing CLI:
scripts/sign-export.ts - Related: Exporting and importing assistants, Signing keys