init repo

This commit is contained in:
Summer Shen
2026-03-31 09:14:32 +08:00
commit 9578366e36
34 changed files with 5200 additions and 0 deletions
@@ -0,0 +1,147 @@
## Context
本项目是一个全新的 Python 项目(greenfield),目标是构建一个基于 LlamaIndex Workflow 的 Agent,能够动态加载和执行 SKILL。
**当前状态:**
- 项目仅有 `src/llama_agent_skills/__init__.py` 中一个空的 `main()` 入口
- 无任何现有依赖(`pyproject.toml``dependencies = []`
- `.opencode/skills/``.github/skills/` 下有 4 个 SKILL.md 示例文件,定义了 SKILL 的标准格式
**SKILL 格式(已有约定):**
- YAML frontmatter`name``description``license``metadata`author、version
- Markdown 正文:自由格式的指令文本,包含 Steps、Guardrails、Input/Output 等段落
**LlamaIndex Workflow 关键能力(调研结论):**
- `Workflow` 基类:事件驱动、`@step` 装饰器、`Context` 状态管理
- `AgentWorkflow.from_tools_or_functions()`:接受 `tools` 列表和 `system_prompt`
- `FunctionAgent`:支持 `system_prompt``tools``can_handoff_to`
- 工具列表存储为实例变量 `self.tools`,可运行时动态增删
- `Context.set/get` 提供步骤间状态共享
**约束:**
- 不引入 Shell/subprocess,纯 Python 运行
- 脚本类 SKILL 功能暂不支持
- 需要支持线上部署场景
## Goals / Non-Goals
**Goals:**
- 实现 SKILL.md 文件的解析器,能提取 frontmatter 元数据和正文指令
- 实现 SKILL 注册表,支持从目录扫描、运行时动态注册/注销
- 构建基于 LlamaIndex Workflow 的核心 Agent,将 SKILL 作为 system prompt 的扩展注入
- 提供清晰的 Python API,方便程序化创建和运行 Agent
- 保持架构简洁,为后续扩展(MCP 工具、多 Agent 协作)留出空间
**Non-Goals:**
- 不实现 Shell/subprocess 执行能力(安全约束)
- 不实现 SKILL 内定义的脚本/命令执行功能
- 不实现多 Agent 协作/handoff(后续迭代)
- 不实现 SKILL 的远程加载(仅支持本地文件系统)
- 不实现 Web UI 或 REST API 层
- 不实现 MCP server/client 集成(后续迭代)
## Decisions
### D1: SKILL 注入方式 — System Prompt 拼接
**决定:** 将 SKILL 的 Markdown 正文作为 system prompt 的一部分注入 Agent。
**备选方案:**
- A) 将 SKILL 转换为 LlamaIndex `BaseTool`(每个 SKILL 变成一个可调用工具)
- B) 将 SKILL 注入 system prompt(当前选择)
- C) 将 SKILL 作为 RAG 文档,通过检索注入
**选择 B 的理由:**
- SKILL 本质是「行为指令」而非「可调用函数」,它定义了 Agent 应该如何行动,而不是提供一个新的能力入口
- System prompt 注入最自然,与 LlamaIndex 的 `system_prompt` 参数直接对应
- 方案 A 需要为每个 SKILL 包装一个工具入口,增加不必要的间接层
- 方案 C 引入 RAG 复杂度,对于有限数量的 SKILL 是过度设计
- 后续如果 SKILL 需要携带工具定义,可以在 SKILL 格式中扩展 `tools` 字段,注册为真正的工具
### D2: SKILL.md 解析策略 — python-frontmatter 库
**决定:** 使用 `python-frontmatter` 库解析 SKILL.md 的 YAML frontmatter + Markdown body。
**备选方案:**
- A) 手写 YAML + Markdown 分割解析器
- B) 使用 `python-frontmatter` 库(当前选择)
- C) 使用 `pyyaml` + 手动分割 `---` 分隔符
**选择 B 的理由:**
- `python-frontmatter` 是成熟的库,专门处理 frontmatter 格式,边界情况覆盖好
- 减少自研代码量和 bug 风险
- 自动处理 YAML 类型转换
### D3: Agent 架构 — 基于 AgentWorkflow 的单 Agent
**决定:** 使用 `AgentWorkflow.from_tools_or_functions()` 构建单 Agent,通过 `system_prompt` 参数注入 SKILL 上下文。
**备选方案:**
- A) 自定义 `Workflow` 子类,手动实现所有步骤
- B) 使用 `AgentWorkflow.from_tools_or_functions()`(当前选择)
- C) 使用 `FunctionAgent` + 多 Agent 编排
**选择 B 的理由:**
- `AgentWorkflow` 提供开箱即用的对话循环、工具调用、流式输出
- 对于第一版,单 Agent 足够验证 SKILL 注入概念
- 如需自定义步骤(如 SKILL 热加载),可以后续继承扩展
- 方案 A 需要重写大量 LlamaIndex 已有逻辑
- 方案 C 在当前阶段是过度设计
### D4: 模块结构 — 职责分离
**决定:** 按职责划分为以下模块:
```
src/llama_agent_skills/
├── __init__.py # 包入口 + main()
├── skill.py # Skill 数据模型 + SKILL.md 解析器
├── registry.py # SkillRegistry(扫描、注册、查询)
├── agent.py # Agent 构建与运行(封装 AgentWorkflow
└── config.py # 配置管理(环境变量、默认值)
```
**理由:**
- `skill.py` 专注数据解析,与 LlamaIndex 无关,可独立测试
- `registry.py` 管理 SKILL 生命周期,依赖 `skill.py` 但不依赖 `agent.py`
- `agent.py` 是唯一依赖 LlamaIndex 的模块,负责将 registry 中的 SKILL 组装为 Agent
- `config.py` 集中管理配置,避免硬编码散落
### D5: SKILL 上下文组装策略
**决定:** 在 Agent 启动时,将所有已注册 SKILL 的正文按固定格式拼接到 system prompt
```
{base_system_prompt}
---
## Active Skills
### Skill: {skill.name}
{skill.description}
{skill.body}
---
### Skill: {skill2.name}
...
```
**理由:**
- 结构化的分隔让 LLM 清楚区分不同 SKILL 的指令
- 每个 SKILL 带有名称和描述作为标题,便于 LLM 理解上下文切换
-`---` 分隔避免 SKILL 间指令混淆
## Risks / Trade-offs
- **[System prompt 长度爆炸]** → 当加载多个大型 SKILL 时,system prompt 可能超出 LLM context window。**缓解:** 限制同时加载的 SKILL 数量,后续可引入选择性加载或摘要机制。
- **[SKILL 间指令冲突]** → 多个 SKILL 可能包含矛盾指令。**缓解:** 第一版不解决,通过文档约定 SKILL 应自包含;后续可增加冲突检测。
- **[LlamaIndex 版本锁定]** → 依赖 `llama-index-core` 的特定 API(如 `AgentWorkflow`),升级可能 break。**缓解:** 通过 `agent.py` 隔离 LlamaIndex 依赖,仅在该模块中引用 LlamaIndex API。
- **[无 Shell 限制降低灵活性]** → 部分 SKILL 可能期望执行 CLI 命令(如 `openspec` CLI)。**缓解:** 明确标记为 Non-Goal,后续可通过安全沙箱或 API wrapper 支持。
- **[SKILL.md 格式无 schema 校验]** → frontmatter 字段错误不会被提前发现。**缓解:** 在 `skill.py` 中做基本校验(必填字段检查),后续可引入 JSON Schema 或 Pydantic 校验。