Three low-priority observations from migrating FrontierAgent onto AgentCore (ApodexAI/FrontierAgent#50). None of them is a bug and none blocks a host today; opening one thread to decide whether any is worth changing, rather than three speculative PRs.
1. Tuning values live in module globals
Some runtime knobs are module-level constants, read at call time from the defining module or, for _RUNAWAY_MAX_RETRIES, frozen at import from the environment:
| Knob |
Where |
_WALL_DEADLINE_FLOOR_S = 20.0 |
runtime/loop/_call.py:145 |
_RETRY_BACKOFF_BASE_S = 2.0, _RETRY_BACKOFF_CAP_S = 5.0 |
runtime/loop/compact_llm.py:134 |
_RUNAWAY_MAX_RETRIES = _env_int(...), _RUNAWAY_BACKOFF_S = 2.0 |
runtime/loop/_runaway.py:104 |
Consequences for a host:
- Hosts expose AgentCore modules through compatibility facades. Patching the facade (
monkeypatch.setattr(host_module, "_RETRY_BACKOFF_BASE_S", …)) silently has no effect, because only the agent_core module's global is read. FrontierAgent's tests now patch agent_core.* directly (ApodexHarness's _call facade documents the same trap).
RUNAWAY_MAX_RETRIES can't be changed per role or per run, only per process, before import.
Option: move them onto the objects that use them (LLMSummaryCompactor(retry_backoff_base_s=..., retry_backoff_cap_s=...), LoopConfig / call_llm keywords for the wall floor and runaway budget), keeping the globals as defaults. It's additive, so a MINOR. Or keep them as is and document "patch agent_core.*, not the facade".
2. Truncation continuations don't consume max_turns
agent_loop.py:~526: a reply cut at the output cap is continued with turn -= 1, bounded separately by LoopConfig.truncation_max_continuations. That's deliberate: the comment says a continuation must not burn the landing turn. It also means the worst-case LLM call count per run is max_turns × (1 + truncation_max_continuations), not max_turns.
That's fine for correctness. The question is whether hosts that use max_turns as a cost or latency proxy want an opt-in (e.g. LoopConfig.continuations_count_as_turns: bool = False), or whether documenting the bound on LoopConfig is enough. truncation_max_continuations=0 already exists as the hard off switch.
3. KeepLastNToolResultsCompactor has no bare-placeholder mode
Older tool results become a mini card: placeholder + tool name + an argument preview + up to max_card_urls URLs + an optional recovery footer. max_card_urls=0 drops the URLs but still emits the tool name and arguments. There's no way to get the pre-0.10 bare placeholder.
No host needs it today; the card is cheap and it prevents re-issued queries. Raising it only because the change was not switchable, which matters for A/B comparisons against older runs. Option: a card: bool = True keyword, or treat it as intended and close.
My take: (1) is the only one with a practical payoff (host tests and per-run tuning); (2) documentation is probably enough; (3) close unless someone needs the A/B knob.
Three low-priority observations from migrating FrontierAgent onto AgentCore (ApodexAI/FrontierAgent#50). None of them is a bug and none blocks a host today; opening one thread to decide whether any is worth changing, rather than three speculative PRs.
1. Tuning values live in module globals
Some runtime knobs are module-level constants, read at call time from the defining module or, for
_RUNAWAY_MAX_RETRIES, frozen at import from the environment:_WALL_DEADLINE_FLOOR_S = 20.0runtime/loop/_call.py:145_RETRY_BACKOFF_BASE_S = 2.0,_RETRY_BACKOFF_CAP_S = 5.0runtime/loop/compact_llm.py:134_RUNAWAY_MAX_RETRIES = _env_int(...),_RUNAWAY_BACKOFF_S = 2.0runtime/loop/_runaway.py:104Consequences for a host:
monkeypatch.setattr(host_module, "_RETRY_BACKOFF_BASE_S", …)) silently has no effect, because only theagent_coremodule's global is read. FrontierAgent's tests now patchagent_core.*directly (ApodexHarness's_callfacade documents the same trap).RUNAWAY_MAX_RETRIEScan't be changed per role or per run, only per process, before import.Option: move them onto the objects that use them (
LLMSummaryCompactor(retry_backoff_base_s=..., retry_backoff_cap_s=...),LoopConfig/call_llmkeywords for the wall floor and runaway budget), keeping the globals as defaults. It's additive, so a MINOR. Or keep them as is and document "patchagent_core.*, not the facade".2. Truncation continuations don't consume
max_turnsagent_loop.py:~526: a reply cut at the output cap is continued withturn -= 1, bounded separately byLoopConfig.truncation_max_continuations. That's deliberate: the comment says a continuation must not burn the landing turn. It also means the worst-case LLM call count per run ismax_turns × (1 + truncation_max_continuations), notmax_turns.That's fine for correctness. The question is whether hosts that use
max_turnsas a cost or latency proxy want an opt-in (e.g.LoopConfig.continuations_count_as_turns: bool = False), or whether documenting the bound onLoopConfigis enough.truncation_max_continuations=0already exists as the hard off switch.3.
KeepLastNToolResultsCompactorhas no bare-placeholder modeOlder tool results become a mini card: placeholder + tool name + an argument preview + up to
max_card_urlsURLs + an optional recovery footer.max_card_urls=0drops the URLs but still emits the tool name and arguments. There's no way to get the pre-0.10 bare placeholder.No host needs it today; the card is cheap and it prevents re-issued queries. Raising it only because the change was not switchable, which matters for A/B comparisons against older runs. Option: a
card: bool = Truekeyword, or treat it as intended and close.My take: (1) is the only one with a practical payoff (host tests and per-run tuning); (2) documentation is probably enough; (3) close unless someone needs the A/B knob.