FRAME supports composite execution: executing multiple intents atomically as a single transaction with rollback on failure.
File: ui/runtime/engine.js — executeCompositeIntent(steps)
Composite execution enables:
- Atomic transactions — All steps succeed or all fail
- Rollback on failure — State restored if any step fails
- Dependency ordering — Steps execute in dependency order
- Multi-step operations — Complex workflows as single transaction
Example: wallet.send might require:
- Check balance
- Validate recipient
- Send payment
- Update ledger
All steps execute atomically.
File: ui/system/agentPlanner.js — planExecution(intent, capabilities, context)
The agent planner builds execution graphs:
{
executionGraph: [
{ id: 'balance', canonical: 'finance.balance', args: {} },
{ id: 'tx', canonical: 'finance.transactions', dependsOn: ['balance'], args: { target, amount } }
]
}Step fields:
id— Unique step identifiercanonical— Canonical capability namedependsOn— Array of step IDs this step depends onargs— Arguments for this stepparallel— Optional: run in parallel with same-level steps
File: ui/system/agentPlanner.js — topoSort(graph)
Process:
- Build dependency graph
- Detect cycles
- Topological sort
- Return execution order
Example:
[
{ id: 'a', dependsOn: [] },
{ id: 'b', dependsOn: ['a'] },
{ id: 'c', dependsOn: ['a'] },
{ id: 'd', dependsOn: ['b', 'c'] }
]
// Execution order: ['a', 'b', 'c', 'd']File: ui/runtime/engine.js — executeCompositeIntent(steps)
if (!Array.isArray(steps) || steps.length < 2) {
return { type: 'error', message: 'Composite execution requires at least 2 steps.' };
}
if (_mode === 'safe') {
return { type: 'error', message: 'Composite execution is not allowed in safe mode.' };
}
if (_mode === 'replay') {
return { type: 'error', message: 'Composite execution is not allowed in replay mode.' };
}var snapshotStorage = await gatherStorageSnapshot();
var snapshotStateRoot = await computeStateRoot(identity);
var snapshotChain = await FRAME_STORAGE.read('chain:' + identity);Snapshots capture:
- Storage state
- State root
- Receipt chain
var results = [];
var failed = false;
var failureResult = null;
for (var i = 0; i < steps.length; i++) {
var step = steps[i];
// Build step intent
var stepIntent = {
action: step.canonical,
payload: step.args,
timestamp: normalizeTimestamp(Date.now())
};
// Inject dependency results
if (step.dependsOn && step.dependsOn.length > 0) {
var deps = {};
for (var d = 0; d < step.dependsOn.length; d++) {
deps[step.dependsOn[d]] = results[step.dependsOn[d]];
}
stepIntent.payload.$deps = deps;
if (step.dependsOn.length === 1) {
stepIntent.payload.$prev = results[step.dependsOn[0]];
}
}
// Execute step
var result = await handleStructuredIntent(stepIntent);
if (result.type === 'error') {
failed = true;
failureResult = result;
break;
}
results[step.id] = result;
}if (failed) {
// Restore storage
await restoreStorageSnapshot(snapshotStorage);
// Restore receipt chain
await FRAME_STORAGE.write('chain:' + identity, snapshotChain);
return failureResult;
}If all steps succeed:
var receipt = await buildReceipt({
intent: { action: 'composite', payload: { steps } },
identity: identity,
dappId: 'system',
capabilitiesDeclared: allCapabilities,
capabilitiesUsed: allCapabilitiesUsed,
previousStateRoot: snapshotStateRoot,
nextStateRoot: await computeStateRoot(identity),
previousReceiptHash: lastReceiptHash,
result: { success: true, results: results }
});
await appendReceipt(identity, receipt);Steps can access results from dependencies:
$deps — Map of all dependency results:
{
balance: { balance: 100 },
validation: { valid: true }
}$prev — Single dependency result (convenience):
{ balance: 100 }Example:
{
id: 'tx',
canonical: 'finance.transactions',
dependsOn: ['balance', 'validation'],
args: {
target: 'Alice',
amount: 10,
$deps: {
balance: { balance: 100 },
validation: { valid: true }
},
$prev: { balance: 100 } // First dependency
}
}File: ui/system/agentPlanner.js — executeGraph(engine, plan, options)
Options:
{
parallel: true // Run same-level steps in parallel
}Process:
- Compute dependency depth for each step
- Group steps by depth level
- Execute same-level steps in parallel
- Wait for all steps to complete before next level
Example:
Level 0: ['a']
Level 1: ['b', 'c'] // Parallel
Level 2: ['d']On step failure:
- Stop execution — No further steps execute
- Rollback state — Restore storage snapshot
- Restore chain — Restore receipt chain
- Return error — Return failure result
Error result:
{
type: 'error',
message: 'Step failed',
step: 'tx',
error: { ... }
}File: ui/system/agentPlanner.js — executeGraph(engine, plan, options)
Options:
{
retries: 3, // Retry up to 3 times
retryDelay: 1000 // 1 second delay between retries
}Process:
- Execute step
- If failure and retries remaining:
- Wait
retryDelay - Retry step
- Wait
- If all retries exhausted:
- Try next provider (if available)
- Or fail
If a step fails after retries:
- Get providers —
getProviders(canonical) - Try next provider — Execute with different dApp
- Continue — If successful, continue execution
Example:
// Step fails with wallet dApp
// Try payments dApp
// If successful, continue[
{ id: 'balance', canonical: 'finance.balance', args: {} },
{ id: 'send', canonical: 'finance.transactions', dependsOn: ['balance'], args: { target: 'Alice', amount: 10 } }
][
{ id: 'validate', canonical: 'contacts.validate', args: { recipient: 'Alice' } },
{ id: 'balance', canonical: 'finance.balance', args: {} },
{ id: 'send', canonical: 'finance.transactions', dependsOn: ['validate', 'balance'], args: { target: 'Alice', amount: 10 } },
{ id: 'notify', canonical: 'messages.send', dependsOn: ['send'], args: { recipient: 'Alice', message: 'Payment sent' } }
]File: ui/system/conversationEngine.js
Process:
- Resolve intent —
resolveIntent(userText) - Plan execution —
agentPlanner.planExecution(intent, capabilities) - Execute graph —
agentPlanner.executeGraph(FRAME, plan) - Return result — Use result for response
Example:
var intent = await resolveIntent("Send 10 frame to Alice");
var plan = await agentPlanner.planExecution(intent, capabilities);
if (plan.executionGraph.length > 1) {
var result = await agentPlanner.executeGraph(FRAME, plan);
return result;
} else {
var result = await executeIntent(intent.action, intent.payload);
return result;
}FRAME composite execution enables:
- Atomic transactions — All steps succeed or all fail
- Rollback on failure — State restored if any step fails
- Dependency ordering — Steps execute in dependency order
- Multi-step operations — Complex workflows as single transaction
Composite execution guarantees:
- Atomicity (all or nothing)
- Consistency (state always valid)
- Isolation (no partial state)
- Durability (receipt generated on success)
- Runtime Pipeline - Execution flow
- Agent System - Agent planner
- Kernel Runtime - Kernel coordination
- Receipt Chain - Receipt generation