agno Agent 输入输出实用指南:6 个机制控制它说什么、怎么说
【免费下载链接】agnoBuild, run, and manage agent platforms.项目地址: https://gitcode.com/GitHub_Trending/ag/agno
agno 是一个用 Python 构建、运行和管理 Agent 平台的框架。实际用起来你会发现,光让 Agent "能跑"远远不够:回复格式不可控、输入只是一段没法校验的字符串、输出是纯文本而下游却要结构化数据。本文从 agno Agent 输入输出的四个痛点切入——约束格式、校验输入、拿结构化结果、落盘与流式消费,每个场景都给出可直接运行的最小代码。读完你会清楚每种需求该配哪个Agent参数。
如何约束 Agent 回复格式:expected_output 指定成品规格
🎯 一句话机制:expected_output用一句自然语言告诉模型"最终回复长什么样",它管的是成品形态,而行为规则仍然归instructions管。
from agno.agent import Agent from agno.models.openai import OpenAIResponses agent = Agent( model=OpenAIResponses(id="gpt-5.2"), # 给模型一个"交付物规格":恰好 5 条,每条含标题 + 一句话描述 expected_output="A numbered list of exactly 5 items, each with a title and one-sentence description.", markdown=True, ) if __name__ == "__main__": agent.print_response("What are the most important principles of clean code?", stream=True)这段代码做的事很直白:模型回答什么内容由问题决定,但"必须编号列表、恰好 5 条、每条一句"由expected_output钉死。markdown=True则让输出按 Markdown 渲染。实际跑下来,它只影响回复结构,不增加额外模型调用。
📌 什么时候用:只关心"长什么样"、不关心"内容怎么来"的场景。需要约束行为逻辑时请改用instructions。
如何传入结构化输入:消息字典与 Pydantic 校验
图文等多模态内容直接拼进消息字典
print_response的第一个参数除了字符串,还可以直接传消息字典。这样就能在代码里组装文本 + 图片的混合输入:
if __name__ == "__main__": agent.print_response( { "role": "user", "content": [ {"type": "text", "text": "What's in this image?"}, {"type": "image_url", "image_url": {"url": "https://example.com/photo.jpg"}}, ], }, stream=True, markdown=True, )不用在提示词里绕弯说"请看这张图",直接把多段content塞进字典,模型同时拿到文字和图片。解析层开销极低,适合程序化拼接的多模态场景。
用 Pydantic 模型给输入定契约
input_schema接收一个 Pydantic 模型类,Agent 会把传入的字典按这个契约做校验和归一化:
from typing import List from agno.agent import Agent from agno.models.openai import OpenAIResponses from agno.tools.hackernews import HackerNewsTools from pydantic import BaseModel, Field class ResearchTopic(BaseModel): topic: str focus_areas: List[str] = Field(description="Specific areas to focus on") target_audience: str sources_required: int = Field(default=5) hackernews_agent = Agent( name="Hackernews Agent", model=OpenAIResponses(id="gpt-5-mini"), tools=[HackerNewsTools()], input_schema=ResearchTopic, ) if __name__ == "__main__": # 传字典即可,内部按 ResearchTopic 校验;也可以直接传 Pydantic 实例 hackernews_agent.print_response( input={ "topic": "AI", "focus_areas": ["AI", "Machine Learning"], "target_audience": "Developers", "sources_required": 5, } )字典进来,规范化后出去:无论字段顺序、类型怎么变(比如数字写成字符串),Pydantic 的宽松转换都会兜住,Agent 内部只见到符合契约的数据。这个示例挂了HackerNewsTools,所以实际执行是多轮工具推理,跑起来比单次生成明显慢。
📌 注意:input_schema只接受 Pydantic 模型类,不支持用裸字典定义。
结构化输出三条路径:schema、parser_model、output_model
让模型直接吐出 Pydantic 对象(output_schema)
output_schema支持 Pydantic 模型类和 JSON Schema 字典两种写法,配好后run.content直接就是结构化对象,不再是字符串:
from typing import List from agno.agent import Agent, RunOutput from agno.models.openai import OpenAIResponses from pydantic import BaseModel, Field from rich.pretty import pprint class BreakingNewsSummary(BaseModel): topic: str summary: str key_updates: List[str] overall_sentiment: str agent = Agent( model=OpenAIResponses(id="gpt-5.2"), description="You summarize current events into clean structured outputs.", output_schema=BreakingNewsSummary, ) if __name__ == "__main__": run: RunOutput = agent.run("Latest news from France?") pprint(run.content) # 拿到的是 BreakingNewsSummary 实例,字段可直接取下游拿到run.content就能按字段取值,省掉一切"从文本里抠 JSON"的脏活。
让第二个模型负责解析(parser_model)
主模型照常推理、调工具,另一个parser_model专门把结果转成目标结构:
agent = Agent( model=OpenAIResponses(id="gpt-5.2"), description="You help people plan amazing national park adventures.", output_schema=NationalParkAdventure, # 11 个字段,可用 Field(ge=..., le=...) 约束数值范围 parser_model=OpenAIResponses(id="gpt-5.2"), ) if __name__ == "__main__": run: RunOutput = agent.run("Yosemite National Park")主模型只管内容,格式遵循交给解析模型,适合主模型输出不可控或本身弱于格式约束的情况。结构化 JSON 输出建议改用 parser_model,而不是让主模型硬扛格式。代价是多一次模型调用,耗时会相应变长。
让第二个模型重写最终回复(output_model)
output_model接收同一轮对话并自己生成回复,直接替换主模型输出。典型玩法是便宜模型做推理和工具调用,强模型做最终润色:
agent = Agent( model=OpenAIResponses(id="gpt-5-mini"), description="You are a helpful chef that provides detailed recipe information.", output_model=OpenAIResponses(id="gpt-5.2"), output_model_prompt="Rewrite the recipe with vivid descriptions and elegant formatting.", ) if __name__ == "__main__": run: RunOutput = agent.run("Give me a recipe for pad thai.")这是"内容精修"而非"结构抽取":需要 JSON 时请走output_schema/parser_model,output_model负责的是把答案写得更好。
响应落盘与流式消费
save_response_to_file 自动落盘
配置一个路径,Agent 每次运行完就把回复写进该文件:
import os from agno.agent import Agent from agno.models.openai import OpenAIResponses agent = Agent( model=OpenAIResponses(id="gpt-5.2"), save_response_to_file="tmp/agent_output.md", ) if __name__ == "__main__": os.makedirs("tmp", exist_ok=True) # 父目录需要自己保证存在 agent.print_response("Write a brief guide on Python virtual environments.", stream=True)跑完终端照常流式显示,文件里同时留了一份存档,适合结果需要归档或人工复核的场景。💾 注意:目录不存在会写失败,示例里显式os.makedirs就是在处理这一点。
run() 捕获变量与事件流
print_response面向人眼,程序化处理要改用run():
# 整个 RunOutput 进变量,后续随便取字段 run: RunOutput = agent.run("What is the stock price of NVDA") # 加 stream=True 后返回事件迭代器,逐个消费 for event in agent.run("What is the stock price of NVDA", stream=True): print(event)前者把完整运行结果(含结构化 content、元数据)交到手里;后者返回事件流,配合stream=True可逐事件处理,是生产集成里做前端推送、日志打点的标准姿势。
参数速查表
| 参数 | 作用 | 默认行为 | 适用场景 |
|---|---|---|---|
expected_output | 自然语言描述回复成品的形态 | 不设置,模型自由发挥 | 只约束格式(条数、列表、标题),不要求程序取值 |
input_schema | 用 Pydantic 模型类校验并归一化输入 | 输入即字符串,无校验 | 调用方传参需要字段契约与类型兜底 |
output_schema | 把输出限定为结构化对象,支持模型类或 JSON Schema 字典 | 输出为纯文本 | 下游需要直接按字段消费 |
parser_model | 指定独立解析模型,承担结构化抽取 | 由主模型自己输出 | 主模型输出不可控、弱于格式遵循 |
output_model | 第二模型重写最终回复并替换主模型输出 | 主模型输出即最终版 | 便宜模型推理 + 强模型精修的分工 |
save_response_to_file | 运行结束自动把回复写入指定文件 | 不落盘 | 结果需要归档、审计 |
跑起来
按 cookbook/02_agents/02_input_output/ 的前置说明配置好环境变量与 demo 环境后,逐文件复现:
.venvs/demo/bin/python cookbook/02_agents/02_input_output/streaming.py💡 下一步建议:先定"输出要什么形态"。只要文本就用expected_output收个尾;要字典就加output_schema,主模型跟不上格式再叠parser_model。同目录下的 followup_suggestions.py 还演示了followups追问建议的生成方式,值得接着看。
【免费下载链接】agnoBuild, run, and manage agent platforms.项目地址: https://gitcode.com/GitHub_Trending/ag/agno
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考