跪拜 Guibai
← All articles
Front-end · Agent

Five-Stage Agent Resuscitation Manual: Keeping Your AI Alive When Concurrency Spikes

By 去伪存真 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Agent latency and timeout failures are a top reason production AI features get rolled back; the fixes here are cheap compared to the cost of an outage, and most apply regardless of which model or vendor you use.

Summary

Running an agent locally feels like having a genius assistant, but the moment it hits production concurrency, it turns into a 504-generating, timeout-drowning mess. This guide breaks down the whole agent lifecycle into five stages, each with its own failure modes and rescue strategies: prompt assembly, RAG retrieval, LLM first reasoning, external tool execution, and final output.

For each stage, the author identities typical bottlenecks like tokenizer CPU burn, vector store latency spikes, shared-API token contention, missing socket timeouts, and ReAct loops that exhaust all resources. The advice is pragmatic: use character-based length estimation instead of repeated tokenization, cache aggressively, prune tool schemas, run independent tool calls in parallel, stream responses, and pass cancellation signals through.

The closing recommendation is to abandon synchronous HTTP for heavy tasks altogether, shifting to an async task queue with a Task ID and SSE subscription. The article's blunt tone and concrete examples make it a practical checklist for anyone running agents behind a public API.

Takeaways
— Prompt assembly in production without caching or approximation can burn CPU with repeated tokenizer calls and exhaust MySQL connection pools.
— Truncate history by estimating character count multiplied by 1.3 to 1.5 instead of running tiktoken in a loop.
— RAG suffers from embedding API rate limits, vector store CPU spikes, and reranking overhead; use Redis hash and semantic caches, and reduce candidate set with BM25 before reranking.
— Lowering HNSW's efSearch parameter trades roughly 1% precision for several times higher QPS.
— Public LLM APIs share a common pool, so TTFT can jump from 800ms to 30s when neighboring traffic spikes; use LiteLLM or OneAPI gateways with fallback keys and a 5-second failover threshold.
— Mount only 3-5 tools per request, using a lightweight intent classifier to select them.
— External tool calls need per-tool timeouts (e.g., 2s internal, 5s scrape); treat timeout as an error text returned to the model.
— Run independent tool calls concurrently with Promise.all or asyncio.gather instead of serial awaits.
— Limit agent execution steps to 3-5 and circuit-break when the same tool is called twice with identical parameters and errors.
— Always use streaming (SSE/WebSocket) for LLM output; otherwise the gateway will return 504 after 60 seconds of silence.
— Clean tool-returned data (HTML/JSON) before feeding it to the model to prevent context bloat.
— For tasks that exceed 30 seconds, switch to an async queue pattern: submit to Redis Stream/BullMQ, return a Task ID, process in workers, and stream progress via SSE.
— Pass cancellation signals (AbortController or framework context) to stop model calls when the user disconnects.
Conclusions

The article's biggest insight is that most agent production failures are not model quality issues but infrastructure and API design issues; the same tricks used for any web service, like caching and timeouts, apply to agent pipelines.

The recommendation to estimate token count by character length instead of using tiktoken is a tradeoff that most developers would hesitate to accept, but the author argues the precision loss is negligible compared to the CPU cost under concurrency.

Tool pruning and intent-based mounting contradict the common advice to give LLMs as many tools as possible; the author bets on speed over capability, which may surprise developers who focus on agent capability benchmarks.

The shift to an async task queue for heavy agents is a structural change that also changes UX: users no longer wait for a single HTTP response but follow a job ID, which is a more robust pattern for long-running AI tasks.

The article's tone treats agents as fragile and untrustworthy in production, which stands in contrast to the hype around autonomous agents; it's a grounded engineering perspective that many teams will recognize.

Concepts & terms
RAG (Retrieval-Augmented Generation)
A pattern where an agent first searches a document or vector store for relevant context, then feeds that context to the LLM to generate a grounded answer.
TTFT (Time to First Token)
The latency from sending a request to an LLM API until the first token of the response is received; high TTFT degrades user-perceived responsiveness.
HNSW (Hierarchical Navigable Small World)
A graph-based algorithm for approximate nearest-neighbor search in vector databases; its efSearch parameter controls the search breadth and thus the precision/speed tradeoff.
ReAct loop
A reasoning pattern where the LLM repeatedly alternates between thought and tool calls; without step limits or error detection, it can loop indefinitely on repeated failures.
SSE (Server-Sent Events)
A protocol for the server to push a stream of updates over a single HTTP connection; commonly used to stream LLM token output so the gateway doesn't time out.
Async task queue
A pattern where a request is enqueued for background processing and the client receives a task ID to poll or subscribe to, instead of waiting synchronously for the result.
From the discussion
Featured comments
星云PLUS团队

Beyond these five stages, here's a pitfall about tool execution: The hardest part of a timeout isn't killing the request, it's not knowing whether the other side actually succeeded. For read APIs you can safely retry, but for write APIs (creating orders, placing orders, sending messages) you must carry an idempotency key or later query the receipt; otherwise one retry after a 504 means duplicate submission. Also, allocate the timeout budget per stage rather than as one global value: give assembly and RAG fixed caps, let tool execution keep margin based on the interface's P99, and always reserve budget for the output stage, or the first four steps could be healthy and the reply still gets a 504. One more low-cost trick: add structured metrics to each stage (stage name + error code + whether retried). When it's unresponsive you can tell at a glance whether it's a 429 or the connection pool refusing to lend, which is far more efficient for troubleshooting than adding just one global trace.

去伪存真

Thanks for the god-tier addition, especially the write-API timeout: the scariest thing isn't an error, it's the downstream actually succeeding while the gateway plays deaf and dumb; blindly retrying just gives the user a 'buy one get one (mandatory)'. And the 'grand-finale budget' reserved for output really is 'walking ninety-nine steps and tripping on the last one right in front of the user'.

See top comments, translated →
Source: juejin.cn ↗ Google Translate ↗ Backup ↗