From 9ef96651cf5486e500188a62961c803f5bc2e3e7 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Wed, 29 Jul 2026 16:50:08 -0400 Subject: [PATCH] feat(workflow): raise the stdin_source ceiling to 30 MiB The 10 MiB cap on resolved stdin_source values is tight for wide fan-in: a context.parallel.results batch from a large for_each round carries tens of structured agent outputs, and a merge step that feeds them to a deterministic command hits the ceiling as a hard deterministic failure. Raise the ceiling to 30 MiB; it still bounds peak memory and remote uploads, just with headroom matched to the fan-out sizes for_each already allows. Co-Authored-By: Claude Fable 5 --- docs/public/workflows/stages-and-nodes.mdx | 2 +- lib/components/fabro-workflow/src/handler/command.rs | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/public/workflows/stages-and-nodes.mdx b/docs/public/workflows/stages-and-nodes.mdx index 79ae0b00f..59f48df69 100644 --- a/docs/public/workflows/stages-and-nodes.mdx +++ b/docs/public/workflows/stages-and-nodes.mdx @@ -117,7 +117,7 @@ When a node has no explicit `shape` or `type`, the presence of `script` makes it For `stdin_source`, strings are passed unchanged. Other JSON values use compact JSON. Fabro does not add a newline. A missing source, or a value larger than -10 MiB, fails before the command starts. +30 MiB, fails before the command starts. ### Human diff --git a/lib/components/fabro-workflow/src/handler/command.rs b/lib/components/fabro-workflow/src/handler/command.rs index 0de483869..6cf7d5741 100644 --- a/lib/components/fabro-workflow/src/handler/command.rs +++ b/lib/components/fabro-workflow/src/handler/command.rs @@ -220,8 +220,10 @@ impl Handler for CommandHandler { /// Ceiling on encoded stdin bytes. `stdin_source` values are runtime data — /// often model-produced — so their size is not something a workflow author /// reviewed; this bounds peak memory and remote uploads the same way -/// `MAX_FOR_EACH_ITEMS` bounds `for_each` fan-out. -const MAX_STDIN_BYTES: usize = 10 * 1024 * 1024; +/// `MAX_FOR_EACH_ITEMS` bounds `for_each` fan-out. Sized for wide fan-in: +/// a `context.parallel.results` batch from a large `for_each` round easily +/// carries tens of structured agent outputs. +const MAX_STDIN_BYTES: usize = 30 * 1024 * 1024; fn validated_stdin_source(node: &Node) -> Result, String> { match node.context_key_attr("stdin_source") {