A local-first workflow engine in a single Go binary: 168 node types, your own Chrome as the browser, AI that runs on the agent CLIs you already have, and a durable human-approval queue. Every number below was measured against the v0.126 source and the installed binary.
Architecture
The workflow engine is the centre. Triggers feed its queue, it dispatches to the node registry, and browser steps go out through the extension bridge to your own Chrome. AI steps are handed to agent CLIs through monomind.
Internal Packages
About 244,000 lines of Go in 1,197 files, plus roughly the same again in tests. internal/ holds 88 top-level packages, so these cards group them by job.
Workflow Engine
DAG execution with Kahn-style topological sorting and cycle rejection on construction. An execution queue (capacity 1,000), a worker limit (default 3, capped at 20), cron triggers via robfig/cron v3, webhooks, pause and resume state, and an hourly history pruner.
Node Registry
168 node types registered through a type-to-factory registry, each with an embedded JSON schema (136 schema files). Browser and social nodes register from action definitions. There is no Go plugin loader; new automations arrive as library packages.
Action Executor
Runs declarative automations step by step, with about 38 step types covering flow control, browser actions, extraction and bridge scripts. Social automations are official packages from monoes.me, installed with library install automation <id>. An opt-in Jev picker backs the three-tier selector fallback.
Browser Bridge
The CLI drives your own logged-in Chrome through the bundled MonoAgent Bridge extension over a loopback WebSocket on 127.0.0.1:9222, guarded by a shared secret. There is no headless fallback. Rod survives only as a page-API wrapper and for PDF rendering.
AI and Orgs
No built-in LLM provider and no stored text-AI keys. Every AI step is one turn run by the monomind runner on an agent CLI you already have installed and signed in to. The same layer runs orgs, dynamic coder orgs and org chat.
Storage and Secrets
SQLite through modernc.org/sqlite (pure Go, no CGO) at ~/.monoagent/monoagent.db, with 61 migrations and about 66 live tables. Secrets use AES-256-GCM with per-profile data keys, wrapped by a key held in the OS keyring.
API Surface
An MCP server over stdio (31 read-only tools, 66 with mutations allowed), a REST server on 127.0.0.1:9322 with an OpenAPI spec, and an OpenAI-compatible /v1 gateway over your installed agent runtimes.
Desktop App
A Wails v2 desktop app with a React 19 front end, in English and Spanish. Pages cover the dashboard, tasks, publication history, people, applications, communications, documents, orgs, vault, logs and settings.
Tasks, Library, Account
A per-profile task board with leases for AI agents, the monoes.me library for workflows, orgs and automations, and an account sign-in that is currently dormant: nothing is enforced for local work.
Execution
From trigger to result in 8 steps. Executions are sequential per run, durable across restarts, and pausable for a human.
A run starts from the CLI, the desktop app, an MCP tool or the HTTP API, from a cron schedule, or from a webhook on 127.0.0.1:9321/webhook/<path>. Scheduled and webhook triggers only fire while monoagentcli daemon is running. workflow run --input passes trigger data.
The request enters the execution queue (capacity 1,000) and a worker picks it up; the engine runs 3 at once by default and never more than 20. The workflow graph is loaded, sorted topologically by in-degree, and a cycle is rejected when the DAG is built. workflow validate runs these checks without saving or running anything.
monoagentcli workflow validate <id>
Nodes run in topological order on a single goroutine per execution. There is no parallel branch fan-out, and merge nodes are driven by waiting counters in that loop. A disabled node is skipped.
String config fields go through text/template with a function map. $json is the current item, $node["Name"].json.field reads a named node's first output item, and $workflow.id and $execution.id are available. $env.VAR resolves to empty unless MONOAGENT_ALLOW_ENV_TEMPLATES=1.
{{$json.username}}
{{$node["Search"].json.title}}
{{upper $json.name}} {{default "n/a" $json.email}}The registry resolves the node type. Browser and social nodes run an action definition through the extension bridge, with three selector tiers: Go bot code, XPath alternatives, then an opt-in Jev element picker. The old ai.* nodes are deprecated stubs that fail with a hint to use agent.ask or ai.choose.
core.human_in_loop pauses each incoming item into a durable SQLite queue that survives restarts, and the run shows WAITING. Approve or reject from the CLI, the desktop app, MCP or the HTTP API. You can mark fields editable, set a timeout (expiry counts as a rejection), and the node releases its worker slot while it waits.
monoagentcli hil list | approve | reject
Each node has an on_error policy: stop, continue, skip, or an error branch. A run with non-fatal failures finishes as SUCCESS_WITH_ERRORS. Per-node outputs are saved in workflow_execution_nodes, and executions are pruned to the last 500 per workflow hourly. WAITING executions are never pruned.
Paused executions persist their resume state. The engine runs resume, stale-reap and webhook-retry loops, and workflow cancel and retry are available from the CLI.
Node Registry
Counted from monoagentcli node list, grouped here by job. A -tags nosocial build leaves out the social nodes and keeps 107.
Browser
Mono Agent no longer launches its own browser. It works inside the Chrome you already use, through an extension you install.
HybridSessionProvider gets pages only through the MonoAgent Bridge extension. The bridge is a loopback WebSocket on 127.0.0.1:9222 and the first frame must carry a shared secret stored at ~/.monoagent/extension.token. extension pair sets it up and extension reset revokes it. If the extension is not connected, a page request fails, because there is no headless fallback.
Each Chrome profile with the extension connects separately and is bound to a Mono Agent profile, so different profiles run their automations in parallel on their own logged-in sessions. The extension asks for per-site host permissions on demand instead of holding all URLs.
Typing is character by character with 50 to 250 ms between keys and a 1 to 3 second pause afterwards. The code says no typing mistakes are simulated. The old go-rod stealth package and anti-detection flags are gone, since the browser is your real one.
Extension 1.6.0 adds tasks to the board: right-click Add selection as task or Add page as task, an Add a task box in the side panel, and a keyboard shortcut. Tasks wait in the extension while Mono Agent is not running. A CDP proxy relays Chrome debugger commands over the same bridge.
AI
There is no model provider to configure. Mono Agent hands each AI step to your installed agent CLI through the monomind runner.
Every AI step is one turn run by the separate monomind runner on an agent CLI you already have installed and logged in. Detected runtimes include claude, codex, opencode, antigravity, grok, crush, copilot, pi and hermes. A runtime must pass agent validate before use, and automatic re-validation is off until you turn it on.
ai.chat, ai.extract, ai.classify, ai.transform, ai.agent, ai.embed and service.openrouter remain registered as stubs that error with a migration hint. Use agent.ask or ai.choose. ai.embed has no replacement.
gemini.generate_image drives Gemini in your own browser session, with no API key, and the bundled gemimg templates wrap it. Jev makes typed decisions such as classification and element picking with its own key, and never writes text.
httpapi and daemon serve /v1/models, /v1/chat/completions (streaming and tool calling) and /v1/images/generations over the installed runtimes, with per-profile API keys stored as SHA-256 hashes and an auto model where Jev picks. The changelog still lists this work as unreleased.
Full-access coder chats stay disabled until coder enable --yes-i-understand. Dynamic orgs can give each writing worker its own git worktree and branch, and workers can ask you a question through an ask_user tool.
Surface
The same engine answers to a CLI, a desktop app, an MCP server and an HTTP API, all running on your machine, alongside a daemon, a task board and a library.
CLI
45 top-level commands
442 command nodes, 378 of them leaves. workflow, node, org, agent, task, people, library, daemon, mcp and ref, a built-in offline reference.
Daemon
Restores every trigger
daemon restores each active workflow's cron and webhook triggers across all profiles, writes a heartbeat every 10 seconds, and installs as a launchd or systemd service. update restarts a stale daemon.
MCP
31 / 66 tools
31 read-only tools over stdio and 66 with --allow-mutations. A --tasks-only mode serves just the task board.
HTTP API
127.0.0.1:9322
REST server with an OpenAPI spec, read-only unless mutations are allowed. The webhook server listens on 127.0.0.1:9321.
Orgs
Via monomind
Org designer with sections, budgets and documents, org chat, and signed definitions that need monomind 2.21 or later. Parsers are tested against recorded 2.24.1 output.
Task board
5 columns
inbox, ready, in_progress, review, done. Agents claim tasks with leases that a comment extends by 30 minutes. A macOS Services menu adds tasks from any app.
Library
monoes.me
library list | install | publish | update for workflows, orgs and automations. Installs verify a sha256, and browsing needs a sign-in.
Distribution
One static binary
install.sh, release builds for linux, macOS and Windows, update with checksum verification, and a desktop app for macOS arm64, Linux amd64 and Windows.
Security and Privacy
All data lives under ~/.monoagent. These are the guarantees from SECURITY.md and the code, including what does leave your machine.
AES-256-GCM with per-profile data keys. The key-encryption key lives in the OS keyring (Keychain, Credential Manager or Secret Service). An opt-in file fallback, MONOAGENT_ALLOW_FILE_KEYRING=1, wraps the key with an argon2id passphrase. There are 43 connectable services across 6 auth methods.
The extension bridge (9222), webhook server (9321) and HTTP API (9322) bind to 127.0.0.1 by default, and the extension bridge requires a shared secret. The /v1 API needs TLS beyond loopback.
SECURITY.md states there is no telemetry and nothing phones home. Crash reports are written to ~/.monoagent/crashes/, and filing one to GitHub needs MONOAGENT_CRASH_REPORT=1 plus a second condition.
The agent CLIs behind AI steps send prompts to their own model providers. Browser automations talk to the platforms you point them at, from your own logged-in Chrome. Library browsing and installs call monoes.me.
Benchmarks
These are the only numbers the project has actually measured.
Measured on an Apple M2 with go1.26.6 on 2026-09-01 (-benchtime=3s -count=5). The project's own BENCHMARKS.md calls them illustrative: a weekly CI job runs them, but nothing gates on them. We removed our earlier latency table for browser clicks, LLM calls and webhooks because none of those were ever measured.