diff --git a/docs/README.md b/docs/README.md index 9c996e2b..289bba1b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -51,7 +51,7 @@ If a local `nanobot agent` session can already answer normally, you can also ask |---|---|---| | Open the bundled browser UI | [`webui.md`](./webui.md) | WebUI on port `8765`, chat workspace, Apps, Skills, Automations, and settings | | Connect Telegram, Discord, WeChat, Slack, and other apps | [`chat-apps.md`](./chat-apps.md) | A gateway-backed chat channel with access control | -| Use slash commands and periodic tasks | [`chat-commands.md`](./chat-commands.md) | Pairing, model presets, heartbeat tasks, and chat-side controls | +| Use slash commands and automations | [`chat-commands.md`](./chat-commands.md) | Pairing, model presets, external triggers, heartbeat tasks, and chat-side controls | | Generate images | [`image-generation.md`](./image-generation.md) | Image provider config, WebUI image mode, and artifact behavior | | Run several isolated bots | [`multiple-instances.md`](./multiple-instances.md) | Separate configs, workspaces, ports, and sessions | | Deploy outside a terminal | [`deployment.md`](./deployment.md) | Docker, systemd user services, and macOS LaunchAgent setup | diff --git a/docs/chat-commands.md b/docs/chat-commands.md index fafce2a0..89c864bb 100644 --- a/docs/chat-commands.md +++ b/docs/chat-commands.md @@ -16,6 +16,8 @@ These commands work inside chat channels and interactive agent sessions: | `/dream-restore` | List recent Dream memory versions | | `/dream-restore ` | Restore memory to the state before a specific change | | `/skill` | List enabled skills and their descriptions | +| `/trigger` | Create a local external trigger for the current chat/session | +| `/trigger ` | Create a named local external trigger for the current chat/session | | `/pairing` | List pending pairing requests | | `/pairing approve ` | Approve a pairing code | | `/pairing deny ` | Deny a pending pairing request | @@ -55,6 +57,53 @@ To switch presets for future turns: Preset names come from the top-level `modelPresets` config. Switching is runtime-only: it does not rewrite `config.json`, and an in-progress turn keeps using the model it started with. See [Configuration: Model presets](./configuration.md#model-presets) for setup details. +## External Triggers + +Use `/trigger` when a local script or another service should be able to send a +message into the current chat/session later. + +Create the trigger from the chat where future messages should arrive: + +```text +/trigger PR review +``` + +nanobot replies with a trigger ID and a command shaped like: + +```bash +nanobot trigger trg_8K4P2Q9X "Review PR #4502" +``` + +Replace `"Review PR #4502"` with the message you want nanobot to receive. The +trigger is bound to the session where it was created, so the message goes back +to that same chat. Keep `nanobot gateway` running so trigger messages can be +delivered. + +For longer or generated content, omit the message argument and pipe stdin: + +```bash +printf '%s\n' "Review the latest failed CI job" | nanobot trigger trg_8K4P2Q9X +``` + +If an external webhook should wake nanobot up, run your own small webhook +service and have it call the trigger command after it builds the final message: + +```bash +nanobot trigger "" +``` + +If you run multiple nanobot instances, pass the same config or workspace +selector used by the gateway: + +```bash +nanobot trigger --config ./bot-a/config.json trg_8K4P2Q9X "Nightly report" +nanobot trigger --workspace ./bot-a/workspace trg_8K4P2Q9X "Nightly report" +``` + +Manage triggers from the WebUI Automations view. You can search, pause/resume, +rename, delete, and copy the trigger command there. A session may have multiple +triggers, just like it may have multiple scheduled automations. + ## Periodic Tasks Periodic background checks are driven by `HEARTBEAT.md` in your workspace (`~/.nanobot/workspace/HEARTBEAT.md`). When `nanobot gateway` starts, it registers a protected heartbeat cron job by default. Every 30 minutes, that job checks the file; if it finds tasks under `## Active Tasks`, the agent executes them and delivers only results that pass the notification gate to your most recently active chat channel. If there are no active tasks, or the result is routine with nothing useful to report, the heartbeat is skipped silently. diff --git a/docs/cli-reference.md b/docs/cli-reference.md index 96feacd1..bc93cff8 100644 --- a/docs/cli-reference.md +++ b/docs/cli-reference.md @@ -13,6 +13,7 @@ Use this page when you know what you want to run and need the command shape. For | Send one test message | `nanobot agent -m "Hello!"` | First proof that install, config, provider, model, and workspace all work | | Chat in the terminal | `nanobot agent` | Interactive local chat; exit with `exit`, `/exit`, `:q`, or `Ctrl+D` | | Use WebUI or chat apps | `nanobot gateway` | Keep this terminal running, or use `nanobot gateway --background` | +| Deliver a local external trigger | `nanobot trigger "message"` | Created first with `/trigger` in the target chat/session | | Serve an OpenAI-compatible API | `nanobot serve` | Starts `/v1/chat/completions`, `/v1/models`, and `/health` | | Check chat channel setup | `nanobot channels status` | Useful before starting `nanobot gateway` | | Log in to QR/OAuth-style channels | `nanobot channels login ` | Used by channels such as WhatsApp and WeChat | @@ -122,6 +123,40 @@ http://127.0.0.1:18790/health The bundled WebUI is served by the WebSocket channel, usually on port `8765`, not by the gateway health endpoint. +## Local Triggers + +`nanobot trigger` delivers one local message to a trigger that was created from +a chat/session with `/trigger [name]`. + +```bash +nanobot trigger trg_8K4P2Q9X "Review PR #4502" +``` + +Keep `nanobot gateway` running so the message can be delivered to the linked +chat/session. + +Use stdin when another local process generates the message: + +```bash +generate-report | nanobot trigger trg_8K4P2Q9X +``` + +Options: + +| Command | Description | +|---|---| +| `nanobot trigger "message"` | Deliver one message through a trigger | +| `nanobot trigger ` | Read the message from stdin | +| `nanobot trigger --config "message"` | Use the workspace from a specific config | +| `nanobot trigger --workspace "message"` | Use a specific workspace | + +Triggers are managed in the WebUI Automations view instead of through separate +`list`, `revoke`, or `delete` CLI subcommands. From there you can pause/resume, +rename, delete, search, and copy the command for each trigger. + +For webhooks or other external systems, run your own small service and have it +call this CLI after it decides what message nanobot should receive. + ## OpenAI-Compatible API | Command | Description | diff --git a/docs/concepts.md b/docs/concepts.md index 5f885083..eb7559be 100644 --- a/docs/concepts.md +++ b/docs/concepts.md @@ -123,7 +123,7 @@ Tools are discovered automatically from built-in modules and plugin entry points - shell execution with configurable sandboxing; - web search and web fetch with SSRF checks; - MCP servers; -- cron reminders and heartbeat tasks; +- cron reminders, external triggers, and heartbeat tasks; - image generation; - subagents and runtime self-inspection. @@ -131,14 +131,23 @@ Security-sensitive controls live in [`configuration.md#security`](./configuratio ## Background Jobs -When `nanobot gateway` starts, it creates workspace-scoped cron storage at `/cron/jobs.json` and registers system jobs: +When `nanobot gateway` starts, it runs workspace-scoped automations and +registers system jobs: - `dream`, when `agents.defaults.dream.enabled` is true; - `heartbeat`, when `gateway.heartbeat.enabled` is true. Heartbeat reads `/HEARTBEAT.md`. If the file has tasks under `## Active Tasks`, nanobot executes them and sends only useful/actionable results to the most recently active chat target. Routine "nothing changed" results are suppressed. -User-created reminders use the same cron service but are not the same as the protected heartbeat system job. They run as scheduled turns in their origin chat/session and normally deliver the result back to that channel. +User-created reminders use the same cron service but are not the same as the +protected heartbeat system job. They run as scheduled turns in their origin +chat/session and normally deliver the result back to that channel. + +External triggers are also session-bound, but they do not have their own +schedule. Create one from the target chat with `/trigger [name]`, then call +`nanobot trigger ""` when a local script or external service wants +nanobot to respond in that session. Webhook servers, third-party auth, and +event-to-message formatting stay outside nanobot. ## Where to Go Next diff --git a/docs/webui.md b/docs/webui.md index a7208e27..1bef8e7b 100644 --- a/docs/webui.md +++ b/docs/webui.md @@ -56,7 +56,7 @@ Enter `tokenIssueSecret` when the WebUI asks for a password. | Composer | Send text, images, voice input, slash commands, and `@` mentions for Apps or MCP presets | | Apps | Install, test, update, and use local CLI App adapters and MCP presets | | Skills | Inspect available built-in and workspace skills before relying on them | -| Automations | Review, search, run, pause, edit, and delete scheduled agent turns | +| Automations | Review, search, run, pause, edit, and delete scheduled and external-trigger agent turns | | Settings | Adjust models, providers, image generation, voice, web tools, runtime, and safety options | ## Chat Workspace @@ -116,10 +116,21 @@ to perform that task. ## Automations -Automations are scheduled agent turns. They should be created from the chat, -channel, or session where they are supposed to run so nanobot keeps the correct -target context. When an automation runs, it normally delivers the result back to -that linked chat. +Automations are agent turns that run later in a linked chat/session. They should +be created from the chat, channel, or session where they are supposed to run so +nanobot keeps the correct target context. When an automation runs, it normally +delivers the result back to that linked chat. + +There are two user-facing automation types: + +- Scheduled automations, created by the agent's cron tool, run at a time, + interval, or cron expression. +- External triggers, created with `/trigger [name]`, run when you call a local + command such as `nanobot trigger trg_8K4P2Q9X "Review PR #4502"`. + +If a GitHub webhook, CI system, or another service should wake nanobot up, keep +that webhook/service outside nanobot and have it call the trigger command with +the final message. For recurring background checks that should stay quiet unless there is something useful to report, use the protected heartbeat job by editing `HEARTBEAT.md` @@ -128,18 +139,25 @@ instead of creating a chat automation. Use the Automations view to: - Filter by all, active, paused, needs-attention, or system jobs. -- Search by task name, message, linked chat, schedule, or status. +- Search by task name, message, trigger command, linked chat, schedule, or status. - Sort by next run, last run, updated time, or name. -- Run now, pause or resume, edit, or delete user-created automations. +- Run scheduled automations now. +- Pause or resume, rename, or delete user-created automations. +- Copy the CLI command for external triggers. - Inspect protected system automations without changing them. Search accepts plain text and field filters such as `name:backup`, -`chat:WeChat`, `schedule:09:30`, `cron:"0 23 * * *"`, and `status:paused`. +`chat:WeChat`, `schedule:09:30`, `cron:"0 23 * * *"`, `trigger`, and +`status:paused`. An automation without a linked chat cannot be enabled or run from the WebUI, because nanobot would not know where to deliver the scheduled turn. Recreate it from the target chat or channel so the automation has complete context. +External triggers do not have a WebUI "Run now" action because each run needs a +message. Use the copied `nanobot trigger ...` command and replace `"message"` +with the content that should be delivered. + ## Settings Settings is the control surface for the browser session and gateway-backed