MAESTROBOT
MaestroBot
MaestroBot is a local Linux user-scoped agent service.
It runs as a systemd --user service, stores its state under
~/.maestrobot, uses Maestro for the agent loop, and supervises Myria
as its memory service. The control plane and the daemon are the same
binary:
maestrobot --daemonruns the daemon directlymaestrobot ...runs the control CLImaestrobot daemon ...manages the installed user service
Install
For a normal user install:
bash install.sh
This builds maestrobot, installs it to ~/.local/bin/maestrobot,
bootstraps ~/.maestrobot when needed, and installs the
systemd --user unit. It also installs shell completions for the
user’s default login shell when that shell is bash, zsh, or fish.
If the installer is run outside a normal login session and cannot reach
the systemd --user bus, it still installs the unit and prints the
systemctl --user commands to run later from a real session.
To install shell completions at the same time:
bash install.sh --shell bash --shell zsh --shell fish
Supported shells are bash, zsh, and fish. The installer rejects
unsupported shell names when they are passed explicitly.
Quick Start
Set the bootstrap values you want:
export OPENROUTER_API_KEY=...
export MAESTROBOT_MODEL=...
Install once:
bash install.sh
Then edit the two operator-owned files:
$EDITOR ~/.maestrobot/config.yaml
$EDITOR ~/.maestrobot/SOUL.md
config.yaml holds credentials, model presets, frontends, onboarding
policy, and runtime settings. SOUL.md is the agent’s identity, voice,
and standing preferences.
Run the setup doctor before starting:
maestrobot doctor
Start the service, create a local test channel, and send a message:
maestrobot daemon start --verbose
maestrobot add-channel local demo
maestrobot chat --channel demo "hello"
maestrobot chat --channel demo --verbose "inspect the current workspace"
maestrobot channel history channel-0001
maestrobot daemon logs
maestrobot daemon stop
For Telegram, configure the Telegram frontend in config.yaml, run
maestrobot doctor, start the daemon, message the bot once, then use
maestrobot user unknown to list the account and attach it to an
internal user.
Use maestrobot daemon start --verbose --debug when you want both
verbose daemon logs and frontend-visible gateway telemetry. --debug
sends compact operator messages through configured frontends for tool
calls, sanitized parameters, tool results, prompt compaction, cumulative
LLM token usage, and sleep/wake bookkeeping. Those debug messages are
not appended to the channel transcript or Myria.
The runtime root defaults to ~/.maestrobot. Override it on any
command with --root PATH.
Before starting the daemon, MaestroBot runs a preset preflight:
maestrobot test
This checks each configured preset with a simple completion probe and a simple agent-compatibility probe.
Each preset in config.yaml can set an OpenRouter provider sort
mode and a context_limit_tokens cap. The default context cap is
262144; lower it for models with smaller context windows.
defaultexactopricethroughputlatency
MaestroBot does not pin a concrete OpenRouter provider. Runtime calls let OpenRouter choose the route for the configured model and sort mode.
Prompt caching is provider-specific. MaestroBot arranges OpenRouter
requests as a stable system prefix plus a dynamic user tail so
providers can reuse cached input where supported. Use:
maestrobot models cache
to send a two-request cache probe for each preset and inspect cached input and cache-write token counts.
Frontends
MaestroBot now treats frontends as real platform adapters.
The runtime owns one canonical outbound content format: authored Markdown. Frontends are responsible for lowering that canonical content into platform-safe output.
The built-in frontends are:
locallocal CLI testing and transcript inspectiontelegramTelegram Bot API delivery and inbound polling
Telegram output is not driven by Telegram-specific prompting. The pipeline is:
- Markdown input
- normalized Telegram-safe intermediate representation
- Telegram renderer
The Telegram frontend prefers text + entities, falls back to HTML
parse mode when needed, and finally falls back to plain text chunking if
format-preserving output fails.
While a Telegram channel run is actively executing, the frontend emits a
Telegram typing indicator until the run sends its reply or finalizes.
Runtime Model
MaestroBot is channel-centric:
- one persistent context per channel
- one message queue per channel
- one workspace per channel
- one priority per channel
- one durable identity map across channels
Each channel owns its own runtime state, workspace, paging metadata, current preset tier, and retained subagent state. Channels may run concurrently up to the configured worker limit, but a single channel is always serialized.
chat --verbose streams daemon-produced trace events for the current
channel run. A trace covers one contiguous execution segment from the
last finalized state to the next finalized state, including prompt
construction, preset/model selection, LLM responses, tool results, and
finalization.
User-visible replies are expected to stay grounded in tool results. Successful tool results are treated as factual observations. Failed tool results are also factual observations about what did not work. The embedded Maestro schema now carries that grounding rule explicitly so the agent reports failures instead of inventing successful outputs.
Runtime Root
The default runtime root looks like this:
~/.maestrobot/
config.yaml
runtime.yaml
state.json
SOUL.md
maestrobot.sock
logs/
service.log
myria.log
subagents/
bin/
maestroc
myria
maestro/
channel_loop.mstr
subagent_loop.mstr
agent_loop.mstro
myria/
myria.json
myria.sqlite3
openrouter-llm.template.json
paging/
<channel-id>.json
transcripts/
<channel-id>.jsonl
users/
<user-id>/
profile.md
workspaces/
<channel-id>/
config.yaml is static operator-authored service config. runtime.yaml
is mutable desired runtime config for internal users and future
operator-managed resources. state.json holds daemon-owned observed
state such as queues, wake timers, unknown identities, and external
account mappings. Installer-managed runtime binaries live under bin/.
Paging snapshots live outside workspaces.
users/<user-id>/profile.md stores concise durable user understanding:
preferences, constraints, communication style, and stable facts. The
agent can update this file through a host-validated profile tool for
known channel participants only. It is not used for secrets, task
history, or full conversation history.
Customization Surface
The main agent behavior is designed to be customized from the runtime root rather than by editing the repo.
The editable Maestro surface is:
~/.maestrobot/maestro/channel_loop.mstr~/.maestrobot/maestro/subagent_loop.mstr
The daemon compiles the root-local Maestro files into
~/.maestrobot/maestro/agent_loop.mstro when the service starts and
when those files change.
Prompt composition is owned by those root-local Maestro files, but
identity is not. SOUL.md is the exclusive source for the agent’s
identity, name, voice, and standing preferences. The Maestro files should
stay identity-neutral: they define operating behavior, prompt layout,
tool policy, and state flow. The runtime injects structured data such as
channel context, working memory, queue summaries, tool contracts, and
the current message.
Those Maestro files also choose the host surface for each state. A state
can request tool groups such as @plan, @workspace, @myria, or an
exact tool name, and can request only the context sections it wants in
the prompt. The Go host expands and validates those requests, then owns
provider calls and tool execution.
Workspaces and Tools
Each channel workspace is a real host directory under
workspaces/<channel-id>/. The agent sees a controlled VFS:
/is the writable channel workspace/.host-path/<n>are read-only mounts of hostPATHdirectories
The built-in tool plane includes:
- queue and state control
- VFS inspection, editing, search, and replace
- command execution and long-running command sessions
- browser automation through Playwright
- web fetch and web search
- image metadata and OCR
- user-note writes and subagent control
- Myria retrieval tools
- external MCP servers over
stdio,streamable-http, and legacysse
The first browser action installs Playwright Chromium into
<root>/cache/playwright/.
Telegram
If config.yaml contains a telegram frontend with a bot token, the
daemon starts a Telegram poller and normalizes inbound Telegram messages
into per-chat channels.
Telegram DMs do not need to be predeclared. Unknown Telegram accounts are discovered and listed for the operator, but they cannot trigger the agent until attached to an internal user. Unknown accounts receive a deterministic onboarding notice up to the configured cap:
Please contact the admin of this MaestroBot deployment for onboarding.
After the cap is reached, the daemon silently ignores further messages
from that account until it is attached. Unknown identities move out of
the normal list after the configured archive window and can still be
viewed with maestrobot user unknown --archive.
Outbound Telegram messages stay canonical inside the runtime and are rendered only at the frontend boundary. That means agent prompts can stay platform-neutral.
For direct frontend delivery tests without waiting for a model reply:
maestrobot add-channel telegram <telegram-chat-id>
maestrobot channel deliver channel-0001 "**hello** from MaestroBot"
channel deliver writes the canonical outbound transcript entry, appends
the event to Myria, and sends the rendered message through the channel’s
configured frontend.
Memory and Myria
Each channel is a complete local agent instance. It owns its local conversation transcript, structured working-memory notebook, current-run history, workspace, queues, and sleep/wake state. Recent same-channel continuity comes from the local transcript first, so follow-up questions such as “what did you just do?” do not require a Myria lookup.
MaestroBot also keeps a local structured working-memory notebook per channel. That notebook is the primary compact operational memory used during planning and reply generation. It is host-persisted in the channel paging snapshot and survives idle periods, restarts, and paging boundaries.
The notebook is intentionally lossy and task-oriented. It carries sections such as user profile, channel facts, active goal, current plan, open loops, workspace state, and handoff notes.
During one live channel run, the runtime also retains a current-run-capability view derived from the tools exposed in that run. That lets Maestro answer capability questions from the broader current-run context even if the current schema step is a narrowed reply-preparation state.
Myria is supervised by the daemon and is query-only from the agent’s perspective. The host runtime appends the truthful inbound and outbound events. Myria is Global Persistent Memory: the durable event substrate and auxiliary retrieval system for older, cross-channel, or uncertain recall. The channel transcript and notebook remain the live local mind.
The generated Myria config uses file-backed SQLite only as a convenience for local setup and testing:
storage.kind = "sqlite"sqlite.path = "<root>/myria/myria.sqlite3"
myria/myria.json and the OpenRouter request template are generated
from config.yaml during init, test, and daemon startup. Treat those
files as derived runtime files rather than hand-authored config.
Common Commands
maestrobot daemon start --verbose
maestrobot daemon start --verbose --debug
maestrobot daemon status
maestrobot daemon logs --lines 100
maestrobot status
maestrobot config show
maestrobot doctor
maestrobot test
maestrobot chat --channel demo --verbose "summarize the last task"
maestrobot user onboard "Ada Lovelace"
maestrobot user unknown
maestrobot user attach usr_example unknown-0001
maestrobot channels list
maestrobot channels add telegram <telegram-chat-id>
maestrobot add-channel telegram <telegram-chat-id>
maestrobot channel deliver channel-0001 "**hello** from MaestroBot"
maestrobot channel history channel-0001
maestrobot tools list
maestrobot tools discover --path .
maestrobot tools inspect <name>
maestrobot runtime show
maestrobot runtime reload
maestrobot runtime pause
maestrobot runtime resume
maestrobot browser install
maestrobot browser probe https://example.com
For the full design and operating model, see:
docs/design.mddocs/configuration.mddocs/operations.mddocs/storage.md