Sage 是一个基于 Skills 模式 的智能 Agent 框架,遵循 Agent Skills 规范设计。
核心理念是将复杂的 Agent 能力拆解为可发现、可组合的 技能(Skills),每个技能通过标准化的 SKILL.md 文件进行描述。Agent 在运行时自动发现这些技能,并根据用户需求动态调用,在隔离的沙盒环境中执行代码,最终完成复杂任务。
这是本项目的核心创新点,采用了类似 Claude Code 的 SKILLS 设计模式:
Agent 启动时自动扫描 services/ 目录下的所有 SKILL.md 文件:
services/
├── websearch_service/
│ └── SKILL.md ← 联网搜索技能
├── sandbox_service/
│ └── SKILL.md ← 沙盒执行技能
├── deepsearch_service/
│ └── SKILL.md ← 深度研究技能
├── rag_service/
│ └── SKILL.md ← RAG 检索技能
└── ...
- 解析 YAML frontmatter 提取技能名称和描述
- 自动构建可用技能列表注入系统提示词
- 支持运行时刷新技能列表
每个技能使用统一的 Markdown 格式描述:
---
name: websearch-service
description: 基于 SearXNG 与 VLM 的实时联网搜索服务
---
## 功能
通过 SearXNG 搜索引擎获取网页结果,使用 VLM 进行智能分析...
## 调用方式
```- python
from services.websearch_service.client import WebSearchClient
client = WebSearchClient()
result = client.search("Python async编程", max_results=5)
```-
## 返回格式
{ "query": "...", "results": [...] }所有技能代码在 Docker 沙盒中安全执行,Agent 本身不依赖任何技能环境:
┌─────────────────────────────────────────────────────────────┐
│ Agent Engine │
│ ┌────────────────┐ ┌─────────────────────────────┐ │
│ │ Skill Registry │ │ LLM Service │ │
│ │ (自动发现技能) │ │ (思考 & 生成代码) │ │
│ └───────┬────────┘ └─────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ Skill Executor │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ Sandbox Service (Docker) │ │ │
│ │ │ ┌─────────────────────────────────────────┐│ │ │
│ │ │ │ • 网络隔离 / 资源限制 / 超时控制 ││ │ │
│ │ │ │ • trusted_mode: 访问内部服务网络 ││ │ │
│ │ │ │ • 执行后自动销毁,无状态残留 ││ │ │
│ │ │ └─────────────────────────────────────────┘│ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
安全限制:
- 内存限制:256MB
- CPU 限制:1 核
- 执行超时:60 秒
- 非 root 用户执行
支持一次回答中多次调用不同技能,形成思考-执行-分析的智能循环:
用户问题
│
▼
┌─────────────────────────────────────────────────────────┐
│ 迭代循环 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 思考 │ → │ 调用技能 │ → │ 分析结果 │ ─┐ │
│ │ Thinking │ │ Execute │ │ Analyze │ │ │
│ └──────────┘ └──────────┘ └──────────┘ │ │
│ ▲ │ │
│ └─────────── 需要更多信息 ─────────────────┘ │
│ │
│ ↓ 信息充足 │
└─────────────────────────────────────────────────────────┘
│
▼
最终回答
实时展示 Agent 的思考和执行过程:
| 事件类型 | 说明 |
|---|---|
THINKING |
Agent 正在思考分析 |
SKILL_CALL |
准备调用某个技能 |
CODE_EXECUTE |
正在执行代码 |
CODE_RESULT |
代码执行结果 |
ANSWER |
回答内容(流式) |
DONE |
执行完成 |
ERROR |
发生错误 |
┌────────────────────────────────────────────────────────────────────┐
│ Frontend (Vue 3 + Vite) │
│ 现代化聊天界面 & 推理过程可视化 │
└────────────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────────┐
│ Backend Services │
│ ┌─────────────────────────┐ ┌─────────────────────────┐ │
│ │ Chat Service │ │ Agent Service │ │
│ │ (Port 8006) │ │ (Port 8009) │ │
│ │ 普通对话 & 会话管理 │ │ Skills 编排 & 执行 │ │
│ └─────────────────────────┘ └─────────────────────────┘ │
└────────────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────────┐
│ Skills Layer │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌────────────┐ │
│ │ WebSearch │ │ DeepSearch │ │ Sandbox │ │ RAG │ │
│ │ 联网搜索 │ │ 深度研究 │ │ 代码执行 │ │ 知识检索 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ └────────────┘ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Embedding │ │ Rerank │ │ OCR │ │
│ │ 向量嵌入 │ │ 重排序 │ │ 图像识别 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└────────────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────────┐
│ Infrastructure │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ PostgreSQL │ │ Milvus │ │ SearXNG │ │
│ │ 会话存储 │ │ 向量数据库 │ │ 搜索引擎 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└────────────────────────────────────────────────────────────────────┘
sage/
├── app/
│ ├── agent/ # Agent 服务 (核心)
│ │ ├── core/
│ │ │ ├── agent_engine.py # Agent 执行引擎
│ │ │ ├── skill_registry.py # 技能注册表 (自动发现)
│ │ │ ├── skill_executor.py # 技能执行器 (沙盒调用)
│ │ │ └── context_manager.py # 上下文/记忆管理
│ │ ├── services/
│ │ │ ├── llm_service.py # LLM 调用服务
│ │ │ └── agent_service.py # Agent 业务逻辑
│ │ ├── api/routes.py # API 路由
│ │ └── server.py # FastAPI 入口
│ └── chat/ # Chat 服务
│
├── services/ # Skills 技能层
│ ├── websearch_service/ # 联网搜索
│ │ ├── SKILL.md # 技能描述文件
│ │ ├── client.py # Python 客户端
│ │ └── server.py # 服务入口
│ ├── sandbox_service/ # 沙盒执行
│ ├── deepsearch_service/ # 深度研究
│ ├── rag_service/ # RAG 检索
│ ├── embedding_service/ # 向量嵌入
│ ├── rerank_service/ # 重排序
│ └── ocr_service/ # OCR 识别
│
├── web/frontend/ # Vue 3 前端
├── docker-compose.yml # Docker 编排
├── .env.example # 环境变量模板
└── README.md
git clone https://github.com/your-repo/sage.git
cd sagecp .env.example .env
# 编辑 .env,填写 LLM API Key 等配置# 启动所有服务
docker-compose up -d
# 查看服务状态
docker-compose ps| 服务 | 地址 |
|---|---|
| 前端界面 | http://localhost:5173 |
| Agent API | http://localhost:8009/docs |
| Chat API | http://localhost:8006/docs |
import requests
import json
response = requests.post(
"http://localhost:8009/api/agent/completions",
json={
"message": "帮我搜索一下 Python 异步编程的最佳实践",
"stream": True
},
stream=True
)
for line in response.iter_lines():
if line:
data = line.decode('utf-8')
if data.startswith("data: ") and data[6:] != "[DONE]":
event = json.loads(data[6:])
print(f"[{event['event_type']}] {event.get('content', '')}")- 在
services/下创建新目录 - 编写
SKILL.md描述文件 - 实现
client.pyPython 客户端 - 重启 Agent 服务或调用刷新 API
# 刷新技能列表
curl -X POST http://localhost:8009/api/agent/skills/refreshSage is an intelligent Agent framework based on the Skills Pattern, designed following the Agent Skills specification.
The core concept is to decompose complex Agent capabilities into discoverable and composable Skills, where each skill is described through a standardized SKILL.md file. The Agent automatically discovers these skills at runtime and dynamically invokes them based on user needs, executing code in an isolated sandbox environment to complete complex tasks.
This is the core innovation of this project, adopting an Agentic design pattern similar to Claude Code:
The Agent automatically scans all SKILL.md files in the services/ directory at startup:
services/
├── websearch_service/
│ └── SKILL.md ← Web search skill
├── sandbox_service/
│ └── SKILL.md ← Sandbox execution skill
├── deepsearch_service/
│ └── SKILL.md ← Deep research skill
└── rag_service/
└── SKILL.md ← RAG retrieval skill
Each skill uses a unified Markdown format:
---
name: websearch-service
description: Real-time web search service based on SearXNG and VLM
---
## Features
Fetches web results through SearXNG, uses VLM for intelligent analysis...
## Usage
```- python
from services.websearch_service.client import WebSearchClient
client = WebSearchClient()
result = client.search("Python async programming", max_results=5)
```-All skill code is executed safely in Docker sandbox. The Agent itself doesn't depend on any skill environment:
- Memory limit: 256MB
- CPU limit: 1 core
- Execution timeout: 60 seconds
- Non-root user execution
trusted_modefor accessing internal service network
Supports multiple skill calls in a single response, forming an intelligent Think-Execute-Analyze loop:
User Question → Think → Execute Skill A → Analyze → Execute Skill B → Final Answer
↑ ↓
└──────── Need more information ──────────┘
Real-time display of Agent's thinking and execution process:
| Event Type | Description |
|---|---|
THINKING |
Agent is thinking/analyzing |
SKILL_CALL |
Preparing to call a skill |
CODE_EXECUTE |
Executing code |
CODE_RESULT |
Code execution result |
ANSWER |
Answer content (streaming) |
DONE |
Execution complete |
ERROR |
Error occurred |
git clone https://github.com/your-repo/sage.git
cd sagecp .env.example .env
# Edit .env and fill in LLM API keysdocker-compose up -d| Service | URL |
|---|---|
| Frontend | http://localhost:5173 |
| Agent API | http://localhost:8009/docs |
| Chat API | http://localhost:8006/docs |
import requests
import json
response = requests.post(
"http://localhost:8009/api/agent/completions",
json={
"message": "Search for Python async programming best practices",
"stream": True
},
stream=True
)
for line in response.iter_lines():
if line:
data = line.decode('utf-8')
if data.startswith("data: ") and data[6:] != "[DONE]":
event = json.loads(data[6:])
print(f"[{event['event_type']}] {event.get('content', '')}")MIT License
Made with ❤️ by Lin
