fix: drop generic repeated tool-call guard

The global guard changed baseline agent and subagent behavior without
proving a real no-progress loop. Keep this PR focused on the cron
contract hardening and validation fixes.

Made-with: Cursor
This commit is contained in:
Xubin Ren
2026-04-18 19:59:58 +00:00
parent adc1e843b4
commit 9c0dc8b276
4 changed files with 11 additions and 127 deletions
-42
View File
@@ -854,48 +854,6 @@ async def test_runner_blocks_repeated_external_fetches():
assert "repeated external lookup blocked" in blocked_tool_message["content"]
@pytest.mark.asyncio
async def test_runner_blocks_repeated_identical_tool_calls():
from nanobot.agent.runner import AgentRunSpec, AgentRunner
provider = MagicMock()
captured_final_call: list[dict] = []
call_count = {"n": 0}
async def chat_with_retry(*, messages, **kwargs):
call_count["n"] += 1
if call_count["n"] <= 3:
return LLMResponse(
content="working",
tool_calls=[ToolCallRequest(id=f"call_{call_count['n']}", name="read_file", arguments={"path": "memory/history.jsonl", "limit": 50, "offset": 1})],
usage={},
)
captured_final_call[:] = messages
return LLMResponse(content="done", tool_calls=[], usage={})
provider.chat_with_retry = chat_with_retry
tools = MagicMock()
tools.get_definitions.return_value = []
tools.execute = AsyncMock(return_value="file content")
runner = AgentRunner(provider)
result = await runner.run(AgentRunSpec(
initial_messages=[{"role": "user", "content": "what happened recently?"}],
tools=tools,
model="test-model",
max_iterations=4,
max_tool_result_chars=_MAX_TOOL_RESULT_CHARS,
))
assert result.final_content == "done"
assert tools.execute.await_count == 2
blocked_tool_message = [
msg for msg in captured_final_call
if msg.get("role") == "tool" and msg.get("tool_call_id") == "call_3"
][0]
assert "repeated identical call to 'read_file' blocked" in blocked_tool_message["content"]
@pytest.mark.asyncio
async def test_loop_max_iterations_message_stays_stable(tmp_path):
loop = _make_loop(tmp_path)
-20
View File
@@ -1,20 +0,0 @@
from nanobot.utils.runtime import repeated_tool_call_error, tool_call_signature
def test_tool_call_signature_sorts_arguments_stably() -> None:
first = tool_call_signature("read_file", {"offset": 1, "path": "memory/history.jsonl"})
second = tool_call_signature("read_file", {"path": "memory/history.jsonl", "offset": 1})
assert first == second
def test_repeated_tool_call_error_blocks_after_two_attempts() -> None:
seen: dict[str, int] = {}
assert repeated_tool_call_error("read_file", {"path": "a.txt"}, seen) is None
assert repeated_tool_call_error("read_file", {"path": "a.txt"}, seen) is None
error = repeated_tool_call_error("read_file", {"path": "a.txt"}, seen)
assert error is not None
assert "repeated identical call to 'read_file' blocked after 2 attempts" in error