Show HN: Symbio self fine-tuning AI loop
Symbio is a local AI agent that learns from your corrections and fine-tunes itself via LoRA. It features a Mixture of Agents mode, on-the-fly skill learning, automatic mistake capture, and local-only data storage.
Notifications You must be signed in to change notification settings
Fork 1
Star 19
BranchesTags
Open more actions menu
Folders and files
NameName
Last commit message
Last commit date
Latest commit
History
107 Commits
107 Commits
docs
docs
spaces/symbio_demo
spaces/symbio_demo
symbio
symbio
symbio_native
symbio_native
tests
tests
tests_mcp
tests_mcp
.env.example
.env.example
.gitignore
.gitignore
CODE_OF_CONDUCT.md
CODE_OF_CONDUCT.md
CONTRIBUTING.md
CONTRIBUTING.md
LICENSE
LICENSE
NOTICE
NOTICE
PLAN.md
PLAN.md
README.md
README.md
benchmark_7b_class.json
benchmark_7b_class.json
benchmark_mlx.json
benchmark_mlx.json
benchmark_mlx_more.json
benchmark_mlx_more.json
benchmark_more_models.json
benchmark_more_models.json
benchmark_qwen25_9b.json
benchmark_qwen25_9b.json
benchmark_qwen_coder.json
benchmark_qwen_coder.json
computer.py
computer.py
config.example.json
config.example.json
conftest.py
conftest.py
debug_response.py
debug_response.py
dollar_tree_apple_sider_bacon.md
dollar_tree_apple_sider_bacon.md
golden_cases.json.example
golden_cases.json.example
install.sh
install.sh
main.py
main.py
memory.db
memory.db
memory_monitor.py
memory_monitor.py
models.json
models.json
planner.py
planner.py
pyproject.toml
pyproject.toml
rag.py
rag.py
raw_generate.py
raw_generate.py
requirements.txt
requirements.txt
seed_training.py
seed_training.py
setup.sh
setup.sh
smoke_test.py
smoke_test.py
stress_chat.py
stress_chat.py
switch_model.py
switch_model.py
symb
symb
test_adapter_idle.py
test_adapter_idle.py
test_auto_learn_e2e.py
test_auto_learn_e2e.py
test_chat_stress.py
test_chat_stress.py
test_cli.py
test_cli.py
test_computer.py
test_computer.py
test_deferred_learn.py
test_deferred_learn.py
test_dispatch.py
test_dispatch.py
test_dynamic_names.py
test_dynamic_names.py
test_eval.py
test_eval.py
test_file_tools.py
test_file_tools.py
test_golden.py
test_golden.py
test_golden_extensible.py
test_golden_extensible.py
test_health.py
test_health.py
test_learn.py
test_learn.py
test_learn_e2e.py
test_learn_e2e.py
test_main_loop.py
test_main_loop.py
test_mcp_tools.py
test_mcp_tools.py
test_rag.py
test_rag.py
test_safety.py
test_safety.py
test_sandbox_remote.py
test_sandbox_remote.py
test_setup.py
test_setup.py
test_skill_adapters.py
test_skill_adapters.py
test_streaming.py
test_streaming.py
test_telegram.py
test_telegram.py
test_threshold_training.py
test_threshold_training.py
test_utils.py
test_utils.py
Repository files navigation
Local Ai that learns from your corrections. No Cloud, No subscriptions.
Symbio takes notes and can construct it into training data to fine-tune itself - so you can stop repeating yourself.
| GitHub | Try it now
Symbio develops as you tell it what to do in repeat.
Try the interactive demo — the agent's real tag parser, self-correction miner, research memory, and RAG retriever running in your browser: https://huggingface.co/spaces/HuyEdits/symbio-demo
MOA feature
Symbio has a MOA (Mixture of Agents) mode. Instead of fine-tuning one big model for every task, the headmaster delegates bounded sub-tasks to smaller worker models via tool calls. The worker executes, and if it fails it returns to the headmaster for guidance. Once it works, a note is saved for both sides. If the same mistake repeats past the configured threshold, both the worker and the headmaster are fine-tuned: the worker learns how to execute the task, and the headmaster learns how to delegate it more efficiently.
Skill feature
Symbio can learn skills on the fly. A skill starts as a simple markdown note with step-by-step instructions. As errors and corrections accumulate, they are logged in a hidden .md.health.jsonl sidecar so the note itself stays clean and readable. Once the mistake threshold is reached, the collected examples are fed into a LoRA fine-tune that creates a dedicated worker adapter for that skill — one adapter = one skill. Adapters are hot-swappable and can be archived if unused.
Use /new-skill or symb skill new to create one, /skill-adapters to list them, and /archive / /restore to manage idle notes and adapters.
What it does
Chat through a local CLI or a Telegram bot.
Save facts and notes as markdown files in notes/.
Read, write, search, and patch files inside the project directory.
Run sandboxed shell commands and short Python snippets.
Check email via IMAP/SMTP (when configured).
Digest notes into training data and fine-tune a LoRA adapter on the fly.
Persist every conversation turn to JSONL and an SQLite store.
Please star this project too. It would help me out SO SO much. :3 # Print one value, e.g. agent.temperature symb config set symb train # Run LoRA training symb skill list # List saved skills and their adapter status symb skill new # Create a new skill (interactive steps) symb skill rm # Delete a skill, adapter, and training data symb archive # Run auto-archive for idle notes/adapters symb archive --dry-run # Preview what would be archived symb archive --restore note|adapter symb gateway status # Check Telegram gateway readiness symb gateway start # Start the Telegram bot symb gateway stop # Stop a running gateway
Legacy python main.py flags still work:
python main.py --telegram python main.py --train
Telegram bot
Run Symbio as a Telegram bot so you can chat from your phone:
symb gateway start
Legacy equivalent: python main.py --telegram
Check gateway readiness first:
symb gateway status
On first run you will be prompted for a bot token from @BotFather. The token is saved to config.json. For better security, set the environment variable SYMBIO_TELEGRAM_TOKEN instead; it overrides the config file.
You must add your Telegram chat ID to telegram.allowed_chat_ids:
symb config set telegram.allowed_chat_ids '[123456789]'
Send any message to the bot, then copy the chat ID from the refusal message if you haven't set it yet.
Dangerous actions from Telegram — blocked shell commands, new browser domains, Python code, config changes, cron jobs, digest, and training — ask for approval via an inline keyboard before running.
Telegram slash commands
Command Description
/start Welcome message
/help List available commands
/ping Last turn latency breakdown
/status Model, adapter, data, and last turn timings
/golden Run golden-set regression check
/train Start LoRA training
/selfcheck Verify enabled features and auto-fix safe issues
/setup How to change configuration
/tools Toggle tool groups
/cancel Clear the current session
Slash commands
Command Description
/quit Exit the chat
/save Save the current conversation to training data
/train Run LoRA fine-tuning and reload the adapter
/learn Manually learn from your last correction (auto-learn is on by default)
/digest Convert notes into training samples
/note [title] Create a markdown note
/notes List saved notes
/new-skill Create a skill note and start training a worker adapter
/skills List saved skill notes
/skill-adapters List skill adapters and their training/idle status
/archive Archive idle notes/adapters (or preview with --dry-run)
`/restore note adapter `
/status Show model, adapter, notes, and session info
/selfcheck Verify enabled features and auto-fix safe issues
/setup Re-run the setup wizard (names, model, features)
/compact Compress memory/profile store and archive the original
/model List model presets
/model Switch to a named model preset (restart to load)
/run Run a sandboxed shell command
/forget_last Remove the last exchange from history
/prune Remove stale adapter checkpoints
Learning from corrections
Symbio detects natural corrections automatically and turns them into training data without you typing /learn. Instead of training on every single correction, it saves each mistake as a markdown note in notes/mistakes/ and only fine-tunes once enough notes have accumulated.
Typical flow:
You: What is my name? Symbio: Your name is Bob. You: No, I'm Alice. Symbio: Your name is Alice. [System] Correction detected (correction phrase). Saved mistake note: 20260715_123456_What_is_my_name.md 1/5 mistake note(s) collected. Training will run after 4 more correction(s).
Symbio will:
Detect correction phrases ("No, ...", "Actually ...", "That's wrong", etc.) or an exact repeat of your last question.
Extract the original question, the wrong answer, the user's correction, and the corrected answer.
Save them as a markdown note in notes/mistakes/.
When learn.mistake_threshold (default 5) notes have accumulated, digest them into training_data/train.jsonl and run a short LoRA update (learn.batch_train_iters, default 25).
Archive the used mistake notes to notes/mistakes/archive/ and reload the adapter.
The /learn command is still available to force a mistake note from the last correction, but it is no longer required.
Learning from its own tool mistakes
The same mistake-note pipeline also captures a second, fully automatic pattern that needs no user involvement at all: a tool call that fails, immediately followed by one that works. This is exactly the "wrong command, try the right one" pattern already hand-seeded into every install's base training data —
You: Open Chrome. Symbio: chrome [Tool: run_command] [Observation] Command 'chrome' exited error. Output: Command not found: chrome Symbio: 'chrome' isn't a command here — trying the native way. open -a 'Google Chrome' [Learn] Tool mistake captured: 20260721_213045_System_observation_Command_chrome.md
— except now it's learned from real usage, not just the seed examples. It feeds into the exact same notes/mistakes/ → threshold → digest → guarded-training pipeline as conversational corrections above, so both count toward the same learn.mistake_threshold. Nothing is saved if the model keeps failing without ever finding a working alternative within the turn — only a confirmed fix gets captured.
Tune the behaviour in config.json:
Key Default Note
learn.enabled true Enable correction learning
learn.auto true Detect corrections automatically
learn.auto_train true Run the fine-tune automatically when the threshold is reached
learn.mistake_threshold 5 Number of mistake notes before a batch fine-tune runs
learn.batch_train_iters 25 LoRA iterations for the threshold-triggered batch update
learn.boost_factor 3 Copies of each correction sample written per mistake note
learn.correction_phrases [...] Phrases that trigger correction detection
Fine-tuning details
Symbio uses LoRA (Low-Rank Adaptation) via Apple's MLX-LM framework. The base model weights stay frozen; only small adapter matrices are trained on curated conversation, notes, and corrections. Training is invoked through the official mlx_lm lora CLI:
symb train # full pass using lora.iters
The resulting adapter is saved to adapters/ and loaded automatically on the next start.
Setting Default What it controls
lora.rank 8 Width of the low-rank matrices
lora.num_layers 8 How many transformer layers get adapters
lora.scale 5.0 Adapter output scaling
lora.dropout 0.1 Dropout for regularization
lora.learning_rate 1e-4 Training step size
lora.iters 50 Iterations for /train
lora.max_seq_length 2048 Training context length
lora.save_every 50 Checkpoint frequency
Golden set: catching a fine-tune that silently breaks things
Every LoRA update (/train, the train_adapter tool, the auto-training that follows enough corrections, or the end-of-session prompt) is checked against a small, fixed go
[truncated for AI cost control]