holon 0.14.1

A headless, event-driven runtime for long-lived agents
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
---
title: RFC: Agent Control Plane Model
date: 2026-04-21
status: draft
---

# RFC: Agent Control Plane Model

## Summary

This RFC defines Holon's top-level runtime and control-plane model.

The central direction is:

- `Agent` is the primary runtime object
- `WorkItem`, `Task`, and `Waiting` are distinct control-plane objects with
  narrower responsibilities
- creating another execution context belongs to the agent plane, not the task
  plane
- workspace or worktree isolation is an execution projection property, not a
  separate first-class noun
- task-created worktrees are supervised artifacts owned by task lifecycle, not
  by child agent identity

This RFC is the parent model for related plane-specific RFCs:

- delegation belongs to the agent plane
- managed command execution belongs to the task plane
- blocked and resumable state belongs to the waiting plane

## Problem

Holon's current model still carries overlapping concepts for context creation
and execution control.

Today the system has several adjacent ideas:

- public session creation
- internal `child_agent_task` supervision
- historical `subagent_task` and `worktree_subagent_task` migration records
- command-backed background tasks
- sleep, callback, and wake mechanisms

These capabilities are all useful, but they do not belong to the same layer.

The result is conceptual overload:

- `Task` is asked to represent command execution, child context creation, and
  waiting-like behavior
- `session` and `subagent` both describe new execution contexts
- worktree isolation is partly expressed as a task kind rather than as a
  property of execution context
- worktree artifact lifecycle must stay separated from child-agent execution
  state
- prompt and tool guidance have to explain several overlapping abstractions at
  once

Because Holon has not yet shipped a stable public contract, this is the right
time to simplify the model directly rather than preserve historical surface
shapes.

## Core Judgment

Holon should unify around `Agent` as the primary context-owning runtime
primitive.

Everything else should become narrower:

- `WorkItem` expresses what meaningful work exists
- `Task` expresses managed execution, primarily command-backed execution
- `Waiting` expresses why work is blocked and what may reactivate it

The important long-term distinction is not `session` versus `subagent`.

The important distinctions are:

- root versus child
- public versus private
- parent-supervised versus self-owned
- fresh versus forked context derivation
- inherited versus isolated workspace projection

## Canonical Runtime Objects

Holon should standardize on four primary control-plane objects.

## 1. `Agent`

`Agent` is the only object that owns an execution context.

An agent owns:

- queue
- lifecycle state
- prompt context and local summaries
- brief or user-facing history
- workspace projection
- ingress policy
- current work focus

This means:

- one agent owns one context
- current public sessions are root self-owned agents
- delegated subagents are child agents with bounded lifecycle modes

Holon should keep one runtime object here.

It should not create separate runtime types for:

- session agents
- child agents
- long-lived named agents
- future collaborative agents

Those should be different profiles of the same `Agent` object.

## 2. `WorkItem`

`WorkItem` is the unit of meaningful work identity.

A work item owns:

- title or objective statement
- plan and progress state
- acceptance or boundary notes
- blocked, active, or done status

A work item does not own:

- prompt context
- shell execution state
- waiting capability lifecycle

Its job is to anchor what the agent is trying to accomplish.

## 3. `Task`

`Task` is the unit of managed execution.

Its primary long-term use is:

- command-backed execution
- supervised execution inspection
- output retrieval
- stop and continuation control

A task does not own an independent reasoning context.

That is why delegated child work should not remain a task-shaped public
creation concept.

However, a task may still serve as a supervision handle for a child agent when
the runtime intentionally returns one.

## 4. `Waiting`

`Waiting` is the unit of blocked or resumable state.

It answers:

- what is this agent waiting on?
- which work item is blocked?
- what future condition should reactivate execution?

Waiting does not own prompt context and should not be treated as a task
substitute.

## Ownership Rules

The runtime should preserve these ownership boundaries strictly.

- only `Agent` owns context
- only `WorkItem` owns work identity
- only `Task` owns managed execution lifecycle
- only `Waiting` owns blocked or resumable state

