diff --git a/src/node/agent/node.lua b/src/node/agent/node.lua
index bf67fda..902504f 100644
--- a/src/node/agent/node.lua
+++ b/src/node/agent/node.lua
@@ -500,7 +500,7 @@ local function process_multiple_inputs(inputs)
if inputs.context and inputs.context.content ~= nil then
local context_content = inputs.context.content
if type(context_content) ~= "table" then
- return nil, nil, nil, nil, "context must be a table/object"
+ return nil, nil, nil, nil, nil, "context must be a table/object"
end
input_context = context_content
end
@@ -509,7 +509,7 @@ local function process_multiple_inputs(inputs)
if inputs.agent_id and inputs.agent_id.content ~= nil then
local agent_id_content = inputs.agent_id.content
if type(agent_id_content) ~= "string" or agent_id_content == "" then
- return nil, nil, nil, nil, "agent_id must be a non-empty string"
+ return nil, nil, nil, nil, nil, "agent_id must be a non-empty string"
end
agent_id_override = agent_id_content
end
@@ -518,14 +518,25 @@ local function process_multiple_inputs(inputs)
if inputs.model and inputs.model.content ~= nil then
local model_content = inputs.model.content
if type(model_content) ~= "string" or model_content == "" then
- return nil, nil, nil, nil, "model must be a non-empty string"
+ return nil, nil, nil, nil, nil, "model must be a non-empty string"
end
model_override = model_content
end
+ local max_iterations_override = nil
+ if inputs.max_iterations and inputs.max_iterations.content ~= nil then
+ local max_iterations_content = tonumber(inputs.max_iterations.content)
+ if not max_iterations_content or max_iterations_content < 1
+ or max_iterations_content ~= math.floor(max_iterations_content) then
+ return nil, nil, nil, nil, nil, "max_iterations must be a positive integer"
+ end
+ max_iterations_override = max_iterations_content
+ end
+
local parts = {}
for key, input in pairs(inputs) do
- if key ~= "context" and key ~= "agent_id" and key ~= "model" and input.content ~= nil then
+ if key ~= "context" and key ~= "agent_id" and key ~= "model" and key ~= "max_iterations"
+ and input.content ~= nil then
local content = input.content
if type(content) == "table" then
content = json.encode(content)
@@ -537,10 +548,10 @@ local function process_multiple_inputs(inputs)
end
if #parts == 0 then
- return input_context, agent_id_override, model_override, "", nil
+ return input_context, agent_id_override, model_override, max_iterations_override, "", nil
end
- return input_context, agent_id_override, model_override, table.concat(parts, "\n\n"), nil
+ return input_context, agent_id_override, model_override, max_iterations_override, table.concat(parts, "\n\n"), nil
end
local function validate_and_resolve_config(config)
@@ -1805,7 +1816,8 @@ local function run(args)
}, inputs_err)
end
- local input_context, agent_id_override, model_override, input_data, input_err = process_multiple_inputs(inputs)
+ local input_context, agent_id_override, model_override, max_iterations_override, input_data, input_err =
+ process_multiple_inputs(inputs)
if input_err then
return n:fail({
code = agent_consts.ERROR.INPUT_VALIDATION_FAILED,
@@ -1917,7 +1929,7 @@ local function run(args)
local saved_state = ((args.node or {}).metadata or {}).state or {}
local iteration = saved_state.current_iteration or 0
- local max_iterations = config.arena.max_iterations or agent_consts.DEFAULTS.MAX_ITERATIONS
+ local max_iterations = max_iterations_override or config.arena.max_iterations or agent_consts.DEFAULTS.MAX_ITERATIONS
local min_iterations = config.arena.min_iterations or agent_consts.DEFAULTS.MIN_ITERATIONS
local tool_calling = config.arena.tool_calling
local show_tool_calls = config.show_tool_calls ~= false
diff --git a/src/node/agent/node_context_test.lua b/src/node/agent/node_context_test.lua
index 392f4ca..2d0ab53 100644
--- a/src/node/agent/node_context_test.lua
+++ b/src/node/agent/node_context_test.lua
@@ -48,21 +48,23 @@ local function define_tests()
-- An input_transform field whose expression resolves to nil produces
-- an entry with nil content; the reserved carriers read it as "not
-- provided", never as a malformed value.
- local input_context, agent_id_override, model_override, input_data, err = process({
+ local input_context, agent_id_override, model_override, max_iterations_override, input_data, err = process({
context = { content = nil, metadata = {} },
model = { content = nil, metadata = {} },
agent_id = { content = nil, metadata = {} },
+ max_iterations = { content = nil, metadata = {} },
lead = { content = { name = "Jane" }, metadata = {} },
})
test.is_nil(err)
test.is_nil(input_context)
test.is_nil(agent_id_override)
test.is_nil(model_override)
+ test.is_nil(max_iterations_override)
test.is_true(input_data:find('', 1, true) ~= nil)
end)
it("renders no input tag for a nil-content input", function()
- local _, _, _, input_data, err = process({
+ local _, _, _, _, input_data, err = process({
empty = { content = nil, metadata = {} },
brief = { content = "text", metadata = {} },
})
@@ -72,10 +74,11 @@ local function define_tests()
end)
it("still merges a table context and applies string overrides", function()
- local input_context, agent_id_override, model_override, input_data, err = process({
+ local input_context, agent_id_override, model_override, max_iterations_override, input_data, err = process({
context = { content = { kb_ids = { "kb-1" } }, metadata = {} },
model = { content = "class:fast", metadata = {} },
agent_id = { content = "ns:researcher", metadata = {} },
+ max_iterations = { content = 80, metadata = {} },
lead = { content = { name = "Jane" }, metadata = {} },
})
test.is_nil(err)
@@ -83,7 +86,20 @@ local function define_tests()
test.eq((input_context :: any).kb_ids[1], "kb-1")
test.eq(model_override, "class:fast")
test.eq(agent_id_override, "ns:researcher")
+ test.eq(max_iterations_override, 80)
test.is_true(input_data:find('', 1, true) == nil)
+ test.is_true(input_data:find('', 1, true) == nil)
+ end)
+
+ it("rejects a max_iterations input that is not a positive integer", function()
+ local _, _, _, _, _, err = process({
+ max_iterations = { content = "eighty", metadata = {} },
+ })
+ test.not_nil(err)
+ local _, _, _, _, _, err2 = process({
+ max_iterations = { content = -3, metadata = {} },
+ })
+ test.not_nil(err2)
end)
end)
end