v0.7.87 — Audit iteration 3: 27 verifier-confirmed fixes (June 2026) A third adversarial-audit sweep over API auth, channels, the kernel scheduler/workflows, memory/knowledge, and request routing — each finding gated behind a 3-lens refute panel. Closes an unauthenticated-Owner auth bypass (spoofed
X-Forwarded-For), redirect-based SSRF in the A2A and cron-webhook clients, an RHP pre-shared-key serialization leak, MCP allowlist/file-read hardening, a ~24× cost-quota over-count, cron validation/timezone correctness, workflow run-leak + persistence races, knowledge-graph multi-hop traversal, and Unicode-aware session search. See the release notes for details.Clone →
cargo run --release -- start→ open the dashboard → talk to an agent. No API key required. When no provider key is found in the environment, RustyHand falls back to a deterministic mock driver and seeds four sample resources so every major dashboard page is interactive on first visit:
rustywelcome agent (chat-ready)demo-pipelineworkflow (2-step sample, click to run)- sample agent-spawn trigger
demo-daily-pingcron job (registered, disabled by default)A welcome modal on first visit lists all four with one-click navigation. The CLI startup banner and Docker entrypoint both announce demo mode as a feature instead of a missing-key warning. Set
ANTHROPIC_API_KEY(or a Kimi / DeepSeek / Zhipu / MiniMax / OpenRouter / Ollama key) and restart for real LLM responses, orRUSTYHAND_DISABLE_DEMO_MODE=1to force a hard fail.Highlights since v0.7.41:
- React dashboard — every subsystem is a page: agents, chat, workflows, automation (cron + triggers), channels, analytics, knowledge graph, skills, approvals, audit, and a full
config.tomleditor.- Autonomous-by-default agents — tuned to act without asking; grant any agent all 72 tools live via
PATCH /api/agents/{id}/config(no respawn).- 72 built-in tools — shell, web/news search, browser automation, RAG, knowledge-graph CRUD, file ops, image vision, and config management.
- Trust-by-default security with visible guardrails —
GET /api/securityreports the real runtime posture (exec mode, approval policy, per-channel gating); flip to allowlist/deny withRUSTYHAND_EXEC_MODE.- Everything persists — audit log (Merkle hash chain), workflows, and triggers all survive daemon restart and are replayed/validated on boot.
Origin
This project is based on OpenFang by RightNow-AI, modified and extended for custom use cases.
Table of Contents
- What is RustyHand?
- Installation
- Quick Start
- Telegram Setup
- Configuration
- CLI Reference
- Autonomous Templates
- 40 Pre-built Agent Templates
- Channel Adapters
- 7 LLM Providers
- Architecture
- API Endpoints
- Dashboard
- Security
- Deployment
- Docker Environment Variables
- Development
- Benchmarks
- MCP Integration (for AI Agents)
- How It Works — Data Flow
- License
What is RustyHand?
RustyHand is an open-source Agent Operating System — not a chatbot framework, not a Python wrapper around an LLM. It is a full operating system for autonomous agents, built from scratch in Rust.
Traditional agent frameworks wait for you to type something. RustyHand runs autonomous agents that work for you — on schedules, 24/7, building knowledge graphs, monitoring targets, generating leads, managing social media, and reporting results directly to your Telegram chat.
Telegram-First Autonomous Agent
Telegram is the primary interface for RustyHand agents. Your agent can:
| Capability | How it works |
|---|---|
| See photos | Auto-describes images via vision API |
| Hear voice | Auto-transcribes voice messages via Whisper |
| Receive files | Downloads documents, forwards to agent |
| Send files/photos/voice | Sends generated content back to chat |
| Ask permission | Inline keyboard buttons (Approve/Reject) pushed automatically |
| Show progress | Real-time tool-use updates: "⚙️ web_search..." → "✅ Done" |
| Report autonomously | Background tasks push results to your chat without prompting |
| 72 built-in tools | Shell, web/news search, browser (wait, JS exec, scroll, download), RAG, knowledge graph, file ops, image vision |
| Markdown formatting | Bold, italic, code blocks render natively in Telegram |
| Reply threading | Responses reply to the user's message for clean conversation flow |
| Sticker/GIF/Location | Agent understands stickers, animations, and shared locations |
The entire system compiles to a single ~32MB binary. One install, one command, your agents are live.
Installation
One-liner (Linux / macOS / WSL)
curl -fsSL https://raw.githubusercontent.com/ginkida/rustyhand/main/scripts/install.sh | sh
Environment variables:
RUSTY_HAND_INSTALL_DIR— custom install path (default:~/.rustyhand/bin)RUSTY_HAND_VERSION— pin a specific version tag
Windows (PowerShell)
irm https://raw.githubusercontent.com/ginkida/rustyhand/main/scripts/install.ps1 | iex
From source
git clone https://github.com/ginkida/rustyhand.git
cd rustyhand
cargo build --release -p rusty-hand-cli
# Binary: target/release/rustyhand (or rustyhand.exe on Windows)
Requires Rust 1.75+ (stable). The rust-toolchain.toml in the repo will auto-select the right toolchain.
Docker
docker compose up --build
# Dashboard at http://localhost:4200
Or run directly with env vars (no config.toml needed):
docker run -p 4200:4200 \
-e ANTHROPIC_API_KEY=your-key \
-e RUSTYHAND_API_KEY=my-secret-bearer-token \
-v rustyhand-data:/data \
ghcr.io/ginkida/rustyhand:latest
All configuration can be set via RUSTYHAND_* environment variables — see Docker Environment Variables.
Quick Start
Option Zero: Try it in 30 seconds, no API key
The fastest possible first run, no credentials, no configuration:
git clone https://github.com/ginkida/rustyhand
cd rustyhand
cargo run --release -- start
# In another tab: open http://localhost:4200
The dashboard banner will read "DEMO MODE — running on the deterministic
mock driver." Spawn an agent, send a message, watch the agent loop run,
session grow, audit log fill up. Every reply is [mock] <your message> —
unmistakably demo, but the full pipeline (sessions, persistence, workflows,
cron jobs) is real. Set ANTHROPIC_API_KEY (or any of 26 other supported
providers' env vars) and restart for real LLM responses.
Option A: Docker (fastest)
docker run -d --name rustyhand \
-p 4200:4200 \
-e ANTHROPIC_API_KEY=your-key \
-v rustyhand-data:/data \
ghcr.io/ginkida/rustyhand:latest
# Dashboard: http://localhost:4200
# API: http://localhost:4200/api/health
To secure the API with a bearer token:
docker run -d --name rustyhand \
-p 4200:4200 \
-e ANTHROPIC_API_KEY=your-key \
-e RUSTYHAND_API_KEY=my-secret-token \
-v rustyhand-data:/data \
ghcr.io/ginkida/rustyhand:latest
# Now all API calls require: -H "Authorization: Bearer my-secret-token"
See Docker Environment Variables for all options.
Option B: From binary
# 1. Initialize — creates ~/.rustyhand/ and walks you through provider setup
rustyhand init
# 2. Start the daemon (API + kernel)
rustyhand start
# Dashboard is live at http://localhost:4200
# 3. Chat with the default agent
rustyhand chat
# 4. Spawn a pre-built agent
rustyhand agent new coder
# 5. Send a one-shot message
rustyhand message researcher "What are the emerging trends in AI agent frameworks?"
# 6. Launch the interactive TUI dashboard
rustyhand tui
# 7. Run diagnostics
rustyhand doctor
Telegram Setup
Telegram is the primary channel for interacting with RustyHand agents. Setup takes 2 minutes:
1. Create a Telegram Bot
- Message @BotFather on Telegram
- Send
/newbot, follow prompts, get your bot token - Set the token:
export TELEGRAM_BOT_TOKEN=123456:ABC-DEF...
2. Configure RustyHand
# ~/.rustyhand/config.toml
[channels.telegram]
bot_token_env = "TELEGRAM_BOT_TOKEN"
allowed_users = [] # Empty = allow anyone. Set [123456] for specific user IDs.
3. Start and chat
rustyhand start
# Open Telegram, message your bot
# /agents — list agents
# /agent assistant — select an agent
# Send text, photos, voice messages — the agent handles all of them
What your agent can do in Telegram
You: [send a voice message]
Agent: [auto-transcribes via Whisper, processes your request]
You: [send a photo]
Agent: [auto-describes the image, responds based on what it sees]
You: "Search for Rust 2024 edition changes"
Agent: ⚙️ web_search...
✅ web_search
Here are the key changes in Rust 2024...
Agent: ⚠️ Agent "coder" wants to execute:
`shell_exec: rm -rf /tmp/cache`
[✅ Approve] [❌ Reject] ⏱️ 60s
You: [click ✅ Approve]
Agent: Done! Cache cleared.
Autonomous mode
Agents with schedule_mode = "continuous" or "periodic" run in the background and push results to your Telegram chat automatically — no prompting needed.
# agent.toml
[schedule]
mode = "periodic"
cron = "0 9 * * *" # Every day at 9 AM
The agent wakes up, performs its task, and sends the result to the last Telegram chat it was used in.
Configuration
RustyHand can be configured in two ways:
- Config file (
~/.rustyhand/config.toml) — for binary installs - Environment variables (
RUSTYHAND_*) — for Docker, see Docker Environment Variables
API Authentication
When api_key is set, all endpoints (except /api/health) require a Bearer token:
# In config.toml:
api_key = "my-secret-token"
# Or via env var (Docker):
RUSTYHAND_API_KEY=my-secret-token
# Clients must include the header:
curl -H "Authorization: Bearer my-secret-token" http://localhost:4200/api/agents
Without api_key, the API is open (fine for local development).
Config file
Location: ~/.rustyhand/config.toml
# API server settings
api_key = "your-bearer-token" # Recommended for non-localhost access
api_listen = "127.0.0.1:4200" # HTTP bind address
[default_model]
provider = "anthropic" # anthropic, kimi, deepseek, zhipu, minimax, openrouter, ollama
model = "claude-sonnet-4-6" # Model identifier
api_key_env = "ANTHROPIC_API_KEY" # Env var holding the API key
# base_url = "https://api.anthropic.com" # Optional: override endpoint
[memory]
decay_rate = 0.05 # Memory confidence decay
# sqlite_path = "~/.rustyhand/data/rustyhand.db"
[network]
listen_addr = "127.0.0.1:4200" # RHP P2P listen address
# shared_secret = "" # Required for P2P authentication
# Session compaction (LLM-based context management)
[compaction]
threshold = 80 # Compact when messages exceed this count
keep_recent = 20 # Keep this many recent messages
max_summary_tokens = 1024
# Usage display in chat responses
# usage_footer = "Full" # Off, Tokens, Cost, Full
# Channel adapters (tokens via env vars)
[telegram]
bot_token_env = "TELEGRAM_BOT_TOKEN"
allowed_users = [] # Empty = allow all
[discord]
bot_token_env = "DISCORD_BOT_TOKEN"
# guild_ids = []
[slack]
bot_token_env = "SLACK_BOT_TOKEN"
app_token_env = "SLACK_APP_TOKEN"
# MCP server connections
[[mcp_servers]]
name = "filesystem"
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
Environment variables
Copy .env.example to ~/.rustyhand/.env and fill in the keys you need:
# LLM providers — set ANY key and RustyHand auto-detects the provider.
# Priority order: Anthropic → Kimi → DeepSeek → Zhipu → MiniMax → OpenRouter.
ANTHROPIC_API_KEY=sk-ant-... # Claude Opus / Sonnet / Haiku (default)
KIMI_API_KEY=sk-kimi-... # Kimi Code — Anthropic-compat, 256K ctx
DEEPSEEK_API_KEY=sk-... # DeepSeek V4 Flash / V4 Pro (V3/R1 legacy, deprecated 2026-07-24)
ZHIPU_API_KEY=... # Zhipu GLM-4.6
MINIMAX_API_KEY=eyJ... # MiniMax M1 / M2.7 (1M context)
OPENROUTER_API_KEY=sk-or-... # Universal gateway (GPT/Gemini/Grok/etc.)
# Local LLM — no key needed, just run `ollama serve`
# (Base URL defaults to http://localhost:11434/v1 — override only if needed)
# Embedding-only upstreams (independent of LLM provider)
VOYAGE_API_KEY=pa-... # Voyage AI (voyage-3-lite, code, legal, ...)
# OPENAI_API_KEY can also be used for text-embedding-3-* — not for LLM completion.
# Channel tokens
TELEGRAM_BOT_TOKEN=123456:ABC-...
DISCORD_BOT_TOKEN=...
SLACK_BOT_TOKEN=xoxb-...
SLACK_APP_TOKEN=xapp-...
# Log level
RUST_LOG=info
# RUST_LOG=rusty_hand=debug # Debug RustyHand only
Manage config from the CLI
rustyhand config show # Print current config
rustyhand config edit # Open in $EDITOR
rustyhand config get default_model.provider # Read a key
rustyhand config set default_model.provider kimi # Switch provider
rustyhand config set-key kimi # Interactively save API key
rustyhand config test-key kimi # Verify connectivity
CLI Reference
Core commands
| Command | Description |
|---|---|
rustyhand init |
Initialize ~/.rustyhand/ and default config |
rustyhand start |
Start the daemon (API server + kernel) |
rustyhand stop |
Stop the running daemon |
rustyhand status [--json] |
Show kernel status |
rustyhand health [--json] |
Quick daemon health check |
rustyhand doctor [--repair] |
Run diagnostic checks |
rustyhand tools [--json] |
List all 72 built-in tools, grouped by category (offline) |
rustyhand tui |
Launch interactive TUI dashboard |
rustyhand dashboard |
Open web dashboard in browser |
rustyhand chat [agent] |
Quick chat with an agent |
rustyhand message <agent> <text> |
Send a one-shot message |
rustyhand logs [--follow] [--lines N] |
Tail the log file |
rustyhand reset [--confirm] |
Reset local config and state |
Agents
| Command | Description |
|---|---|
rustyhand agent new [template] |
Spawn from a template (interactive picker if omitted) |
rustyhand agent templates [--json] |
List the bundled agent templates (offline) |
rustyhand agent spawn <manifest.toml> |
Spawn from a manifest file |
rustyhand agent list [--json] |
List running agents |
rustyhand agent chat <id> |
Interactive chat with an agent by ID |
rustyhand agent kill <id> |
Kill an agent |
Channels
| Command | Description |
|---|---|
rustyhand channel list |
List configured channels and status |
rustyhand channel setup [name] |
Interactive channel setup wizard |
rustyhand channel test <name> |
Send a test message |
rustyhand channel enable <name> |
Enable a channel |
rustyhand channel disable <name> |
Disable a channel |
Models
| Command | Description |
|---|---|
rustyhand models list [--provider X] |
Browse available models |
rustyhand models aliases |
Show model shorthand names |
rustyhand models providers |
List providers and their auth status |
rustyhand models set [model] |
Set the default model |
Skills
| Command | Description |
|---|---|
rustyhand skill install <source> |
Install from ClawHub, local path, or git URL |
rustyhand skill list |
List installed skills |
rustyhand skill search <query> |
Search ClawHub marketplace |
rustyhand skill remove <name> |
Remove a skill |
rustyhand skill create |
Scaffold a new skill |
Workflows & scheduling
| Command | Description |
|---|---|
rustyhand workflow list |
List workflows |
rustyhand workflow create <file.json> |
Create from JSON |
rustyhand workflow run <id> <input> |
Run a workflow |
rustyhand trigger list [--agent-id X] |
List event triggers |
rustyhand trigger create <agent-id> <pattern-json> |
Create a trigger |
rustyhand cron list |
List scheduled jobs |
Integrations (MCP)
| Command | Description |
|---|---|
rustyhand add <name> [--key TOKEN] |
Install an integration (e.g., github, notion) |
rustyhand remove <name> |
Remove an integration |
rustyhand integrations [query] |
List / search integrations |
Security & vault
| Command | Description |
|---|---|
rustyhand vault init |
Initialize the credential vault (AES-256-GCM) |
rustyhand vault set <key> |
Store a credential |
rustyhand vault list |
List stored keys (values hidden) |
rustyhand vault remove <key> |
Remove a credential |
rustyhand security audit |
View the audit trail |
rustyhand security rbac |
Manage access control |
Other
| Command | Description |
|---|---|
rustyhand mcp |
Start MCP server over stdio |
rustyhand sessions [agent] |
List conversation sessions |
rustyhand approvals list |
List pending approval requests |
rustyhand qr |
Generate device pairing QR code |
rustyhand onboard |
Interactive onboarding wizard |
rustyhand completion <shell> |
Generate shell completions (bash/zsh/fish/powershell) |
rustyhand new skill|integration |
Scaffold a new skill or integration |
All list/status commands support --json for scripting.
Autonomous Templates
RustyHand ships autonomous templates as agent presets in the dashboard. They are not a separate runtime entity: each template creates a normal agent, and you can optionally attach a cron schedule during creation.
Each autonomous template bundles:
- Agent preset — model, profile, prompt, and capabilities
- Schedule defaults — suggested cron expression and trigger message
- Operational playbook — multi-phase prompt for recurring work
- Guardrails — approval and tool constraints where needed
Bundled Autonomous Templates
| Template | What It Does |
|---|---|
| GitHub Monitor | Monitors repositories, runs tests, detects regressions, and files issues on a schedule. |
| Web Researcher | Runs recurring research sweeps, cross-references sources, and produces structured reports. |
| Content Clipper | Processes long-form video into short clips with captions and packaging. |
| Lead Generator | Discovers and enriches qualified leads on a recurring schedule. |
| Intel Collector | Monitors targets, detects changes, and updates a living knowledge base. |
| Predictor | Collects signals, updates forecasts, and tracks prediction accuracy. |
| Twitter Manager | Creates, schedules, and reviews social content with approval controls. |
| Web Browser | Executes recurring browser automation tasks with strict purchase approval gates. |
Use the dashboard to launch one: Agents → Templates or Create Agent → enable schedule.
40 Pre-built Agent Templates
Spawn any template with rustyhand agent new <name>:
| Template | Description |
|---|---|
analyst |
Data analysis and reporting |
api-monitor |
API endpoint monitoring |
architect |
System design and architecture |
assistant |
General-purpose assistant |
capability-builder |
Meta-agent — writes new skills at runtime via privileged skill_install tool |
ci-monitor |
CI/CD pipeline monitoring |
code-reviewer |
Code review and feedback |
coder |
Software development |
coordinator |
Meta-agent — delegates work across other agents via agent_send |
customer-support |
Customer support |
dag-monitor |
DAG/workflow monitoring |
data-scientist |
Data science and ML |
db-reporter |
Database reporting |
debugger |
Bug investigation |
devops-lead |
DevOps and infrastructure |
diagnostic |
Meta-agent — read-only observability (self-history, metrics, audit log) |
doc-writer |
Documentation |
email-assistant |
Email drafting and management |
health-tracker |
Health and fitness tracking |
hello-world |
Starter agent for new users |
home-automation |
Smart home control |
legal-assistant |
Legal document review |
log-analyzer |
Log analysis and alerting |
meeting-assistant |
Meeting notes and follow-ups |
ops |
Operations management |
orchestrator |
Multi-agent orchestration |
personal-finance |
Financial tracking |
planner |
Project planning |
recruiter |
Recruiting and screening |
researcher |
Research and analysis |
sales-assistant |
Sales support |
security-auditor |
Security analysis |
slack-notifier |
Slack notification automation |
social-media |
Social media management |
test-engineer |
Testing and QA |
translator |
Multi-language translation |
travel-planner |
Travel planning |
tutor |
Education and tutoring |
weekly-digest |
Weekly summary reports |
writer |
Content writing |
Agent manifest format (agent.toml)
name = "hello-world"
version = "0.1.0"
description = "A friendly greeting agent"
author = "rusty-hand"
module = "builtin:chat"
[model]
provider = "anthropic"
model = "claude-sonnet-4-6"
max_tokens = 4096
temperature = 0.6
system_prompt = """Your system prompt here..."""
[resources]
max_llm_tokens_per_hour = 100000
[capabilities]
tools = ["file_read", "file_list", "web_fetch", "web_search", "memory_store", "memory_recall"]
network = ["*"]
memory_read = ["*"]
memory_write = ["self.*"]
agent_spawn = false
Channel Adapters
RustyHand ships three messaging adapters — the ones whose APIs work without a public webhook URL, which is what most users actually run:
- Telegram — long-polling Bot API (
@BotFathertoken). - Discord — Gateway WebSocket (Developer Portal bot token).
- Slack — Socket Mode (
xapp-app token +xoxb-bot token).
Each adapter supports per-channel model overrides, DM/group policies, rate limiting, and output formatting.
v0.7.4 and earlier shipped 38 adapters (Matrix, WhatsApp, Signal, Teams, IRC, ...). They were dropped in v0.7.5 — most were webhook-only and broken in typical localhost / home-Docker setups, and many were sprint fillers without real usage. Pin to v0.7.4 if you need them, or open an issue and we'll discuss a route.
Channel policies
Configure each channel under the [channels.*] table in config.toml:
[channels.telegram]
bot_token_env = "TELEGRAM_BOT_TOKEN"
allowed_users = [123456789] # Restrict to specific users
default_agent = "assistant" # Route inbound messages here
[channels.telegram.overrides]
dm_policy = "Respond" # Respond | AllowedOnly | Ignore
group_policy = "MentionOnly" # All | MentionOnly | CommandsOnly | Ignore
output_format = "TelegramHtml" # Markdown | TelegramHtml | SlackMrkdwn | PlainText
Zero-config Telegram on Docker
Since v0.7.10, the Docker entrypoint generates default_agent = "assistant"
under each [channels.*] section automatically (override with the
RUSTYHAND_{TELEGRAM,DISCORD,SLACK}_DEFAULT_AGENT env var, or set it to
an empty string to leave it blank). The bundled assistant manifest uses
provider = "anthropic", so a fresh container with ANTHROPIC_API_KEY
plus a bot token replies to the first message without any extra config or
rustyhand init step.
If the router can't resolve a target at message time (no
default_agent, no bindings, no direct routes), the bridge tries to
auto-route to a running agent first, then to spawn one of the bundled
meta-agents (assistant → coordinator → coder). The user only sees
a config-pointing error message when every fallback fails.
7 LLM Providers
RustyHand v0.7.0 ships with a deliberately lean set of 7 providers, driven by 2 wire protocols (Anthropic Messages API + OpenAI-compatible Chat Completions). Anthropic and Kimi Code are the two first-class coding providers:
| Provider | Env var | Role |
|---|---|---|
| Anthropic (default) | ANTHROPIC_API_KEY |
Claude Opus/Sonnet/Haiku — best-in-class tool use + extended thinking |
| Kimi (Moonshot) | KIMI_API_KEY |
Kimi Code — Anthropic-compatible, 256K ctx, vision, reasoning |
| DeepSeek | DEEPSEEK_API_KEY |
V4 Flash + V4 Pro — fast & reasoning (V3/R1 deprecated 2026-07-24). Also exposes an Anthropic-compatible endpoint at /anthropic |
| Zhipu GLM | ZHIPU_API_KEY |
GLM-4.6 — Chinese frontier |
| MiniMax | MINIMAX_API_KEY |
M1/M2 — 1M context |
| OpenRouter | OPENROUTER_API_KEY |
Universal gateway — any model via one key |
| Ollama | (no key) | Local on localhost:11434 |
Default auto-detect order: Anthropic → Kimi → DeepSeek → Zhipu → MiniMax → OpenRouter. Set whichever key you have; RustyHand picks the first one found.
Prefer Kimi? Set KIMI_API_KEY and auto-detect will route to the stable kimi-for-coding model ID on the Kimi Code endpoint (api.kimi.com/coding); Moonshot maps that ID to the current Kimi Code backend. Change anytime via rustyhand config set default_model.provider <name>.
v0.6.x shipped 27 providers (OpenAI, Gemini, Groq, xAI, Copilot, Mistral, Together, Fireworks, Perplexity, Cohere, AI21, Cerebras, SambaNova, HuggingFace, Replicate, vLLM, LM Studio, Moonshot, Qwen, Qianfan, Bedrock). They were removed in v0.7.0 — use
openrouterto reach any of those models through one gateway.
Features:
- Intelligent routing with task complexity scoring
- Automatic fallback between providers
- Per-model pricing and cost tracking
- Per-agent budget limits
Embedding providers
Vector embeddings power semantic memory recall. The catalog is independent of
the LLM provider list — OPENAI_API_KEY is still usable for text-embedding-3-*
even though OpenAI is not a first-class LLM provider in v0.7.0.
Auto-detected at boot (first available wins):
| Provider | Models | Key required |
|---|---|---|
| Voyage AI | voyage-3, voyage-3-lite, voyage-code-3, voyage-finance-2, voyage-law-2, voyage-multilingual-2 | VOYAGE_API_KEY |
| OpenAI (embedding-only) | text-embedding-3-small, text-embedding-3-large, text-embedding-ada-002 | OPENAI_API_KEY |
| Ollama | nomic-embed-text, all-MiniLM-L6-v2, mxbai-embed-large | No |
| Any OpenAI-compat endpoint | whatever the server exposes | provider-specific |
Configure explicitly in config.toml:
[memory]
embedding_provider = "voyage" # or "openai", "ollama", "<custom>"
embedding_api_key_env = "VOYAGE_API_KEY"
Or let RustyHand auto-detect: it probes Voyage → OpenAI → Ollama at boot and uses the first available provider. Falls back to text search (SQLite LIKE) when no embedding driver is found.
rustyhand models list # Browse all models
rustyhand models list --provider kimi # Filter by provider
rustyhand models set claude-sonnet # Set default model
Architecture
10 Rust crates with a modular kernel design:
rusty-hand-types Core types, traits, config, taint tracking, Ed25519 manifest signing
|
+-- rusty-hand-memory SQLite persistence, vector embeddings (Voyage/OpenAI/Ollama), session compaction
+-- rusty-hand-wire RHP P2P protocol (JSON-RPC over TCP, HMAC-SHA256 auth)
+-- rusty-hand-channels Telegram + Discord + Slack adapters with rate limiting
+-- rusty-hand-skills Skill system + ClawHub marketplace
+-- rusty-hand-extensions 25 MCP integrations, AES-256-GCM credential vault, OAuth2
|
+-- rusty-hand-runtime Agent loop, 2 LLM drivers (Anthropic + OpenAI-compat), 53+ tools, WASM sandbox, MCP, A2A
|
+-- rusty-hand-kernel Orchestration: lifecycle, scheduling, metering, RBAC, workflows
|
+-- rusty-hand-api Axum HTTP daemon, 120+ endpoints, WebSocket, SSE, OpenAI-compat
|
+-- rusty-hand-cli CLI binary + TUI dashboard (ratatui)
Key internals
| Concept | Implementation |
|---|---|
| Agent loop | rusty-hand-runtime — iterative LLM call → tool execution → response cycle |
| Kernel | RustyHandKernel struct (40+ fields) — central orchestration for all subsystems |
| AppState | Bridges kernel to HTTP routes via Arc<RustyHandKernel> in Axum state |
| Sandbox | WASM (wasmtime) with fuel metering + epoch interruption + watchdog thread |
| Memory | SQLite + vector embeddings (Voyage AI, OpenAI, Ollama) for semantic search + knowledge graph |
| Metering | Per-agent token/cost tracking with budget enforcement and alerts |
| P2P | RHP (RustyHand Protocol) — JSON-RPC over TCP, Ed25519 identity, nonce-based auth |
| A2A | Agent-to-Agent protocol for cross-instance agent communication |
API Endpoints
Default: http://127.0.0.1:4200. All endpoints return JSON. Authenticate with Authorization: Bearer <api_key> when api_key is set in config.
Health & status
| Endpoint | Method | Description |
|---|---|---|
/api/health |
GET | Health check |
/api/status |
GET | Full kernel status |
Agents
| Endpoint | Method | Description |
|---|---|---|
/api/agents |
GET | List all agents |
/api/agents |
POST | Spawn a new agent |
/api/agents/{id} |
GET | Agent details |
/api/agents/{id} |
DELETE | Kill an agent |
/api/agents/{id}/message |
POST | Send message (triggers LLM) |
Budget
| Endpoint | Method | Description |
|---|---|---|
/api/budget |
GET | Global budget status |
/api/budget |
PUT | Update budget settings |
/api/budget/agents |
GET | Per-agent cost ranking |
/api/budget/agents/{id} |
GET | Single agent budget detail |
Network & P2P
| Endpoint | Method | Description |
|---|---|---|
/api/network/status |
GET | RHP network status |
/api/peers |
GET | Connected peers |
A2A (Agent-to-Agent)
| Endpoint | Method | Description |
|---|---|---|
/api/a2a/agents |
GET | External A2A agents |
/api/a2a/discover |
POST | Discover agent at URL |
/api/a2a/send |
POST | Send task to external agent |
/api/a2a/tasks/{id}/status |
GET | Check task status |
OpenAI-compatible
Drop-in replacement for OpenAI API:
curl -X POST http://localhost:4200/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "researcher",
"messages": [{"role": "user", "content": "Analyze Q4 market trends"}],
"stream": true
}'
Full REST/WS/SSE endpoints cover agents, memory, workflows, channels, models, skills, sessions, approvals, triggers, crons, security, and more (120+ total).
Dashboard
The web dashboard is served at http://localhost:4200 when the daemon is running. Since v0.7.45 it's a React 18 control panel (industrial-rust palette, 15 pages); React + ReactDOM UMD bundles and the precompiled JSX are inlined into the binary at compile time, so the dashboard ships single-binary like before — no CDN, no node_modules at runtime.
Sections
| Section | What you see |
|---|---|
| Overview | Live tiles (running agents, cost, audit entries, errors), recent activity, approvals waiting, demo-seed shortcuts, providers, audit chain head |
| Agents | Spawn (template or custom), kill / restart, drawer with Info / Config / Identity / Activity tabs editing the agent's manifest live |
| Chat | WebSocket streaming with HTTP fallback, markdown rendering, tool-trace cards, sessions list per agent |
| Workflows | Visual step builder with HTML5 drag-and-drop reorder, fan-out / collect / conditional / loop modes, runs history, run-with-JSON-input |
| Automation | Cron jobs (3 schedule × 3 action variants), triggers (9 pattern variants), toggle / run-now / delete |
| Channels | Configure modal generated from /api/channels field metadata, test / reload / disconnect |
| Skills | Custom install via inline editor, ClawHub browse + search + install, uninstall |
| Analytics | Cost, requests, cache hit-rate, p95 latency, top agents, provider state, CSV export |
| Knowledge | Live graph viz + mini-cypher query (source:foo relation:works_at depth:3 → POST /api/knowledge/query) |
| Memory | Sessions list with label edit + delete, export to markdown, full backup / restore via /api/memory/{export,import} |
| Approvals | Pending decisions with one-click approve / reject |
| Audit log | Recent + chain-verify + JSON export |
| MCP servers | Configured + connected MCP bridges from /api/mcp/servers |
| Network | RHP P2P status + known peers (/api/network/status, /api/peers) |
| Bindings | Agent → channel/trigger bindings (/api/bindings) |
| Settings | Provider key set / delete / test, demo-mode info, build info |
Other niceties: ⌘K / Ctrl-K command palette, toast notifications, tweaks fab (theme dark/light, accent rust/copper/amber/forest/electric, density), AuthGate + LoginScreen for remote deployments, error boundary so a component crash shows a recovery card instead of a blank #root.
Maintaining the panel
JSX sources live in crates/rusty-hand-api/static/js/panel/src/*.jsx; compiled outputs sit one level up at static/js/panel/*.js. After editing JSX, recompile via:
cd crates/rusty-hand-api/static/js/panel/src && ./build.sh
The build needs Node + esbuild (npm i -g esbuild or use ESBUILD="npx --yes [email protected]" ./build.sh). The Rust build itself doesn't touch Node — it include_str!s the .js files. A build.rs checks JSX/JS mtimes and emits a cargo:warning= if you forget to recompile.
Tests pinning the panel contract:
tests/panel_dashboard_test.rs— 10 tests asserting HTML response, React inlined, every page component + endpoint wired, no Alpine residue, bundle size 100 KB ≤ x ≤ 1 MBtests/panel_jsx_smoke.rs— runs the compiled bundle under Node with a React shim and asserts every page component instantiates without throwing (catches JSX runtime errors that string-match tests miss)
Security
16 independent security layers — defense in depth, no single point of failure.
| # | System | Description |
|---|---|---|
| 1 | WASM Dual-Metered Sandbox | Tool code runs in WebAssembly with fuel metering + epoch interruption. Watchdog kills runaway code. |
| 2 | Merkle Hash-Chain Audit Trail | Every action cryptographically linked. Tamper with one entry and the chain breaks. |
| 3 | Taint Tracking | Information flow labels propagate through execution — secrets tracked from source to sink. |
| 4 | Ed25519 Signed Manifests | Agent identity and capabilities are cryptographically signed. |
| 5 | SSRF Protection | Blocks private IPs, cloud metadata endpoints, DNS rebinding. |
| 6 | Secret Zeroization | Zeroizing<String> auto-wipes API keys from memory when no longer needed. |
| 7 | RHP Mutual Auth | HMAC-SHA256 nonce-based, constant-time verification for P2P. |
| 8 | Capability Gates | Role-based access control — agents declare tools, kernel enforces. |
| 9 | Security Headers | CSP, X-Frame-Options, HSTS, X-Content-Type-Options on every response. |
| 10 | Health Redaction | Public health check returns minimal info. Full diagnostics require auth. |
| 11 | Subprocess Sandbox | env_clear() + selective passthrough. Process tree isolation with cross-platform kill. |
| 12 | Prompt Injection Scanner | Detects override attempts, data exfiltration patterns, shell injection in skills. |
| 13 | Loop Guard | SHA256-based tool call loop detection with circuit breaker. |
| 14 | Session Repair | 7-phase message history validation and automatic recovery. |
| 15 | Path Traversal Prevention | Canonicalization with symlink escape prevention. |
| 16 | GCRA Rate Limiter | Cost-aware token bucket rate limiting with per-IP tracking. |
Deployment
Systemd
A service file is provided in deploy/rustyhand.service:
sudo cp deploy/rustyhand.service /etc/systemd/system/rustyhand.service
# Edit ExecStart path and user as needed
sudo systemctl daemon-reload
sudo systemctl enable --now rustyhand
The service includes security hardening: NoNewPrivileges, ProtectSystem=strict, ProtectHome, PrivateTmp, and resource limits.
Docker Environment Variables
The Docker entrypoint generates config.toml from environment variables automatically — no config file needed. If you mount your own config.toml, env vars are ignored.
Set RUSTYHAND_FORCE_ENV_CONFIG=1 to always regenerate config from env vars (overrides mounted file).
Core
| Env var | Default | Description |
|---|---|---|
RUSTYHAND_API_KEY |
(none) | Bearer auth token. When set, all API endpoints require Authorization: Bearer <token> header. Strongly recommended for non-local access. |
RUSTYHAND_API_LISTEN |
0.0.0.0:4200 |
HTTP bind address |
RUSTYHAND_LOG_LEVEL |
info |
Log level: trace, debug, info, warn, error |
LLM Provider
| Env var | Default | Description |
|---|---|---|
RUSTYHAND_PROVIDER |
anthropic |
LLM provider: anthropic, kimi, deepseek, zhipu, minimax, openrouter, ollama |
RUSTYHAND_MODEL |
claude-sonnet-4-6 |
Model identifier |
RUSTYHAND_MODEL_KEY_ENV |
ANTHROPIC_API_KEY |
Which env var holds the LLM API key |
RUSTYHAND_MODEL_BASE_URL |
(auto) | Override provider API endpoint |
RUSTYHAND_FALLBACK_PROVIDER |
(none) | Fallback provider if primary fails |
RUSTYHAND_FALLBACK_MODEL |
(none) | Fallback model |
RUSTYHAND_FALLBACK_KEY_ENV |
(none) | Env var for fallback API key |
LLM API Keys (pass through to agents)
| Env var | Provider |
|---|---|
| `ANTHROPI |
No comments yet
Be the first to share your take.