Clone of nanoclaw in Elixir
Обзор
A personal AI agent built in Elixir on Jido. - Elixir ~> 1.17 - Just command runner - An Anthropic API key mix goodwizard.setup creates the workspace directory, config.toml, and bootstrap files (IDENTITY.md, SOUL.md, USER.md, etc.). Edit config.toml to set your preferred model, enabled channels, and other options. The agent's personality and knowledge are shaped by editable files in the workspace: - — who the agent is (name, role, tone) - — values, principles, and behavioral guidelines - — what the agent knows about you - — guidance for how the agent uses its tools - — conventions for sub-agent behavior At startup, the Preamble module assembles these files plus runtime state (available tools, knowledge base schemas, skills) into a full system prompt via the Hydrator. A file-backed structured entity store with JSON Schema validation. Entities are stored as markdown with YAML frontmatter in knowledge_base/ / .md.
README
Goodwizard
A personal AI agent built in Elixir on Jido.
Getting Started
Prerequisites
- Elixir ~> 1.17
- Just command runner
- An Anthropic API key
Install & Setup
mix deps.get
mix goodwizard.setup
mix goodwizard.setup creates the workspace directory, config.toml, and bootstrap files (IDENTITY.md, SOUL.md, USER.md, etc.).
Configure
Copy and edit .env with your API keys:
cp .env.example .env
ANTHROPIC_API_KEY=your-anthropic-key
TELEGRAM_BOT_TOKEN=your-telegram-bot-token # optional, for Telegram channel
Edit config.toml to set your preferred model, enabled channels, and other options.
Run
# Interactive CLI REPL
mix goodwizard.cli
# Full OTP application (Telegram, heartbeat, scheduling)
mix goodwizard.start
Commands
| Command | Description |
|---|---|
just setup |
Run setup |
just up |
Start the agent |
just cli |
Start the CLI REPL |
just status |
Show agent status |
just test |
Run tests |
just check |
Run quality checks (compile, format, credo, doctor, dialyzer, test) |
just build |
Compile the project |
just clean |
Clean build artifacts |
How the Agent Works
Character & Identity
The agent’s personality and knowledge are shaped by editable files in the workspace:
IDENTITY.md— who the agent is (name, role, tone)SOUL.md— values, principles, and behavioral guidelinesUSER.md— what the agent knows about youTOOLS.md— guidance for how the agent uses its toolsAGENTS.md— conventions for sub-agent behavior
At startup, the Preamble module assembles these files plus runtime state (available tools, knowledge base schemas, skills) into a full system prompt via the Hydrator.
Knowledge Base
A file-backed structured entity store with JSON Schema validation. Entities are stored as markdown with YAML frontmatter in knowledge_base//.md.
Built-in types: people, places, events, notes, tasks, companies, tasklists, webpages
At startup, type-specific actions are auto-generated from the schemas — create_person, update_company, search_notes, etc. — so the agent can manage entities through natural conversation. Entities can cross-reference each other via "type/uuid" strings in their fields.
Memory System
Three complementary memory types:
- Semantic (
MEMORY.md) — persistent free-form context the agent maintains about you. Updated as the agent learns your preferences, habits, and ongoing projects. - Episodic (
memory/episodic/) — immutable records of past experiences: task completions, errors, decisions, and outcomes. Provides a factual history the agent can reference. - Procedural (
memory/procedural/) — learned workflows and patterns with confidence tracking, usage-based promotion/demotion, and time-based decay. The agent builds these by recognizing repeated patterns.
When a conversation grows long, a consolidation pass extracts new episodes and procedures from the session and updates MEMORY.md.
Skills
Prompt-based capability extensions stored in skills//SKILL.md.
Skills use two-tier loading: a summary of each skill is included in every system prompt so the agent knows what’s available, but the full skill body is only loaded on demand via activate_skill. This keeps the base prompt compact while allowing rich, detailed instructions when a skill is actually used.
Bundled: weather (wttr.in + Open-Meteo forecasts)
Scheduled Tasks
Recurring tasks use cron expressions (standard 5-field, day names, or aliases like @daily, @hourly). Each tick spawns an isolated sub-agent so scheduled work can’t interfere with your active conversation.
| Format | Example | Meaning |
|---|---|---|
| Standard 5-field | 0 9 * * * |
Daily at 9:00 AM |
| Day of week | 0 9 * * MON |
Every Monday at 9:00 AM |
| Interval | */15 * * * * |
Every 15 minutes |
| Alias | @daily |
Once a day (midnight) |
| Alias | @hourly |
Once an hour |
One-time tasks fire after a delay or at an absolute time, then are cleaned up.
Both types persist to disk and reload on restart.
Heartbeat
A GenServer that polls HEARTBEAT.md on a configurable interval. When the file’s modification time changes, its contents are dispatched through the agent pipeline.
Since HEARTBEAT.md is just a file, anything that can write to the filesystem can trigger the agent — scripts, CI pipelines, cron jobs, monitoring tools, or other services. Example:
echo "What tasks are due today?" > priv/workspace/HEARTBEAT.md
On the next tick, the agent reads the file, processes the prompt, and saves the response. The same content won’t be processed twice.
Use cases: reminders, deploy hooks, monitoring alerts, automated reporting, cross-system orchestration.
Tools
The agent has access to these tool categories:
| Category | Description |
|---|---|
| Filesystem | Read, write, edit, list, grep — restricted to the workspace by default |
| Shell | Command execution with safety guards (regex deny-list blocks dangerous commands) |
| Browser | Full automation: navigate, click, type, screenshot, extract content |
| Knowledge Base | Auto-generated CRUD actions for each entity type |
| Memory | Store and recall semantic, episodic, and procedural memories |
| Messaging | Send messages to rooms |
| Sub-agent | Spawn isolated child agents for delegated work |
| Scheduling | Create recurring or one-time scheduled tasks |
Sessions
Conversation history is persisted as JSONL in sessions/.
- CLI: A new session is created per invocation.
- Telegram: One persistent session per chat, survives restarts.
Channels
CLI — Interactive REPL via mix goodwizard.cli. Best for local development and quick interactions.
Telegram — Long-polling bot with user allowlist, automatic splitting of long messages, and per-channel personality overrides via character_overrides in config. See Telegram Bot Setup below.
Configuration Reference
| Section | Key | Default | Description |
|---|---|---|---|
[agent] |
model |
anthropic:claude-sonnet-4-5 |
LLM model identifier |
max_tokens |
8192 |
Max tokens per response | |
temperature |
0.7 |
Sampling temperature | |
workspace |
priv/workspace |
Workspace directory path | |
max_tool_iterations |
20 |
Max ReAct loop iterations per turn | |
memory_window |
50 |
Recent messages loaded into context | |
[channels.cli] |
enabled |
true |
Enable CLI channel |
[channels.telegram] |
enabled |
false |
Enable Telegram channel |
allow_from |
[] |
User ID allowlist (empty = allow all) | |
character_overrides |
— | Override tone/style for Telegram | |
[tools] |
restrict_to_workspace |
true |
Restrict filesystem/shell to workspace |
[tools.exec] |
timeout |
60 |
Shell command timeout in seconds |
deny_patterns |
(see config.toml) | Regex patterns that block shell commands | |
[heartbeat] |
enabled |
false |
Enable heartbeat polling |
interval_minutes |
5 |
How often to check the file | |
timeout_seconds |
120 |
Max agent response time | |
channel |
cli |
Delivery channel (cli or telegram) |
|
chat_id |
heartbeat |
Room identifier for delivery | |
[scheduling] |
channel |
cli |
Default channel for scheduled tasks |
chat_id |
— | Default chat ID for scheduled tasks | |
[scheduled_tasks] |
max_concurrent_agents |
50 |
Max isolated agents running at once |
ask_timeout |
120000 |
Timeout (ms) per scheduled agent call | |
max_jobs |
50 |
Max total persisted scheduled tasks | |
[browser] |
headless |
true |
Run browser without GUI |
adapter |
vibium |
Browser adapter (vibium or playwright) |
|
timeout |
30000 |
Browser action timeout in ms | |
[browser.search] |
brave_api_key |
— | Brave Search API key |
[session] |
max_cli_sessions |
50 |
Max retained CLI session files |
Env var overrides: GOODWIZARD_WORKSPACE, GOODWIZARD_MODEL, BRAVE_API_KEY, TELEGRAM_BOT_TOKEN, ANTHROPIC_API_KEY
Telegram Bot Setup
1. Create the bot
- Open Telegram and message @BotFather
- Send
/newbot - Choose a display name (e.g. “Good Wizard”)
- Choose a username ending in
bot(e.g.goodwizard_bot) - Copy the API token BotFather gives you
2. Add the token to your environment
Add the token to your .env file:
TELEGRAM_BOT_TOKEN=7123456789:AAFmtwQR...your-token
3. Enable the Telegram channel
Edit config.toml:
[channels.telegram]
enabled = true
allow_from = [] # empty = allow all users
To restrict access to specific Telegram users, add their user IDs:
[channels.telegram]
enabled = true
allow_from = [123456789]
You can find your Telegram user ID by messaging @userinfobot.
4. Customize the bot profile (optional)
Message @BotFather and use /mybots to:
- Edit Botpic — set a profile picture
/setdescription— text users see before starting a chat/setabouttext— bio in the bot’s profile/setname— change the display name/setcommands— set the command menu
Agent Concurrency
Goodwizard limits concurrent agents to prevent resource exhaustion. This applies to scheduled-task agents and manually spawned sub-agents.
The default limit is 50 concurrent agents (configurable via scheduled_tasks.max_concurrent_agents). Scheduled tasks that fire while at capacity are skipped with a warning logged. Sub-agent spawns at capacity return an error to the caller.
Рекомендуемые инструменты
Попробуйте другой запрос или уберите фильтр.
Установка
npx skillfish add agoodway/goodwizard