The search agent returns a paragraph of live web content. You want a structured fact and its source. What is the natural next step?
Feed the paragraph into a second agent with a Pydantic result_type? The pattern from Day 10, but on live search output?
Exactly. Two agents, two responsibilities. The first retrieves the content, the second extracts. Here is the Pydantic model that enforces the shape:
from pydantic import BaseModel
class Fact(BaseModel):
fact: str
source: strTwo fields — the single most important fact from the retrieved text, and the name of the source it came from.
Why two agents? Couldn't I set result_type=Fact on the search agent itself and skip one call?
You can, and for quick prototypes it works. For production, splitting the jobs is more reliable. Perplexity's search model is tuned for retrieval — finding and summarizing web content. A dedicated extraction agent with a narrow system_prompt is better at enforcing a strict schema. When you ask the same model to retrieve and extract simultaneously, structured-output compliance drops:
def research_and_extract(query: str) -> dict:
search_agent = Agent(model)
search_result = search_agent.run_sync(query).output
extract_agent = Agent(
model,
result_type=Fact,
system_prompt="Extract the single most important fact from the text and its source (website or publication name)."
)
return extract_agent.run_sync(search_result).output.model_dump()Both agents use the same model variable? The search agent does the retrieving, the extract agent does the parsing?
Same model object, different roles. Perplexity is fine for both — retrieval happens inside the model automatically when you pass a query that wants it; extraction happens because result_type=Fact enforces the schema. The second agent never touches the web; it only sees the text the first one retrieved.
So the chain is query → search agent → string → extract agent → Fact → .model_dump() → dict. Each arrow is one variable hop.
That is the whole pattern. Agents are functions, their outputs are values, and the pipeline is a chain of variables. Write research_and_extract(query) now: search, then extract with result_type=Fact, return the dict.
TL;DR: search agent retrieves, extract agent enforces the schema.
result_type; raw string from Perplexityresult_type=Fact + focused system_prompt.model_dump() — Pydantic instance → plain dict| Step | Type |
|---|---|
search_agent.run_sync(query) | RunResult |
.output | str |
extract_agent.run_sync(str) | RunResult[Fact] |
.output.model_dump() | dict |
Separation of retrieval and extraction keeps each agent narrow and reliable.
The search agent returns a paragraph of live web content. You want a structured fact and its source. What is the natural next step?
Feed the paragraph into a second agent with a Pydantic result_type? The pattern from Day 10, but on live search output?
Exactly. Two agents, two responsibilities. The first retrieves the content, the second extracts. Here is the Pydantic model that enforces the shape:
from pydantic import BaseModel
class Fact(BaseModel):
fact: str
source: strTwo fields — the single most important fact from the retrieved text, and the name of the source it came from.
Why two agents? Couldn't I set result_type=Fact on the search agent itself and skip one call?
You can, and for quick prototypes it works. For production, splitting the jobs is more reliable. Perplexity's search model is tuned for retrieval — finding and summarizing web content. A dedicated extraction agent with a narrow system_prompt is better at enforcing a strict schema. When you ask the same model to retrieve and extract simultaneously, structured-output compliance drops:
def research_and_extract(query: str) -> dict:
search_agent = Agent(model)
search_result = search_agent.run_sync(query).output
extract_agent = Agent(
model,
result_type=Fact,
system_prompt="Extract the single most important fact from the text and its source (website or publication name)."
)
return extract_agent.run_sync(search_result).output.model_dump()Both agents use the same model variable? The search agent does the retrieving, the extract agent does the parsing?
Same model object, different roles. Perplexity is fine for both — retrieval happens inside the model automatically when you pass a query that wants it; extraction happens because result_type=Fact enforces the schema. The second agent never touches the web; it only sees the text the first one retrieved.
So the chain is query → search agent → string → extract agent → Fact → .model_dump() → dict. Each arrow is one variable hop.
That is the whole pattern. Agents are functions, their outputs are values, and the pipeline is a chain of variables. Write research_and_extract(query) now: search, then extract with result_type=Fact, return the dict.
TL;DR: search agent retrieves, extract agent enforces the schema.
result_type; raw string from Perplexityresult_type=Fact + focused system_prompt.model_dump() — Pydantic instance → plain dict| Step | Type |
|---|---|
search_agent.run_sync(query) | RunResult |
.output | str |
extract_agent.run_sync(str) | RunResult[Fact] |
.output.model_dump() | dict |
Separation of retrieval and extraction keeps each agent narrow and reliable.
Create a free account to get started. Paid plans unlock all tracks.