How to Run a Long-Running AI Agent with nanoinfra
nanoinfra can keep agent work alive across turns through sustained goals, persistent sessions, scheduled automations, local triggers, and a gateway process that stays running.
What you will build
- a working local agent
- a persistent chat session
- a long-running goal or automation
- a gateway process for background delivery
When to use this
Use this when the task is not a one-shot answer. It suits project work, recurring checks, scheduled summaries, file maintenance, multi-step research, and local triggers from scripts and build jobs.
Install
Quick Start ranks four install methods easiest first. This is the first of them. Use pip, Docker or a source checkout instead if you prefer, and come back here.
uv tool install nanoinfra
nanoinfra onboard --wizard
nanoinfra agent -m "Hello!"
Minimal working example
Start a gateway:
nanoinfra gateway
There are three ways to keep an agent working, and they differ in who decides when it runs. Pick by that, not by the length of the task.
| Who decides when | Use | How you start it |
|---|---|---|
| The agent, now, until the goal is met | a sustained goal | /goal <goal> in the chat |
| A clock | a scheduled automation | ask the agent to schedule it, or use Automations in the WebUI |
| Something outside nanoinfra | a local trigger | /trigger <name> in the chat, then nanoinfra trigger <name> from a script |
| A protected system schedule, reporting only what matters | the heartbeat | edit <workspace>/HEARTBEAT.md |
A sustained goal
Start it in the chat you want it to work in:
/goal Review this workspace, identify missing tests, and propose the smallest next fix.
The agent treats the request as ongoing rather than as one question. It keeps
working across turns in that session. Use /status to see where it is, and
/stop to end it.
A scheduled automation
There is no /cron command. You ask the agent in words, and it uses its cron
tool:
Every weekday at 08:00, review this workspace for new test gaps and post the
smallest next fix.
Create it from the chat you want it to run in. The automation binds to that session and that workspace. One created somewhere else runs somewhere else. Automations in the WebUI is the same thing with a form.
A scheduled run is unattended, which is the part that needs care rather than the schedule. Creating one rehearses it. nanoinfra forces every gated tool to preview for one turn, and records what the gate would answer. So an automation that the gate would refuse at 03:00 is refused now, while you are watching. Read Creating One Rehearses It before the first one.
A local trigger
When the schedule is not a clock but an event — a build finished, a script ran, a webhook arrived:
/trigger nightly-review
Then fire it from anywhere that can run a command:
nanoinfra trigger nightly-review
Local Triggers covers firing one over HTTP with its own key.
Choosing between a goal and an automation
The two can look like the same request and are not the same thing. The boundary, with the cases that decide it, is in Is This an Automation at All?.
In one line: a goal holds context across turns in one session, and an automation starts clean each run.
Production notes
- Keep the gateway running for chat apps, WebUI sessions, automations, and local triggers.
- Use stable session keys or chat sessions for work that should preserve context.
- Keep goals bounded and explicit about done-ness.
- Review Automations in the WebUI before relying on a schedule. Creating one rehearses it. Read the commissioning finding rather than waiting for the first scheduled run. An automation saved disabled was found to need a permission it does not have.
Security notes
- Treat long-running goals as delegated work with real tool access.
- Restrict workspaces and shell execution before scheduling unattended tasks.
- Keep chat access narrow so unknown users cannot create goals or automations.
Troubleshooting
- If a goal appears stuck, inspect the active session and gateway logs.
- If an automation does not run, check that it is linked to a chat/session and that the gateway is still running. If it is disabled with a commissioning finding, the rehearsal already said what it needs — see Automations.
- If a local trigger fails, check the command copied from the WebUI Automations view.