These rules matter because they prevent several common sources of confusion:

- a shell command pretending to be a delegated agent
- a waiting record pretending to be a background task
- a work item pretending to be a runtime scheduler

## Agent Profile Model

Holon should use one `Agent` definition with profile-based variation.

In other words:

- child agent is not a separate runtime type
- long-lived private child is not a separate runtime type
- public named agent is not a separate runtime type

They are different combinations of agent profile fields.

The detailed first-pass profile contract now lives in:

- `agent-profile-model.md`

This control-plane RFC keeps the higher-level rule:

- the runtime should have one `Agent` object model
- public tools may expose a smaller set of stable spawn modes that map onto a
  richer internal agent profile

## Control Planes

The public control surface should be split into four planes.

## 1. Agent Plane

The agent plane owns context creation and agent lifecycle.

Its responsibilities are:

- create another execution context
- define parent-child relationships
- define public or private visibility
- define supervision and cleanup ownership
- define result routing and addressability

The central expansion primitive should be:

- `SpawnAgent`

This should be the only public way to create another reasoning context.

The central inspection primitive should be:

- `AgentGet`
  - Returns an `AgentGetResult` envelope carrying the current `AgentSummary`.

`AgentGet` should read agent-plane state for the context-owning agent:

- identity and visibility
- lifecycle / closure posture
- active work focus and waiting state
- visible child-agent lineage where policy allows

`AgentGet` is distinct from task-plane inspection. `TaskStatus` should inspect a
managed execution handle, while `AgentGet` should inspect the agent that owns
the broader context.

The agent plane also owns the current-run intervention surface.

`current_run_id` identifies the provider/tool turn currently executing inside
the agent. Operator abort is a control-plane mutation, not an enqueued message.
It should:

- cancel only the current provider/tool future;
- preserve the agent, work item, ledger, and workspace state;
- reject an optional stale `run_id` guard if the observed run has changed;
- record an aborted terminal turn with reason `operator_aborted`;
- record the dequeued message outcome as aborted rather than processed;
- pause the agent by default after the abort so it does not immediately repeat
  the same path.

For bounded parent-supervised delegation, `SpawnAgent` should always return the
new `agent_id` and return a task-plane handle when the parent keeps a
supervising execution record for that child.

Under this model:

- "start a new session" becomes root-agent creation
- "delegate bounded work" becomes child-agent creation

## 2. Work Plane

The work plane owns work identity and plan continuity.

Its responsibilities are:

- create and update work items
- mark active, blocked, or done work
- keep plan and boundary state attached to the right work item

The work plane should answer:

- what is the agent currently trying to achieve?
- what remains open?
- what is blocked versus active?

## 3. Task Plane

The task plane owns managed execution.

Its responsibilities are:

- start command execution
- inspect running execution
- accept later input for interactive execution
- read output
- stop execution
- later continue interactive execution

The task plane should narrow toward command-backed execution as its center of
gravity.

This means:

- `ExecCommand` is the startup primitive
- `TaskList`, `TaskStatus`, `TaskOutput`, `TaskStop`, and later `TaskInput`
  inspect and control managed execution state
- delegated child context creation should move out of task language

The task plane may still supervise other managed execution handles when they
share the same operational semantics.

The clearest non-command example is:

- a bounded child agent spawned through `SpawnAgent` and returned to the parent
  as a supervision handle

## 4. Waiting Plane

The waiting plane owns blocked work and future reactivation.

Its responsibilities are:

- create waiting intents
- represent timer-backed and callback-backed waiting
- cancel obsolete waits
- reactivate the right work when future conditions arrive

Waiting should usually be anchored to a work item, not left as detached
runtime residue.

## Lifecycle Axes

Holon should describe agent lifecycle through explicit orthogonal axes rather
than overloaded product nouns.

## Root versus child

- root agents are primary entry points
- child agents are spawned from another agent and preserve provenance

## Public versus private

- public agents may receive external ingress
- private agents only receive parent-directed work or runtime-controlled input

