v0.126 · Go · One static binary

How Mono Agent
Is Actually Built

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.

168Node Types
45Top-level Commands
244KLines of Go
60+DB Tables
31MCP Tools (read-only)
0Telemetry

Architecture

System Overview

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.

ManualCLI · UI · MCP · APICrondaemonWebhook127.0.0.1:9321Workflow engineDAG · queue 1,000 · 3 workers (max 20)topological order · resume state · HIL pauseAction executor~38 step typeslibrary packages from monoes.meExpression enginetext/template · FuncMap{{$json.*}} · {{$node["…"].json.*}}Browserextension bridgeyour own ChromeSocial60 nodesIG · LI · X · TikTok · HN · PHAIagent.askvia monomind runnerServices36 nodesGitHub · Gmail · Slack · …Coreif · switch · mergefilter · code · limitHIL queuedurable pauseapprove · edit · rejectStorage (modernc.org/sqlite · pure Go · no CGO) · ~/.monoagent/monoagent.dbworkflows · executions · people · tasks · publications · messages · secrets (AES-256-GCM, OS keyring)Your Chrome + MonoAgent Bridgeloopback WebSocket :9222 · shared secretExternal APIsSlack · GitHub · Gmail · …Agent CLIs you have installedclaude · codex · agy · opencode · …

Internal Packages

9 Building Blocks

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

internal/workflow/

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.

DAGqueue 1,000cron + webhookresume state
🧩

Node Registry

internal/nodes/ + noderegistry/

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.

168 types136 schemasregistry + aliases
🎬

Action Executor

internal/action/

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.

~38 step typeslibrary packages3-tier fallback
🌐

Browser Bridge

internal/browser/ + chrome-extension/

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.

your own Chromeextension bridgeno headless fallback
🧠

AI and Orgs

internal/monomind/ + dynorg/ + org*/

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.

agent runtimesmonomind runnerorg chat
🗄

Storage and Secrets

internal/storage/ + 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.

pure Go61 migrationsAES-256-GCMOS keyring
🔌

API Surface

internal/mcp/ + httpapi/ + openaiapi/

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.

MCPREST + OpenAPIOpenAI-compatible
🖥

Desktop App

wails-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.

Wails v2React 19en + es
📋

Tasks, Library, Account

internal/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.

5-column boardlibraryaccount (dormant)

Execution

Workflow Execution Flow

From trigger to result in 8 steps. Executions are sequential per run, durable across restarts, and pausable for a human.

1

Trigger

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.

2

Queue and DAG

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>
3

Sequential execution loop

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.

4

Expressions

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}}
5

Node execution

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.

6

Human-in-the-loop

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
7

Errors

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.

8

Resume and recovery

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

168 Node Types

Counted from monoagentcli node list, grouped here by job. A -tags nosocial build leaves out the social nodes and keeps 107.

60

Social platforms

Instagram 18TikTok 16LinkedIn 12X 7Hacker News 4Product Hunt 3
36

Services and messaging

GitHubGoogle SheetsGmailAirtableAsanaSlackOutlookRedditMastodon
17

Data, images and files

spreadsheetmarkdownhtmlxmlcryptoresizecropremove_background
15

AI and agents

agent.askai.choosegemini generate_imagebrowser.jevread_page
15

Core and control

ifswitchmergefilterlimitcodehuman_in_loop
14

Orgs, people and records

org.runorg.askpeopleapplicationspublication.registerdocuments.render
11

Databases, HTTP and systems

PostgresMySQLMongoDBRedisHTTP requestSSHexecute_commandvault

Browser

Your Own Chrome, Not a Hidden One

Mono Agent no longer launches its own browser. It works inside the Chrome you already use, through an extension you install.

01

Your own Chrome, through an extension bridge

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.

02

One Chrome profile per Mono Agent profile

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.

03

Human pacing, no stealth layer

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.

04

The extension also feeds the task board

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

AI Runs on the Agent CLIs You Already Have

There is no model provider to configure. Mono Agent hands each AI step to your installed agent CLI through the monomind runner.

01

No built-in provider, no stored text-AI keys

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.

02

Deprecated nodes fail loudly

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.

03

Images and decisions

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.

04

An OpenAI-compatible gateway over your runtimes

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.

05

Coder mode is off by default

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

What Runs Around the Engine

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

Local by Default, With the Limits Stated

All data lives under ~/.monoagent. These are the guarantees from SECURITY.md and the code, including what does leave your machine.

01

Secrets are encrypted per profile

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.

02

Everything listens on loopback

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.

03

No telemetry, local crash reports

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.

04

What does leave your machine

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

Measured, Not Promised

These are the only numbers the project has actually measured.

Expression eval (simple / nested / fallback)
6.8 / 9.0 / 19.4 µs
Workflow save, 100 nodes and 200 edges
4.65 ms
Workflow load, 100 nodes and 200 edges
2.73 ms
Workflow list (cached / uncached)
2.69 / 27 ms
core.set over 1,000 items
8.9 ms
core.filter over 1,000 items
16.8 ms
core.code (goja) over 1,000 items
13.2 ms
Redact 1,000 items
29.5 ms

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.