Learned nodes let an MCP-connected agent create a new permanent Blacknode node
type when the current catalog does not contain the capability it needs. The node
is stored as plain Python under nodes/learned/<Name>/, appears in the editor
palette under Learned or a chosen category, and can be reused in later
workflows.
This feature is opt-in. On first use, create_node_type refuses the request
unless BLACKNODE_LEARNED_NODES_CONSENT=1 is set. After opt-in, consent is
persisted at ~/.blacknode/learned-nodes-consent.json; delete that file to
revoke consent.
Agents call the MCP tool:
create_node_type(
name="ParseRSS",
description="Parse RSS XML text into a list of entries.",
inputs=["feed:Text"],
outputs=["entries:List"],
code="def run(feed): ...",
requires_network=False,
category="RAG",
)
The tool validates:
- PascalCase node name, 3-40 characters
- unique node type name
- port declarations in
name:Typeformat - allowed port types:
Text,Int,Float,Bool,List,Dict,Any - palette category names, defaulting to
Learnedwhen omitted - AST-only static check for dangerous imports and names
- presence of
def run(...) - exact match between
runparameters and input port names - description length of 10-200 characters
The generated files are:
nodes/learned/<Name>/
node.py
manifest.json
Pass category to create_node_type when the learned node belongs in a real
palette group such as RAG, Search, Vision, Parsing, or Research.
Existing learned nodes without a category continue to load under Learned.
When a learned node is stable enough to run in the host process, promote it:
promote_learned_node(
name="ParseRSS",
target="custom-nodes",
category="RAG",
)
Promotion writes a reviewed @node module to custom-nodes/ or
community-nodes/, registers it, and removes the learned-node source by
default. Use keep_learned=True to copy the file without migrating the live
node type. The editor's Learned Nodes tab exposes the default
custom-nodes/ promotion path.
Built-in @node functions execute in the host Python process. Learned nodes do
not. They are registered in the same node registry, but their implementation is
a wrapper that delegates to blacknode.sandbox.docker_runner.run_in_container.
That wrapper reads node.py as text and sends it to a fresh Docker container.
The user code is imported and executed only inside the container runner.
When create_node_type succeeds, the MCP tool notifies the editor backend. The
backend broadcasts a Server-Sent Event, and the frontend refreshes:
/learned-nodes/node-defs- the relevant palette category
- the read-only Learned Nodes sidebar tab
Newly added learned nodes pulse briefly in the palette so the user can see the new capability appear without restarting the editor.
The sidebar is intentionally read-only. Edit learned nodes in files on disk, not through the UI.
Learned nodes require Docker Desktop or a compatible Docker daemon.
blacknode doctorblacknode doctor reports Docker reachability, whether
blacknode-sandbox:latest is present, how many learned nodes are loaded, and the
last sandbox run duration recorded in the current process.
Run the camera-demo dry run:
$env:BLACKNODE_LEARNED_NODES_CONSENT="1"
python scripts\demo_dry_run.pyThe script starts the editor backend when needed, creates a temporary learned
RSS parser through MCP, verifies it appears in /learned-nodes, runs a workflow
through the Docker sandbox, and deletes the node.
Run the deterministic category/plumbing demo without Docker:
python scripts\complex_learned_demo.py --mock-sandboxIt uses built-in fixture text and deterministic learned-node source. This is a test/demo of learned-node creation, category placement, graph validation, and editor opening. It is not a real-world data demo.
Run the real-world local repository demo against an actual folder:
$env:BLACKNODE_LEARNED_NODES_CONSENT="1"
python scripts\real_repo_learned_demo.py --target F:\PROJECTS\NVDIA\BlacknodeThat script samples real readable source/docs files from --target, creates
learned nodes in Repo, Audit, and Research, builds a 14-node workflow,
runs the audit, and prints findings derived from those files.
For a live editor demo, start Blacknode first:
.\start.batThen run the Docker-backed demo from another terminal:
$env:BLACKNODE_LEARNED_NODES_CONSENT="1"
python scripts\real_repo_learned_demo.py --target F:\PROJECTS\NVDIA\Blacknode --open-editorThe script opens Real Repo Audit - Blacknode as a new editor tab and keeps the three real repo demo learned nodes available so the palette categories remain live. After the demo, clean them up:
python scripts\real_repo_learned_demo.py --cleanup-demo-nodesFor the full command-by-command validation path, including Docker integration tests, MCP smoke checks, consent-gate verification, and the visible editor pulse test, see Learned Nodes Test Plan.