The Newsroom
Five calls, one verdict, and only the last one is read by a machine
The pipeline is described in its own docstring as data-first: gather everything with free calls, then spend exactly five model invocations instead of two dozen tool-calling round trips. That framing is accurate, and it is the most deliberate design decision in the repository.
services/nim_agents_service.py
339 lines
Five model calls per analysis
The common way to build an LLM analyst is to give the model tools and let it decide what to fetch. That produces a variable number of round trips, unpredictable cost, and a trace that is hard to reproduce. This pipeline inverts it. Seven fetches run first, unconditionally, through free interfaces: a quote, technical indicators, fundamentals, up to eight news articles, and three web searches with fixed query templates. The results are concatenated into one markdown block with seven headed sections and a date line.
That block is the research context, and it is the only thing the model ever sees about the outside world. There is no tool-calling, no retrieval loop, no agent deciding to look something up. The cost of an analysis is therefore known in advance: seven free calls and five paid ones, every time.
The five stages are an analyst, a bull, a bear, a judge, and a risk committee. Each is a separate call with its own system prompt and a user payload assembled from prior stages. They run sequentially on worker threads. Notably the bull and bear stages are independent of one another — neither sees the other's output — yet they still run one after the other rather than concurrently, which wastes roughly a fifth of the wall-clock time for no benefit.
This also means the word “debate” overstates what happens. The bull and the bear each write an opening brief against the same evidence. Neither rebuts the other. The judge then reads both briefs and picks a winner. It is adversarial construction followed by adjudication, which is a reasonable design, but it is not a dialogue and the codebase's own naming invites the misreading.
Only the fifth stage has an output contract. Its prompt requires three literal labels — a final recommendation, a confidence percentage, and a target price — because the fifth stage is the only one parsed. The other four exist entirely to condition it. Their text is stored verbatim for human reading and never machine-interpreted.
There is no caching anywhere in this service. Every analysis re-runs all seven fetches and all five model calls. The unattended weekly job that drives it processes stocks in batches of five with a five-second pause between batches, which is the only rate limiting applied.
The bull and the bear never read each other. It is adversarial construction followed by adjudication — not a debate, whatever the module is called.
On stages two, three and four