English | 中文
Version: 0.5.0 | Python >= 3.12 | License: MIT
Rooster is a multi-role Agent framework that autonomously handles complex tasks including desktop automation, web browsing, file processing, and data queries.
- CCP Capability-Constrained Planning: Six-step planning protocol — blocker detection, owner labeling (AGENT/USER), confidence rating, deliverable declaration, feasibility analysis, DAG construction. Planner explicitly declares capability boundaries and risk notes before execution.
- Tool Dependency Injection (RoosterContext): Unified
RoosterContextdataclass injects session, task, memory, LLM client, blackboard, and config into every tool call. Zero-breakage migration — old tools continue working unchanged. - Schema Validation Self-Healing (ToolCallValidator): Pydantic-based tool call validator with two auto-healing paths (JSON syntax fix + schema structure repair). Invalid parameters are automatically corrected by a lightweight router model before execution, with a hard budget of 2 retries.
- Progressive History Compression: Per-10-step semantic distillation during ReAct execution. Preserves the latest 5 raw steps while compressing older context, eliminating the "hard truncation degradation" that plagued long-running tasks.
- Thin routing pipeline: Router hard rules → SkillIndex hint → Strategist.decide() → MissionRunner / Schedule
- Unified execution modes:
DIRECT_REPLY/SINGLE_STEP/DAG_PLAN/SCHEDULE - Typed Signal Exceptions: Native Python
EscalateSignal/AbortSignalreplace magic string parsing for control flow, enabling precise exception catching and stack traces. - Structured Observability: Prometheus histograms for tool latency, subtask duration, Provider failover rate, and LLM error tracking. Automatic
mission_idcorrelation across all log entries. - Visual grounding: YOLO-driven desktop UI element detection and manipulation
- Multi-LLM failover: Zhipu / MiMo / Jiutian / OpenAI / Anthropic / Kimi / Qwen / Cloud / Local — 10+ provider auto-switching
- Gateway security: API Key auth + HMAC signing + IP rate limiting + security headers + request size limits
- Dashboard UI: Real-time monitoring — 13 panels, bilingual (ZH/EN), mobile-responsive
V15 Routing Architecture: Three-layer triage — zero-LLM gate + capability index + semantic judgment:
- L1 Hard-Rule Gate (< 5ms, pure code): Security keywords → BLOCK / Schedule keywords → SCHEDULE / Download keywords → Reframer pre-processing
- L2 SkillIndex (~20ms, TF-IDF): Local capability index matching, outputs SkillHint for Strategist reference
- Strategist.decide() (fast LLM): Semantic depth judgment →
DIRECT_REPLY(streaming) /SINGLE_STEP(single task) /DAG_PLAN(multi-step DAG) /CLARIFY(ambiguity intercept)
Low-latency hard gate: Built-in download/schedule/security trigger dictionaries handle deterministic branching in code. Router no longer spends an LLM call on semantic triage.
Thin-router handoff: The hard gate only decides BLOCK / SCHEDULE / reframe-preprocess. Everything else continues into SkillIndex + Strategist.decide() instead of a separate Router-owned planner model.
Single semantic decision point: Semantic depth is judged exactly once by Strategist.decide(). That keeps routing thin while still preserving DIRECT_REPLY, SINGLE_STEP, DAG_PLAN, and CLARIFY.
Built on a "defense-in-depth" philosophy covering the network edge, runtime environment, and LLM call layer. The guiding principle is "prefer false negatives over blocking the user" — every interception supports graceful degradation.
Data Privacy Physical Isolation Funnel
| Layer | Mechanism | Latency |
|---|---|---|
| L0 Physical cutoff | LOCAL_DIRS path matching → matched files/requests are force-routed to a local model (e.g. Ollama), cutting off cloud egress at the source |
0ms |
| L1 Entity cleansing | Deep-customized Microsoft Presidio — millisecond bilingual PII scan, detecting phone numbers (0.8), ID cards (0.85), bank cards (0.6), and other sensitive assets | 5–20ms |
| Vision-level privacy circuit breaker | Screenshots never leave the machine — local PaddleOCR extracts on-screen text → Presidio redaction → only a safe text description is sent to cloud; original screenshots remain local permanently | per-frame |
AdvancedGuard LLM Defense Engine
- Jailbreak immunity: Three-tier regex matching matrix, blocking DAN-mode, "ignore previous instructions", unrestricted roleplay, and similar prompt injection attempts in real time.
- Output injection interception: When the Agent uses the browser or reads external files, tool return content is scanned in real time to prevent maliciously hidden web instructions from hijacking the Agent.
- Skill supply-chain poison detection: Third-party skill packages (
SKILL.md) are statically analyzed on mount — blockseval/base64 obfuscation, hidden malicious network requests, and system commands embedded in skill descriptions.
Runtime Sandbox & State Control
- PathGuard directory sandbox: Strict
os.path.realpathprefix validation — blocks symlink bypass and../directory traversal attacks. - StateGuard atomic lock (RSA-Synchronizer): Cross-process atomic transaction lock designed for multi-agent concurrency — eliminates race conditions and dirty-write injection.
- Tool abuse rate limiting: Automatically interrupts infinite loop calls triggered by LLM hallucination, preventing unexpected exhaustion of compute and API quota.
Boundary Gateway & Compliance Audit
- Full-stack traffic control: API Key auth + Webhook HMAC-SHA256 anti-tampering signature + IP sliding-window rate limiting (100 req/min).
- Log secrets mask: API keys, tokens, and other credentials are irreversibly masked before log writes, preventing credential leakage.
- Dynamic config immunity (Input Guard): Key allowlist validation + oversized-value circuit breaker on hot-reload endpoints, guarding against buffer-overflow style attacks.
A dual-engine "system API + computer vision" architecture — no API access required from the target application. If it's on screen, Rooster can interact with it.
- UIA (UI Automation) engine: Retrieves standardized information on all on-screen controls (type, name, position, state) via system accessibility APIs — broad coverage, deterministic, fast, precise, and stable.
- YOLO vision engine: Ships with a 39 MB ultra-lightweight detection model bundled in the repository — zero extra download. Effectively fills UIA blind spots: custom controls, game icons, non-standard UI elements.
- Complementary operation:
desktop_grounding_scanhandles full-scene element sensing;desktop_acthandles precise click/input simulation. UIA ensures efficiency; YOLO ensures coverage.
An external watchdog fully independent of the main process — even a complete main process crash leaves Guardian unaffected. Designed for true unattended operation.
Three parallel monitoring threads
| Thread | Mechanism | Trigger |
|---|---|---|
| Heartbeat | Poll /api/health every 30s |
3 consecutive failures → force-kill and restart |
| Resource circuit breaker | Sample CPU/memory every 15s | CPU > 95% or RAM > 2 GB sustained 120s → force-kill to prevent freeze |
| Time wheel | Poll schedules.json every 60s |
Dispatch scheduled tasks on time via POST |
Fully automatic fault recovery
- Missing package auto-install: Catches
ModuleNotFoundError, matches against a 23-entry safe library allowlist, and runspip install. The allowlist prevents malicious package injection. - Port conflict resolution: Matches port-in-use errors, extracts the port number via cross-platform regex, and immediately terminates the blocking process.
- Service wakeup: Automatically restarts
aria2cand similar daemons when their RPC becomes unresponsive.
Enterprise-grade resilience: circuit breaker (2 identical consecutive errors → stop retry), restart storm guard (5 restarts in 300s → alert + stop), exponential backoff with jitter, single-instance PID mutex, Feishu/DingTalk/Slack webhook alerts.
Zero-latency self-evolution engine
After each conversation turn, a background scan fires instantly without blocking the current user interaction. A local model (never cloud) analyzes the last 5 turns (200 chars/turn), detects three core signal types, and writes them to the memory store:
| Signal | Example triggers | Write target |
|---|---|---|
CORRECTION |
"That's wrong", "You misunderstood" | SOUL.md → core behavior principles |
PREFERENCE |
"From now on", "I prefer" | USER.md → user preference profile |
MILESTONE |
"It's live", "Successfully done" | USER.md → current key projects |
Core identity fields (Identity / Hard Limits / Memory Protocol) are code-level protected — the evolution engine cannot modify them.
Independent Auditor quality gate
After Executor completes, an independent Auditor renders the final verdict with five outcomes:
| Verdict | Meaning | User experience |
|---|---|---|
AFFIRM |
Approved | Receives a passing result |
REMAND |
Quality below standard | Silently re-executed, seamless to user |
REPLAN |
Path dead end | Strategist replans the task structure |
CLOSURE |
Cannot be completed | Graceful shutdown, no half-finished results |
ESCALATE |
High-risk / permission block | Proactively escalates to human intervention |
Strong robustness: _robust_json_parse() auto-repairs malformed LLM output — Markdown code-block wrapping, trailing commas, Chinese quotation marks (\u201c/\u201d), etc. Auditor timeouts degrade safely to PASS_WITH_WARNING — the audit system never blocks the user flow.
┌─────────────────────────────────────────────────────────────────────┐
│ Rooster Memory Anti-Garbage v2 │
│ │
│ User msg → Router → MissionRunner → Executor(ReAct) │
│ │ │
│ ▼ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ Layer 1: Source Interception (mission_runner.py)│ │
│ │ │ │
│ │ On subtask completion: │ │
│ │ ✖ Success notification ───── DROPPED │ │
│ │ ✖ Output file ───── Deferred │ │
│ │ │ │
│ │ On mission close (batch commit): │ │
│ │ ✖ Mission complete ───── DROPPED │ │
│ │ ✖ Output file (dup) ───── DROPPED │ │
│ │ ✖ Tool call traces ───── DROPPED │ │
│ │ ✔ Output file path ───── Written 1x │ │
│ │ ✔ Execution summary ───── Kept + filtered│ │
│ │ (len > 50 AND no template phrases) │ │
│ │ │ │
│ │ Before: 5-8 facts/task, each triggers rebuild │ │
│ │ After: 0-2 facts/task, all trigger 1 rebuild │ │
│ └───────────────┬──────────────────────────────────┘ │
│ │ │
│ │ batch_update_facts(_batch) │
│ │ Collect all → single add_fact → single rebuild│
│ ▼ │
│ ┌─────────────────────────────────────────────┐ │
│ │ LTM Storage │ │
│ │ project_memory.json │ │
│ │ Current: ~9 valid facts │ │
│ │ (cleaned from ~50, garbage → zero) │ │
│ └───────────────────┬────────────────────────────┘ │
│ │ │
│ ┌─────────┴─────────┐ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────┐ ┌───────────────────────┐ │
│ │ Read Path │ │ Distill Path │ │
│ │ │ │ │ │
│ │ Each ReAct │ │ Three triggers: │ │
│ │ step calls │ │ │ │
│ │ once │ │ · Timer: every │ │
│ │ │ │ 10 min, auto │ │
│ │ Semantic │ │ scan quiet │ │
│ │ recall │ │ sessions │ │
│ │ query= │ │ │ │
│ │ current │ │ · Passive: token │ │
│ │ task │ │ > 60% capacity │ │
│ │ │ │ memory_compactor│ │
│ │ Outputs: │ │ │ │
│ │ ┌────────┐ │ │ · Manual: │ │
│ │ │Key │ │ │ /distill or API │ │
│ │ │entities│ │ │ │ │
│ │ │≤10 │ │ │ ─────────────────│ │
│ │ │500 ch │ │ │ │
│ │ └────────┘ │ │ Layer 2: │ │
│ │ ┌────────┐ │ │ Distill Negative │ │
│ │ │Key │ │ │ Rules (manager.py)│ │
│ │ │facts │ │ │ │ │
│ │ │semantic│ │ │ LLM explicitly │ │
│ │ │recall │ │ │ told NOT to │ │
│ │ │top 15 │ │ │ extract: │ │
│ │ │2000 ch │ │ │ · Template OK msg │ │
│ │ └────────┘ │ │ · Tool traces │ │
│ │ │ │ · Truncated output│ │
│ │ Relevance- │ │ · No-context text │ │
│ │ based, not │ └────────────┬─────────────┘ │
│ │ fixed top 15│ │ │
│ └───────────────┘ ▼ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Layer 3: Decay & Eviction │ │
│ │ periodic_housekeeping runs every 6 hours │ │
│ │ │ │
│ │ Facts > 30 → dedup │ │
│ │ Facts > 50 → quality audit + low-score drop │ │
│ │ Facts > 60 → hard cap eviction (lowest wgt) │ │
│ │ 7-day half-life → unrecalled facts decay │ │
│ │ │ │
│ │ Residual low-value facts auto-evict over time│ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Bonus: Conversation Summary Layer │ │
│ │ _prune_history → async │ │
│ │ │ │
│ │ On token overflow: compress middle turns │ │
│ │ into 300-char summary via local LLM │ │
│ │ Keep head + tail + summary → zero info loss │ │
│ └─────────────────────────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────┘
How it works — three layers in series, each independent, combined pushing garbage facts to near-zero:
Layer 1: Source Interception — the most critical layer, solving "where garbage comes from." Before the refactor, MissionRunner unconditionally wrote 5 types of status notifications at two moments (subtask completion + mission close), with the same output file written twice causing duplicates. After the refactor: nothing is written on subtask completion; everything is batched to batch_update_facts at mission close. Only the output file path (written once) and a template-filtered execution summary are kept. Result: from 5-8 facts/task to 0-2, with index rebuilt only once.
Layer 2: Distill Filtering — even if Layer 1 misses some templated content in conversation history, distillation won't extract it. All three distill entry points (10-min timer, passive token threshold, manual /distill) are constrained by the same negative rules. This was the smallest change (one string edit) but has the widest coverage.
Layer 3: Decay & Eviction — long-term safety net. Unrecalled facts decay via a 7-day half-life. Thresholds at 30/50/60 facts trigger dedup, quality audit, and hard eviction respectively. Residual garbage naturally disappears over time.
Bonus: Conversation Summary — when the ReAct loop hits the token limit, _prune_history compresses middle turns into a 300-char summary via local LLM instead of discarding them outright. Combined with LTM semantic recall (per-step relevance-based retrieval instead of fixed top-15), the LLM always sees complete context.
v0.5.0 introduces the CCP (Capability-Constrained Planning) protocol, a six-step planning discipline that forces the Strategist to explicitly declare what it can and cannot do before any execution begins.
Step 1: Blocker Detection — Identify missing credentials, resources, or authorizations
Step 2: Owner Labeling — Mark each subtask as AGENT (AI-executable) or USER (requires human action)
Step 3: Confidence Rating — Rate HIGH / MEDIUM / LOW per subtask
Step 4: Deliverable Declaration — List concrete artifacts the plan will produce
Step 5: Feasibility Note — State the boundary between "promised" and "guaranteed"
Step 6: DAG Construction — Build dependency graph with cycle detection
USER step routing: Subtasks marked owner: USER (e.g., "purchase a server", "provide API key") pause execution and prompt the human via the existing confirmation mechanism. They don't consume concurrency slots, and upstream cancellation automatically cascades to dependent downstream steps — no dead-wait loops.
Pydantic self-healing: The entire planning pipeline is wrapped in ValidationError / JSONDecodeError interception. Malformed LLM JSON output is auto-repaired (Markdown wrapping, trailing commas, Chinese quotes) and retried through the model before falling back to a safe default.
RoosterContext injection (src/toolset/context.py): A RoosterContext dataclass carries session_id, task_id, workspace_dir, memory_manager, llm_client, blackboard, config, and security_policy into every tool's execute() call. Tools opt-in by implementing execute(self, args, ctx) alongside the legacy run(**kwargs) — the dispatcher auto-detects which signature to use. Existing tools require zero changes.
ToolCallValidator (src/toolset/validation.py): Before any tool executes, its arguments pass through a Pydantic-based validator. Two self-healing paths kick in on failure:
- JSON syntax healing: Fixes malformed JSON (missing quotes, trailing commas, single quotes) via lightweight LLM correction
- Schema structure healing: When
model_validateraisesValidationError, the error message is packaged into a prompt for the router model (temperature=0.1) to fix the parameters
Each path allows up to 2 retries. After budget exhaustion, the call degrades to a SchemaValidationFailed error for the ReAct loop to handle autonomously. The system never infinite-loops.
Security defaults upgraded: ADVANCED_SECURITY defaults to true, CONFIRMATION_BEHAVIOR defaults to block. Dangerous operations require explicit user confirmation instead of silent pass-through. PI scan exemptions cleared — python_exec, terminal, and other high-impact tools are no longer exempt from Prompt Injection scanning.
Typed signal exceptions (src/utils/exceptions.py): EscalateSignal and AbortSignal replace the fragile raise Exception("__ESCALATE__: ...") + .replace() magic-string pattern. Exception catching is now type-safe with precise stack traces.
Structured metrics (gateway/metrics.py): New Prometheus instruments — observe_tool_execution() (tool latency histogram + status counter), observe_subtask_execution() (subtask duration), observe_failover() (Provider failover rate), observe_llm_error() (LLM error tracking). Breaks the previous blind spot of token-count-only monitoring.
Mission correlation ID (src/utils/logging_context.py): ContextVar-based mission_id injection. Once MissionRunner calls set_mission_id(), all logs produced by that mission carry the [mission=xxx] tag — across Router, Strategist, Executor, and Auditor.
Resource governance: Unified cleanup() shutdown hook in launcher.py ensures Router, DistillationScheduler, and ModelFactory release their HTTPX connection pools on process exit. Bare except: clauses eliminated in favor of targeted except (json.JSONDecodeError, ValueError).
rooster/
├── .env # Non-sensitive config (model routing, behavior policies)
├── .env.local.example # Secrets template
├── pyproject.toml # Project config & dependencies
├── guardian.py # Process guardian (lifecycle, port cleanup, auto-restart)
├── start.bat # Windows launch script (macOS: double-click Rooster.app)
├── CONTRIBUTING.md # Contribution guidelines
├── SECURITY.md # Security policy
│
├── resources/
│ └── models/ # Vision model weights (committed to git, no extra download)
│ └── grounding/
│ └── icon_detect/
│ └── model.pt # YOLO UI element detection model (39 MB)
│
├── skills/ # External skills (12 built-in)
│ ├── coding-agent/ # Coding agent
│ ├── data-analysis/ # Data analysis
│ ├── dev-tools/ # Dev tools
│ ├── git-ops/ # Git operations
│ ├── github/ # GitHub operations
│ ├── pdf-tools/ # PDF tools
│ ├── resource-downloader/ # Resource downloader
│ ├── self-improving/ # Self-improvement
│ ├── summarize/ # Summarization
│ ├── visual-control/ # Visual control
│ ├── weather-query/ # Weather query
│ └── web-search/ # Web search
│
├── src/
│ ├── main.py # Entry: preflight + launch
│ ├── launcher.py # Launcher: gateway + CLI + channels + memory warmup
│ │
│ ├── agents/ # Core Agent roles
│ │ ├── protocol.py # Data protocol (MissionPlan / SubTask / Report / AuditVerdict)
│ │ ├── router.py # Entry router: L1 Gate → SkillIndex → Strategist.decide() → MissionRunner
│ │ ├── reframer.py # Intent normalizer (vague → structured instructions)
│ │ ├── short_circuit.py # Short-circuit router (fast-path for common tasks)
│ │ ├── strategist.py # Strategist (DAG subtask decomposition + replan)
│ │ ├── executor.py # Executor (ReAct loop + tool dispatch)
│ │ ├── auditor.py # Auditor (AFFIRM / REMAND / REPLAN / ESCALATE)
│ │ ├── orchestrator.py # Tool orchestrator (visual strategy + self-healing)
│ │ ├── mission_tactician.py# Tactician (DAG topo sort + parallel grouping)
│ │ ├── mission_blackboard.py# Shared blackboard for concurrent subtasks
│ │ ├── reflection_engine.py# Reflection engine (error pattern analysis)
│ │ ├── llm_client.py # LLM client (multi-provider rotation + cooldown + backoff)
│ │ ├── prompt_builder.py # 5-layer System Prompt builder
│ │ ├── tool_dispatch.py # Tool call extraction & execution
│ │ └── runners/
│ │ └── mission_runner.py# Multi-step orchestration (V15: DIRECT_REPLY / SINGLE_STEP / DAG_PLAN)
│ │
│ ├── toolset/ # Tool registry (55 tools, 32 exposed to LLM)
│ │ ├── base.py # BaseTool base class (platform / kit / fc_hidden)
│ │ ├── registry.py # Global tool registry (auto-discovery + schema validation)
│ │ ├── context.py # RoosterContext — unified DI container for tool execution
│ │ ├── validation.py # ToolCallValidator — schema self-healing (JSON + structure repair)
│ │ └── definitions/ # Tool implementations (22 modules)
│ │ ├── browser_automation.py # Browser automation (nav / read / click / act)
│ │ ├── visual_control.py # Desktop visual control (grounding_scan / read_screen / act)
│ │ ├── file_system.py # File system (file_system_op — read/write/list/search/mkdir)
│ │ ├── office.py # Office (excel_op / docx_write / pdf_op)
│ │ ├── interpreter.py # Python execution (E2B sandbox / local)
│ │ ├── web_search.py # Search (Linkup / Exa / GLM / 7-lane / Playwright 5-tier dynamic fallback)
│ │ ├── subagent.py # SubAgent orchestration
│ │ ├── task_manager.py # Task management
│ │ ├── task_scheduler.py # Scheduled tasks (Windows schtasks / macOS launchd)
│ │ ├── email.py # Email sending
│ │ ├── ocr.py # OCR text extraction
│ │ ├── memory.py # Long-term memory write
│ │ └── ... # 22 definition files total
│ │
│ ├── gateway/ # HTTP / WebSocket gateway
│ │ ├── server.py # FastAPI application factory
│ │ ├── auth.py # API Key auth + HMAC + rate limiting
│ │ ├── security.py # Security headers + request size limits
│ │ ├── run_manager.py # Run task management (with global cancel)
│ │ ├── connection_manager.py# Node connection pool
│ │ ├── dashboard_ws.py # Dashboard WebSocket push
│ │ ├── event_handler.py # Agent events → WebSocket broadcast
│ │ ├── local_node.py # Local controlled desktop node
│ │ ├── metrics.py # Prometheus metrics
│ │ ├── stream.py # Streaming protocol
│ │ └── routes/
│ │ ├── websockets.py # WebSocket endpoints
│ │ ├── config.py # /api/config read/write
│ │ ├── memory.py # /api/memory CRUD
│ │ ├── models.py # /api/models (Ollama / HuggingFace)
│ │ ├── skills.py # /api/skills marketplace
│ │ └── system.py # /api system endpoints
│ │
│ ├── channels/ # Input channels
│ │ ├── cli.py # Console interaction (bilingual /lang switch)
│ │ ├── feishu.py # Feishu/Lark bot (lazy-loaded)
│ │ ├── webhook.py # HTTP Webhook channel
│ │ └── registry.py # Channel registry
│ │
│ ├── models/ # LLM provider adapters
│ │ ├── factory.py # ModelFactory (provider → client factory)
│ │ ├── openai_adapter.py # OpenAI-compatible adapter
│ │ ├── anthropic_adapter.py# Anthropic Claude adapter
│ │ └── vision_strategy.py # Vision strategy
│ │
│ ├── memory/ # Memory system
│ │ ├── manager.py # LTM core (embedding + retrieval + decay)
│ │ ├── backends.py # JSON / Markdown storage backend
│ │ ├── soul_loader.py # SOUL.md / USER.md loading + 5-layer prompt build
│ │ ├── embeddings.py # Embedding vector generation
│ │ ├── semantic_search.py # Semantic search
│ │ ├── dedup.py # Memory deduplication
│ │ ├── indexer.py # Full-text indexer
│ │ ├── compactor.py # Memory compaction
│ │ └── watcher.py # File system watcher (hot reload)
│ │
│ ├── evolution/ # Self-evolution engine
│ │ ├── engine.py # Signal detection → LLM extraction → auto-write SOUL/USER
│ │ ├── soul_writer.py # SOUL.md append-only writer
│ │ └── user_writer.py # USER.md writer
│ │
│ ├── sessions/ # Session management
│ │ └── store.py # Global session store (atomic write)
│ │
│ ├── prompts/ # Prompt templates (Markdown)
│ │ ├── base.md # Base behavior protocol
│ │ ├── strategist.md # Strategist prompt
│ │ ├── executor.md # Executor prompt
│ │ ├── auditor.md # Auditor prompt
│ │ ├── replan.md # Replan prompt
│ │ ├── strategist_triage.md # V15 depth judgment prompt
│ │ └── intent_reframer.md # Intent reframer prompt
│ │
│ └── utils/ # Utilities
│ ├── config/ # Config system
│ │ ├── _base.py # Env var reading helpers (with typo detection)
│ │ ├── _settings.py # Composite Settings
│ │ ├── loader.py # Config loader (deprecated — .env is the sole config source)
│ │ ├── providers.py # LLM provider config
│ │ ├── runtime.py # Runtime config
│ │ ├── hardware.py # Hardware/vision config
│ │ ├── channels.py # Channel config
│ │ └── memory.py # Memory config
│ ├── security/ # Security modules
│ │ ├── path_guard.py # Path guard (symlink bypass prevention)
│ │ ├── state_guard.py # State guard
│ │ ├── advanced_guard.py# Jailbreak detection (PI scan — no tool exemptions)
│ │ ├── input_guard.py # Input validation
│ │ ├── secrets_mask.py # Log secret masking
│ │ └── tool_rate_limiter.py # Per-tool rate limiting
│ ├── exceptions.py # Typed signal exceptions (EscalateSignal / AbortSignal)
│ ├── logging_context.py # Mission correlation ID (ContextVar-based log injection)
│ ├── vision/ # Vision engine (YOLO)
│ ├── browser/ # Browser tools (Playwright)
│ └── audit/ # Audit tools
│
├── tests/ # Test suite (31 test files)
└── .rooster/ # Runtime data (gitignored)
├── SOUL.md # Agent soul file
├── USER.md # User profile file
├── project_memory.json # Long-term memory
├── schedules.json # Scheduled tasks
├── sessions/ # Session data
└── logs/ # Logs
User Message (CLI / Feishu / WebSocket / Dashboard)
│
▼
L1 Hard-Rule Gate (< 5ms, pure code)
├─ BLOCK ────────► Safety intercept
├─ SCHEDULE ─────► Scheduled task registration → schedules.json
├─ Download KW ──► Reframer pre-processing
└─ Other ────────► Continue to planner path
│
▼
L2 SkillIndex (~20ms, TF-IDF)
│
▼
Strategist.decide() (fast LLM)
│
├─ DIRECT_REPLY ──► Streaming response
├─ SINGLE_STEP ───► MissionRunner single task
├─ DAG_PLAN ──────► MissionRunner multi-step DAG
└─ CLARIFY ────────► Send clarification question
│
▼
MissionRunner
│
▼
Strategist (Planning Phase)
├─ DAG decomposition: task → ordered subtasks
├─ Dependency analysis: parallel grouping
└─ Domain routing: local vs cloud per subtask
│
┌─────┴─────┐
▼ ▼
Executor Executor
(ReAct loop (parallel
+ 29 tools) subtasks)
│ │
└─────┬─────┘
▼
┌──────────────┐
│ Privacy │
│ Router │
│ ┌──────────┐ │
│ │L0: Folder│ │ LOCAL_DIRS → local model
│ │L1: PII │ │ Presidio scan → local model
│ │L3: Policy│ │ Memory/Compaction → local
│ └──────────┘ │ Screenshots → OCR + strip
└──────────────┘
│
▼
Auditor
(quality review)
│
┌─────┴─────┐
▼ ▼
AFFIRM REMAND / REPLAN / ESCALATE
(continue) (redo / replan / escalate)
Layer 1: SOUL.md — Agent soul / personality (highest priority)
Layer 2: USER.md — User profile / preferences
Layer 3: Skills digest — Installed skills summary
Layer 4: LTM context — Long-term memory semantic recall
Layer 5: Base prompt — Role prompt (strategist.md / executor.md / etc.)
Multi-provider automatic failover, degrading by priority:
| Provider | Env Variable | Notes |
|---|---|---|
| Zhipu CodingPlan | ZHIPU_KEY |
Enhanced coding GLM, current primary |
| Zhipu GLM Standard | ZHIPU_GLM_KEY |
Standard API fallback |
| Xiaomi MiMo | MIMO_KEY |
Lightweight, default for reframer |
| Jiutian MoMA | JIUTIAN_KEY |
Dual-model (large/small) auto-routing |
| OpenAI | OPENAI_KEY |
GPT-4o etc. |
| Anthropic Claude | ANTHROPIC_KEY |
Native Messages API |
| Kimi (Moonshot) | KIMI_KEY |
Moonshot AI |
| Qwen (Tongyi Qianwen) | QWEN_KEY |
DashScope compatible |
| Cloud | CLOUD_KEY |
Generic OpenAI-compatible |
| Local | LOCAL_KEY |
llama.cpp / Ollama local inference |
55 tools registered, 32 exposed to LLM for Function Calling (23 are internal/legacy). All tool calls pass through ToolCallValidator for schema auto-healing before execution. Tools can opt into RoosterContext dependency injection by implementing execute(self, args, ctx) alongside the legacy run(**kwargs). Grouped by Kit:
| Kit | Core Tools | Capabilities |
|---|---|---|
| Browser | browser_nav, browser_act, web_fetch, batch_web_fetch |
Web browsing & scraping |
| Search | web_search |
Multi-engine search (Linkup / Exa / GLM / 7-lane / Playwright 5-tier dynamic fallback) |
| Vision | desktop_grounding_scan, desktop_act, desktop_read_screen |
Desktop UI control |
| FileSystem | file_system_op |
File read/write/list/search/mkdir/download |
| Office | excel_op, office_docx_write, pdf_op |
Excel / Word / PDF |
| Interpreter | python_interpreter |
Python execution (E2B sandbox / local) |
| Memory | memory_add_fact |
Long-term memory write |
| Task | task_manager, task_scheduler |
Task management + scheduled tasks |
| SubAgent | subagent_spawn, subagent_result |
SubAgent orchestration |
| Comms | email_send, feishu_push_file |
Email / Feishu push |
| Multimedia | multimedia_download, movie_downloader |
Resource downloads |
| OCR | ocr_extract |
Image text extraction (PaddleOCR) |
| Plan | plan_mode |
Planning mode (pause → user review → continue) |
| System | tool_info, skill_read, wait_until |
Meta-tools |
| Layer | Mechanism | Details |
|---|---|---|
| Gateway auth | API Key (X-API-Key / Authorization: Bearer) |
Skipped when GATEWAY_API_KEY is empty (local dev) |
| Webhook signing | HMAC-SHA256 | Enabled when WEBHOOK_HMAC_SECRET is set |
| Rate limiting | IP sliding window (100 req/min) | Localhost automatically exempt |
| Security headers | CSP / X-Frame-Options / X-Content-Type-Options | Global middleware |
| Request size | 1 MB limit | Prevents oversized request bodies |
| Input validation | Config key whitelist + value length limits | /api/config/save endpoint |
| File sandbox | PathGuard (realpath + prefix) | Prevents symlink bypass |
| Jailbreak detection | AdvancedGuard | Detects prompt injection / skill poisoning |
| Log masking | secrets_mask | Auto-masks secrets in logs |
| Tool rate limiting | tool_rate_limiter | Per-tool quota rate limiting |
# 1. Clone and install (Dashboard is pre-built, no Node.js needed)
git clone https://github.com/zzycxz/rooster.git
cd rooster
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
# 2. Configure API keys (at least one LLM key required)
cp .env.local.example .env.local
# Edit .env.local — fill in at least one API Key
# 3. Launch (guardian mode with auto-restart)
python guardian.pyDashboard opens automatically at http://localhost:8765/dashboard.
First-time user notes:
- Ready to use after
git clone— model weights and Dashboard frontend are included in the repo- If the browser doesn't open automatically, navigate to
http://localhost:8765/dashboard- Dashboard supports bilingual ZH/EN (Language button at sidebar bottom)
- Only one LLM API key is needed to run (Zhipu recommended — has free tier)
- Ollama users: install Ollama and pull a model first
| Method | How |
|---|---|
| Double-click | Double-click Rooster.app (macOS launcher, venv auto-activated) |
| Terminal | python3 guardian.py |
macOS Sequoia (15.x) Gatekeeper: If you see "无法执行,因为你没有正确的访问权限" when double-clicking for the first time, go to System Settings → Privacy & Security → Security and click "Open Anyway". This is a one-time approval — subsequent launches work normally. Alternatively, use
python3 guardian.pyfrom Terminal to bypass Gatekeeper entirely.
Core features (LLM, browser, file ops, Dashboard) work identically on macOS. Known differences:
| Feature | macOS Status | Notes |
|---|---|---|
| Visual desktop control | Partial | Screenshots + pyautogui work; UIA window scanning unavailable |
window_visible wait |
Needs permission | Grant Accessibility access to Terminal/Python in System Settings |
| Playwright | Needs install | playwright install chromium |
| YOLO grounding | Manual install | pip install -e ".[vision]" |
On first launch, the Dashboard automatically detects whether .env.local is configured. If not:
- Open
http://localhost:8765/dashboard - Click the "Setup" tab on the left
- Select an LLM provider → Enter API Key → Click "Save Config"
- The system auto-restarts with the new config
- Use "Test Connection" to verify provider connectivity
The Setup panel also includes:
- Ollama Guardian: Detect local Ollama status, pull models, assign roles
- HuggingFace Model Browser: Search/download GGUF models, import to Ollama or launch llama.cpp
- Role Matrix: Assign providers to Router / Strategist / Executor / Auditor / Solo individually
Dashboard is a single-page web app (Alpine.js + Tailwind) with 13 panels:
| Panel | Features |
|---|---|
| Execution | Agent chat + real-time Pipeline visualization (Router→Strategist→Executor→Auditor status) + session management + image paste |
| Downloader | Full-featured visual download manager (AriaNg integration + aria2c status) |
| Steps | Detailed timeline of every Agent action (tool args / return values), with filter and search |
| Logs | Real-time log stream (level filter + search + export + stack trace expand) |
| Errors | Error collection (stack traces + fix suggestions) |
| Tools | Tool call history (args + results + duration) + per-tool success/fail/latency stats |
| Skills | Installed skill management (load/unload/test/fix-deps) + ClawHub online marketplace |
| Memory | Memory facts browser (search / delete / decay) + SOUL.md / USER.md editor |
| Metrics | Active sessions/subtasks/requests + LLM/Tool/HTTP latency percentiles + Guardian watchdog status |
| Config | .env config view (grouped by category, secrets masked) |
| Setup | 10 provider cards + Ollama manager + HF model browser + role matrix + failover config + danger zone |
| Health | Service connectivity check + CPU / Memory / Disk / Network / Top processes |
| Scheduler | Cron task list + editor + execution history + dashboard |
Gateway listens on ws://127.0.0.1:8765/ws/gateway by default.
Send a task:
{
"method": "chat.send",
"params": {
"sessionKey": "my_session_001",
"message": "Search for Python asyncio usage"
},
"id": "req_001"
}Cancel execution:
{
"method": "chat.cancel",
"params": { "sessionKey": "my_session_001" },
"id": "cancel_001"
}System endpoints:
| Endpoint | Method | Description |
|---|---|---|
/api/health |
GET | Health check (LLM + .env.local) |
/api/version |
GET | Version number |
/api/cancel |
POST | Global cancel all running tasks |
/api/metrics/summary |
GET | JSON metrics summary |
/metrics |
GET | Prometheus metrics |
/api/system/stats |
GET | System resources (CPU / memory / disk / network) |
/api/guardian/status |
GET | Guardian watchdog status |
/api/sessions |
GET | Session list |
/api/toolset |
GET | Registered tools (grouped by Kit) |
/api/security/status |
GET | Security configuration status |
Config endpoints (/api/config):
| Endpoint | Method | Description |
|---|---|---|
/api/config/save |
POST | Save config to .env.local (auto-restart) |
/api/config/reload |
POST | Hot-reload .env files (no restart) |
/api/config/models |
GET | Configured provider list |
/api/config/masked |
GET | Masked full config |
/api/config/test |
GET | Test provider connectivity |
Memory endpoints (/api/memory):
| Endpoint | Method | Description |
|---|---|---|
/api/memory/stats |
GET | Memory statistics |
/api/memory/facts |
GET | Memory facts list |
/api/memory/facts/{id} |
DELETE | Delete a memory |
/api/memory/decay |
POST | Trigger memory decay |
/api/memory/soul |
GET / PUT | SOUL.md read/write |
/api/memory/user |
GET / PUT | USER.md read/write |
Skills endpoints (/api/skills):
| Endpoint | Method | Description |
|---|---|---|
/api/skills |
GET | Installed skills list |
/api/skills/market |
GET | ClawHub skill marketplace |
/api/skills/install |
POST | Install a skill |
/api/skills/uninstall |
POST | Uninstall a skill |
/api/skills/reload |
POST | Hot-reload skill cache |
/api/skills/toggle |
POST | Enable / disable a skill |
/api/skills/test |
POST | Test a skill |
Model endpoints (/api/models):
| Endpoint | Method | Description |
|---|---|---|
/api/models/ollama/scan |
GET | Scan local Ollama models |
/api/models/ollama/pull |
POST | Pull Ollama model |
/api/models/ollama/apply |
POST | Assign model to role |
/api/models/ollama/delete |
POST | Delete Ollama model |
/api/models/hf/search |
GET | Search HuggingFace GGUF models |
/api/models/hf/download |
POST | Download HF model |
/api/models/hf/import/ollama |
POST | Import to Ollama |
/api/models/hf/import/llamacpp |
POST | Launch llama.cpp server |
python guardian.py
# Enters interactive CLI
# Available commands:
/new - Start a new session
/list - List sessions
/switch - Switch session
/model - Switch model
/proxy - Proxy control (status / on / off)
/lang - Switch language (zh/en)
/exit - ExitWS /ws/gateway — Main gateway WebSocket (Dashboard push)
WS /ws/dashboard — Dashboard real-time updates
WS /v1/node/ws — Controlled desktop node (with auth_required handshake)
.env.local.exampleonly templates secrets. Runtime behavior, routing, and model selection live in.env.
# Recommended (Zhipu — has free tier)
ZHIPU_KEY=your_key
# Or other providers (any one is sufficient)
OPENAI_KEY=your_key
ANTHROPIC_KEY=your_key
MIMO_KEY=your_key
JIUTIAN_KEY=your_key
KIMI_KEY=your_key
QWEN_KEY=your_key
CLOUD_KEY=your_keyGATEWAY_API_KEY=your-secret-key # Leave empty to skip auth (local dev)
WEBHOOK_HMAC_SECRET=your-hmac # Webhook signing keySTRATEGIST_MODEL_MODE=zhipu # Strategist (default: zhipu)
EXECUTOR_MODEL_MODE=jiutian # Executor (default: jiutian)
AUDITOR_MODEL_MODE=jiutian # Auditor (default: jiutian)FAST_MODEL_PROVIDER=mimo # Lightweight provider for decide() / validator repair
FAST_MODEL_NAME=mimo-v2.5 # Fast-path model (must match FAST_MODEL_PROVIDER; see providers.py comment)
MODEL_TIER_FAST= # Optional override for fast tier
MODEL_TIER_STANDARD= # Optional override for standard executor tier
MODEL_TIER_REASONING= # Optional override for reasoning executor tier
SKILL_INDEX_THRESHOLD=0.3 # TF-IDF hint threshold
# Runtime priority: OLLAMA domain > model tier > executor defaultsLLM_FAILOVER_ENABLED=true
LLM_FAILOVER_ORDER=jiutian,zhipu,mimo,local
LLM_FAILOVER_RETRY_MAX=2GATEWAY_PORT=8765
OLLAMA_URL=http://localhost:11434 # Ollama management API
HF_ENDPOINT=https://huggingface.co # HuggingFace mirror (China: hf-mirror.com)
# HTTP_PROXY=http://127.0.0.1:7897 # Configure in .env.local# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest -q
# Lint
ruff check .Create a directory and SKILL.md under skills/:
---
name: my-skill
description: "Skill description"
metadata:
rooster:
emoji: "🔧"
platform: ["any"]
category: "automation"
requires:
python_packages: ["pandas"]
bins: ["git"]
---Create a Python file under src/toolset/definitions/, inheriting BaseTool:
from toolset.base import BaseTool
from toolset.context import RoosterContext
from pydantic import BaseModel
class MyToolArgs(BaseModel):
query: str
class MyTool(BaseTool):
name = "my_tool"
description = "A custom tool"
kit = "custom"
args_schema = MyToolArgs
# New: use execute() for RoosterContext injection (preferred)
async def execute(self, args: MyToolArgs, ctx: RoosterContext):
return {"result": "done", "session": ctx.session_id}
# Legacy: run(**kwargs) still works for backward compatibility
async def run(self, **kwargs):
return {"result": "done"}See CONTRIBUTING.md for detailed guidelines.
| Issue | Check First |
|---|---|
| Startup failure | Console output — preflight checks indicate missing API keys |
| Task not executing | src/agents/router.py → handle_inbound() |
| Subtask timeout | src/agents/strategist.py → timeout parameter |
| Tool call failure | src/agents/tool_dispatch.py → _execute_tool_with_healing() |
| LLM call failure | src/agents/llm_client.py → Provider switching logic |
| Vision grounding inaccurate | src/utils/vision/grounding.py (requires pip install -e ".[vision]") |
| Dashboard disconnected | Check GATEWAY_API_KEY config and browser console |
| Feishu channel not starting | Normal — auto-skipped when lark-oapi is not installed |
| Symptom | Cause | Solution |
|---|---|---|
| "No LLM API keys" error | .env.local not configured | cp .env.local.example .env.local and fill in a key |
| Web scraping returns empty | Anti-scraping block | Check HTTP_PROXY or playwright install chromium |
| Vision tool error | Missing YOLO dependencies | pip install -e ".[vision]" |
| Dashboard shows disconnected | Auth mismatch | Ensure browser has auth header injected, or clear GATEWAY_API_KEY |
| Tool registration failed | BaseTool subclass missing name/description/run | Refer to toolset/base.py contract |
| Ollama connection failed | Ollama not running or wrong port | Check OLLAMA_URL config, default http://localhost:11434 |
MIT