## Parent-supervised versus self-owned

- parent-supervised agents remain inside a parent-owned supervision contract
- self-owned agents expose their own operator-facing lifecycle surface

This distinction is separate from visibility in the general model, even though
the first-pass presets intentionally couple:

- `private_child` with parent supervision
- `public_named` with self-owned lifecycle

Restart behavior should follow supervision semantics, not a separate lifetime
label.

That means:

- a supervised child must remain restart-safe while its supervision handle is
  still live
- child cleanup should happen when the supervision contract reaches terminal
  state or the parent runtime explicitly cleans up the child
- daemon restart may interrupt execution, but it must not silently erase a live
  supervised child handle

## Fresh versus forked

- fresh agents start from explicit handoff only
- forked agents start from an inherited parent context view

This distinction should be modeled explicitly.

It is an execution-context derivation choice, not a separate runtime type.

These axes are more stable and more expressive than preserving `session`
versus `subagent` as parallel primary abstractions.

## Fork Context Derivation

`fork` should not mean "copy the parent's raw transcript."

It should mean:

- the runtime derives a bounded inherited context view
- the parent agent may provide explicit handoff
- the child starts from the combination of both

The default contract should be:

- `fork` = runtime-derived context + handoff
- `fresh` = no inherited parent conversation view + handoff

If a parent wants to fully redefine the child's starting context, it should use
`fresh` rather than trying to override `fork`.

### Runtime responsibility

The runtime should own the base derivation logic for `fork`.

This is important because the runtime has the structured state needed to make a
stable cut:

- active work item
- active work plan
- waiting and callback state
- recent turn memory
- durable working memory
- finalized episode memory

The runtime should therefore build the inherited child context from structured
runtime state first, not from naive transcript replay.

### Parent-agent responsibility

The parent agent should still participate, but through explicit handoff rather
than through full manual context reconstruction.

Handoff is where the parent expresses:

- what the child is being asked to do
- what constraints matter most
- what output form or return contract is expected
- which details deserve extra emphasis beyond the default inherited context

This gives the parent useful steering power without making `fork` semantics
unpredictable.

### Default fork anchor: active work item

When a parent has an active work item, `fork` should anchor inheritance on that
active work item by default.

This means the child should usually inherit:

- the full current snapshot of the active work item
- the full current snapshot of the active work plan
- waiting or callback state attached to that active work item
- the small hot-turn tail most relevant to that active work item
- finalized episode summaries associated with that active work item when needed

This does **not** mean the runtime should blindly copy every historical turn
tagged to that work item.

The default inherited view should remain a bounded projection centered on the
active work item, not a work-item-filtered transcript dump.

### Non-active work should stay out by default

History and state from non-active work items should normally stay out of the
forked child context.

They should only enter when one of the following is true:

- the handoff explicitly references them
- they contain constraints or decisions the child must obey
- they carry unresolved dependencies that still block the active work item
- they share the same delivery target or parent work chain in a way the runtime
  can identify structurally

This keeps delegated children focused and reduces contamination from unrelated
long-session history.

### Cache and stability implications

This rule also improves prompt stability.

The inherited fork prefix should be composed mostly of structured durable
projections that do not change every turn, while:

- hot tail remains small and volatile
- handoff remains explicit and task-shaped

That is better than rebuilding a large transcript-shaped blob on every fork,
and it leaves room for prompt-prefix cache reuse.

## Provenance Versus Supervision

Holon should not overload one `parent_agent_id` field with every possible
meaning.

There are at least two different relationships:

- provenance: which agent created or derived this one?
- supervision: which agent currently owns control, result routing, or cleanup?

These should be modeled separately.

Useful distinctions include:

- `lineage_parent_agent_id` for origin and audit
- `supervisor_agent_id` for current control responsibility

This matters most once an agent becomes long-lived or externally reachable.

A public named agent may still preserve lineage provenance, while no longer
remaining under strong parent supervision.

## Workspace Projection Model

Workspace or worktree isolation should not be modeled as a separate control
plane object.

