streamlitagentsui

Streamlit Multi-Agent Research UI 2026

Build a Streamlit UI for multi-agent research workflows. Agents search, extract, and synthesize. UI shows progress, sources, and lets users steer.

8 min

A Streamlit frontend paired with a LangGraph multi-agent backend creates a research UI where specialized agents handle web search, Reddit analysis, and synthesis. The user enters a research question, agents fan out to gather data from multiple sources, and the UI shows each agent's progress, raw search results, and the final synthesized answer with citations.

Architecture Overview

  • Streamlit frontend: input form, agent status panel, search results panel, synthesis output
  • LangGraph backend: orchestrates 3 agents (web researcher, Reddit analyst, synthesizer) as a state graph
  • Search grounding: web researcher and Reddit analyst each call the search API with different query strategies
  • State: LangGraph manages shared state between agents; Streamlit renders state updates via session_state

LangGraph Agent Graph

Python
from langgraph.graph import StateGraph, END
from typing import TypedDict
import requests, os

API_KEY = os.environ["SCAVIO_API_KEY"]

class ResearchState(TypedDict):
    question: str
    web_results: list
    reddit_results: list
    synthesis: str
    status: str

def web_researcher(state: ResearchState) -> dict:
    resp = requests.post(
        "https://api.scavio.dev/api/v1/search",
        headers={"x-api-key": API_KEY},
        json={"query": state["question"], "num_results": 10},
        timeout=15,
    )
    results = resp.json().get("results", [])
    return {
        "web_results": [{"title": r["title"], "url": r["url"],
                         "snippet": r.get("snippet", "")} for r in results],
        "status": "web_search_complete",
    }

def reddit_analyst(state: ResearchState) -> dict:
    query = f'{state["question"]} site:reddit.com'
    resp = requests.post(
        "https://api.scavio.dev/api/v1/search",
        headers={"x-api-key": API_KEY},
        json={"query": query, "num_results": 10},
        timeout=15,
    )
    results = resp.json().get("results", [])
    return {
        "reddit_results": [{"title": r["title"], "url": r["url"],
                            "snippet": r.get("snippet", "")} for r in results],
        "status": "reddit_analysis_complete",
    }

Synthesizer Agent

Python
from langchain_anthropic import ChatAnthropic

llm = ChatAnthropic(model="claude-sonnet-4-20250514")

def synthesizer(state: ResearchState) -> dict:
    web = state.get("web_results", [])
    reddit = state.get("reddit_results", [])
    sources = []
    for i, r in enumerate(web + reddit, 1):
        sources.append(f"[{i}] {r['title']}\n{r['snippet']}\nURL: {r['url']}")
    context = "\n\n".join(sources)
    prompt = f"""Synthesize an answer to this question using the sources below.
Cite sources inline using [1], [2], etc. Be specific and factual.

Question: {state['question']}

Sources:
{context}"""
    response = llm.invoke(prompt)
    return {"synthesis": response.content, "status": "complete"}

# Build the graph
graph = StateGraph(ResearchState)
graph.add_node("web_researcher", web_researcher)
graph.add_node("reddit_analyst", reddit_analyst)
graph.add_node("synthesizer", synthesizer)
graph.set_entry_point("web_researcher")
graph.add_edge("web_researcher", "reddit_analyst")
graph.add_edge("reddit_analyst", "synthesizer")
graph.add_edge("synthesizer", END)
research_chain = graph.compile()

Streamlit Frontend

Python
import streamlit as st

st.set_page_config(page_title="Research Agent", layout="wide")
st.title("Multi-Agent Research")

question = st.text_input("Research question")

if st.button("Research") and question:
    col1, col2 = st.columns(2)

    with st.spinner("Agents working..."):
        # Run the LangGraph chain
        result = research_chain.invoke({
            "question": question,
            "web_results": [],
            "reddit_results": [],
            "synthesis": "",
            "status": "started",
        })

    with col1:
        st.subheader("Web Results")
        for r in result["web_results"]:
            st.markdown(f"**{r['title']}**")
            st.caption(r["url"])
            st.write(r["snippet"])
            st.divider()

        st.subheader("Reddit Discussions")
        for r in result["reddit_results"]:
            st.markdown(f"**{r['title']}**")
            st.caption(r["url"])
            st.write(r["snippet"])
            st.divider()

    with col2:
        st.subheader("Synthesis")
        st.markdown(result["synthesis"])

Adding Real-Time Status Updates

Python
# Use Streamlit's session_state + callbacks for live status
if st.button("Research") and question:
    status_placeholder = st.empty()
    progress = st.progress(0)

    # Step 1: Web search
    status_placeholder.info("Searching the web...")
    progress.progress(25)
    web_state = web_researcher({"question": question})

    # Step 2: Reddit search
    status_placeholder.info("Analyzing Reddit discussions...")
    progress.progress(50)
    reddit_state = reddit_analyst({"question": question})

    # Step 3: Synthesis
    status_placeholder.info("Synthesizing findings...")
    progress.progress(75)
    full_state = {
        "question": question,
        **web_state,
        **reddit_state,
        "synthesis": "",
        "status": "",
    }
    final = synthesizer(full_state)
    progress.progress(100)
    status_placeholder.success("Research complete")

    st.markdown(final["synthesis"])

Cost per Research Query

  • Web search: 1 credit ($0.005)
  • Reddit search: 1 credit ($0.005)
  • LLM synthesis (Claude Sonnet): ~$0.01-0.03 depending on context size
  • Total per query: ~$0.02-0.04
  • 100 research queries/day: $2-4/day = $60-120/mo

Extending the System

Add more specialized agents without changing the UI: a TikTok trends agent for consumer research, a patent search agent for technical research, a news-only agent with date filtering. Each agent is a LangGraph node that calls the search API with a different query strategy. The synthesizer agent handles combining results regardless of how many source agents contributed. The Streamlit layout scales horizontally by adding columns or tabs for each agent's output.