Skip to content

Notes Persistence Pattern

Persist structured data that survives workflow restarts or needs to be shared between workflow steps. Notes provide key-value storage with versioning and tagging.

Use CaseExample
Session recoveryStore intermediate results for resume after interruption
Cross-step data sharingPass complex data between agent-directive nodes
User preferencesRemember choices, settings, configuration
Analysis resultsStore research findings, comparisons, recommendations
Execution historyTrack decisions made during workflow execution
[collect-data] → [write-note] → [other-steps] → [read-note] → [use-data]

Store output from an agent-directive node:

{
"id": "save-analysis",
"type": "write-note",
"key": "purchase-{{executionId}}-01-analysis",
"source": "{{analyze-step-output}}",
"tags": ["purchase-{{executionId}}", "analysis"],
"connections": {
"default": "next-step",
"error": "handle-error"
}
}

Key pattern: {domain}-{{executionId}}-{sequence}-{description}

PartPurposeExample
domainWorkflow areapurchase, research
scopeExecution isolation{{executionId}}
sequenceOrdering01, 02, 03
descriptionContent hintuser-needs, analysis

Write multiple notes from an array:

{
"id": "save-batch",
"type": "write-note",
"source": "{{items-to-save}}",
"batchMode": true,
"connections": { "default": "next" }
}

Source array format:

[
{ "key": "item-001", "value": "content 1", "tags": ["batch"] },
{ "key": "item-002", "value": "content 2", "tags": ["batch"] }
]

Load notes into context variable:

{
"id": "load-data",
"type": "read-note",
"outputVariable": "previousData",
"filter": {
"keyPattern": "purchase-{{executionId}}"
},
"connections": { "default": "use-data" }
}

Single mode for exactly one note:

{
"id": "load-preferences",
"type": "read-note",
"outputVariable": "userPrefs",
"filter": { "tag": "preferences" },
"singleMode": true,
"connections": { "default": "apply-prefs" }
}

Update existing or create new:

{
"id": "update-preferences",
"type": "upsert-note",
"search": {
"tag": "user-prefs",
"keyPattern": "prefs-{{userId}}"
},
"keyTemplate": "prefs-{{userId}}-new",
"value": "{{collected-preferences}}",
"tags": ["user-prefs"],
"outputVariable": "saveResult",
"connections": { "default": "confirm" }
}

Access notes directly in directives:

{
"id": "research-step",
"type": "agent-directive",
"directive": "Research based on user needs.\n\n**User needs:**\n{{note:purchase-{{executionId}}-01-user-needs}}\n\nDetermine main categories.",
"completionCondition": "Research completed"
}

Syntax: {{note:key-name}}

The note content is injected into the directive before the agent receives it.

Within agent-directive nodes, use the notes MCP tool:

// Save a note
notes({
action: "save",
key: "user-preferences",
value: JSON.stringify({ theme: "dark", lang: "en" }),
tags: ["preferences"]
})
// Get a note
notes({
action: "get",
key: "user-preferences"
})
// List notes by tag
notes({
action: "list",
tag: "preferences"
})
// Check quota
notes({
action: "stats"
})

From smart-purchase-assistant.json:

{
"id": "write-note-step-1",
"type": "write-note",
"key": "purchase-{{executionId}}-01-user-needs",
"source": "{{step-1-identify}}",
"tags": ["purchase-{{executionId}}", "smart-purchase"],
"connections": { "default": "step-2-research" }
}

Later in the workflow:

{
"directive": "Create final purchase report.\n\n**User needs:**\n{{note:purchase-{{executionId}}-01-user-needs}}\n\n**Research results:**\n{{note:purchase-{{executionId}}-02-research}}"
}
  • Use execution-specific tag: purchase-{{executionId}}
  • Use category tag: smart-purchase, research-flow
  • Enables efficient filtering and cleanup
{
"id": "write-critical",
"type": "write-note",
"key": "critical-data-{{executionId}}",
"source": "{{results}}",
"connections": {
"default": "continue",
"error": "handle-write-error"
}
}
  • Objects and arrays auto-serialize to JSON
  • Primitive values stored as strings
  • For large objects, consider chunking or artifacts
// Wrong - shared across executions
{ "key": "user-analysis" }
// Right - isolated per execution
{ "key": "user-analysis-{{executionId}}" }

Don’t store loop counters or temporary values in notes. Use expression nodes or context variables instead.

Notes are for structured text data. Use Artifacts for HTML content or large files.