Documentation Index
Fetch the complete documentation index at: https://mintlify.com/AllianceBioversityCIAT/alliance-risk-analysis-tool/llms.txt
Use this file to discover all available pages before exploring further.
The CGIAR Risk Intelligence Tool implements comprehensive version control for AI prompts, allowing full audit trails, rollback capabilities, and change tracking.
Version Strategy
Current Version Pattern
Prompts follow a snapshot-on-update versioning strategy:
- The
prompts table stores the latest version only (no JOINs needed for reads)
- On every update, the current state is snapshotted to
prompt_versions table
- Version number is auto-incremented on each update
- Version 1 is created automatically when the prompt is first created
Database Schema
model Prompt {
id String @id @default(uuid())
name String
version Int @default(1) // Current version
// ... other fields
versions PromptVersion[] // Historical snapshots
changes PromptChange[] // Audit trail
}
model PromptVersion {
id String @id @default(uuid())
promptId String
version Int
// Snapshot of all prompt fields at this version
name String
section AgentSection
systemPrompt String
userPromptTemplate String
// ... all other prompt fields
createdAt DateTime @default(now())
@@unique([promptId, version])
}
model PromptChange {
id String @id @default(uuid())
promptId String
version Int
changeType PromptChangeType // CREATE, UPDATE, DELETE, ACTIVATE, DEACTIVATE
changes Json // { field: { old: value, new: value } }
comment String?
authorId String
createdAt DateTime @default(now())
}
Endpoints
Get Prompt (Current or Historical Version)
GET /api/admin/prompts/:id
Retrieve the current version or a specific historical version.
Query Parameters
Historical version number to retrieve (omit for current version)Example: 2
Example: Get Current Version
curl -X GET https://api.example.com/api/admin/prompts/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Example: Get Historical Version
curl -X GET "https://api.example.com/api/admin/prompts/550e8400-e29b-41d4-a716-446655440000?version=2" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Response
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Gap Detection — Market Risk v2",
"version": 2,
"systemPrompt": "You are an expert agricultural risk analyst...",
// ... all prompt fields
"createdAt": "2026-02-20T10:00:00.000Z",
"updatedAt": "2026-03-01T14:30:00.000Z"
}
}
Get Change History
GET /api/admin/prompts/:id/history
Returns the full version history of a prompt, including diffs between versions, who made each change, and when.
Response Fields
Array of change recordsVersion number this change created
Type of changeValues: CREATE, UPDATE, DELETE, ACTIVATE, DEACTIVATE
Field-level diff objectFormat: { field: { old: value, new: value } }Example:{
"systemPrompt": {
"old": "You are an expert risk analyst.",
"new": "You are an expert agricultural risk analyst with 15+ years of experience."
},
"tags": {
"old": ["v2", "production"],
"new": ["v3", "production", "reviewed"]
}
}
Optional comment explaining the change
User who made the change
id (string): User UUID
email (string): User email
ISO 8601 timestamp of the change
Example Request
curl -X GET https://api.example.com/api/admin/prompts/550e8400-e29b-41d4-a716-446655440000/history \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Example Response
{
"data": [
{
"id": "change-uuid-3",
"version": 3,
"changeType": "UPDATE",
"changes": {
"systemPrompt": {
"old": "You are an expert risk analyst.",
"new": "You are an expert agricultural risk analyst with 15+ years of experience."
},
"tags": {
"old": ["v2", "production"],
"new": ["v3", "production", "reviewed"]
}
},
"comment": "Enhanced system prompt with experience level",
"author": {
"id": "user-uuid-456",
"email": "admin@example.com"
},
"createdAt": "2026-03-04T14:30:00.000Z"
},
{
"id": "change-uuid-2",
"version": 2,
"changeType": "UPDATE",
"changes": {
"name": {
"old": "Gap Detection — Market Risk v1",
"new": "Gap Detection — Market Risk v2"
},
"userPromptTemplate": {
"old": "Identify gaps for: {{categories}}",
"new": "Given the following business plan section:\n\n{{document_excerpt}}\n\nIdentify gaps in risk coverage for the following categories: {{categories}}"
}
},
"comment": null,
"author": {
"id": "user-uuid-123",
"email": "editor@example.com"
},
"createdAt": "2026-03-01T10:00:00.000Z"
},
{
"id": "change-uuid-1",
"version": 1,
"changeType": "CREATE",
"changes": {},
"comment": "Initial creation",
"author": {
"id": "user-uuid-123",
"email": "editor@example.com"
},
"createdAt": "2026-02-20T10:00:00.000Z"
}
]
}
Version Lifecycle
1. Creation (v1)
When a prompt is created via POST /api/admin/prompts/create:
// Prisma transaction:
1. Create prompt record with version: 1
2. Create initial version snapshot in prompt_versions
3. Create change record with changeType: CREATE
2. Update (v2, v3, …)
When a prompt is updated via PUT /api/admin/prompts/:id/update:
// Prisma transaction:
1. Read current prompt state
2. Snapshot current state to prompt_versions (preserves previous version)
3. Compute field-level diffs (old vs new)
4. Increment version number
5. Update prompt record with new values
6. Create change record with changeType: UPDATE and diffs
3. Toggle Active State
When toggling via POST /api/admin/prompts/:id/toggle-active:
// Prisma transaction:
1. Snapshot current state to prompt_versions
2. Increment version
3. Flip isActive flag
4. Create change record with changeType: ACTIVATE or DEACTIVATE
4. Deletion
When deleting via DELETE /api/admin/prompts/:id:
// Option A: Delete entire prompt
1. Create change record with changeType: DELETE
2. Delete prompt (cascades to versions, comments, changes)
// Option B: Delete specific version
1. Delete version snapshot from prompt_versions
2. Create change record documenting version deletion
Diff Computation
The changes field in PromptChange records contains field-level diffs:
type ChangesDiff = {
[field: string]: {
old: any;
new: any;
}
};
// Example:
{
"systemPrompt": {
"old": "Original text...",
"new": "Updated text..."
},
"tags": {
"old": ["v1"],
"new": ["v2", "reviewed"]
},
"isActive": {
"old": false,
"new": true
}
}
Only changed fields are included in the diff.
Rollback Pattern
To rollback to a previous version:
- Fetch the historical version:
GET /api/admin/prompts/:id?version=2
- Extract all fields from the response
- Update the prompt with those values:
PUT /api/admin/prompts/:id/update
// Fetch version 2
const { data: v2 } = await fetch('/api/admin/prompts/550e8400-e29b-41d4-a716-446655440000?version=2');
// Rollback by updating with v2 values
await fetch('/api/admin/prompts/550e8400-e29b-41d4-a716-446655440000/update', {
method: 'PUT',
body: JSON.stringify({
name: v2.name,
systemPrompt: v2.systemPrompt,
userPromptTemplate: v2.userPromptTemplate,
// ... all other fields
})
});
// This creates version 4 (a copy of version 2)
Version Retention
All versions are retained indefinitely unless:
- The entire prompt is deleted (CASCADE deletes all versions)
- A specific version is explicitly deleted:
DELETE /api/admin/prompts/:id?version=2
Recommendation: Implement a cleanup policy for old versions (e.g., keep last 10 versions per prompt).
Conflict Detection
The update endpoint implements optimistic locking to detect concurrent modifications:
// Pseudo-code in PromptsService.update():
const currentPrompt = await prisma.prompt.findUnique({ where: { id } });
if (currentPrompt.updatedAt > clientLastReadTimestamp) {
throw new ConflictException('Prompt was modified by another user');
}
// Proceed with update...
This prevents lost updates in multi-user scenarios.
Best Practices
1. Version Naming
Include version numbers in the prompt name for easy identification:
✅ "Gap Detection — Market Risk v3"
❌ "Gap Detection — Market Risk (updated)"
Use the comment field in change records to explain significant updates:
await promptsService.update(id, dto, userId, {
comment: 'Refined output format based on user feedback'
});
3. Version Review
Before activating a new version, review the change history:
# Get change history
curl /api/admin/prompts/:id/history
# Compare current vs previous version
curl /api/admin/prompts/:id?version=2 # Old
curl /api/admin/prompts/:id # New
# If satisfied, activate
curl -X POST /api/admin/prompts/:id/toggle-active
4. Version Cleanup
Periodically delete old version snapshots to reduce database size:
# Delete version 1 (keep versions 2-5)
curl -X DELETE "/api/admin/prompts/:id?version=1"
Source Code
- Versioning logic:
packages/api/src/prompts/prompts.service.ts
- Change history service:
packages/api/src/prompts/change-history.service.ts
- Get prompt endpoint:
packages/api/src/prompts/prompts.controller.ts:141
- Get history endpoint:
packages/api/src/prompts/prompts.controller.ts:244