Artifacts are bounded once, at the point they are collected
The rule
- An implementation bounds the artifacts one run may collect and enforces that bound at the single point of collection; nothing downstream re-checks what one run collected.
- It must accept a payload of at least 512 KB once JSON-encoded, at least 50 artifacts in a run, and at least 2 MB of encoded payload across a run in aggregate.
- An artifact whose payload does not encode, or which exceeds a bound, is dropped with a warning naming the tool, the run, the artifact's type and the call; the run is not failed, and the retained list carries no placeholder for what was dropped.
- A drop is per artifact, so a later, smaller artifact that fits the remaining budget is still kept.
- An artifact with an empty
typeis refused outright. - A payload is untrusted tool and model output: a consumer must treat every value in it as plain text and escape it on output.
What it means
Once a run's collection has accepted or dropped an artifact at the point it was collected, nothing downstream checks it again — a consumer reading the retained list is not re-validating what it receives. A drop never leaves a gap for the entry it removed: the list a consumer sees is exactly the artifacts that survived, in the order they arrived, with no placeholder marking where one was dropped. The drop is decided per artifact, not once for the whole run: an artifact that crosses a bound does not disqualify a later, smaller one that still fits what remains of the budget.
Example
A run's aggregate budget is already mostly spent by earlier artifacts; the next one would cross it and is dropped, but a small one after that still fits what is left:
{ "type": "citation", "payload": { "ref": "kept" }, "tool_call_id": "call_last" }Nothing in the retained list marks where the dropped artifact would have sat.