It should be modeled as an execution projection property owned by the agent,
and consumed by execution started under that agent.

Useful projection modes include:

- `inherit`
- `worktree`
- `explicit_root`

This means:

- a worktree-isolated delegated run is a child agent with
  `workspace_mode=worktree`
- a task usually executes within its owning agent's workspace projection
- task tools should not become the long-term home for workspace-context
  creation semantics
- a task-created worktree is artifact state owned by the supervising task
  lifecycle
- a child agent may hold that worktree as its active execution projection while
  running, but the child agent should not be the artifact owner

This keeps workspace isolation explicit without creating another overlapping
kind such as "workspace task."

The historical `worktree_subagent_task` shape has converged into a unified
supervised `child_agent_task` handle with `workspace_mode=worktree` metadata.
Cleanup is driven by task cleanup or future artifact GC rather than by
model-facing workspace switching.

## Routing And Result Rules

Message and result routing must stay explicit.

### External ingress

Direct operator ingress should target a public self-owned agent unless an
explicit future policy says otherwise.

Private child agents should not receive direct operator ingress.

### Delegated child results

By default:

- private child agents report status and results to the parent
- child-local reasoning history stays local unless summarized back explicitly

Parent agents remain responsible for synthesis, prioritization, and final
user-facing reasoning.

Child results should be treated as bounded outputs or observations, not as a
transfer of overall understanding.

## Spawn Result Contract

`SpawnAgent` should always return the created `agent_id`.

In the first stable model, private child creation should also return
`task_handle`.

`SpawnAgent` should expose one caller-provided spawn text field:
`initial_message`. For `private_child`, `initial_message` is required, is
delivered as the child's first delegation message, and is the source for the
stable parent-visible task label. For `public_named`, `initial_message` is
optional bootstrap input and must not imply parent-supervised task provenance.
The spawn surface should not expose separate `summary`, `task_summary`,
`prompt`, or `work_item` fields.

The important rule is:

- `agent_id` identifies the context-owning runtime object
- `task_handle` is a structured `TaskHandle` execution receipt that identifies
  the parent's managed supervision handle

This keeps the control planes distinct:

- the agent plane creates and identifies the child context
- the task plane may supervise that child when the runtime chooses to expose a
  bounded handle

`TaskHandle` is shared by any operation that produces asynchronous execution
state:

```rust
pub struct TaskHandle {
    pub task_id: String,
    pub task_kind: String,
    pub status: TaskStatus,
    pub initial_output: Option<String>,
}
```

The handle is not an independently creatable control-plane object. It is an
execution receipt returned as a side effect of an operation verb such as
`SpawnAgent` or `ExecCommand`.

### When a task handle should exist

A `task_handle` is appropriate when the spawned child is:

- private
- bounded
- parent-supervised
- still part of the parent's managed lifecycle

This is the most natural shape for delegated work that still behaves like a
managed execution unit from the parent's perspective.

In the first-pass profile model, this is not just a common case. It is the
default rule:

- private spawned agents return `task_handle`

### When a task handle should not exist

A `task_handle` should normally be absent when the spawned agent is:

- public
- operator-addressable
- not under strong parent supervision
- intended to remain open as its own long-lived runtime object

In those cases, the runtime should return only `agent_id` and rely on
agent-plane addressing rather than a parent-scoped supervision handle.

In the first-pass profile model, this means:

- public named agents return `agent_id` without `task_handle`

### Task-handle capabilities for supervised children

When a child agent is returned with a `task_handle`, the parent should use the
task plane for bounded supervision:

- `TaskStatus` for handle-level lifecycle state using `task_handle.task_id`
- `TaskInput` for supervisor follow-up input
- `TaskOutput` for progress and result output
- `TaskStop` for cancellation or termination of the supervised execution

This should not replace future mailbox-style agent communication.

It only defines the bounded supervision path for parent-controlled child work.

### Relationship to `AgentGet`

`AgentGet` and task-handle inspection should answer different questions.

- `AgentGet` should inspect the agent as a context-owning runtime object
- `TaskStatus` should inspect the parent-visible supervision handle

