Autonomous runs
Running a goal to completion
Describe what "done" means in a TOML file and let the agent work at it without you — with budgets that stop it.
Interactive mode is a conversation. Autonomy is different: you write down what success looks like, hand it over, and come back to a result.
snaga --autonomy goal.toml
Writing a goal
A goal file has three parts: what you want, what "done" means, and how much it may spend getting there.
id = "blink-firmware"
description = """
Write a Rust firmware for a Raspberry Pi that blinks GPIO17 every
500 ms, runs as a systemd service, and reports heartbeat over
MQTT. Must compile with the stable toolchain.
"""
[budget]
max_rounds = 80
max_minutes = 45
[[success_criteria]]
kind = "shell_exit_zero"
cmd = "cargo build --release"
[[success_criteria]]
kind = "file_exists"
path = "target/release/blink"
min_bytes = 50000
TOML rather than YAML, deliberately: mixed indentation breaks subtly when a model edits it, and this is a file a model will edit.
What "done" can mean
kind | Passes when |
|---|---|
shell_exit_zero | a command exits 0 |
file_exists | a file exists, optionally above min_bytes |
tests_pass | the test suite passes |
http_ok | an endpoint answers |
telemetry_reports | a value appears on a topic within a window |
Write these as tightly as you can. They are the only thing standing between
"the agent decided it was finished" and "the thing works". A criterion of
shell_exit_zero on cargo build says the code compiles and nothing about
whether it does the job — pair it with a test.
Budgets
max_rounds and max_minutes bound the run. They are not a suggestion: the
executor stops there, whether or not the goal is met.
There is also a loop guard. A run that keeps hitting the same unresolvable obstacle is detected and stopped, rather than burning the whole budget rediscovering it.
Profiles
snaga --profile robotics --autonomy goal.toml
Stock profiles: robotics, drone, server-ops, space, auto. A profile
presets the behaviour for a domain. For your own, use custom:<path>.
Resuming
A run persists under .snaga/autonomy/<goal-id>/, so a crash or an interrupt is
not the end of it:
snaga autonomy list # runs, with their progress
snaga --autonomy-resume <goal-id> # continue one
autonomy list shows which runs still have pending work; those are the ones
worth resuming.
Watching without interfering
From another terminal:
snaga tail <session-id>
This follows the session's structured event log. You see gap detections, tool calls and decisions as they happen, without attaching to the process or interrupting it.
When a long run finishes, Snaga notifies you — a terminal bell always, and a
desktop notification where the platform has one. Opt out with
SNAGA_NO_NOTIFY=1.
Before you let one run unattended
Autonomy does not relax any of the other rules. Confirmation requests still happen — and with nobody to answer, they resolve to deny, so a goal that needs a privileged command will stall on it rather than proceed. Decide in advance what the run may do:
- widen the shell policy for what it genuinely needs — see Changing the rules;
- set the trust policy for what it may install — see Installing tools from the registry;
- or accept that it stops where a human would have been asked.
--yolo removes that friction and every guard with it. On an unattended run,
that is a decision to think about while you are still in the room.