Your First Agent
This page walks the macOS happy path: complete the guided mono-agent init wizard, let it start the durable background agent, then edit, validate, restart, and open the ordinary TUI. A real model reply still requires provider credentials or a configured local provider.
The shortest working path
Section titled “The shortest working path”If Node.js and a model provider are already ready, start here:
npm i -g create-mono-agentmkdir my-agent && cd my-agentmono-agent initmono-agent status # guided macOS init starts the agent# Otherwise: mono-agent start --foregroundThe wizard reviews the files before writing, proves each selected runtime route, validates the committed folder, and starts the managed agent on macOS. If you use flags, non-TTY input, Linux, or another platform, init creates the scaffold without claiming readiness; run mono-agent validate, then start the service or foreground process yourself. The rest of this page explains those branches and their safety contracts.
Prerequisites
Section titled “Prerequisites”You need Node.js installed, the mono-agent CLI available, and credentials for whatever model you choose. The quickest path is the npm create mono-agent@latest installer (equivalently npx create-mono-agent) with no global install, or npm i -g create-mono-agent for the persistent command. The CLI itself ships in @mono-agent/agent-app, so installing or invoking that scoped package is equivalent.
Guided init searches every bundled model for the Pi providers — Anthropic, GitHub Copilot, OpenAI Codex, and OpenCode-Go — plus discovered local models. Other hand-authored refs remain runtime-compatible but are outside guided cloud-provider setup. The provider-declared Codex default leads when discovery succeeds; curated openai-codex:gpt-5.6-terra is the offline fallback. The offline entry does not guess effort support and therefore offers only Provider default until live model/list metadata is available. The wizard keeps catalog availability, credential detection, and live verification separate. Credentials come from the app-owned Pi OAuth flow: mono-agent auth login openai-codex prints an auth URL to open in a browser, waits for the localhost callback, and a remote/headless machine can paste the returned redirect URL or authorization code into the live prompt instead. GPT-6 Astra is available as openai-codex:gpt-6-astra; openai:gpt-6-astra is the corresponding hand-authored OpenAI API-key route. GPT-5.6 Sol remains available as openai-codex:gpt-5.6-sol. See Install and Environment Variables for other providers.
If you are testing unreleased source from a clone, replace mono-agent in the commands below with the built CLI entry:
node /absolute/path/to/mono-agent/packages/agent-app/dist/cli.js1. Scaffold the folder (cli)
Section titled “1. Scaffold the folder (cli)”Run bare init inside an empty folder on a TTY. This guided path is the only init mode that proves readiness:
mkdir my-agentcd my-agentmono-agent initThe wizard starts from a preset or custom answers, asks what the agent should be called, and labels the next answer as the exact Role text for IDENTITY.md → ## Role. Creation review repeats both the destination and the exact text. If IDENTITY.md already exists, the wizard says it will remain unchanged and that the entered Role will not be written. It then walks through the same model, channel, memory, runtime-appropriate tool/safety, and observability decisions either way. Type to search the primary and fallback catalogs; add as many fallbacks as you need and choose each route’s supported effort or Provider default. Escape moves back one logical step. Ctrl-C asks before exiting.
Journal and BuJo add a dedicated local-embeddings step. Choose Ollama or LM Studio,
confirm its service root, select a model from provider-native typed discovery, and let the
wizard prove and record the actual vector dimension. Ollama discovery checks /api/show
for the embedding capability; LM Studio accepts only /api/v1/models entries whose type
is embedding. If discovery is unavailable you may enter the model and a positive dimension
manually, but guided readiness still requires a real /api/embed or /v1/embeddings probe.
The selected provider never falls back to the other one. LM Studio is keyless by default;
when its server uses authentication, name the populated owner-only .env variable through
apiKeyEnv rather than putting a token in config.
Allow all tools is the default and includes shell, file, web, and enabled channel-send tools. A mixed chain requires explicit per-route acceptance after the wizard displays the concrete route matrix. Pi keeps mono-agent tools and optional managed SRT; provider-owned routes use their documented native contract. Unsupported capabilities are never silently dropped.
After the explicit Creation review, the wizard makes one disposable no-tool call for every selected route, sequentially, with a 90-second cloud or 240-second local deadline per route. A detected Pi auth-store entry or declared apiKeyEnv credential skips redundant authentication, but it is not called verified until the exact route succeeds. Escape or Ctrl-C interrupts safely. Recovery can resume routes already verified under the same non-secret plan fingerprint, restart all checks, edit choices, or cancel without writing. Choosing authentication repair clears all prior route proofs before the checks rerun. Provider failure, timeout, empty output, or any tool action fails that route. On macOS, Agent ready additionally requires the committed config and every selected credential, channel, sandbox, memory, and observability expectation to be ready. The managed background process must then prove its live identity, exact committed snapshot, durable environment, and reachable TUI endpoint before the wizard opens the TUI. See Setup security and managed runtime for the closure-integrity, single-instance, frozen-input, and snapshot-commitment contracts behind that proof.
Passing any flag or running without a TTY skips the wizard and writes a scaffold only. It never runs the readiness proof, starts a process, or labels the result ready. These flags remain useful for automation:
Optional flags:
| Flag | Purpose |
|---|---|
--name <display-name> | Public agent name. Display metadata only; never used for paths/service/session ids. |
--model <ref> | Primary runtime model. Format: <provider>:<model> (e.g. openai-codex:gpt-5.6-terra, anthropic:claude-sonnet-4-6, ollama:gemma4:31b). Defaults to openai-codex:gpt-5.6-terra. |
--fallback <ref> | Repeatable canonical fallback route. Follow immediately with --fallback-effort <provider-default|level> when needed. |
--auth | Opt in to provider setup before writing: the app-owned Pi OAuth flows and local-provider preflight. Detected credentials are reused |
--memory lite|journal|bujo | Adds a memory section with the chosen tier. Omit it and no memory is configured. See Capture and Recall. |
A fuller example:
mono-agent init \ --name "Research Companion" \ --model openai-codex:gpt-5.6-terra \ --fallback anthropic:claude-sonnet-5 --fallback-effort xhigh \ --fallback ollama:gemma4:31b --fallback-effort provider-default \ --memory bujoWhat init scaffolds
Section titled “What init scaffolds”init is non-destructive for scaffold/config files (app.cli-init): existing config, identity, and capability files are reported as unchanged. Guided secret setup is the explicit exception and may securely harden/update .env plus .gitignore. In a clean folder it creates:
mono-agent.config.json— the single config file that declares the whole agent. It enables the webhook channel (webhook.enabled: true) as the zero-credential smoke channel so you can get a response immediately, and wiresartifacts,traceability, andcontext.identityPathto the scaffolded paths.IDENTITY.md— the reviewed Role is stored only as the body of## Role, alongside boundaries and a Knowledge section that references anyAGENTS.md,CLAUDE.md,README.md, orSOUL.mdalready present in the folder. An existing file is preserved byte-for-byte; in that case the entered Role is not written, and you add or edit its## Rolesection later. See Identity and Soul.skills/mono-agent-memory— the versioned project-local memory skill selected with index disclosure.ReadSkillloads its body only when needed.skills/.mono-agent-managed.jsonrecords its hash for safe drift checks and updates..mono-agent/— working directories:.mono-agent/artifacts(run output) and.mono-agent/workspace.
When a fresh init selects built-in Journal or BuJo memory, init also creates one empty managed generation without indexing content. Guided setup has already made its separate fixed, non-user readiness probe; flag/non-TTY scaffolding makes no provider call and no readiness claim. Init never adopts or changes a pre-existing memory root; stop the agent and use the explicit mono-agent memory rebuild path for an existing root. Fresh managed init rejects environment overrides for memory backend, mode, path, and embedding provider/model/dimension; put that identity in the generated config. Credential and endpoint environment values remain valid inputs.
The generated config (with canonical --fallback routes and --memory bujo) looks like this — note that tools.allowedTools defaults to allow-all (["*"]), and the bujo tier scaffolds its embeddings, capture LLM, and recall tool:
{ "agent": { "name": "Research Companion" }, "runtime": { "model": "openai-codex:gpt-5.6-terra", "fallbacks": [ { "model": "anthropic:claude-sonnet-5", "effort": "xhigh" }, { "model": "ollama:gemma4:31b" } ], "workspace": "." }, "context": { "identityPath": "./IDENTITY.md", "skillsRoot": "./skills", "selectedSkills": ["mono-agent-memory"], "skillDisclosure": "index" }, "tools": { "allowedTools": ["*"], "disallowedTools": [] }, "artifacts": { "dir": "./.mono-agent/artifacts" }, "traceability": { "registryDir": "./.mono-agent/trace-sources", "sourceLabel": "Research Companion" }, "webhook": { "enabled": true }, "memory": { "mode": "bujo", "path": "./.mono-agent/memory", "writeMode": "capture", "embeddings": { "provider": "ollama", "model": "nomic-embed-text:v1.5", "endpoint": "http://localhost:11434", "dim": 768 }, "llm": { "provider": "agent-host", "model": "openai-codex:gpt-5.6-terra" }, "recallTool": { "enabled": true } }}Every field has a MONO_AGENT_* env override (env > JSON > defaults) — for example MONO_AGENT_NAME, MONO_AGENT_MODEL, and MONO_AGENT_FALLBACKS_JSON. See Configuration for the annotated blueprint. The scaffolder also adds an artifacts.retention block and a $schema reference, omitted here for brevity.
For selected channel secrets, the guided wizard never shows values in config, examples, review output, or logs. Existing non-empty dotenv assignments and comments are preserved, and a shell-only value cannot make a later background start appear durable. Automatic persistence fails closed when the agent folder, dotenv, ignore rules, or a concurrent update cannot be verified safely; unsupported platforms receive manual instructions. The complete ownership, locking, promotion, race-recovery, and provider-auth-store rules live in Setup security and managed runtime. Never copy .env.example over an already populated .env.
2. Configure and apply (cli)
Section titled “2. Configure and apply (cli)”Edit mono-agent.config.json and IDENTITY.md directly. Then validate the
resolved configuration, restart the agent, and open the ordinary console:
mono-agent validatemono-agent restartmono-agent tuiDo not put secrets in JSON or identity files. Keep them in the documented owner-only dotenv or provider authentication store, and do not claim a change is active until validation and restart have succeeded.
3. Validate (cli)
Section titled “3. Validate (cli)”Check the config section by section before starting:
mono-agent validatevalidate (app.cli-validate) prints a per-section report — core, runtime,
provenance and routes, provider credentials, context, memory, tools, sandbox,
observability, runs health, managed launchd logs, secret placement, and every
channel — each tagged with a status. The launchd-log section reports active,
retained, and total bytes for every safely inspected stream, reports unsafe or
unreadable inventory as unavailable, and never rotates or changes permissions:
| Status | Meaning | Action |
|---|---|---|
[ok] | Section is healthy. | None. |
[waiting] | Enabled but missing a credential, process, or live dependency. | Resolve it before calling the selected capability ready. |
[disabled] | Capability is off (not enabled in config). | None. |
[error] | A real misconfiguration. | Fix before starting. |
Fix every [error] section. Standalone validate keeps waiting non-fatal for operators intentionally starting partial configurations, so exit 0 means structurally valid, not that every selected capability is live. The guided wizard’s Agent ready gate is stricter: no selected expectation may be waiting, and every selected runtime route must have succeeded in its exact live check. Read-only credential detection (the Pi auth store and declared apiKeyEnv variables) is not a model-turn claim. Hidden memory and static-trigger dependencies are also validated.
Point validate at a non-default config or env file with mono-agent validate --config ./other.config.json --env-file ./.env. To check a downstream agent folder from elsewhere, use mono-agent validate --consumer ../local-agent-alpha; the consumer .env loads by default and relative --config / --env-file paths resolve inside that folder.
4. Start or inspect the service (cli)
Section titled “4. Start or inspect the service (cli)”mono-agent startGuided macOS init has already started this service before configuration mode. Run mono-agent status to inspect it; use mono-agent start when continuing from a scaffold or manually recovered setup. This boots the runtime and every enabled channel. The webhook channel listens on loopback (127.0.0.1) and, because the default port is 0, picks a free port. start prints the resolved webhook invoke URL — copy it for the smoke test below.
On macOS, mono-agent start backgrounds the agent with launchd and returns. On other platforms, use mono-agent start --foreground.
5. Smoke-test with curl
Section titled “5. Smoke-test with curl”Send a request to the printed webhook path. The default endpoint path is /webhook/invoke and the default mode is sync, so the HTTP response carries the agent’s reply directly:
PORT=3000 # Replace 3000 with the printed port.curl -s "http://127.0.0.1:${PORT}/webhook/invoke" \ -H 'content-type: application/json' \ -d '{"text": "Say hello and tell me what you are."}'Replace 3000 with the port from the start output. A response means the runtime, model, identity, and webhook channel are all wired correctly — you have a working agent. Without valid provider credentials or a reachable local provider, the webhook request should fail honestly rather than returning a fake model reply.
The webhook channel binds to loopback by default. To accept non-loopback requests you must set both webhook.allowNonLoopback: true and MONO_AGENT_WEBHOOK_API_KEY (plus, ideally, a non-zero port); callers send the key as a bearer on invocation and status requests. A key is optional on loopback and leaving it unset preserves the zero-credential smoke flow above. For async invocation, status polling, multiple named endpoints, and per-endpoint prompts, see Webhook.
Where to next
Section titled “Where to next”- Turn this into a real assistant: add a credentialed channel like Telegram or Slack.
- Understand the moving parts: Core Concepts.
- See the full config surface: Configuration and the Config Blueprint.
- Build something end to end: the Playbooks — e.g. Local-only Ollama agent or Telegram personal assistant.
- Embed the agent in your own code instead of the CLI: Programmatic.