Lifecycle state
Whether work has started, is running, finished successfully, failed, or is stalled.
Learn
How can a human remain informed about autonomous work without becoming a permission gate for every action?
Removing routine approvals should not mean removing visibility. A system can allow work to continue without synchronous human permission while independently exposing enough state for a human to inspect what is happening.
Observation is a control in its own right: a way to inspect autonomous work. It is not proof of safety, and not a substitute for containment or for human acceptance of results.
Human control over autonomous systems is often collapsed into a single phrase (“human in the loop”). That phrase hides four different controls. They answer different questions and act at different moments.
Execution pauses until a human grants permission for the next step.
Execution continues while a human can inspect live state and history.
A human may stop or alter a run where such a control exists.
After work exists, a human decides whether it becomes authoritative state.
| Control | What happens to execution |
|---|---|
| Approval | Waits for human permission before proceeding |
| Observation | Continues while a human can inspect |
| Intervention | Human may stop or change the run where control exists |
| Acceptance | Decision occurs after work exists |
The central distinction:
observation is not approval · execution is not acceptance
OpenTendril’s current Objective requires that a Botanist can grant an LLM full freedom inside a Terrarium, be asked for nothing while it works, and still receive reviewable Git output, with nothing outside the declared boundary touched. One of the conditions that series of runs must carry is whether the run could be watched while it happened, not only reconstructed afterwards.
The Objective states the tension deliberately:
stop being asked + keep being able to look
These are opposite operational requirements. Being asked for nothing is only tolerable if looking remains available. An unobservable run is not framed here as automatically insecure. It fails the current OpenTendril delegation objective: it is the blindness that makes people return to approving every step. Details of measurement live on the experiment page.
For governed autonomous systems, useful observation tends to fall into durable categories. These are general categories, not a claim that every product field exists in every system, and not a claim that OpenTendril currently records every one of them completely.
Whether work has started, is running, finished successfully, failed, or is stalled.
What tools or commands ran, with arguments and outcomes where recorded.
Which paths changed, when the workspace can measure it.
Which mind carried the run, where resolution is known.
Whether external reach was attempted, and under which policy.
Time, tokens, memory, process limits, where measured.
Which operation classes were authorised or denied, where audited.
Terminal verdict of the run, plus a durable record for later inspection.
Desired measurements in an objective document are not the same thing as implemented telemetry. The next sections describe only what OpenTendril currently exposes.
In OpenTendril, sprout.grow is a synchronous capability: it answers
when the run matures or withers. While that wait proceeds, observation
surfaces can be watched:
/ws EventBus stream;
sprout.watch is the delegated view authority for that
observation. Those surfaces are independent of routine step approval. A
run can execute without pausing for human permission on each action while
still emitting lifecycle and action events.
/ws) and history endpoints.
OpenTendril’s observation UI is the Greenhouse.
execution continues independently of the observer →
Current implementation surfaces (verified on the product default branch):
sprout-emerged, sprout-matured, sprout-withered,
sprout-detached, sprout-dormant, tool-invoked,
sprout-transcript, terrarium resource events, delegation authorised/denied,
hormonal-trigger blocked). Sinks persist events and feed remote transporters; a slow
sink does not block publish.
/ws: WebSocket gateway over the EventBus. Optional
?replay=N prepends a short in-memory recent history (bounded, not a full
archive). The same surface is mounted on the main API mux and a standalone gateway
listener.
.tendril/history.db when
enabled (default). Records sessions, chat messages, EventBus rows, and Sprout-run
records (status, transcript, model, genotype, substrate, dispatching Pollen, timings,
output/error). Can be disabled for headless runs; can prune by configurable retention.
sprout.watch: a real operation-class used for
delegated observation authority: who may watch stored run records, persisted
events, and the live stream for phytomers they own. It is deliberately not a command
projected onto every surface the way sprout.grow is; it authorises the
view without authorising growth. The operator (Stem key, no Pollen) retains the full
view.
Run results also report lifecycle status (matured / withered),
a refined outcome (for example complete, no-changes, failed, timed-out), files modified
when measurable, and the resolved provider/model. That is what a surface records, not
a guarantee that every useful category above is always fully populated.
Greenhouse is the Command Center UI: the observation surface a Botanist watches through. Taxonomy: external observability UI, not the Stem and not the worker.
The current UI (React app under ui/) is a decoupled client of the Stem’s
HTTP and WebSocket contracts. What it actually presents today:
It re-hydrates cold state from REST after load or reconnect, and uses
/ws?replay=… as a bounded supplement for recent session-less sequence
telemetry. It is not a full command-replay product, cost dashboard, credential graph,
universal kill switch, or forensic timeline. Those should not be assumed from the
Greenhouse concept alone.
Seeing a run does not grant its next action, and does not accept its result.
observe ≠ approve · observe ≠ accept · observe ≠ necessarily intervene
Current OpenTendril observation surfaces are read-oriented: stream, history, and Greenhouse drill-down. There is no verified universal operator “kill switch” in the Greenhouse UI for arbitrary live intervention.
Lifecycle machinery does include internal endings: growth budgets that stop waiting (detach) rather than always killing work immediately, orphan reaping when nothing still waits on a run, terrarium timeouts, and Hormonal Triggers that can abort before a Sprout emerges. Those are system controls and pre-execution gates, not a general claim that every human observer can stop or rewrite any running Sprout from the dashboard.
If you need the acceptance half of the story (whether the resulting code becomes project state), that is Git handoff, not observation.
Both matter, and they answer different questions:
/ws EventBus feed)
Live stream alone is ephemeral without a sink. History alone is retrospective; under
the current Objective it is not a full substitute for being able to watch while work
runs. The in-memory bus window used for ?replay= is short and lossy by
design. Durable rows live in SQLite when logging is enabled, and optional retention
pruning means those rows are not described here as immutable audit logs.
Observation reports; acceptance decides
OpenTendril’s job under the Objective is to hold the boundary and to say what happened. It does not decide whether the work was good. A Botanist may observe a perfectly contained run that still produces bad code. That is a work-quality issue, not necessarily a containment failure.
Conflating “we saw the run finish” with “we should keep the change” is the same scope error as conflating containment with correctness. See the experiment, Git and human acceptance, and containment.
sprout.watch grants allow, not necessarily the whole fleet.