Artifacts leave a tool call on their own port, apart from the model's prose
The rule
- A node that invokes tools surfaces every call's artifacts on a dedicated
tool_artifactsoutput port, as a list of exactly{type, payload, tool_call_id}entries built key by key, so a tool can neither override the realtool_call_idnor smuggle keys of its own through. - That port is not exposed by default.
- The prose fed back to the model is built from a result's
dataalone and never from its artifacts. - Delivery of a run's artifacts must not depend on whether the author exposed the port.
What it means
The prose the model reads back is built from data alone — an artifact
never leaks into it, even as a stray mention of a URL or a name that also
appears in the artifact's payload. The two travel on entirely separate
paths: prose in the tool message, artifacts on tool_artifacts, paired to
the call that produced them by tool_call_id so a node invoking several
tools at once can still tell whose artifact is whose. That port carries the
artifacts whether or not the author exposed it — delivery does not wait on
an exposure decision that governs only what a person sees in an editor.
Example
One tool call returns a result whose data is a short confirmation string
and whose artifact is a link the confirmation never mentions.
{
"data": { "result": "Created node 5 (draft)." },
"artifacts": [{ "type": "link", "payload": { "url": "https://example.com/node/5" } }]
}[{ "type": "link", "payload": { "url": "https://example.com/node/5" }, "tool_call_id": "c1" }]The prose fed back to the model stays "Created node 5 (draft)." — nothing
about the link appears in it.