Structured deliverable
Return a typed decision with the call, conviction, allocation, rationale, and citations.
Make the final pipeline step return a typed decision that downstream code can validate and use. Define the call, conviction, allocation, rationale, and citations in a Pydantic schema, then pass it as the final agent's output_schema.
These are composition examples adapted from the Investment Team application. Follow its clone, database, credentials, and research-loading setup for a complete application. Its agents/, teams/, and workflows/ define the components referenced here; agents/settings.py supplies shared knowledge and paths.
Import those components into your application module, or define your own before composing them. The application uses Gemini; the OpenAI variants on these pages require uv pip install "agno[openai]" and OPENAI_API_KEY as well. Shared knowledge/storage still needs the application's database and embedding-provider setup. Prose context, analyst-output variables, and local archives must be supplied by your application.
from typing import List, Literal
from agno.agent import Agent
from agno.models.openai import OpenAIResponses
from pydantic import BaseModel, Field
class Decision(BaseModel):
call: Literal["BUY", "HOLD", "PASS"] = Field(..., description="The committee decision")
conviction: Literal["low", "medium", "high"] = Field(..., description="Confidence in the call")
allocation_usd: float = Field(..., description="Dollar allocation, 0 if not BUY")
rationale: str = Field(..., description="Why, referencing the analyst inputs")
citations: List[str] = Field(..., description="Sources and prior memos used")
chair = Agent(
name="Committee Chair",
model=OpenAIResponses(id="gpt-5.5"),
output_schema=Decision,
instructions=(
"Synthesize the analyst inputs into a decision. Every BUY needs a "
"dollar amount. Every decision must reference at least one risk."
),
)
def briefing(*analyst_outputs: str) -> str:
return "Analyst inputs:\n\n" + "\n\n".join(analyst_outputs)
result = chair.run(briefing(market, fundamentals, technicals, risk)).content
# Decision(call='BUY', conviction='high', allocation_usd=2_000_000.0,
# rationale='Momentum and fundamentals align; sized within the
# sector cap the Risk Officer set.',
# citations=['memo:NVDA-2024Q3', 'research:semiconductors'])output_schema=Decision requests a parsed Decision. If output parsing fails, content can remain a string. Check that the run completed and isinstance(run.content, Decision) before reading fields or acting on the result.
The chair weighs the specialists' inputs and commits to a call. Its configuration omits tools and supplies a briefing as context. That does not guarantee that every conclusion is supported by the briefing; validate claims against the supplied evidence.
Decision and memo
A research system usually produces both a machine-actionable decision and a human-readable memo.
| Artifact | Form | Consumer |
|---|---|---|
| Decision | Typed object (output_schema) | Downstream automation, dashboards, audit |
| Memo | Markdown written to disk | Humans, the next review's context |
The memo is written by a dedicated agent with file tools and a fixed template, then archived. The next review reads it back as prior work. The decision is the row you store and act on.
Required decision fields
| Field | Purpose |
|---|---|
conviction | Lets you threshold: act on high, queue medium for review |
rationale | Records the reasoning trail for review and audit |
citations | Carries source identifiers for downstream verification |
The schema requires a citations field but allows an empty list and does not check source identifiers. Before a downstream action, application code should require the necessary citations, resolve them against the actual research, and enforce its allocation and action thresholds.
Add approval for consequential actions
When a decision triggers a real action, such as moving capital or publishing a number, add human approval before the action executes. See human approval.
Next steps
| Task | Guide |
|---|---|
| Carry the memo into the next run | Grounding research |
| Make decisions improve over time | Institutional learning |
| Serve the decision to a surface | Serve and embed |