- Published on
开源通用 Agent - Suna 解析
- Authors
- Name
- 青雲
1. 项目简介
Suna 是一个开源的通用型 AI Agent 项目,通过自然语言对话帮助用户完成真实世界的任务。它定位为数字伴侣,结合强大的功能(浏览器自动化、文件管理、代码执行)和直观的用户界面,理解用户需求并高效交付成果。
2. 核心特点
- 对话式交互: 用户通过聊天界面与 AI Agent进行自然语言交流
- 安全沙盒环境: 所有风险操作都在 Docker 沙盒环境中运行,确保安全性
- 多工具编排: 智能选择并组合使用多种工具完成复杂任务
- 浏览器自动化: Agent能够自主操作浏览器,包括导航、信息提取、表单填写
- 异步Agent执行: 使用 Dramatiq 进行Agent会话的异步执行,避免阻塞
- 多 LLM 支持: 通过 LiteLLM 集成多种大语言模型提供商
3.1 整体架构图
3.2 核心组件
前端 (Next.js/React)
- 用户界面,提供聊天、仪表盘、账户管理
- 通过 REST API 与后端通信
- 使用 Supabase 进行客户端认证
后端 API (Python/FastAPI)
- 系统核心协调者,处理前端请求
- 管理 AgentPress(Agent编排引擎)
- 通过 LiteLLM 与大语言模型通信
- 与沙盒环境交互管理
Agent执行服务 (Dramatiq)
- 异步执行完整的Agent会话,避免阻塞主API
- 使用 RabbitMQ 作为消息Agent进行任务调度
- 通过 Redis 进行状态管理和实时通信
- 支持Agent运行的启动、停止、状态监控
沙盒执行环境 (Daytona & Docker)
- 为每个Agent任务提供安全隔离的执行环境
- 预装浏览器、Python 库、系统工具
- 通过 Daytona SDK 进行统一管理和交互
数据库 (Supabase)
- 用户认证与管理
- 会话线程、消息、配置存储
- 团队管理(通过 Basejump)
3.3 典型交互流程
4. AgentPress 框架核心
4.2 ThreadManager(线程管理器)
- 协调Agent执行的核心组件
- 管理会话历史、工具注册、LLM 交互
- 组合模式设计,整合多个专业组件
4.3 ToolRegistry(工具注册表)
- 管理所有可用工具及其接口
- 支持 OpenAPI 和 XML 两种工具调用格式
- 动态工具发现和注册机制
4.4 ResponseProcessor(响应处理器)
- 解析 LLM 响应流
- 提取工具调用请求并执行
- 支持并行和串行执行策略
4.5 ContextManager(上下文管理器)
- 管理 token 使用和上下文窗口
- 智能压缩历史消息
- 优化 LLM 输入以符合限制
5. 工具系统设计
5.1 工具调用流程图
5.2 工具基类架构
@xml_schema(tag_name="tool_name", example="<tool_name>...</tool_name>")
def tool_method(self, param: str):
# 工具实现
return self.success_response(result)
5.3 工具调用流程
- LLM 生成 XML 格式的工具调用
- ResponseProcessor 解析 XML 提取参数
- ToolRegistry 查找对应工具实例
- 执行工具方法并返回结果
- 结果注入回 LLM 上下文
6. Prompt 设计策略
6.1 核心设计原则
- 高度指令性: 为Agent的各个方面设定详细规则
- todo.md 工作流: 强制使用 todo.md 进行任务规划和跟踪
- 叙述性更新: 要求Agent解释行为和思考过程
- 模型特定优化: 针对不同 LLM 调整 Prompt 策略
6.2 基础系统Prompt源码示例
# 文件: suna/backend/agent/prompt.py
SYSTEM_PROMPT = f"""
You are Suna.so, an autonomous AI Agent...
# 2.2 SYSTEM INFORMATION
- UTC DATE: {datetime.datetime.now(datetime.timezone.utc).strftime('%Y-%m-%d')}
- UTC TIME: {datetime.datetime.now(datetime.timezone.utc).strftime('%H:%M:%S')}
# 5.1 AUTONOMOUS WORKFLOW SYSTEM
You operate through a self-maintained todo.md file...
# 7.3 ATTACHMENT PROTOCOL
- CRITICAL: ALL VISUALIZATIONS MUST BE ATTACHED:
* When using the 'ask' tool <ask attachments="file1, file2, file3"></ask>, ALWAYS attach ALL visualizations...
"""
def get_system_prompt():
return SYSTEM_PROMPT
6.3 针对不同模型的Prompt策略
# 文件: suna/backend/agent/run.py
if "gemini-2.5-flash" in model_name.lower():
# Gemini模型使用包含详细示例的Prompt
system_message = { "role": "system", "content": get_gemini_system_prompt() }
elif "anthropic" not in model_name.lower():
# 非Anthropic模型添加示例响应
sample_response_path = os.path.join(os.path.dirname(__file__), 'sample_responses/1.txt')
with open(sample_response_path, 'r') as file:
sample_response = file.read()
system_message = { "role": "system", "content": get_system_prompt() + "\n\n <sample_assistant_response>" + sample_response + "</sample_assistant_response>" }
else:
# Anthropic模型使用基础Prompt
system_message = { "role": "system", "content": get_system_prompt() }
6.4 XML工具调用示例
# 文件: suna/backend/agentpress/tool.py
def xml_schema(tag_name: str, mappings: List[Dict[str, Any]] = None, example: str = None):
"""XML schema装饰器,定义工具的XML调用格式"""
def decorator(func):
# 创建XMLTagSchema实例
xml_tag_def = XMLTagSchema(tag_name=tag_name, example=example)
# 添加参数映射
if mappings:
for mapping_info in mappings:
xml_tag_def.add_mapping(
param_name=mapping_info["param_name"],
node_type=mapping_info.get("node_type", "element"),
path=mapping_info.get("path", "."),
required=mapping_info.get("required", True)
)
# 将schema附加到函数
tool_schema_entry = ToolSchema(schema_type=SchemaType.XML, xml_schema=xml_tag_def)
return _add_schema(func, tool_schema_entry)
return decorator
6.5 关键机制
- XML 工具调用: 使用结构化 XML 进行工具调用
- 动态上下文注入: 实时提供浏览器状态和图像信息
- 示例学习: 通过详细示例指导 LLM 行为
7. Agent异步执行
7.1 异步执行源码示例
# 文件: suna/backend/run_agent_background.py
@dramatiq.actor
async def run_agent_background(
agent_run_id: str,
thread_id: str,
instance_id: str,
project_id: str,
model_name: str,
enable_thinking: Optional[bool],
reasoning_effort: Optional[str],
stream: bool,
enable_context_manager: bool
):
"""在后台异步运行Agent,使用Redis进行状态管理"""
await initialize()
# 初始化Agent生成器
agent_gen = run_agent(
thread_id=thread_id,
project_id=project_id,
stream=stream,
model_name=model_name,
enable_thinking=enable_thinking,
reasoning_effort=reasoning_effort,
enable_context_manager=enable_context_manager
)
# 异步处理Agent响应
async for response in agent_gen:
# 将响应存储到Redis并发布通知
await redis.rpush(response_list_key, response_json)
await redis.publish(response_channel, "new")
7.2 核心特性
- 基于 Dramatiq + RabbitMQ 的异步任务调度
- Redis 用于实时状态管理和 pub/sub 通信
- 支持Agent运行的启动、停止、监控
- 完整的错误处理和清理机制
7.3 沙盒执行环境
沙盒创建源码示例
# 文件: suna/backend/sandbox/sandbox.py
def create_sandbox(password: str, project_id: str = None):
"""创建新的沙盒环境"""
params = CreateSandboxParams(
image=Configuration.SANDBOX_IMAGE_NAME,
public=True,
env_vars={
"CHROME_PERSISTENT_SESSION": "true",
"RESOLUTION": "1024x768x24",
"VNC_PASSWORD": password,
"CHROME_DEBUGGING_PORT": "9222",
},
resources={
"cpu": 2,
"memory": 4, # GB
"disk": 5, # GB
}
)
sandbox = daytona.create(params)
start_supervisord_session(sandbox)
return sandbox
Docker 镜像特性
- 基于 Python 3.11-slim
- 预装 Chromium 浏览器
- 包含数据科学和自动化库
- 使用 supervisord 管理服务
安全隔离机制
- 每个Agent任务独立的Docker沙盒环境
- 受限权限和只读挂载
- 通过 Daytona SDK 进行安全交互和管理
- 沙盒与宿主系统完全隔离
8. 技术亮点与借鉴价值
8.1 架构设计
- 模块化设计: 清晰的职责分离和组件化
- 异步处理: Agent会话的异步执行机制,保持响应性
- 安全沙盒: 基于 Daytona 和 Docker 的创新沙盒执行环境
8.2 工程实践
- 工具框架: 灵活的工具定义和注册机制
- 上下文管理: 智能的 token 优化和历史压缩
- Prompt 工程: 针对不同模型的精细化 Prompt 设计
8.3 开发者体验
- 自托管友好: 详尽的安装脚本和文档
- 现代技术栈: Next.js + FastAPI + Supabase 组合
- 清晰代码结构: 易于理解和扩展的项目组织
Suna 项目展示了构建复杂 AI Agent平台的优秀工程实践,其在安全性、模块化、可扩展性和开发者体验方面的设计值得学习和借鉴。