← Back to list

LionAG2: Recursive Exploratory Research with AG2 beta — Typed multi-agent handoff

In the day 2 tutorial, we explored how to use ag2 to create structured output. To recap, the agent was granted the exa search tool and was…

Haiyang(Ocean) Li · 2026-05-13 19:29 · 2 claps · 3.0 min read
#ai-agent #ag2 #autogen #python #multi-agent-systems
Open on Medium ↗
Wiki topics: AGT · AI Agents FT · Fine-tuning & Adaptation

LionAG2: Recursive Exploratory Research with AG2 beta — Typed multi-agent handoff

In the day 2 tutorial, we explored how to use ag2 to create structured output. To recap, the agent was granted the exa search tool and was asked to create a structured output as a Finding with citations.

from pydantic import BaseModel

class Citation(BaseModel):
    title: str = Field(description="The cited work or source.")
    relevance: str = Field(description="One sentence on why this source supports the finding.")

class Finding(BaseModel):
    """One self-contained research result."""
    topic: str = Field(description="The specific aspect of the question this finding addresses.")
    summary: str = Field(description="2-3 sentences capturing the core mechanism or claim.")
    citations: list[Citation] = Field(description="Sources behind the summary; emit [] if none.")
    novelty: float = Field(ge=0.0, le=1.0, description="0 = textbook, 1 = cutting edge.")

The structured output is handy for downstream data manipulation and adding conditions to the agentic workflows. In today’s tutorial, we will look into how to use structured output to create a multi-agent handoff workflow.

Setup

import os

from dotenv import load_dotenv
from IPython.display import Markdown, display
from pydantic import BaseModel, Field

from autogen.beta import Agent
from autogen.beta.config import OpenAIConfig
from autogen.beta.tools import ExaToolkit

load_dotenv()

config = OpenAIConfig(
    model="gpt-5.4-mini",
    api_key=os.getenv("OPENAI_API_KEY"),
    base_url="https://api.openai.com/v1",
)
exa_tool = ExaToolkit(api_key=os.getenv("EXA_API_KEY"))

The schema from before was quite straightforward — produce a finding with citations from search results. Let’s add some richer schemas:

class OpenQuestion(BaseModel):
    question: str = Field(description="A specific unresolved question surfaced by the survey.")
    novelty: float = Field(
        ge=0.0, le=1.0,
        description="0 = well-studied, 1 = barely explored.",
    )

class Survey(BaseModel):
    """Surveyor output: landscape of a topic plus open frontiers."""
    topic: str
    overview: str = Field(description="2-3 sentence summary of the current state of knowledge.")
    key_findings: list[str] = Field(description="Major established results (3-5 bullets).")
    open_questions: list[OpenQuestion] = Field(
        description="Unresolved questions ranked by novelty. At least 2.",
    )

class Hypothesis(BaseModel):
    """Theorist output: one falsifiable claim with a test."""
    claim: str = Field(description="One-sentence falsifiable claim.")
    mechanism: str = Field(description="Why this claim might hold — the causal story.")
    testable_prediction: str = Field(
        description="An observable that would confirm or refute the claim."
    )
    confidence: float = Field(ge=0.0, le=1.0, description="Subjective confidence in the claim.")
    source_question: str = Field(description="The open question this hypothesis addresses.")

OpenQuestion carries a novelty score, this will become the key signal for deciding which questions are worth drilling deeper into.

Pipeline

The pipeline today will go as follows:

  • a surveyor agent will conduct survey via search tools over literature and produce a survey object with open questions
  • for each open question, we will launch one theorist agent will then take to research further and create hypothesis
topic = "high-Tc superconductivity"

surveyor = Agent(
    name="surveyor",
    prompt=(
        f"You are a meticulous research surveyor. Search broadly on {topic}"
        ", then summarize what is known and what remains open. Be specific "
        "about novelty — textbook material is 0.0, active frontiers are 0.7+."
    ),
    config=config,
    response_schema=Survey,
    tools=[exa_tool],
)

survey_reply = await surveyor.ask(
    "Survey the current state of high-Tc superconductivity research."
)
survey = await survey_reply.content()

The survey is a pydantic object of type Survey(BaseModel) as defined above, and now since we have more than one open questions, we can launch parallel theorists to investigate them at the same time.

async def hypothesize(question: OpenQuestion, survey=survey) -> Hypothesis:
  theorist = Agent(
      name="theorist",
      prompt=(
          "You are a theoretical physicist. Given a survey and an open question, "
          "produce a precise, falsifiable hypothesis. Be concrete about the "
          "mechanism and what experiment would test it."
      ),
      config=config,
      response_schema=Hypothesis,
      tools=[exa_tool],
  )

  theorist_prompt = (
      f"Survey topic: {survey.topic}\n"
      f"Overview: {survey.overview}\n\n"
      f"Key findings:\n"
      + "\n".join(f"- {kf}" for kf in survey.key_findings)
      + f"\n\nFocus on this open question (novelty={question.novelty:.2f}):\n"
      f"{question.question}\n\n"
      f"Produce a falsifiable hypothesis with a concrete testable prediction."

  hyp_reply = await theorist.ask(theorist_prompt)
  return await hyp_reply.content()

results = await asyncio.gather(*(hypothesize(q) for q in survey.open_questions))

Let’s view the result

for i, hyp in enumerate(results):
    lines = [
        f"### Hypothesis {i+1}",
        f"**Claim:** {hyp.claim}",
        f"**Mechanism:** {hyp.mechanism}",
        f"**Test:** {hyp.testable_prediction}",
        f"**Confidence:** {hyp.confidence:.2f}",
        f"**Addresses:** {hyp.source_question}",
    ]
    display(Markdown("\n\n".join(lines)))

Note there are multiple hypothesis because each open question was processed by one theorist, and this is the basic mechanism of hierarchical multi-agent orchestration.

In the next tutorial we will introduce the concept of event in ag2, and dive deeper into multi agent orchestration.

check the notebook here


메타데이터
post_id
fb752f9c0265
slug
lionag2-recursive-exploratory-research-with-ag2-beta-typed-multi-agent-handoff-fb752f9c0265
url
https://medium.com/@haiyangli_38602/lionag2-recursive-exploratory-research-with-ag2-beta-typed-multi-agent-handoff-fb752f9c0265
canonical_url
https://medium.com/@haiyangli_38602/lionag2-recursive-exploratory-research-with-ag2-beta-typed-multi-agent-handoff-fb752f9c0265
author_url
https://medium.com/@haiyangli_38602
status
ok
fetched_at
2026-06-09 15:37:30