Skip to content

Commit d9302a2

Browse files
authored
fix: prevent ag2 infinite tool-call loop and agno request timeouts (CopilotKit#4242)
## Summary - **ag2**: Add `max_consecutive_auto_reply=15` to `ConversableAgent` to prevent infinite tool-call loops that flood Railway's log stream at 500+ logs/sec and starve health probes - **agno**: Raise `OpenAIChat` timeout from default to 120s (aimock proxy latency) and add `tool_call_limit=15` safety net ## Root Cause **ag2 (9/12 ticks 503)**: AG2's `ConversableAgent` with `human_input_mode="NEVER"` has no built-in turn limit. When the LLM enters a repetitive tool-call pattern (observed: hundreds of `get_weather(Tokyo)` calls per second), the agent loops indefinitely. This generates 500+ log lines/sec hitting Railway's rate limit, the agent becomes unresponsive to health probes, the watchdog kills it after 90s, and the container restarts. Cycle repeats. **agno (3/12 ticks 503)**: The agno `OpenAIChat` model uses httpx's default timeout, which is too short when requests route through the aimock proxy under load. Observed `"Error in Agent run: Request timed out."` in logs followed by agent restart. Less frequent than ag2 because it only happens under concurrent load. ## Test plan - [ ] Deploy ag2 and agno via CI (push to main triggers showcase_deploy) - [ ] Monitor health for 30 min post-deploy: `curl showcase-ag2-production.up.railway.app/api/health` - [ ] Verify Railway logs no longer show rate-limit messages or infinite tool-call output - [ ] Verify watchdog kill events drop to zero
2 parents 10942da + 6ad352b commit d9302a2

4 files changed

Lines changed: 26 additions & 2 deletions

File tree

showcase/packages/ag2/src/agents/agent.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,12 @@ async def generate_a2ui(
148148
),
149149
llm_config=LLMConfig({"model": "gpt-4o-mini", "stream": True}),
150150
human_input_mode="NEVER",
151+
# Guard against infinite tool-call loops: AG2's ConversableAgent with
152+
# human_input_mode="NEVER" will keep executing tool calls indefinitely
153+
# if the LLM keeps requesting them. Without this limit the agent floods
154+
# Railway's log stream (500 logs/sec rate-limit), becomes unresponsive
155+
# to health probes, and gets killed by the watchdog.
156+
max_consecutive_auto_reply=15,
151157
functions=[
152158
get_weather,
153159
query_data,

showcase/packages/agno/src/agents/main.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,11 @@ def generate_a2ui(context: str):
173173

174174

175175
agent = Agent(
176-
model=OpenAIChat(id="gpt-4o"),
176+
# Raise the HTTP timeout so requests routed through aimock don't time out
177+
# under normal load. The default httpx timeout is too short when aimock
178+
# is proxying to the upstream LLM — observed "Request timed out" errors
179+
# that crash the agent run and trigger watchdog restarts.
180+
model=OpenAIChat(id="gpt-4o", timeout=120),
177181
tools=[
178182
get_weather,
179183
query_data,
@@ -184,6 +188,8 @@ def generate_a2ui(context: str):
184188
search_flights,
185189
generate_a2ui,
186190
],
191+
# Prevent runaway tool-call loops — same guard as the ag2 package.
192+
tool_call_limit=15,
187193
description="You are a helpful sales assistant for the CopilotKit showcase demos.",
188194
instructions="""
189195
SALES PIPELINE:

showcase/starters/ag2/agent/agent.py

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

showcase/starters/agno/agent/main.py

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)