Project Overview
Language: 中文 | English
FSAR (Fully Self-evolving AI Companion) is a local-first AI companion: conversations, memories, decisions, and tools all run on your own machine, stored in a SQLite database under ~/.fsar/. Nothing is uploaded to any FSAR server. It belongs to the user, not to a vendor.
The name is the design contract: Faithful · Safe · Adaptive · Reflective.
The four pillars
- Faithful — FSAR is the character you configured (character card: name, personality, scenario, emotion state), talking to the user you described (user card). It does not drift into a "generic assistant".
- Safe — Every tool call passes through layered checks: a hardcoded hardline guard blocks destructive commands (
rm -rf /,shutdown,mkfs) before anything else; a risk engine classifies each tool as SAFE/LOW/MEDIUM/HIGH/CRITICAL; a workspace gate contains file access; a subprocess env scrubber strips API keys and tokens before running skills. SeeSECURITY.md. - Adaptive — Each tool call is logged. A strategy injector synthesises a
## Learned Strategiesblock from the decision log and user model; an experience store persists procedural knowledge so an MCP server installed in one session is recalled in the next. - Reflective — Three reflection modes (per-task, on-failure, idle-batch) re-read conversations and update the user model: explicit preferences ("uses VSCode"), inferred profile ("often codes in the evening"), and recurring patterns. The next session opens with that context already in the system prompt.
What it can do
- Run shell commands (PowerShell on Windows, bash elsewhere) with a hardline guard
- Read, write, and search files within a scoped workspace
- Open apps and URLs via a sandboxed alias map
- Search and fetch the web via the free Exa MCP server (no API key required)
- Analyze images and PDFs locally
- Operate your computer (Computer Use / cua): screenshot, click, type, keypress — gated separately
- Persist new skills as SQLite experience rows (install once, recall many times)
- Talk through Telegram, Feishu (Lark), and WeChat
- Hold a spoken conversation with an on-screen avatar (Live Companion): pick a character + model, talk, and FSAR replies aloud with lip-synced, expression-driven VRM or Live2D models (bring your own model files)
- Share one room with several characters and you — the characters elect among themselves who speaks next, and naming one with
@hands them the floor - Work a room as a project: a plan board, one turn per member in that member's own copy of your repo, patches you land or refuse by hand, and snapshots you publish by allowlist
- Screen stored memories for prompt injection and quarantine what is flagged, in a notification center that also carries new releases and official announcements
- Know the date, how long you have been away, and your birthday
- Run a single turn without the UI (
fsar run,fsar room say/fsar room read)
Tech stack
| Layer | Technology |
|---|---|
| Backend | Python 3.12+, FastAPI + WebSocket |
| Frontend | React + TypeScript (Vite), served in the browser by the backend |
| Storage | SQLite (memory.db etc.) + ChromaDB (semantic vectors) |
| Models | OpenAI / Anthropic / Google / DeepSeek / any OpenAI-compatible endpoint / Ollama / LM Studio |
| CLI entry | fsar (full-screen Textual TUI); python main.py (legacy simple REPL) |
Architecture at a glance
┌───────────────────────────────────────────┐
│ Frontend (React) frontend/dist │
│ Chat / Rooms / Cards / Memory / ... │
└───────────────┬───────────────────────────┘
│ WebSocket (JSON) + HTTP /ws
┌───────────────▼───────────────────────────┐
│ src/server FastAPI app + ChatEngine │
│ handlers/ (~27 routers) RiskBridge │
└───────────────┬───────────────────────────┘
│
┌───────────────┬────────┴────────┬────────────────┐
▼ ▼ ▼ ▼
src/core src/memory src/tools src/social
agent loop / short / long / tool registry + Telegram / Feishu /
prompts / semantic / user built-in tools WeChat adapters
injectors model / reflect
│ │ │
│ ┌──────┴─────────────────┴──────────┐
│ ▼ ▼
│ src/security risk engine / perms / src/sandbox hardline /
│ confirm / audit workspace gate / sensitive
│ │ │
└────────┴──────────┬─────────────────────────┘
▼
src/skills skill review gate + subprocess execution
src/mcp external MCP servers
src/providers LLM / TTS / ASR adapters
src/notifications review / release / announcement feed
src/updates release checks / announcements / git update flow
src/utils config / prompt-cache bookkeeping / logging / migrations
A message, end to end
Taking a chat message from the GUI as an example (details in src/server/chat_engine.py):
- Ingress — The frontend sends a JSON message over
/ws;ws_server._dispatchtries each handler in turn.chat.sendlands inhandlers/chat.py, which spawns a task callingChatEngine.handle_send. - Preparation — Ensures the conversation and its workspace binding, resolves the character card, and emits
chat.thinking. Then it branches:/-prefixed text → slash command; an "integration" model selection → a multi-model integration graph;companionmode → a one-shot companion turn; otherwise → the agent loop. - Prompt assembly — Loads the agent tier (
agent.tier), builds the system prompt fromAGENT_SYSTEM_PROMPT+ the character/user persona +## Learned Strategies+## Experiences, hydrates short-term memory, and fits it to the model's context window. - Agent loop — Iterates up to
max_tool_turnsturns: compacts context as needed, calls the LLM (with provider-side prompt caching where the endpoint supports it), and — when the response contains tool calls — executes them (in parallel where allowed). Higher tiers add adversarial verification and micro-reflection, until the model produces a final answer with no tool calls. - The security gauntlet per tool call (run in order; any deny stops the action):
- MCP gate — tools carrying a
server_namemust pass server review/verification; - Sandbox gate —
WorkspaceGatevalidates paths/commands; leaving the workspace triggers a "sandbox escape" confirmation awaitingdeny / allow_once / allow_session / allow_always; - Risk gate —
RiskEngine.evaluateyieldsproceed / confirm / deny; on confirm it awaits the frontend's response (which may grant session trust, trust the whole MCP server, or permanently deny); - Execution — for
run_command, network-egress and read-blacklist checks run first, and the working directory is pinned to the workspace root; - Post-execution — a small model reviews the result, secrets are redacted,
chat.tool_resultis emitted, and the decision is written to the audit log.
- MCP gate — tools carrying a
- Wrap-up — Tool results are appended and the loop continues until the answer is final; the conclusion is saved and streamed (optionally triggering TTS); per-tier task reflection runs, the idle reflector is bumped, and a conversation title is generated lazily.
Where the data lives
Everything about you lives under ~/.fsar/:
~/.fsar/config/ yaml configuration
~/.fsar/data/
memory.db conversations, decisions, user model, experience
chroma/ semantic embeddings
llm_cache.db provider prompt-cache bookkeeping
tts_cache.db TTS audio cache
scheduler.db scheduled tasks
logs/ rotating logs + audit.log
Delete ~/.fsar/ to reset FSAR completely.
What to read next
- Module reference — the responsibility and key files of every source module
- Configuration guide —
fsar.yamlitem by item - Build / Test / Develop
SECURITY.md— the security model and vulnerability reportingCONTRIBUTING.md— contributing
Source docs-public/overview.mdView on GitHub ↗