Context Chains Enhancements
These context chain enhancements are planned for a future release. Basic context chains are fully implemented—see the Context Chain Design documentation for current capabilities.
Context chains link related contexts together in parent-child relationships, enabling workflows like multi-step tasks, recursive agents, and conversation threading. Current features include addChild(), getChain(), status tracking, and participant management.
Current Capabilities
Context chains already support:
- Parent-child relationships with
addChild() - Chain traversal with
getChain() - Status tracking (active, completed, cancelled, blocked)
- Participant management
- Custom data fields
- Conversation linking (ACID)
Planned Enhancements
1. Status Transition Validation
Enforce valid status transitions to prevent invalid state changes.
Current Behavior:
// Any status transition is accepted
await cortex.contexts.update(spaceId, contextId, {
status: "completed",
});
// Even invalid transitions work
await cortex.contexts.update(spaceId, contextId, {
status: "active", // From completed → active (invalid!)
});
Planned Behavior:
// Valid transitions enforced
await cortex.contexts.update(spaceId, contextId, {
status: "completed", // active → completed ✓
});
// Invalid transitions throw errors
await cortex.contexts.update(spaceId, contextId, {
status: "active", // completed → active ✗
});
// Error: Invalid status transition (completed → active)
Valid Transitions:
active→completed|cancelled|blockedblocked→active|cancelledcompleted→ (terminal state, no transitions)cancelled→ (terminal state, no transitions)
2. Auto-Complete Parent Contexts
Automatically complete parent contexts when all children are completed.
Current Behavior:
// Manual completion required
const parent = await cortex.contexts.get(spaceId, parentId);
const children = await cortex.contexts.getChain(spaceId, parentId);
const allComplete = children.every(c => c.status === "completed");
if (allComplete) {
await cortex.contexts.update(spaceId, parentId, { status: "completed" });
}
Planned Behavior:
// Automatic completion when all children complete
await cortex.contexts.update(spaceId, childId, {
status: "completed", // Last child
});
// Parent automatically marked as "completed"
Configuration:
await cortex.contexts.create(spaceId, {
purpose: "Multi-step workflow",
autoComplete: true, // Enable automatic completion
});
3. Automatic Inherited Data Merging
Children automatically access parent data without manual traversal.
Current Behavior:
// Manual traversal required to merge data
const chain = await cortex.contexts.getChain(spaceId, contextId);
const mergedData = {};
for (const ctx of chain.reverse()) {
Object.assign(mergedData, ctx.data);
}
console.log(mergedData.apiKey); // From ancestor
Planned Behavior:
// Automatic data inheritance
const context = await cortex.contexts.get(spaceId, contextId, {
inheritData: true, // Merge data from ancestors
});
console.log(context.data.apiKey); // Inherited from parent
Inheritance Rules:
- Child data overrides parent data
- Nearest ancestor takes precedence
- Original
datafield preserved indata._original
Example:
// Parent context
await cortex.contexts.create(spaceId, {
purpose: "API Integration",
data: { apiKey: "sk_...", timeout: 5000 },
});
// Child context (overrides timeout)
const child = await cortex.contexts.addChild(spaceId, parentId, {
purpose: "Fetch User Data",
data: { timeout: 10000, endpoint: "/users" },
});
// Automatic merge
const childData = await cortex.contexts.get(spaceId, child.id, { inheritData: true });
console.log(childData.data);
// {
// apiKey: "sk_...", // Inherited
// timeout: 10000, // Overridden
// endpoint: "/users", // Child-specific
// }
4. Chain-Wide Participant Propagation
Add a participant to a context and all ancestors automatically.
Current Behavior:
// Manual propagation required
const chain = await cortex.contexts.getChain(spaceId, contextId);
for (const ctx of chain) {
await cortex.contexts.addParticipant(spaceId, ctx.id, "user-123");
}
Planned Behavior:
// Automatic propagation to ancestors
await cortex.contexts.addParticipant(spaceId, contextId, "user-123", {
propagateToAncestors: true, // Add to entire chain
});
Use Case: When a user joins a nested context (e.g., a sub-task), they should automatically have access to parent contexts (e.g., the main task).
5. Depth Limit Enforcement
Prevent excessively deep context chains that could cause performance issues.
Current Behavior:
// No depth limit enforced
let currentId = rootId;
for (let i = 0; i < 100; i++) {
const child = await cortex.contexts.addChild(spaceId, currentId, {
purpose: `Level ${i}`,
});
currentId = child.id;
}
// Works, but could cause performance issues
Planned Behavior:
// Depth limit enforced
const child = await cortex.contexts.addChild(spaceId, currentId, {
purpose: "Too deep!",
});
// Error: Maximum context depth exceeded (limit: 10)
Configuration:
const cortex = new Cortex({
convexUrl: process.env.CONVEX_URL!,
contextChainDepthLimit: 15, // Default: 10
});
6. GDPR Cascade Deletion
Delete user data from context chains when a user is deleted (Cloud Mode).
Planned Behavior:
// Cloud Mode: Cascade delete user-specific contexts
await cortex.users.delete("user-123", { cascade: true });
Deletion Rules:
- Contexts with explicit
userIdfield are deleted - Contexts with
userIdinparticipantsare NOT deleted (shared contexts) - Children without explicit
userIdare preserved (workflow metadata)
Example:
// User-specific context (deleted)
await cortex.contexts.create(spaceId, {
purpose: "User's personal task",
userId: "user-123",
});
// Shared context (preserved)
await cortex.contexts.create(spaceId, {
purpose: "Team workflow",
participants: ["user-123", "user-456"],
});
Implementation Priority
These enhancements will be implemented in phases:
High Priority:
- Status transition validation - Prevents invalid state changes
- Auto-complete parent contexts - Reduces manual workflow management
- Depth limit enforcement - Prevents performance issues
Medium Priority: 4. Automatic inherited data merging - Improves developer experience 5. Chain-wide participant propagation - Simplifies access control
Low Priority (Cloud Mode): 6. GDPR cascade deletion - Enterprise compliance feature
Migration Path
All enhancements are opt-in and backward compatible. Existing code will continue to work unchanged.
Example:
// Existing code (works unchanged)
await cortex.contexts.update(spaceId, contextId, {
status: "completed",
});
// New features (opt-in)
await cortex.contexts.update(spaceId, contextId, {
status: "completed",
validateTransition: true, // Opt-in to validation
});
Workarounds (Current Implementation)
Until these features are available, use these patterns:
Manual Status Validation
function validateTransition(from: ContextStatus, to: ContextStatus) {
const valid = {
active: ["completed", "cancelled", "blocked"],
blocked: ["active", "cancelled"],
completed: [],
cancelled: [],
};
if (!valid[from].includes(to)) {
throw new Error(`Invalid transition: ${from} → ${to}`);
}
}
// Use before updates
validateTransition(context.status, "completed");
await cortex.contexts.update(spaceId, contextId, { status: "completed" });
Manual Auto-Completion
async function checkAndCompleteParent(spaceId: string, parentId: string) {
const chain = await cortex.contexts.getChain(spaceId, parentId);
const children = chain.filter(c => c.parentContextId === parentId);
const allComplete = children.every(c => c.status === "completed");
if (allComplete) {
await cortex.contexts.update(spaceId, parentId, { status: "completed" });
}
}
Manual Data Inheritance
async function getWithInheritedData(spaceId: string, contextId: string) {
const chain = await cortex.contexts.getChain(spaceId, contextId);
const mergedData = {};
for (const ctx of chain.reverse()) {
Object.assign(mergedData, ctx.data);
}
return mergedData;
}