Self-improving AI agent on C# / .NET 10
Creates skills from experience Β· improves them during use Β· remembers context between sessions
Hercules is a compact self-improving micro-agent that reproduces the key self-improving characteristics of "hermes-style" agents (Nous Research) in a runnable form factor.
The agent creates skills from experience, improves them during use, retains knowledge across sessions,
and builds a deepening model of the user. It supports YandexGPT, Ollama Cloud, and Ollama Local
through a single OpenAI-compatible interface (Microsoft.Extensions.AI).
This is the default landing page (English). For the Russian version, see README-RU.md.
| Subsystem | What it does |
|---|---|
| Self-Improving Skill System | Automatically proposes creating a skill on repeated queries (>2 times), versions skills, and improves them when success rate is low |
| Long-term Memory | Stores user profile, preferences, entities, and session context in Markdown; carries context across restarts |
| Reflection Engine | Self-analysis after a session or every N commands β what went well / poorly / what to improve |
| Skill Router | Query routing: skill by triggers or direct LLM response |
| Hybrid Storage | Files (Markdown + JSON) for skills and memory + SQLite for logs and metrics |
| Multi-provider LLM | YandexGPT (primary), Ollama Cloud / Local, LM Studio β through a single OpenAI-compatible interface with automatic fallback |
| Interfaces | CLI (REPL, primary) + Telegram bot (secondary) |
Hercules/
βββ Program.cs # Entry point, DI and configuration setup
βββ appsettings.json # Provider and agent thresholds configuration
βββ Config/
β βββ AppConfig.cs # Configuration models
βββ Agent/ # Agent core
β βββ AgentCore.cs # Main request-processing loop
β βββ SkillRouter.cs # Skill-based routing (triggers)
β βββ SkillManager.cs # Skill CRUD + versioning (via LLM)
β βββ ReflectionEngine.cs # Self-analysis, reflection reports
β βββ MemoryManager.cs # Long-term memory, user model
βββ LLM/ # LLM layer (Microsoft.Extensions.AI)
β βββ ILLMClient.cs # Unified provider interface
β βββ ChatClientLLMClient.cs # Base over IChatClient
β βββ YandexGPTClient.cs # YandexGPT (OpenAI-compatible endpoint)
β βββ LocalLLMClient.cs # Ollama Cloud/Local, LM Studio
β βββ LlmClientFactory.cs # Client factory by provider name
β βββ ResilientLLMClient.cs # Resilience + fallback chain
βββ Storage/ # Storage
β βββ FileSkillRepository.cs # Skills/ β skill files
β βββ MemoryStore.cs # Memory/ β Markdown memory
β βββ SqliteSessionStore.cs # SQLite: sessions, logs, metrics, counters
β βββ Models.cs # Domain models (Skill, SkillMeta, ...)
βββ CLI/
β βββ ConsoleUI.cs # REPL loop (Spectre.Console)
βββ Telegram/
β βββ TelegramBot.cs # Telegram bot (long polling)
βββ Agent/WebApiAdapter.cs # Core adapter for Web API + DTO
Additional "faΓ§ade" projects on top of the core:
Hercules.WebApi/ # ASP.NET Core Minimal API (REST), port :5000
βββ Program.cs # DI + CORS + middleware, reuses the core
βββ Auth/ApiKeyMiddleware.cs # X-Api-Key header validation
βββ Config/WebApiConfig.cs # API key + allowed CORS origins
βββ Controllers/ # Chat / Skills / Memory / Stats (Minimal API)
hercules-web/ # Astro + TailwindCSS frontend, port :4321
βββ src/lib/api.ts # Web API client
βββ src/layouts/Layout.astro # Base layout (dark theme, navigation)
βββ src/components/ # ChatBox, SkillCard, ProfileEditor, StatsDashboard
βββ src/pages/ # index / skills / profile / stats
All runtime data goes into the data/ directory:
data/
βββ Skills/ # skill.{id}.md / .prompt.md / .meta.json / .usage.json / .v{N}.md
βββ Memory/ # user_profile.md, preferences.md, entities.md, context_{date}.md
βββ sessions.db # SQLite: sessions, interactions, metrics
cd Hercules
dotnet restore
dotnet builddotnet rundotnet run -- --telegram(set Telegram:BotToken in appsettings.json beforehand)
# from repository root
dotnet run --project Hercules.WebApiThe server starts on http://localhost:5000. The agent core (AgentCore) is reused
through the WebApiAdapter adapter β there is no separate agent logic in the Web API.
dotnet run --project Hercules -- --cli # REPL mode
dotnet run --project Hercules # same thing (CLI by default)ASP.NET Core Minimal API. All responses are JSON (UTF-8, camelCase). Protection is the
X-Api-Key header (value from WebApi:ApiKey, default dev-local-key). CORS is open for
the local frontend (http://localhost:4321, http://localhost:3000). Every interaction
is logged in SQLite (data/sessions.db).
| Method | Route | Description |
|---|---|---|
GET |
/api/health |
Liveness check (no key required) |
POST |
/api/chat |
Send a message to the agent β response + mode/confidence/skill |
GET |
/api/skills |
List skills |
POST |
/api/skills |
Create a skill manually; ?ai=true β generate via LLM |
GET |
/api/skills/{id} |
Skill details (metadata + prompt) |
PUT |
/api/skills/{id} |
Update a skill (triggers/prompt/description) β new version |
POST |
/api/skills/{id}/improve |
Improve a skill via LLM β new version |
GET |
/api/memory/profile |
Long-term memory profile (Markdown) |
PUT |
/api/memory/profile |
Overwrite the memory profile |
POST |
/api/memory/reset |
Reset long-term memory |
GET |
/api/reflect |
Run reflection β Markdown report |
GET |
/api/stats |
Metrics: total, skill/direct, success rate, per-day |
Example:
curl -X POST http://localhost:5000/api/chat \
-H "X-Api-Key: dev-local-key" -H "Content-Type: application/json" \
-d '{"message":"what is the weather in Moscow?"}'Web API configuration (Hercules.WebApi/appsettings.json):
Minimalist SPA on Astro + TailwindCSS (dark theme, monospaced code blocks).
Located in the hercules-web/ directory.
| Page | Purpose |
|---|---|
/ |
Chat with the agent (mode/confidence/provider badges, typing effect, skill hints) |
/skills |
Skill list, manual creation and AI improvement, editing |
/profile |
Long-term memory profile editor + reset |
/stats |
Metrics dashboard, skill/direct ratio, daily activity, reflection |
Components: ChatBox, SkillCard, ProfileEditor, StatsDashboard. API client β src/lib/api.ts.
cd hercules-web
npm install
npm run dev # dev server on http://localhost:4321The backend address and key are configured via environment variables (hercules-web/.env file):
PUBLIC_API_BASE=http://localhost:5000
PUBLIC_API_KEY=dev-local-key# Terminal 1 β backend
dotnet run --project Hercules.WebApi # β :5000
# Terminal 2 β frontend
cd hercules-web && npm run dev # β :4321Open http://localhost:4321.
{
"Llm": {
"Provider": "yandexgpt", // active provider
"Fallback": ["ollama-cloud", "ollama-local"], // fallback order
"YandexGpt": {
"Endpoint": "https://llm.api.cloud.yandex.net/v1",
"ApiKey": "<IAM or API key>",
"FolderId": "<Yandex Cloud folder id>",
"Model": "yandexgpt", // becomes gpt://{folderId}/yandexgpt/latest
"Temperature": 0.6,
"MaxTokens": 2000
},
"OllamaCloud": {
"Endpoint": "https://ollama.com/v1",
"ApiKey": "<Ollama Cloud key>",
"Model": "gpt-oss:120b"
},
"OllamaLocal": {
"Endpoint": "http://localhost:11434/v1",
"ApiKey": "", // no key required locally
"Model": "llama3.1"
}
},
"Agent": {
"SkillCreationThreshold": 3, // repetitions before proposing a skill
"SkillImprovementThreshold": 0.6, // success_rate threshold for improvement
"SkillEvaluationWindow": 5, // skill evaluation window
"ReflectionEveryNCommands": 10 // auto-reflection every N commands
},
"Telegram": { "Enabled": false, "BotToken": "" }
}Any setting can be overridden via environment variables with the
HERCULES_prefix, for example:HERCULES_Llm__Provider=ollama-local.
All providers work through an OpenAI-compatible interface and the
Microsoft.Extensions.AI abstraction (IChatClient). Supported providers:
- YandexGPT β primary (Russia). The model is passed as
gpt://{folderId}/{model}/latest. - Ollama Cloud β cloud fallback (
https://ollama.com/v1). - Ollama Local / LM Studio β local fallback (
http://localhost:11434/v1).
If the primary provider is unavailable, ResilientLLMClient automatically switches
to the next one in the Fallback list.
| Command | Description |
|---|---|
> text |
Direct query to LLM with profile context |
/skills |
Show all skills (table) |
/skills create "name" |
Create a skill manually |
/skills improve {id} |
Improve a skill (new version) |
/memory show |
Show user profile |
/memory reset |
Reset memory |
/reflect |
Run reflection manually |
/help |
Help |
/exit |
Exit with context saving and final reflection |
/startβ initialization/skillsβ list of skills/profileβ what the agent knows about the user/resetβ reset memory- plain text β agent response
- Request β load profile and context from memory
- Routing β find a matching skill by triggers (
SkillRouter) - LLM response β with the active skill (skill-prompt) or directly (direct)
- Logging β input/output/confidence/mode in SQLite
- Skill threshold β if the request has been repeated
SkillCreationThresholdtimes β propose creating a skill (with confirmation) - Improvement threshold β if
success_rate < SkillImprovementThresholdβ propose updating the skill - Memory saving β facts about the user, entities, preferences
- Reflection β at the end of a session or every N commands
- Never stop learning β every session enriches memory or skills
- Explicit improvement loop β the agent itself proposes fixes
- Transparent β the user sees all creations/improvements
- Human-in-the-loop β skills are created only after confirmation
- Versioned β old skill versions are not deleted (
skill.{id}.v{N}.md)
| Criterion | How to verify |
|---|---|
| A skill is created automatically | Repeat the same query 3 times β the agent proposes a skill |
| A skill is used | After creation β the query goes through skill: ... |
| A skill improves | After a series of bad responses β a proposal to update |
| Profile is saved | Restart β /memory show remembers facts |
| Context is carried over | Session 1: fact β Session 2: agent remembers |
| Reflection runs | After /exit β Reflection Engine output |
Microsoft.Extensions.AI+Microsoft.Extensions.AI.OpenAIβ AI abstractionsOpenAIβ OpenAI-compatible SDK (YandexGPT, Ollama)Microsoft.Data.Sqliteβ SQLiteYamlDotNetβ metadata parsingSpectre.Consoleβ improved CLITelegram.Botβ Telegram interfaceMicrosoft.Extensions.Hosting/Configuration.Jsonβ DI and configuration
All documents are available in two languages. The default links point to the English version.
| Document | Description |
|---|---|
| docs/QUICKSTART-EN.md Β· RU | Quick start in a few minutes |
| docs/ARCHITECTURE-EN.md Β· RU | Core and interface architecture |
| docs/AGENT-MESH-EN.md Β· RU | Micro-agent mesh concept |
| docs/IOT-SCENARIOS-EN.md Β· RU | B2C/B2B IoT deployment scenarios |
| docs/ROADMAP-EN.md Β· RU | Planned features and milestones |
| docs/CONFIGURATION-EN.md Β· RU | Full settings reference |
| docs/API-EN.md Β· RU | REST Web API reference |
| CONTRIBUTING-EN.md Β· RU | How to contribute |
| CHANGELOG-EN.md Β· RU | Change history |
| SECURITY.md | Security policy |
| CODE_OF_CONDUCT.md | Code of conduct |
PRs and Issues are welcome! Before starting, please read CONTRIBUTING-EN.md and CODE_OF_CONDUCT.md. Report vulnerabilities via SECURITY.md.
MIT Β© 2026 Victor Buzin.