← Series overview

PART 11 OF 14 · 7 MIN READ · ARUNANK SHARAN · 24 OCTOBER 2025

When financial research needs more than one retrieval step

Some research questions can be answered with one retrieval pass. Others reveal new questions as the evidence is read.

“Compare margin pressure across three peers and identify whether management expects it to persist” is not a single lookup. The system may need filings, earnings-call commentary, consistent metric definitions and a check for contradictory statements. A fixed top-k search can miss an entire part of the task.

The client’s retrieval pipeline provides the foundation: query processing, retrieval, reranking, synthesis and source inspection. The design below extends that foundation into bounded agentic research. It is the 2026 design for tasks that need controlled iteration beyond the earlier retrieval path.

Give the agent a research task, not unrestricted browsing

An agentic loop chooses actions based on the evidence collected so far. The key design question is which actions it may take and what constitutes completion.

The ReAct paper describes interleaving reasoning and actions. Self-RAG explores retrieval and critique through trained reflection behaviour. These are useful research references, but adding a search loop to an application does not mean the application implements either paper’s full method. ReAct, Self-RAG

For a financial research task, a small tool set is often sufficient:

Tool Purpose Required boundary
search_passages Find candidates under issuer/time/source constraints Authorised corpus and bounded result count
read_context Expand a passage to adjacent source blocks Maximum tokens and immutable source IDs
get_reported_fact Retrieve a typed financial fact Period, unit, basis and provenance
calculate Derive a value from validated facts Allowlisted operations, no arbitrary code
compare_evidence Identify agreement, distinction or contradiction Retain both source references
finish Produce a supported answer or partial result Completion validator

The tools should be callable independently of the planner model. That makes them testable and allows model replacement without rewriting the evidence system.

Plan the evidence requirements first

For the peer-margin question, the plan might require:

For each of three issuers:
  1. Obtain comparable reported margin inputs for the requested period.
  2. Retrieve management commentary on the drivers.
  3. Retrieve forward-looking commentary on persistence.
Across issuers:
  4. Check metric definitions and reporting periods.
  5. Compare only compatible measures.
  6. Cite each factual claim and identify missing coverage.

The planner should output a structured task graph, not an unbounded stream of thoughts. Store decisions, tool inputs, observations and evidence references. An audit trail does not require publishing private model reasoning.

Each node has a completion condition. A search result count is not a completion condition for “find management’s explanation.” The condition is that a supporting passage has been identified, or the search budget has been exhausted with the gap recorded.

Maintain an evidence ledger

The ledger separates source evidence from planner notes and generated summaries:

{
  "task": "peer-margin-comparison",
  "requirements": {
    "peer_a_reported_margin": {"status": "supported", "evidence": ["E1"]},
    "peer_a_outlook": {"status": "missing", "evidence": []}
  },
  "facts": [{"id": "F1", "evidence_id": "E1", "value": "15.0", "unit": "percent"}],
  "contradictions": [],
  "search_history": [{"query_key": "peer-a-outlook-fy2024", "new_evidence": 0}],
  "corpus_snapshot": "financial-corpus-v3"
}

Deduplicate evidence by immutable source span, not by the planner’s wording. Two summaries of the same paragraph are one source, not independent confirmation.

The ledger also supports stopping. If repeated searches produce no new useful evidence, the agent should stop and report the missing coverage rather than rephrasing the same query indefinitely.

The bounded research loop checks evidence and budget before each tool call.

Put budgets in the executor

Prompting the model to be economical is not a hard cost control. The executor should enforce limits on tool calls, tokens, wall-clock duration, candidate count and estimated spend.

A worked task budget might permit six search calls, four context expansions and two calculation calls, with a 30-second wall-clock limit. These are configuration examples; choose actual values from measured task quality and latency.

Before a provider call, reserve its maximum allowed cost. Afterward, settle actual usage. If several actions run in parallel, reservations must be atomic so they cannot all spend the same remaining balance.

from dataclasses import dataclass
from decimal import Decimal

@dataclass
class Budget:
    remaining: Decimal
    calls_left: int

    def reserve(self, maximum_cost: Decimal):
        if maximum_cost < 0:
            raise ValueError("Negative reservation")
        if self.calls_left <= 0 or maximum_cost > self.remaining:
            raise RuntimeError("Research budget exhausted")
        self.calls_left -= 1
        self.remaining -= maximum_cost
        return maximum_cost

    def settle(self, reserved: Decimal, actual: Decimal):
        if not Decimal("0") <= actual <= reserved:
            raise ValueError("Usage outside reservation")
        self.remaining += reserved - actual

This single-process example demonstrates the accounting invariant. A concurrent service needs transactional storage and idempotent settlement records. Keep an upper bound on response tokens so that a reservation corresponds to an enforceable request limit.

Parallelise independent evidence gathering

Queries for three independent issuers can run concurrently. Reading a footnote discovered in one query depends on that query and should follow it.

A planner that treats every tool call as sequential increases latency unnecessarily. A planner that launches everything at once can exceed provider quotas, duplicate work and lose the dependency structure. Execute a bounded task graph, with concurrency limits per provider and per user.

If one issuer’s source is unavailable, return the other results with the gap identified when the product permits partial completion. Do not hold all completed work hostage to an endless retry on one source.

Retrieval content cannot change the rules

A document can contain instructions such as “ignore previous instructions” or a link that attempts to send data elsewhere. The agent must treat retrieved content as evidence, not authority over tools or permissions.

Keep the allowed corpus, credentials and output destinations outside document-controlled text. Validate tool arguments server-side. A source passage cannot grant access to another tenant’s documents or authorise a new external action.

Cache keys should include access scope and corpus version. Reusing another user’s evidence packet because the natural-language question matches is a serious boundary failure.

When a graph helps

A graph can help questions about relationships: which companies share an exposure, which subsidiaries appear in a supply chain, or which themes recur across a corpus. GraphRAG research explores building graph-derived structures and summaries for global questions. That introduces extraction and indexing work; it should be justified by the tasks that benefit. GraphRAG research

A graph edge is also a claim. It needs source provenance, time and a distinction between explicitly reported and inferred relationships. An attractive graph of ungrounded edges is not stronger evidence than an ungrounded paragraph.

For exact financial lookups, a well-scoped hybrid retriever and structured fact tool may be simpler and more reliable. Use graph traversal where relationship structure is necessary, not as a requirement for calling the system agentic.

Define completion and useful failure

A task can finish as supported, partial, insufficient_evidence, conflicting_evidence or budget_exhausted. These states are more informative than a single success boolean.

The final validator checks required evidence coverage, citations, calculations and scope. The answer should explain what was found and what remains unresolved. An agent that stops with a precise evidence gap has done more useful work than one that fills the gap with unsupported confidence.

Evaluation should compare this loop against the fixed retrieval baseline on the same tasks, including simple questions. If the agent adds latency and cost without improving completed research, the fixed path should remain the default for that task class.