Returning Pinned Data
Pinned data is a separate data payload that persists permanently across executions, unlike OutputData which is scoped to the current execution. It appears in the Node Inspector's "Pinned" tab and survives even after the execution is purged from ExecutionMemory.
What Pinned Data Is For
Use pinned data when you want important outputs to be visible in the observer panel long after the execution completes — for example: the last API response body from an HTTP node, the AI agent's final answer, an extracted data set, or a form submission snapshot. Pinned data is stored in a persistent store (not just in-memory execution state).
Returning Pinned Data
NodeExecutionResult has an OutputBranches field that accepts an INodeResultBranches implementation. The built-in NodeResultBranches class carries both main output and pinned output:
return new NodeExecutionResult
{
IsSuccess = true,
OutputPortKey = "main",
OutputData = new Dictionary<string, object>
{
{ "statusCode", 200 },
{ "body", body }
},
// Pinned data — persists beyond the execution lifetime
OutputBranches = new NodeResultBranches
{
PinnedData = new Dictionary<string, object>
{
{ "lastResponseBody", body },
{ "lastStatusCode", 200 },
{ "lastRequestAt", DateTime.UtcNow }
}
}
};
Pinned vs Output Data
| Property | OutputData | PinnedData |
|---|---|---|
| Scope | Current execution only | Persists permanently |
| Access in designer | Node Inspector > Output tab | Node Inspector > Pinned tab |
| Access in expressions | $output.{nodeId}.field | Not available in expressions |
| Storage | ExecutionMemory (in-process) | Persistent store (DB or blob) |
| Purged with execution | Yes | No |
| Typical use | Data flow between nodes | Audit record, last-known-good response |
Null Pinned Data
If you do not set OutputBranches (or set PinnedData to null/empty), no pinned data is written. This is the default for most nodes. Only write pinned data when it adds meaningful value for operators or developers inspecting the workflow.
// Most executors — no pinned data needed
return new NodeExecutionResult
{
IsSuccess = true,
OutputPortKey = "main",
OutputData = new Dictionary<string, object> { { "ok", true } }
// OutputBranches = null (omitted) — no pinned data
};