For example:

- `AgentGet` may expose profile, visibility, work focus, and waiting state
- `TaskStatus` should stay focused on lifecycle and control metadata for the
  managed execution handle

This avoids collapsing agent identity and task supervision into one overloaded
detail surface.

### Long-lived child agents

If Holon later introduces long-lived named child agents, they should be treated
as addressable agents, not as upgraded tasks.

If such an agent becomes public or externally reachable, Holon should weaken or
remove strong parent-supervision semantics by default while preserving lineage
metadata.

## Default Child Boundary

The initial Holon model should optimize for bounded private child agents, not
for open-ended multi-agent collaboration.

The default bounded-child contract should therefore be:

- direct operator ingress is not allowed
- child-to-child direct messaging is not part of the initial model
- recursive child spawning is disabled by default
- shared persistent memory writes are disabled by default
- external side effects remain governed by runtime policy and profile
  capability boundaries

This keeps delegation useful without prematurely turning bounded child work
into a public team model.

## Bounded Children Versus Collaborative Agents

Holon should distinguish between:

- bounded child agents
- long-lived private child agents
- public collaborative agents

These should still be profiles of one `Agent` object, not different runtime
types.

The important distinction is not the noun. The important distinction is the
profile.

A useful first-phase mental model is:

- bounded private child: private, parent-only ingress, rejoin-parent
- long-lived private child: private, machine-only or parent-only ingress,
  restart-safe while supervised, still belongs to the parent's supervision tree
- public named agent: public ingress, self-owned lifecycle, lineage preserved
  for audit only

Holon does not need public collaborative agents to validate the core agent
plane model.

The first stable milestone should optimize for bounded private child agents,
with long-lived private children added only when delegated objectives
truly require them.

## Tool Surface Direction

The intended public direction is:

- agent plane: create and manage contexts
- work plane: express meaningful work identity
- task plane: manage command execution
- waiting plane: manage blocked and resumable state

This RFC therefore sets the parent model for these related RFCs:

- [Agent Delegation Tool Plane]./agent-delegation-tool-plane.md
- [Task Surface Narrowing]./task-surface-narrowing.md
- [Command Tool Family]./command-tool-family.md
- [Waiting Plane And Reactivation]./waiting-plane-and-reactivation.md

Those RFCs should stay narrower than this one.

They refine one plane each.

This RFC defines the shared object model and plane boundaries underneath them.

## Simplification Decision

Because Holon has not yet shipped a stable public API, the preferred direction
is direct simplification rather than compatibility layering.

That means the preferred direction is not:

- keep `session`, `subagent`, and workspace-task concepts as parallel primary
  nouns

It is:

- make `Agent` the primary runtime primitive
- treat root sessions as the product-facing form of root agents
- treat delegated subagents as child-agent lifecycle modes
- treat worktree isolation as a projection mode
- keep `Task` focused on managed execution

## Open Questions

The following questions remain open after this RFC:

- should Holon expose long-lived named child agents early, or keep the public
  agent plane bounded-only for longer?
- should worktree-isolated child creation become a parameter on `SpawnAgent`
  or a specialized convenience tool built on the same model?
- should long-lived private child agents be exposed early as an explicit spawn
  profile for workflows such as PR shepherding, CI follow-up, or webhook-driven
  continuation?
- how much waiting state should appear by default in prompt context versus
  on-demand inspection?
- should the product continue using the word `session` as a user-facing term
  even after the runtime fully migrates to `Agent`?

## Summary

Holon should adopt one top-level control-plane model:

- `Agent` owns context
- `WorkItem` owns work identity
- `Task` owns managed execution
- `Waiting` owns blocked and resumable state

From that model:

- delegation belongs to the agent plane
- command execution belongs to the task plane
- waiting belongs to the waiting plane
- workspace or worktree isolation is a projection property, not a separate
  runtime noun

This gives Holon a clearer foundation for context isolation, delegation,
worktree-backed execution, and future multi-agent growth.