~/TechPurAI
~/tutorials/building-ai-agents/teaching-your-research-agent-to-cite-sources
advanced·part 12 of 22·3 min read

Teaching Your Research Agent to Cite Sources

Updated Aug 16, 2026AI

Part 11's agent cites source URLs, but only as a plain-text instruction the model may or may not follow precisely. This part makes citation genuinely structural — tracking exactly which real search result backs each specific claim.

The real problem with plain-text citation instructions

text
"Cite the real source URL for every claim" is a real, honest
  instruction, but nothing structurally VERIFIES the model actually
  followed it correctly for every single sentence — a genuinely
  common, real gap between instruction and guaranteed behavior

This directly extends the same honest limitation the AI Projects series flagged for RAG citations — an instruction is a real, effective nudge, not a structural guarantee.

Real, structured source tracking during the research loop

python
def run_research_agent_with_tracked_sources(request: str) -> dict:
    messages = [{"role": "user", "content": request}]
    all_sources = []  # real, actual accumulated source list

    for _ in range(8):
        response = client.messages.create(
            model="claude-sonnet-5", max_tokens=2048,
            system=SYSTEM_PROMPT, tools=tools, messages=messages,
        )
        messages.append({"role": "assistant", "content": response.content})

        if response.stop_reason != "tool_use":
            return {"report": response.content[0].text, "sources": all_sources}

        tool_call = next(b for b in response.content if b.type == "tool_use")
        result = web_search(**tool_call.input)
        all_sources.extend(result)  # real, structural tracking, not
                                      # relying on the model to report it
        messages.append({
            "role": "user",
            "content": [{"type": "tool_result", "tool_use_id": tool_call.id, "content": str(result)}],
        })

This real, structural change — accumulating all_sources directly in your own code, rather than trusting the model's final text to accurately list every source it consulted — is genuinely more reliable, exactly the same principle from part 5: safety and correctness belong in code, not solely in a prompt instruction.

A real, second-pass claim verification step

python
def verify_claims(report: str, sources: list[dict]) -> str:
    source_text = "\n".join(f"{s['url']}: {s['snippet']}" for s in sources)
    response = client.messages.create(
        model="claude-sonnet-5", max_tokens=1024,
        system=(
            f"Review this research report against the real sources "
            f"actually consulted. Flag any specific claim NOT "
            f"genuinely supported by these sources:\n\n{source_text}"
        ),
        messages=[{"role": "user", "content": report}],
    )
    return response.content[0].text

This real, second, independent LLM call directly applies the LLM & Advanced AI series' own LLM-as-judge evaluation technique — a genuine, structural check flagging any claim in the final report that isn't actually traceable back to a real, consulted source, catching exactly the kind of subtle drift a plain instruction alone can't guarantee against.

Why it matters

This two-pass approach — generate, then independently verify — is a real, meaningfully more rigorous pattern than a single-pass instruction, directly worth the added real cost for Bright Leaf Coffee's competitive research specifically, since the marketing team may make real, actual budget decisions based on this report's claims.

Presenting real, structured citations to the marketing team

python
def format_report_with_footnotes(report: str, sources: list[dict]) -> str:
    footnotes = "\n".join(f"[{i+1}] {s['url']}" for i, s in enumerate(sources))
    return f"{report}\n\n---\nSources:\n{footnotes}"

A real, genuine footnote-style presentation — every source consulted, listed explicitly and numbered — gives the marketing team a real, direct way to independently verify any specific claim before acting on it, the same honest transparency principle running throughout this site's entire AI curriculum.

A real, honest cost trade-off

text
Part 11's version: one real research pass, trusting the citation
  instruction
This part's version: research pass + a real, second verification
  pass — genuinely more reliable, at real, additional API cost

For a genuinely high-stakes real report informing actual marketing spend decisions, this added real cost and rigor is a reasonable, deliberate trade-off — directly the same calibrated judgment the LLM & Advanced AI series applied to re-ranking: reach for added rigor when the real stakes genuinely justify it.

Next: building a real AI coding assistant — applying this series' agent patterns to a genuinely technical, code-focused real task.

VK

Vijay Kumar

Founder of TechPurAI — writing hands-on tutorials and honest tool breakdowns.

LinkedIn ↗
← previous11. Build an AI Web Research Agentnext →13. Build an AI Coding Assistant