# OpenFang — Agent Instructions ## Project Overview OpenFang is an open-source Agent Operating System written in Rust (14 crates). - Config: `~/.openfang/config.toml` - Default API: `http://127.0.0.1:4200` - CLI binary: `target/release/openfang.exe` (or `target/debug/openfang.exe`) --- ## Architecture Overview ### Crate Structure (14 crates) ``` openfang-types # 基础类型 (零依赖,被所有 crate 使用) openfang-memory # 存储层 (SQLite + 向量 + 知识图谱) openfang-runtime # Agent 运行时 (LLM 驱动 + 工具执行 + WASM) openfang-kernel # 核心协调器 (Registry + Scheduler + EventBus) openfang-api # HTTP 服务 (Axum + WebSocket + SSE) openfang-wire # P2P 协议 (OFP + HMAC 认证) openfang-channels # 消息渠道 (40+ 适配器) openfang-skills # 技能系统 (4 运行时 + 60 技能) openfang-hands # 自主能力包 (7 预构建 Agent) openfang-extensions # 集成系统 (25+ MCP 模板) openfang-cli # 命令行 (14+ 子命令) openfang-desktop # 桌面应用 (Tauri 2.0) openfang-migrate # 迁移工具 (OpenClaw 导入) ``` ### Dependency Rules 1. `openfang-types` 不能依赖任何内部 crate 2. `openfang-kernel` 依赖 `openfang-runtime`, `openfang-memory` 3. `openfang-api` 依赖 `openfang-kernel` 4. **禁止循环依赖** - 使用 `KernelHandle` trait 解决 runtime ↔ kernel 循环 ### Key Design Patterns - **KernelHandle Trait**: 解决 runtime ↔ kernel 循环依赖 - **Plugin Architecture**: Skills/Hands/Extensions 可扩展 - **Event-Driven**: EventBus 发布订阅模式 - **Dual Persistence**: 内存 (DashMap) + SQLite 双写 --- ## Build & Verify Workflow After every feature implementation, run ALL THREE checks: ```bash cargo build --workspace --lib # Must compile (use --lib if exe is locked) cargo test --workspace # All tests must pass (currently 1744+) cargo clippy --workspace --all-targets -- -D warnings # Zero warnings ``` --- ## MANDATORY: Live Integration Testing **After implementing any new endpoint, feature, or wiring change, you MUST run live integration tests.** Unit tests alone are not enough — they can pass while the feature is actually dead code. ### Live Test Checklist - [ ] Route registered in `server.rs` router - [ ] Handler implemented in `routes.rs` - [ ] GET returns real data (not empty/null) - [ ] POST/PUT persists data (read back to verify) - [ ] LLM integration works (real API call) - [ ] Side effects tracked (metering/budget) - [ ] Dashboard UI shows new components ### Quick Integration Test Script ```bash # Stop any running daemon tasklist | grep -i openfang && taskkill //PID //F sleep 3 # Build and start cargo build --release -p openfang-cli GROQ_API_KEY= target/release/openfang.exe start & sleep 6 # Verify health curl -s http://127.0.0.1:4200/api/health # Test your new endpoint curl -s http://127.0.0.1:4200/api/ # Cleanup taskkill //PID //F ``` --- ## Persistence Rules (CRITICAL) ### Rule 1: Dual Write Pattern 所有 Agent 修改操作必须同时更新: 1. **内存**: `registry.xxx()` 更新 DashMap 2. **SQLite**: `memory.save_agent(&entry)` 持久化 ```rust // ✅ 正确: Kernel 层包装方法 pub fn set_agent_mode(&self, agent_id: AgentId, mode: AgentMode) -> KernelResult<()> { self.registry.set_mode(agent_id, mode)?; // 内存 if let Some(entry) = self.registry.get(agent_id) { let _ = self.memory.save_agent(&entry); // SQLite } Ok(()) } // ❌ 错误: 直接调用 registry (不持久化) state.kernel.registry.set_mode(agent_id, mode) ``` ### Rule 2: 使用 Kernel 包装方法 在 API 层 (`routes.rs`) 始终调用 kernel 方法,不要直接调用 registry: | ❌ 错误调用 | ✅ 正确调用 | |------------|------------| | `registry.set_mode()` | `kernel.set_agent_mode()` | | `registry.set_state()` | `kernel.set_agent_state()` | | `registry.update_identity()` | `kernel.update_agent_identity()` | | `registry.update_name()` | `kernel.update_agent_name()` | | `registry.update_description()` | `kernel.update_agent_description()` | ### Rule 3: 已持久化的操作 以下操作已正确实现持久化,可直接使用: - `kernel.update_agent_model()` - `kernel.update_agent_system_prompt()` - `kernel.set_agent_skills()` - `kernel.set_agent_mcp_servers()` - `kernel.kill_agent()` (调用 `memory.remove_agent()`) --- ## API Development Rules ### Rule 1: Route Registration 新路由必须在两处注册: 1. `server.rs` - 添加到 router 2. `routes.rs` - 实现 handler 函数 ```rust // server.rs .route("/api/agents/{id}/custom", axum::routing::get(routes::get_custom).put(routes::set_custom)) // routes.rs pub async fn get_custom(...) -> impl IntoResponse { ... } pub async fn set_custom(...) -> impl IntoResponse { ... } ``` ### Rule 2: AppState Access ```rust // AppState 结构 pub struct AppState { pub kernel: Arc, pub started_at: Instant, pub peer_registry: Option>, // 注意: Option> pub bridge_manager: tokio::sync::Mutex>, pub channels_config: tokio::sync::RwLock, pub shutdown_notify: Arc, } ``` ### Rule 3: Error Response Format ```rust // 统一错误响应格式 (StatusCode::NOT_FOUND, Json(serde_json::json!({"error": "Agent not found"}))) (StatusCode::BAD_REQUEST, Json(serde_json::json!({"error": "Invalid input"}))) (StatusCode::CONFLICT, Json(serde_json::json!({"error": "Name already exists"}))) ``` ### Rule 4: Success Response Format ```rust // 统一成功响应格式 (StatusCode::OK, Json(serde_json::json!({"status": "ok", "agent_id": id}))) (StatusCode::CREATED, Json(serde_json::json!({"id": new_id, "name": name}))) ``` --- ## Config & Types Rules ### Rule 1: New Config Fields 添加新配置字段需要: 1. 在 struct 中添加字段 2. 添加 `#[serde(default)]` 3. 在 `Default` impl 中添加默认值 4. 确保 `Serialize + Deserialize` derived ```rust #[derive(Debug, Clone, Serialize, Deserialize)] pub struct KernelConfig { // ... existing fields ... #[serde(default)] pub new_field: String, // 必须有 #[serde(default)] } impl Default for KernelConfig { fn default() -> Self { Self { // ... existing defaults ... new_field: String::new(), // 必须在 Default 中 } } } ``` ### Rule 2: Type Definitions 新类型定义放在正确的 crate: - **共享类型**: `openfang-types/` - **API 特有**: `openfang-api/src/` - **Kernel 特有**: `openfang-kernel/src/` --- ## Security Rules ### 16-Layer Security Model 1. Capability-based access control 2. Path traversal protection 3. SSRF protection (私有 IP 阻断) 4. Ed25519 signed manifests 5. Merkle hash chain audit 6. Information flow taint tracking 7. HMAC-SHA256 mutual auth 8. API key Bearer auth 9. GCRA rate limiter 10. Security headers (CSP/HSTS/X-Frame-Options) 11. Secret zeroization 12. Subprocess environment isolation 13. Health endpoint redaction 14. Loop guard with SHA256 detection 15. Session repair 16. Circuit breaker thresholds ### Security Checklist for New Features - [ ] 输入验证 (sanitize user input) - [ ] 权限检查 (capability-based) - [ ] 路径安全 (no path traversal) - [ ] SSRF 防护 (block private IPs) - [ ] 敏感信息脱敏 (logs, health endpoint) --- ## Common Gotchas ### Build Issues | 问题 | 解决方案 | |------|----------| | `openfang.exe` locked | 使用 `--lib` flag 或 kill daemon | | cargo not found | 检查 PATH 环境变量 | | clippy warnings | 所有 warning 必须修复 (`-D warnings`) | ### Type Mismatches | 问题 | 解决方案 | |------|----------| | `PeerRegistry` 类型 | kernel: `Option`, AppState: `Option>` | | `AgentLoopResult.response` | 不是 `.response_text` | | UUID parsing | 使用 `.parse::()` | ### Windows-Specific | 问题 | 解决方案 | |------|----------| | taskkill syntax | `taskkill //PID //F` (double slashes) | | Path separators | 使用 `/` 或 `std::path::PathBuf` | | Sleep command | `sleep` 在 Git Bash/MSYS2 中可用 | ### CLI Commands - 启动守护进程: `openfang start` (不是 `daemon`) - 停止守护进程: `taskkill //PID //F` --- ## Frontend Rules (Alpine.js SPA) ### File Locations - HTML: `crates/openfang-api/static/index_body.html` - JS: `crates/openfang-api/static/js/` - CSS: `crates/openfang-api/static/css/` ### Adding New UI Components 1. 在 `index_body.html` 添加 HTML 结构 2. 在对应的 JS 文件中添加 Alpine.js data/methods 3. 在 `api.js` 中添加 API 调用方法 ### Alpine.js Pattern ```javascript // 在页面组件中 function myPage() { return { data: [], loading: false, async loadData() { this.loading = true; try { this.data = await OpenFangAPI.getData(); } finally { this.loading = false; } }, init() { this.loadData(); } } } ``` --- ## Testing Rules ### Test Categories 1. **Unit Tests**: `#[cfg(test)] mod tests { ... }` 在各模块内 2. **Integration Tests**: `tests/` 目录 3. **Live Tests**: 运行 daemon 后 curl 测试 ### Test Requirements - 所有新功能必须有测试 - 测试覆盖率目标: 90%+ - 测试名称: `test_<功能>_<场景>` ### Test Pattern ```rust #[cfg(test)] mod tests { use super::*; #[test] fn test_feature_success() { // Arrange let store = setup(); // Act let result = store.do_something(); // Assert assert!(result.is_ok()); } #[test] fn test_feature_error_case() { // Test error handling } } ``` --- ## LLM Provider Support ### Supported Providers (30+) - Anthropic (Claude) - OpenAI (GPT) - Google (Gemini) - Groq, OpenRouter, DeepSeek, Together, Mistral, Fireworks - Ollama, vLLM, LM Studio (local) - Perplexity, Cohere, AI21, Cerebras, SambaNova - HuggingFace, xAI, Replicate - GitHub Copilot, Codex, Claude Code CLI - 中国提供商: 智谱 GLM, 百炼, Moonshot, Qwen, Minimax, 千帆 ### Adding New Provider 1. 在 `openfang-types/src/model_catalog.rs` 添加 BASE_URL 常量 2. 在 `openfang-runtime/src/model_catalog.rs` 添加模型和提供商信息 3. 在 `openfang-runtime/src/drivers/mod.rs` 添加 `provider_defaults()` 条目 4. 添加测试用例 --- ## Code Style Guidelines ### Rust Conventions - 使用 `use` 导入,避免完整路径 - 错误处理使用 `Result` 和 `?` 操作符 - 使用 `tracing` crate 进行日志记录 - 异步代码使用 `tokio` 运行时 ### Naming Conventions - 函数/变量: `snake_case` - 类型/Trait: `PascalCase` - 常量: `SCREAMING_SNAKE_CASE` - 模块: `snake_case` ### Documentation - 公共 API 必须有文档注释 (`///`) - 复杂逻辑必须有注释说明 - 使用 `//!` 作为模块级文档 --- ## Key Files Quick Reference | 文件 | 用途 | |------|------| | `crates/openfang-kernel/src/kernel.rs` | 核心协调器,所有子系统的入口 | | `crates/openfang-kernel/src/registry.rs` | Agent 内存注册表 (DashMap) | | `crates/openfang-memory/src/structured.rs` | Agent SQLite 持久化 | | `crates/openfang-api/src/server.rs` | HTTP 路由注册 | | `crates/openfang-api/src/routes.rs` | HTTP 处理函数 | | `crates/openfang-api/src/ws.rs` | WebSocket 处理 | | `crates/openfang-runtime/src/drivers/mod.rs` | LLM 提供商驱动 | | `crates/openfang-types/src/model_catalog.rs` | 模型/提供商常量 | --- ## Current Date Today's date is 2026-03-01.