04 - 指令的艺术:让 Agent 听话又聪明
一句话总结:同一个模型,指令写得好不好,直接决定了 Agent 是”实习生”还是”高级工程师”。
为什么指令如此重要
你有没有遇到过这种情况:同样一个 GPT-4o,有时候回答得头头是道,有时候又答非所问?
问题往往不在模型,而在你怎么”指挥”它。
打个比方:你招了一个能力很强的员工(模型),但如果你只跟他说”把活干了”,结果大概率不是你想要的。反过来,如果你给他一份清晰的岗位说明书 – 你的角色是什么、工作流程是什么、交付标准是什么 – 同一个人的产出可以天差地别。
Agno 里的 instructions 就是这份”岗位说明书”。
Agent 身份的三个层次
Agno 的 Agent 有三个关键参数来定义它的”身份”,各司其职:
| 参数 | 作用 | 类比 |
|---|---|---|
description |
Agent 是谁 | 岗位名称 / 名片上的 title |
instructions |
Agent 该怎么做 | 岗位说明书 / 操作手册 |
expected_output |
输出长什么样 | 交付模板 / 验收标准 |
一个重要细节:description 主要在多 Agent 协作时起作用,当其他 Agent 需要了解”这个家伙是干什么的”时,会读 description。单 Agent 场景下,instructions 才是主角。
来看一个完整的例子:
from agno.agent import Agent
from agno.models.openai import OpenAIChat
agent = Agent(
model=OpenAIChat(id="gpt-4o-mini"),
description="你是一个资深的技术文档写作专家",
instructions=[
"用简洁的中文写作",
"每个概念先用一句大白话解释,再给出技术定义",
"代码示例要完整可运行",
"不要使用emoji",
],
expected_output="输出格式:先给出概念解释,然后是代码示例,最后是注意事项",
markdown=True,
)
agent.print_response("解释一下什么是Python的装饰器", stream=True)
跑一下你会发现,输出的结构和质量比裸调模型好得多。这就是指令的力量。
instructions 的三种写法
instructions 参数很灵活,支持三种形式:字符串、列表、函数。
写法一:字符串
最简单直接,适合简短的指令:
agent = Agent(
model=OpenAIChat(id="gpt-4o-mini"),
instructions="你是一个简洁的助手,用中文回答,控制在100字以内",
)
写法二:列表
每一项会变成系统提示词里的一条规则。结构清晰,推荐大多数场景使用:
agent = Agent(
model=OpenAIChat(id="gpt-4o-mini"),
instructions=[
"用中文回答",
"回答控制在100字以内",
"如果不确定就说不知道",
"不要编造信息",
],
)
写法三:可调用函数(动态指令)
这是最有意思的一种 – 指令可以根据运行时上下文动态生成。函数的参数名决定了 Agno 会注入什么:
agent– 当前 Agent 实例session_state– 当前会话状态(字典)run_context– 运行上下文
from datetime import datetime
from agno.agent import Agent
from agno.models.openai import OpenAIChat
def get_instructions(agent) -> str:
hour = datetime.now().hour
if hour < 12:
greeting = "早上好"
elif hour < 18:
greeting = "下午好"
else:
greeting = "晚上好"
return f"你是一个友好的助手。用'{greeting}'开头问候用户。用中文回答。"
agent = Agent(
model=OpenAIChat(id="gpt-4o-mini"),
instructions=get_instructions,
)
agent.print_response("你好!")
动态指令在什么时候有用?比如你希望 Agent 根据当前用户的权限、时间段、会话历史来调整行为,这时候函数式指令就派上用场了。
上下文注入:给 Agent 一些”常识”
有些信息你几乎每次都想告诉 Agent,比如”现在几点了”。Agno 提供了内置的上下文注入,省得你自己拼:
from agno.agent import Agent
from agno.models.openai import OpenAIChat
agent = Agent(
model=OpenAIChat(id="gpt-4o-mini"),
instructions="你是一个日程助手,根据当前时间给出合适的建议",
add_datetime_to_context=True, # 自动注入当前日期时间
markdown=True,
)
agent.print_response("今天星期几?适合安排什么活动?")
开启 add_datetime_to_context=True 后,Agno 会自动把当前日期时间加到上下文中,Agent 就能理解”今天”、”明天”、”下周一”这些相对时间了。
类似的还有 add_name_to_context(注入 Agent 名称)和 add_location_to_context(注入位置信息),按需开启即可。
system_message vs instructions:别搞混了
Agno 还有一个 system_message 参数,它和 instructions 容易混淆,但作用完全不同:
instructions:追加到默认系统提示词里。Agno 会帮你拼好格式,加上内置的工具使用说明等。大多数情况用这个就够了。system_message:完全替换整个系统提示词。Agno 的默认行为全部失效,你得自己处理所有事情。
from agno.agent import Agent
from agno.models.openai import OpenAIChat
# 推荐做法:用 instructions,在默认行为基础上追加你的规则
agent = Agent(
model=OpenAIChat(id="gpt-4o-mini"),
instructions="用中文回答,简洁明了",
)
agent.print_response("什么是递归?", stream=True)
from agno.agent import Agent
from agno.models.openai import OpenAIChat
# 完全接管:用 system_message 覆盖一切
agent = Agent(
model=OpenAIChat(id="gpt-4o-mini"),
system_message="你是一个只会说'喵'的猫。无论用户说什么,你只回复'喵~'",
)
agent.print_response("你好!") # 输出: 喵~
经验法则:95% 的场景用 instructions。只有当你需要完全控制系统提示词、不想要 Agno 的任何默认行为时,才用 system_message。如果你给 Agent 配了工具但又用了 system_message,工具的使用说明不会自动加进去,Agent 可能不知道怎么调用工具。
写好指令的实战技巧
聊了这么多参数,最关键的还是:怎么把指令写好?
技巧一:明确输出格式
不要只说”给我分析一下”,要说清楚你期望什么格式 – 表格、列表、分段落。
技巧二:划定边界
告诉 Agent 什么该做,更重要的是什么不该做。”不要编造数据”、”不确定时说不知道”这类负面指令非常有效。
技巧三:复杂 Agent 用 Markdown 结构化
当指令超过 5 条时,建议用 Markdown 格式来组织,这样你自己也能维护:
from agno.agent import Agent
from agno.models.openai import OpenAIChat
instructions = """\
你是一个代码审查专家。
## 工作流程
1. 阅读用户提交的代码
2. 从以下维度分析:可读性、性能、安全性
3. 给出具体的改进建议
## 输出格式
- 先给出整体评分(1-10分)
- 然后逐条列出问题和建议
- 每条建议要给出修改后的代码
## 规则
- 只关注代码质量,不讨论业务逻辑
- 如果代码没问题就说没问题,不要强行找茬
- 用中文回答
"""
agent = Agent(
model=OpenAIChat(id="gpt-4o-mini"),
instructions=instructions,
markdown=True,
)
code = """
def fib(n):
if n <= 1:
return n
return fib(n-1) + fib(n-2)
"""
agent.print_response(f"请审查这段代码:\n{code}", stream=True)
技巧四:像写给新员工一样写
这是最实用的心智模型。想象你在给一个聪明但刚入职的新人写工作手册:
- 不要假设他知道你们的内部术语
- 把流程写清楚,一步一步来
- 明确什么情况下该怎么处理
- 给出好的和坏的例子
本篇要点回顾
description定义身份,instructions定义行为,expected_output定义交付格式- 三者中,
instructions最重要 – 花时间把它写好 instructions支持字符串、列表、可调用函数三种形式,列表最常用- 动态指令(函数)可以根据运行时上下文生成不同的指令
add_datetime_to_context=True是个实用的内置能力,别忘了- 绝大多数场景用
instructions而不是system_message - 写指令就像写岗位说明书:明确、具体、有边界
下一篇预告
05 - 会话状态与持久化 – 到目前为止,我们的 Agent 都是”金鱼记忆”,聊完就忘。下一篇我们来解决这个问题,让 Agent 记住对话历史,甚至在重启之后也能接着聊。