fix(agent-v2): make workflow context value truncation length configurable

The Agent v2 node hard-coded a 2000-character cutoff for previous node
output values embedded in the workflow context prompt, silently
dropping content beyond that length. Move the limit to
WORKFLOW_AGENT_V2_CONTEXT_VALUE_MAX_LENGTH (default 400000, matching
TEMPLATE_TRANSFORM_MAX_LENGTH) so long outputs are no longer truncated
by default and the limit can be tuned when needed.

Fixes #40729
This commit is contained in:
chelsealong 2026-08-13 10:21:33 +00:00
parent b9248690b0
commit 6676425e2f
4 changed files with 53 additions and 2 deletions

View File

@ -897,6 +897,14 @@ class WorkflowConfig(BaseSettings):
default=5,
)
WORKFLOW_AGENT_V2_CONTEXT_VALUE_MAX_LENGTH: PositiveInt = Field(
description=(
"Maximum number of characters for a previous node output value included "
"in an Agent node's workflow context before it is truncated"
),
default=400_000,
)
MAX_VARIABLE_SIZE: PositiveInt = Field(
description="Maximum size in bytes for a single variable in workflows. Default to 200 KB.",
default=200 * 1024,

View File

@ -436,8 +436,9 @@ class WorkflowAgentRuntimeRequestBuilder:
return json.dumps(prompt_payload, ensure_ascii=False, separators=(",", ":"))
text = str(value)
if len(text) > 2000:
return text[:2000] + "...[truncated]"
max_length = dify_config.WORKFLOW_AGENT_V2_CONTEXT_VALUE_MAX_LENGTH
if len(text) > max_length:
return text[:max_length] + "...[truncated]"
return text
@classmethod

View File

@ -1398,6 +1398,47 @@ def test_previous_node_remote_url_file_mapping_is_not_truncated_in_workflow_cont
assert "...[truncated]" not in _workflow_user_prompt(result)
def test_previous_node_long_text_output_is_not_truncated_under_default_limit():
long_text = "a" * 2500
class LongTextVariablePool(FakeVariablePool):
def get(self, selector):
if list(selector) == ["previous-node", "text"]:
return StringSegment(value=long_text)
return super().get(selector)
context = replace(_context(), variable_pool=LongTextVariablePool())
context.binding.node_job_config = WorkflowNodeJobConfig.model_validate(
{
"workflow_prompt": "Review {{#previous-node.text#}} before responding.",
}
)
result = WorkflowAgentRuntimeRequestBuilder(credentials_provider=FakeCredentialsProvider()).build(context)
user_prompt = _workflow_user_prompt(result)
assert f" - previous-node.text: {long_text}" in user_prompt
assert "...[truncated]" not in user_prompt
def test_previous_node_text_output_respects_configured_max_length(monkeypatch):
monkeypatch.setattr(
"core.workflow.nodes.agent_v2.runtime_request_builder.dify_config.WORKFLOW_AGENT_V2_CONTEXT_VALUE_MAX_LENGTH",
10,
)
context = _context()
context.binding.node_job_config = WorkflowNodeJobConfig.model_validate(
{
"workflow_prompt": "Review {{#previous-node.text#}} before responding.",
}
)
result = WorkflowAgentRuntimeRequestBuilder(credentials_provider=FakeCredentialsProvider()).build(context)
user_prompt = _workflow_user_prompt(result)
assert " - previous-node.text: Previous r...[truncated]" in user_prompt
# ── Agent config declaration layer ────────────────────────────────────────────

View File

@ -201,6 +201,7 @@ TEMPLATE_TRANSFORM_MAX_LENGTH=400000
WORKFLOW_MAX_EXECUTION_STEPS=500
WORKFLOW_MAX_EXECUTION_TIME=1200
WORKFLOW_CALL_MAX_DEPTH=5
WORKFLOW_AGENT_V2_CONTEXT_VALUE_MAX_LENGTH=400000
MAX_VARIABLE_SIZE=204800
WORKFLOW_GENERATOR_NODE_BUILDER_MAX_WORKERS=6
WORKFLOW_FILE_UPLOAD_LIMIT=10