1. 什么是 AgentOS 依赖传递?
AgentOS 依赖传递是一种强大的机制,允许在运行时向 Agent 注入动态上下文和参数。通过这种方式,您可以创建更加灵活、可配置的 Agent 系统,适应各种复杂的业务场景。
2. 核心概念
2.1 依赖(Dependencies)
依赖是指在 Agent 执行过程中需要的动态参数或上下文信息。依赖可以是:
– 基本数据类型(字符串、数字、布尔值等)
– 复杂数据类型(字典、列表等)
– 可调用对象(函数、方法等)
– 协程函数(仅在异步环境中支持)
2.2 模板变量
模板变量是指在 Agent 指令或用户消息中使用的占位符,格式为 {variable_name}。这些变量会在运行时被依赖中的对应值替换。
2.3 运行上下文(RunContext)
运行上下文是存储依赖和其他运行时信息的对象,贯穿整个 Agent 运行过程。
3. 示例代码分析
让我们详细分析 pass_dependencies_to_agent.py 示例代码:
3.1 代码结构
"""Example for AgentOS to show how to pass dependencies to an agent."""
from agno.agent import Agent
from agno.db.postgres import PostgresDb
from agno.os import AgentOS
Setup the database
db = PostgresDb(id="basic-db", db_url="postgresql+psycopg://ai:ai@localhost:5532/ai")
Setup basic agents, teams and workflows
story_writer = Agent(
id="story-writer-agent",
name="Story Writer Agent",
db=db,
markdown=True,
instructions="You are a story writer. You are asked to write a story about a robot. Always name the robot {robot_name}",
)
Setup our AgentOS app
agent_os = AgentOS(
description="Example AgentOS to show how to pass dependencies to an agent",
agents=[story_writer],
)
app = agent_os.get_app()
if __name__ == "__main__":
"""Run your AgentOS.
Test passing dependencies to an agent:
curl --location 'http://localhost:7777/agents/story-writer-agent/runs'
--header 'Content-Type: application/x-www-form-urlencoded'
--data-urlencode 'message=Write me a 5 line story.'
--data-urlencode 'dependencies={"robot_name": "Anna"}'
"""
agent_os.serve(app="pass_dependencies_to_agent:app", reload=True)
3.2 关键组件解析
#### 3.2.1 数据库设置
db = PostgresDb(id="basic-db", db_url="postgresql+psycopg://ai:ai@localhost:5532/ai")
– 创建了一个 Postgres 数据库实例,用于存储 Agent 的运行数据
– id 参数用于标识数据库实例
– db_url 参数指定了数据库连接 URL
#### 3.2.2 Agent 创建
story_writer = Agent(
id="story-writer-agent",
name="Story Writer Agent",
db=db,
markdown=True,
instructions="You are a story writer. You are asked to write a story about a robot. Always name the robot {robot_name}",
)
– 创建了一个故事编写 Agent
– id 和 name 参数用于标识和命名 Agent
– db 参数指定了 Agent 使用的数据库
– markdown=True 表示 Agent 的输出将使用 Markdown 格式
– instructions 参数包含了 Agent 的核心指令,其中 {robot_name} 是一个模板变量,将在运行时被替换
#### 3.2.3 AgentOS 应用设置
agent_os = AgentOS(
description="Example AgentOS to show how to pass dependencies to an agent",
agents=[story_writer],
)
app = agent_os.get_app()
– 创建了一个 AgentOS 应用实例
– description 参数描述了应用的功能
– agents 参数指定了应用中包含的 Agent 列表
– get_app() 方法返回一个 FastAPI 应用实例,用于启动 Web 服务
#### 3.2.4 启动服务
if __name__ == "__main__":
agent_os.serve(app="pass_dependencies_to_agent:app", reload=True)
– 启动 AgentOS 服务
– app 参数指定了要启动的应用
– reload=True 表示在开发模式下自动重载代码
4. 依赖传递流程
4.1 API 调用示例
curl --location 'http://localhost:7777/agents/story-writer-agent/runs'
--header 'Content-Type: application/x-www-form-urlencoded'
--data-urlencode 'message=Write me a 5 line story.'
--data-urlencode 'dependencies={"robot_name": "Anna"}'
这个 curl 命令演示了如何通过 API 向 Agent 传递依赖:
– message 参数包含了用户请求
– dependencies 参数包含了要传递的依赖,这里是 {"robot_name": "Anna"}
4.2 依赖传递的完整流程
1. 接收请求:AgentOS 接收 API 请求,包含用户消息和依赖
2. 创建运行上下文:为当前运行创建一个 RunContext 对象
3. 传递依赖:将 dependencies 中的值存储到 RunContext 中
4. 解析依赖:如果依赖是可调用对象,执行它们并将结果存储到 RunContext 中
5. 模板替换:使用 RunContext 中的依赖值替换 Agent 指令和用户消息中的模板变量
– 替换前:"You are a story writer. You are asked to write a story about a robot. Always name the robot {robot_name}"
– 替换后:"You are a story writer. You are asked to write a story about a robot. Always name the robot Anna"
6. 模型调用:将处理后的消息发送给 LLM 模型
7. 返回结果:将模型生成的结果返回给用户
5. 依赖的类型和使用
5.1 基本数据类型依赖
最常见的依赖类型是基本数据类型,如字符串、数字等:
# API 调用示例
dependencies={"robot_name": "Anna", "story_length": 5}
对应的 Agent 指令
instructions="You are a story writer. Write a {story_length} line story about a robot named {robot_name}"
5.2 复杂数据类型依赖
依赖也可以是复杂数据类型,如字典或列表:
# API 调用示例
dependencies={
"robot": {
"name": "Anna",
"type": "service robot",
"color": "blue"
},
"story_elements": ["adventure", "friendship", "discovery"]
}
对应的 Agent 指令
instructions="You are a story writer. Write a story about a {robot.type} named {robot.name} with the following elements: {story_elements}"
5.3 可调用对象依赖
依赖可以是函数或方法,这些函数会在运行时被执行,其结果会被用作依赖值:
# 定义一个依赖函数
def get_current_time(run_context):
from datetime import datetime
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
代码调用示例
agent.run(
"Write a story about a robot created on {creation_date}",
dependencies={"creation_date": get_current_time}
)
当依赖是可调用对象时,Agent 会根据其签名自动注入以下参数:
– agent:当前 Agent 实例
– run_context:当前运行上下文对象
6. 依赖的作用域
6.1 全局依赖
全局依赖是在 Agent 初始化时定义的,对所有运行有效:
story_writer = Agent(
id="story-writer-agent",
instructions="You are a story writer. Always name the robot {robot_name}",
dependencies={"robot_name": "DefaultRobot"} # 全局依赖
)
6.2 局部依赖
局部依赖是在运行时传递的,仅对当前运行有效,会覆盖全局依赖:
# API 调用示例,局部依赖会覆盖全局依赖
dependencies={"robot_name": "Anna"}
7. 技术实现细节
7.1 依赖解析机制
Agent 提供了两种依赖解析方法:
– 同步解析:_resolve_run_dependencies – 用于同步执行场景
– 异步解析:_aresolve_run_dependencies – 用于异步执行场景
依赖解析过程包括以下步骤:
1. 验证依赖是否为字典类型
2. 逐个处理依赖项
3. 如果值是可调用对象,执行它并获取结果
4. 将结果更新到 RunContext 中
5. 如果值是普通值,直接存储到 RunContext 中
7.2 模板替换机制
模板替换是通过 Python 的字符串格式化功能实现的,使用 str.format(**dependencies) 方法将模板变量替换为实际值。
7.3 依赖的注入参数
当依赖是可调用对象时,Agent 会使用反射机制分析其签名,并自动注入以下参数:
– agent:当前 Agent 实例
– run_context:当前运行上下文对象
8. 最佳实践
8.1 使用明确的依赖键名
选择清晰、描述性的键名,便于理解和维护:
# 好的做法
dependencies={"robot_name": "Anna", "story_genre": "science fiction"}
不好的做法
dependencies={"rn": "Anna", "sg": "scifi"}
8.2 避免依赖之间的相互依赖
依赖的解析顺序是不确定的,因此不建议在依赖函数中引用其他依赖项:
# 不推荐的做法
dependencies={
"robot_name": "Anna",
"story_title": lambda run_context: f"The Adventures of {run_context.dependencies['robot_name']}" # 依赖其他依赖项
}
8.3 合理使用全局和局部依赖
– 全局依赖用于通用配置
– 局部依赖用于动态值
# 全局依赖用于通用配置
story_writer = Agent(
instructions="You are a {role} writing {genre} stories",
dependencies={"role": "story writer", "genre": "science fiction"} # 全局依赖
)
局部依赖用于动态值
agent.run(
"Write a story about a robot",
dependencies={"robot_name": "Anna"} # 局部依赖
)
8.4 处理依赖解析错误
依赖函数可能会抛出异常,确保有适当的错误处理:
def get_robot_name(run_context):
try:
# 可能会失败的操作
return get_robot_name_from_external_service()
except Exception as e:
# 提供默认值或处理错误
return "DefaultRobot"
8.5 使用类型注解
为依赖函数添加类型注解,提高代码可读性和可维护性:
def get_current_time(run_context: RunContext) -> str:
from datetime import datetime
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
9. 常见问题和解决方案
9.1 依赖不生效
问题:模板变量没有被正确替换
解决方案:
1. 检查依赖键名是否与模板变量名匹配
2. 检查依赖是否正确传递
3. 检查依赖值是否为预期类型
9.2 依赖函数执行失败
问题:依赖函数抛出异常
解决方案:
1. 在依赖函数中添加适当的错误处理
2. 确保依赖函数的签名正确
3. 检查依赖函数所需的外部资源是否可用
9.3 依赖解析顺序问题
问题:依赖之间存在相互依赖,导致解析失败
解决方案:
1. 避免依赖之间的相互依赖
2. 如果必须依赖其他依赖项,可以将它们合并到一个依赖函数中
10. 扩展应用场景
10.1 多 Agent 协作
在多 Agent 协作场景中,可以使用依赖传递机制在 Agent 之间共享上下文:
# 创建多个 Agent
story_writer = Agent(
id="story-writer-agent",
instructions="You are a story writer. Write a story about {topic}",
)
story_editor = Agent(
id="story-editor-agent",
instructions="You are a story editor. Edit the following story: {story}",
)
在工作流中传递依赖
workflow = Workflow(
id="story-creation-workflow",
steps=[
Step(agent=story_writer, output_key="story"),
Step(agent=story_editor, dependencies={"story": "{{steps.story.output}}"})
]
)
10.2 动态配置 Agent 行为
可以使用依赖传递机制动态配置 Agent 的行为:
# 创建一个可配置的 Agent
configurable_agent = Agent(
id="configurable-agent",
instructions="You are a {role}. {additional_instructions}",
)
根据不同场景传递不同的配置
agent.run(
"Perform the requested task",
dependencies={
"role": "customer service representative",
"additional_instructions": "Be polite and helpful"
}
)
agent.run(
"Perform the requested task",
dependencies={
"role": "technical support engineer",
"additional_instructions": "Provide detailed technical information"
}
)
11. 总结
AgentOS 依赖传递机制是一个强大的工具,允许您创建灵活、可配置的 Agent 系统。通过合理使用依赖传递,您可以:
1. 动态配置 Agent 行为
2. 在运行时注入上下文信息
3. 实现 Agent 之间的协作
4. 创建更加灵活和可扩展的应用
掌握依赖传递机制对于构建复杂的 AgentOS 应用至关重要。希望本文能帮助您深入理解 AgentOS 依赖传递的工作原理和最佳实践,为您的 Agent 开发之旅提供指导。
12. 进一步学习资源
– AgentOS 官方文档
– FastAPI 文档
– PostgreSQL 文档
通过不断学习和实践,您将能够充分利用 AgentOS 依赖传递机制,构建出更加智能、灵活和强大的 Agent 应用。
