Chaz is an experimental AI agent framework built on eidetica. It features a ReAct tool-calling loop, multi-agent orchestration, and persistent + syncable per-session state. The primary gateway is a Matrix bot connecting to any OpenAI-compatible LLM provider; a TUI is also included.
⚠️ Experimental. APIs, config, and on-disk state may change without notice. Don't run against data you can't afford to lose.
For a more mature Matrix chatbot focused on day-to-day use, see baibot.
Announcement Blog Post: Chaz: An LLM <-> Matrix Chatbot
There is a public Matrix room available at #chaz:jackson.dev
- ReAct tool-calling loop — agents reason, act, and observe in a loop with 9 built-in tools
- Multi-agent orchestration — agents can spawn sub-agents with depth limiting and transitive tool narrowing
- TUI mode — local terminal interface for testing and debugging without Matrix
- Session sharing — share sessions between chaz instances via eidetica sync
- Security — leak detection, network controls, shell sandboxing, tool approval gates
- Persistent sessions — conversation history survives restarts via eidetica SQLite
| Tool | Description |
|---|---|
get_time |
Current UTC time |
calculate |
Math expressions |
read_file |
Read file contents |
write_file |
Write to files |
web_fetch |
HTTP GET/POST |
web_search |
Search the web (Tavily/Brave/Serper/DuckDuckGo) |
shell |
Execute commands (approval required) |
remember |
Store key-value facts (own memory or a granted bank) |
recall |
Search stored facts |
list_memory_banks |
List shared memory banks this agent can access |
spawn_agent |
Delegate to sub-agents |
Connect to Matrix rooms and respond to messages:
chaz --config config.yamlLocal terminal interface for testing, debugging, and session management:
chaz --config config.yaml --tui| Command | Description |
|---|---|
/help |
Show all commands and key bindings |
/sessions, /s |
Open session picker |
/new |
Create a new session |
/join <id> |
Switch to session by name or eidetica DB ID |
/info |
Show current session details |
/share |
Generate shareable ticket for current session |
/sync <ticket> |
Sync a remote session via ticket |
/agents, /agent list |
List agents attached to this session (host marked) |
/agent add <ref> |
Attach an agent (<ref> = display name or DB ID) |
/agent remove <ref> |
Detach an agent |
/agent host [<ref>] |
Set (or with no arg, clear) the host agent |
/agent new <name> [k=v ...] |
Create a Living Agent (see docs/ for fields) |
/agent set <ref> <field> <value> |
Edit one field on a Living Agent's config |
/agent hosted |
List Living Agents hosted on this peer |
/agent delete <ref> |
Unregister a Living Agent locally (DB preserved) |
/agent share <ref> |
Share an agent DB via ticket |
/agent import <ticket> |
Sync + register an agent DB from a ticket |
/pubkey |
Print this peer's pubkey (for /agent invite) |
/agent invite <ref> <pubkey> [admin|write|read] |
Authorise another peer to co-own an agent |
/agent revoke-peer <ref> <pubkey> |
Revoke a co-owner's access |
/heartbeat list |
List heartbeat rules on this session |
/heartbeat add <id> <cron(6 fields)> <ref> <task> |
Upsert a cron-driven heartbeat rule |
/heartbeat remove <id> |
Remove a heartbeat rule |
/clear |
Clear display (entries remain in DB) |
/raw |
Dump raw entry data for debugging |
/debug |
Toggle debug mode (also Ctrl+D) |
/quit, /q |
Exit |
| Key | Action |
|---|---|
Ctrl+D |
Toggle debug mode (shows timestamps, entry types) |
Ctrl+C |
Quit |
Up/Down |
Scroll messages |
PageUp/PageDown |
Fast scroll (20 lines) |
Home/End |
Move cursor in input |
Chaz instances can share sessions over the network using eidetica's sync protocol. This enables:
- Viewing a remote agent's conversation from a local TUI
- Multiple instances collaborating on the same session
- Real-time updates — writes from either side propagate automatically
Each chaz instance starts an HTTP sync server automatically. Sessions are shared via database tickets — URLs that encode the session's database ID and the server's address.
On the instance that has the session:
/share
This prints a ticket URL like:
eidetica:?db=sha256:abc123...&pr=http:127.0.0.1:12345
On another instance, paste the ticket:
/sync eidetica:?db=sha256:abc123...&pr=http:192.168.1.10:12345
After syncing, use /sessions to find and open the synced session. New messages on either side will propagate automatically.
- Both instances must be able to reach each other over the network
- The sync server binds to a random port by default (logged at startup)
- Sessions synced from Matrix will appear in the TUI session list
When in a Matrix room, Chaz responds to !chaz prefixed commands. In DMs, it responds to every message.
!chaz help — Show available commands
!chaz print — Print the conversation context
!chaz send <msg> — Send a message without context
!chaz model <m> — Select the model to use
!chaz backend <name> <api_base> <api_key> — Add a custom backend
!chaz role [<role>] [<prompt>] — Get/set/define roles
!chaz list — List available models
!chaz clear — Ignore messages before this point
!chaz rename — Rename the room based on conversation
!chaz agents — List agents attached to this session
!chaz agent add <ref> — Attach an agent to this session
!chaz agent remove <ref> — Detach an agent
!chaz agent host [<ref>] — Set or clear the host agent
!chaz agent new <name> [k=v ...] — Create a Living Agent
!chaz agent set <ref> <field> <value> — Edit one field
!chaz agent hosted — List hosted Living Agents
!chaz agent delete <ref> — Unregister locally (DB preserved)
!chaz agent share <ref> — Share an agent via ticket
!chaz agent import <ticket> — Sync + register an agent DB
!chaz pubkey — Print this peer's pubkey
!chaz agent invite <ref> <pubkey> [admin|write|read] — Authorise a co-owner
!chaz agent revoke-peer <ref> <pubkey> — Revoke a co-owner
!chaz heartbeat list — List heartbeat rules
!chaz heartbeat add <id> <cron(6 fields)> <ref> <task...> — Upsert a heartbeat rule
!chaz heartbeat remove <id> — Remove a rule
!chaz attach <session> — Bind this room to a session
!chaz detach — Unbind this room
!chaz channels — List rooms attached to this session
Create a YAML config file:
homeserver_url: https://matrix.org
username: "chaz"
password: ""
allow_list: "@user:matrix.org" # Regex for allowed accounts
state_dir: "/path/to/state" # Persistence directory
# LLM backends (OpenAI-compatible)
backends:
- name: openrouter
type: openaicompatible
api_key: "${OPENROUTER_API_KEY}" # Supports env var references
api_base: https://openrouter.ai/api/v1
models:
- name: anthropic/claude-sonnet-4
# Agent definitions
agents:
- name: default
role: chaz
allowed_tools: null # null = all tools
can_spawn: ["researcher"]
- name: researcher
role: researcher
max_iterations: 20
allowed_tools: ["web_fetch", "calculate", "get_time"]
# Security settings
security:
auto_approved_tools:
["get_time", "calculate", "read_file", "remember", "recall"]
tool_policies:
shell:
approval: Always
grants:
shell:
allow: ["ls", "cat", "grep", "find"]
deny: ["rm", "sudo"]
web_fetch:
grants:
network:
endpoints:
- host: "api.example.com"
allow_private: false # SSRF blocking (default)
# Per-agent grant overlays are merged per-kind over the config above:
# agents:
# - name: researcher
# grants:
# web_fetch:
# network:
# endpoints:
# - host: "*.wikipedia.org"nix run github:arcuru/chazThe flake contains an overlay and a home-manager module:
{inputs, ... }: {
imports = [ inputs.chaz.homeManagerModules.default ];
services.chaz = {
enable = true;
settings = {
homeserver_url = "https://matrix.jackson.dev";
username = "chaz";
password = "hunter2";
allow_list = "@me:matrix.org";
};
};
}services:
chaz:
image: arcuru/chaz:main
restart: unless-stopped
network_mode: host
volumes:
- ./config.yaml:/config.yaml
- chaz-state:/state
# Cap log size — chaz can be chatty under tracing=debug
logging:
driver: "json-file"
options:
max-size: "1m"
max-file: "1"
volumes:
chaz-state:cargo build --release
./target/release/chaz --config config.yamlUses Nix flakes with direnv:
direnv allow # or: nix develop .#
just build # cargo build
just test # cargo test
just lint # clippy + lints
just fmt # treefmt
just ci # all checksMirrored on GitHub and Codeberg. GitHub is the official repo, but use either repo to contribute.