Repository navigation
AUDIT-15 — Medium — Duplicate-tool-call detector only catches consecutive repeats #72
Description
Summary
Severity: Medium
Area: Agent loop
Affected files: agentkit/core/agent.py:218-229
Suggested branch: fix/duplicate-tool-call-detector
Suggested PR title: fix(agent): detect non-consecutive tool call loops
This is finding AUDIT-15 of 18 from a consolidated audit of agentkit/. It is deliberately self-contained so it can be fixed on its own branch with its own PR.
Related findings: Independent of the other findings.
AUDIT-15 — Medium — Duplicate-tool-call detector only catches consecutive repeats
File — agentkit/core/agent.py:218-229
for call in response.tool_calls:
args_json = json.dumps(call.arguments, sort_keys=True, default=str)
sig = (call.name, args_json)
if sig == last_tool_signature:
consecutive_duplicate_count += 1
else:
last_tool_signature = sig
consecutive_duplicate_count = 1
if (
consecutive_duplicate_count
>= self.config.max_consecutive_duplicate_tool_calls
):Why this is a bug
Only the immediately preceding signature is remembered. An alternating pattern A, B, A, B, … resets the counter every time, so the documented "halt run if identical tool calls are repeated" guard never fires. The run then burns all max_steps (each step costing tokens, latency and money) before being stopped by the step limit instead of by the loop detector.
Pass cases
- A repeating non-consecutive pattern (e.g.
calculator(1),calculator(2),calculator(1),calculator(2), …) is detected as a loop and terminates the run with a clearfailure_reasonbeforemax_stepsis reached. - The consecutive-duplicate case keeps working (existing tests).
- A legitimate sequence of different tool calls is not flagged.
- The detector's scope is documented (window size / repetition count) and configurable.
Definition of done (per AGENTS.md)
- New/updated unit and integration tests covering the pass cases above, all passing (
pytest). -
ruff check .,ruff format --check .andmypy agentkitclean. - Docstrings updated where behaviour changed;
docs/PROGRESS.mdupdated (status, PR link, commit count, notes). - A new ADR in
docs/DECISIONS.mdif an architectural decision was made. - Branch pushed and PR opened (never commit directly to
main).
Baseline at the time of writing: pytest is green on main (all tests pass; tests/real/* skipped unless AGENTKIT_REAL_INFRA=1).
Activity
getdownandcode commentedon Oct 20, 2026
Audit index (18 separate issues, fix one by one)
Each issue is self-contained: current code, reproduction, pass cases, suggested branch and PR title. Reference the relevant one with
Fixes #NNin your PR.HamzaKhanBUIC commentedon Oct 20, 2026
Opened PR #83 with the complete fix and regression test suite:
aise_on_failure=True behavior.
uff check,
uff format --check, and mypy agentkit.