203 lines
11 KiB
Markdown
203 lines
11 KiB
Markdown
# Fischer AgentKit — Project Context
|
|
|
|
## Rules
|
|
|
|
- Python >= 3.11, type hints required, `pydantic>=2.0` for all data models
|
|
- Ruff for lint + format: `ruff check src/ && ruff format src/` (target py311, line-length 100)
|
|
- Tests: `pytest` (asyncio_mode=auto), markers: `integration`, `redis`, `postgres`
|
|
- Never use `any` type — use proper Pydantic models or `Unknown`
|
|
- API key comparison must use `hmac.compare_digest` (constant-time)
|
|
- Expert names validated with `_EXPERT_NAME_RE = re.compile(r"^[a-zA-Z0-9_-]{1,64}$")`
|
|
- HandoffTransport queues bounded (`maxsize=1024`), close uses sentinel pattern
|
|
- Frontend: Vue 3 + TypeScript + Ant Design Vue, Pinia stores, no `require()` calls
|
|
- **Async generator safety**: Never use early `return` before the first `yield` in `async def` — use `return; yield` pattern instead (see `.trae/rules/project_rules.md`)
|
|
|
|
## Tech Stack
|
|
|
|
- **Backend**: Python 3.11+, FastAPI, Uvicorn, Pydantic v2, SQLAlchemy 2 (async)
|
|
- **Frontend**: Vue 3, TypeScript, Vite 5, Ant Design Vue 4, Pinia, Vue Router 4
|
|
- **Desktop**: Tauri 2.x (Rust shell + Python sidecar)
|
|
- **Infra**: Redis (bus/cache/state), PostgreSQL + pgvector (episodic memory)
|
|
- **CLI**: Typer + Rich
|
|
- **Exact versions**: see `pyproject.toml` (Python), `package.json` (Node)
|
|
|
|
## Commands
|
|
|
|
```bash
|
|
# Backend
|
|
pip install -e ".[dev]" # Install with dev deps
|
|
agentkit gui --port 8002 # Web GUI (frontend + API)
|
|
agentkit serve --port 8001 # API-only server
|
|
agentkit chat # CLI interactive chat
|
|
agentkit init # Generate agentkit.yaml
|
|
agentkit version / doctor / usage # Utility commands
|
|
agentkit task submit/status/list/cancel # Task management
|
|
agentkit skill list/load/info # Skill management
|
|
agentkit pair --name X # Generate API key for external system
|
|
pytest # Run all tests
|
|
pytest -m "not integration" # Unit tests only
|
|
ruff check src/ && ruff format src/ # Lint + format
|
|
|
|
# Frontend
|
|
cd src/agentkit/server/frontend
|
|
npm install # Install deps
|
|
npm run dev # Vite dev server (proxy /api -> :8000)
|
|
npm run build:frontend # Production build -> ../static
|
|
npm run typecheck # TypeScript check
|
|
|
|
# Desktop
|
|
cd src/agentkit/server/frontend
|
|
npm run tauri dev # Tauri dev mode
|
|
npm run tauri build # Tauri production build
|
|
|
|
# Docker
|
|
docker-compose up -d # AgentKit + Redis + PostgreSQL
|
|
```
|
|
|
|
## Architecture
|
|
|
|
### Request Flow
|
|
|
|
```
|
|
User Input
|
|
├─ @board prefix -> BoardRouter (experts/board_router.py) -> BoardOrchestrator (multi-round discussion)
|
|
├─ @team prefix -> ExpertTeamRouter (experts/router.py) -> TeamOrchestrator (pipeline collaboration)
|
|
└─ otherwise -> RequestPreprocessor (chat/request_preprocessor.py)
|
|
Layer 0: @skill:xxx prefix -> explicit skill selection (SKILL_REACT or skill's configured mode)
|
|
Layer 1: Trivial-input regex (~0ms, 0 tokens) -> DIRECT_CHAT
|
|
(greetings, identity, factual Q&A, math, translation; guarded by _TOOL_CONTEXT_RE)
|
|
Default: -> REACT (LLM decides tool usage autonomously in the agent loop)
|
|
-> ExecutionMode: DIRECT_CHAT / REACT / SKILL_REACT / REWOO / REFLEXION / PLAN_EXEC / TEAM_COLLAB
|
|
(chat handler currently supports DIRECT_CHAT, REACT, SKILL_REACT; others raise "not yet supported")
|
|
```
|
|
|
|
**Note**: The old 3-layer `CostAwareRouter` (with `RegexRules` / `HeuristicClassifier` / `SemanticRouter` / `Vickrey Auction`) has been replaced by `RequestPreprocessor`. The `IntentRouter` (`router/intent.py`) exists but is not wired into the chat flow. `AuctionHouse` with Vickrey auction lives in `marketplace/auction.py` (marketplace subsystem, not routing).
|
|
|
|
### Agent Hierarchy
|
|
|
|
```
|
|
BaseAgent (core/base.py) — abstract, execute() is final
|
|
+-- ConfigDrivenAgent (core/config_driven.py) — YAML-driven, 3 task modes
|
|
+-- ReActEngine (core/react.py) — Think->Act->Observe
|
|
+-- ReflexionAgent (core/reflexion.py) — reflection-driven
|
|
+-- ReWOOAgent (core/rewoo.py) — plan-without-observation
|
|
+-- StandaloneAgent (core/standalone.py) — standalone runner
|
|
```
|
|
|
|
### Expert Team Mode (Pipeline)
|
|
|
|
```
|
|
ExpertConfig (extends AgentConfig) -> Expert (wraps ConfigDrivenAgent via AgentPool)
|
|
ExpertTeam: manages experts, shared workspace, team status (FORMING→PLANNING→EXECUTING→SYNTHESIZING→COMPLETED)
|
|
TeamOrchestrator: pipeline execution — Lead decomposes task into PlanPhase with depends_on, topological sort, parallel layers
|
|
PlanPhase: id, name, assigned_expert, task_description, depends_on, status (PENDING/RUNNING/COMPLETED/FAILED)
|
|
TeamPlan: phases with dependencies, topological_sort() returns execution layers (Kahn's algorithm)
|
|
ExpertTeamRouter: @team prefix routing, @team:dev_team template expansion, name validation, MAX_EXPERTS=10
|
|
HandoffTransport: InProcess (asyncio.Queue) + Redis Pub/Sub — used for event broadcasting only
|
|
```
|
|
|
|
**Pipeline Flow**:
|
|
1. `@team` prefix triggers team mode (or `@team:dev_team` for template, `@team:expert1,expert2` for explicit)
|
|
2. `ExpertTeam.create_team()` sets status to PLANNING
|
|
3. Lead Expert decomposes task into phases via LLM (fallback to single phase on failure)
|
|
4. `topological_sort()` arranges phases into layers (same-layer parallel, inter-layer serial)
|
|
5. Each phase creates an isolated `ConfigDrivenAgent` via `AgentPool.create_agent` (context isolation, KTD3)
|
|
6. Phase outputs passed via `SharedWorkspace` (`{plan_id}/phase/{phase_id}/output`)
|
|
7. Lead synthesizes results (BEST strategy)
|
|
8. On all-phases-fail: fallback to single agent mode
|
|
|
|
**Event Sequence**: `team_formed` → `plan_update` → `phase_started` → `expert_step` → `expert_result` → `phase_completed` → `team_synthesis` → `team_dissolved`
|
|
|
|
**Team Templates**: `configs/experts/dev_team.yaml` stores member list in `bound_skills` field (tech_lead, frontend_engineer, backend_engineer, qa_engineer, code_reviewer)
|
|
|
|
Lifecycle: FORMING -> PLANNING -> EXECUTING -> SYNTHESIZING -> COMPLETED -> DISSOLVED
|
|
On failure: fallback to single-agent mode (lead or first active expert).
|
|
|
|
### Module Map
|
|
|
|
| Layer | Modules | Purpose |
|
|
|-------|---------|---------|
|
|
| API | `server/`, `cli/` | FastAPI routes + Typer CLI |
|
|
| Auth | `server/auth/` | JWT + RBAC + terminal security (6-layer whitelist) |
|
|
| Service | `core/`, `chat/`, `skills/`, `experts/` | Agent engine, routing, skills, expert teams |
|
|
| Data | `memory/`, `session/`, `bus/` | Persistence, sessions, messaging |
|
|
| Utility | `llm/`, `tools/`, `evolution/`, `quality/`, `mcp/` | LLM gateway, tools, self-evolution, quality, MCP |
|
|
| Client | `client/` | ConfigSync, RemoteLLMProvider integration |
|
|
|
|
### Key Subsystems
|
|
|
|
- **LLM Gateway** (`llm/`): 6 providers (OpenAI/Anthropic/Gemini/Doubao/Wenxin/Yuanbao), fallback, semantic cache, usage tracking, RemoteLLMProvider (client→server proxy with 401 refresh retry)
|
|
- **Memory** (`memory/`): 4-layer (SOUL/USER/MEMORY/DAILY), WorkingMemory (Redis), EpisodicMemory (PG+pgvector), SemanticMemory (HTTP RAG)
|
|
- **Evolution** (`evolution/`): Reflector, PromptOptimizer (genetic), PitfallDetector, ABTester
|
|
- **Tools** (`tools/`): 21 built-in + MCP extension, composition (SequentialChain/ParallelFanOut/DynamicSelector)
|
|
- **Pipeline** (`orchestrator/`): PipelineEngine, SagaOrchestrator, DynamicPipeline, HandoffManager
|
|
- **Bus** (`bus/`): MemoryBus (in-process), RedisBus (distributed)
|
|
- **Auth** (`server/auth/`): JWT (access 15min + refresh 7d, HS256), API Key (constant-time compare), 3-level RBAC (member/operator/admin + permission bits), 6-layer terminal security (blocklist→shell-ops→builtin→global→user→session→danger), bcrypt password hashing (rounds=12)
|
|
|
|
### Server Routes (22 modules)
|
|
|
|
| Prefix | Module | Purpose |
|
|
|--------|--------|---------|
|
|
| `/api/v1/agents` | agents.py | Agent CRUD |
|
|
| `/api/v1/tasks` | tasks.py | Task submit/query/cancel |
|
|
| `/api/v1/skills` | skills.py | Skill register/list |
|
|
| `/api/v1/chat` | chat.py | Chat REST + WebSocket |
|
|
| `/api/v1/ws` | ws.py | WebSocket channel |
|
|
| `/api/v1/llm` | llm.py | LLM usage |
|
|
| `/api/v1/llm/chat` | llm_gateway.py | LLM gateway proxy (JWT auth, SSE streaming) |
|
|
| `/api/v1/health` | health.py | Health check |
|
|
| `/api/v1/metrics` | metrics.py | Metrics |
|
|
| `/api/v1/evolution` | evolution.py + evolution_dashboard.py | Self-evolution API |
|
|
| `/api/v1/memory` | memory.py | Memory management |
|
|
| `/api/v1/portal` | portal.py | Portal |
|
|
| `/api/v1/kb` | kb_management.py | Knowledge base |
|
|
| `/api/v1/skill-mgmt` | skill_management.py | Skill management |
|
|
| `/api/v1/workflows` | workflows.py | Workflows |
|
|
| `/api/v1/terminal` | terminal.py | Local terminal (client sidecar PTY) |
|
|
| `/api/v1/terminal/server` | terminal_server.py | Server terminal (server PTY + admin approval) |
|
|
| `/api/v1/terminal` | terminal_whitelist.py | Whitelist/blocklist/audit-log management |
|
|
| `/api/v1/settings` | settings.py | Settings |
|
|
| `/api/v1/auth` | auth.py | Login/refresh/logout/me |
|
|
| `/api/v1/system` | system.py | System resources (SYSTEM_CONFIG permission) |
|
|
| `/api/v1/config` | config_sync.py | Config version + sync (polling) |
|
|
|
|
### WebSocket Chat Protocol
|
|
|
|
Client -> Server: `message`, `reply`, `confirmation_reply`, `cancel`, `ping`
|
|
Server -> Client: `connected`, `token`, `thinking`, `step`, `final_answer`, `skill_match`, `confirmation_request`, `confirmation_result`, `ask_human`, `error`, `pong`
|
|
Expert Team events: `team_formed`, `expert_step`, `expert_result`, `plan_update`, `phase_started`, `phase_completed`, `phase_failed`, `team_synthesis`, `team_dissolved`
|
|
|
|
### Frontend Pages
|
|
|
|
- `/agent/chat` — Chat with Expert Team view
|
|
- `/agent/code` — Code/workflow
|
|
- `/agent/monitor` — Evolution dashboard
|
|
- `/computer-use` — Desktop control
|
|
- `/login` — Login page (JWT auth)
|
|
- Terminal panel — Local + server terminal with whitelist manager
|
|
|
|
### Configuration Priority
|
|
|
|
CLI args > `agentkit.yaml` > env vars (`${VAR:-default}`) > `.env` > hardcoded defaults
|
|
|
|
Config search: `--config` path > `./agentkit.yaml` > `~/.agentkit/agentkit.yaml`
|
|
|
|
## Conventions
|
|
|
|
- Skill configs: `configs/skills/*.yaml` (15 presets)
|
|
- LLM configs: `agentkit.yaml` llm section (unified with server config)
|
|
- Pipeline configs: `configs/pipelines/*.yaml`
|
|
- Expert templates: `configs/experts/*.yaml` (5 programming experts + dev_team team template), registered via `ExpertTemplateRegistry`
|
|
- Team templates: `bound_skills` field stores member list (e.g., `dev_team.yaml` lists tech_lead, frontend_engineer, backend_engineer, qa_engineer, code_reviewer)
|
|
- All Pydantic models use `model_config = ConfigDict(...)` not `class Config`
|
|
- Test files: `tests/unit/` and `tests/integration/`
|
|
- Frontend stores: Pinia, one per domain (chat, team, settings)
|
|
- Frontend components: `src/agentkit/server/frontend/src/components/`
|
|
|
|
## Boundaries
|
|
|
|
- Never modify `pyproject.toml` version without explicit request
|
|
- Never push to main directly — use feature branches
|
|
- Integration tests require Docker (Redis + PostgreSQL)
|
|
- Desktop builds require Rust toolchain + PyInstaller
|