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
|
# panto-subagents design
## Product shape
`panto-subagents` is a separate rock exposing one extension named
`subagents`. Its model-facing tools use the `subagents.*` namespace. It does
not shell out to `panto -p`; every child is an ordinary in-process
libpantograph `Agent` driven by pantograph.
The primary owns delegation. Children share its workspace, but not its
dialogue, and cannot call `subagents.*`. Recursive delegation, worktree
management, and merge orchestration are outside this design.
## v0 tools
### `subagents.run`
One tool call starts or resumes one conversational child:
```lua
-- Start a new child.
{
agent = "reviewer",
prompt = "Review the authentication changes.",
model = "anthropic:sonnet", -- optional; always provider:model
reasoning = "high", -- optional
}
-- Resume an existing child owned by this primary session.
{
id = "0198...",
prompt = "Now focus on the missing tests.",
model = "openai:gpt-5.6", -- optional per-turn change
reasoning = "xhigh", -- optional per-turn change
}
```
`prompt` must be non-empty. Exactly one of `agent` and `id` is required:
`agent` selects the profile for a new child; `id` identifies a persisted child
conversation. An ID cannot be resumed by a different primary session, and
only one turn may be active for an ID.
Once a valid new child has been allocated, every settled result includes its
ID:
```lua
{
id = "0198...",
agent = "reviewer",
status = "completed", -- completed, failed, or cancelled
output = "...", -- present on success
error = nil, -- present on failure
resumable = true,
}
```
Validation failures that happen before a child is allocated have no ID.
Under the existing filesystem-store flush discipline, a new child that fails
before producing its first assistant message has no durable file; such a
result reports `resumable = false` rather than promising continuation.
Parallel delegation uses ordinary model tool batching. The primary emits
several `subagents.run` calls in one batch; pantograph starts them concurrently
under one session-wide bound, initially four. A failure in one call does not
discard successful siblings. There is no second `tasks` array, task ID, or
extension-specific batch report format.
### `subagents.models`
The model catalog is too large to place in `subagents.run`'s description or
JSON schema. A small query tool exposes it on demand:
```lua
subagents.models {}
-- Current inherited model/reasoning plus configured provider names and counts.
subagents.models {
provider = "anthropic",
query = "sonnet",
limit = 10,
}
subagents.models { model = "anthropic:sonnet" }
subagents.models { agent = "reviewer" }
```
An exact model or agent lookup returns its effective model, default reasoning,
and the reasoning levels known to be valid for it. A search returns only the
requested bounded matches and says when more exist. The tool reuses
pantograph's model registry and provider-specific reasoning-option logic,
including effort choices reported dynamically by Lua protocols.
The `subagents.run` description tells the primary to omit overrides normally
and call `subagents.models` before choosing an unfamiliar model or reasoning
level. Runtime validation remains authoritative when catalog capability data
is incomplete.
## Agent profiles
Profiles are Markdown files with YAML frontmatter, compatible at the common
format boundary used by other agent harnesses:
```markdown
---
name: reviewer
description: Reviews changes for correctness and missing tests
model: anthropic:sonnet
reasoning: high
---
You are a focused code reviewer.
Report only concrete, evidence-backed findings.
```
They are discovered recursively from two layers, lowest precedence first:
1. `${XDG_CONFIG_HOME:-$HOME/.config}/panto/agents/**/*.md`
2. `<cwd>/.panto/agents/**/*.md`
The project definition shadows a user definition with the same resolved name.
`name` is optional and defaults to the extension-less filename.
`description` is included with the discovered names in `subagents.run`'s tool
description so the primary can choose a profile without loading its full
prompt.
The portable contract is `name`, `description`, and the Markdown body as the
profile's system prompt. Panto additionally recognizes `model` only in full
`provider:model` form and recognizes its existing reasoning labels. Unknown
frontmatter is ignored. A foreign model spelling that is not valid Panto
syntax is ignored with a warning so the prompt remains usable and inherits
the primary model.
For a new child, model and reasoning are resolved independently:
```text
model = tool.model ?? profile.model ?? primary.model
reasoning = tool.reasoning ?? profile.reasoning ?? primary.reasoning
```
Pantograph resolves the selected model against the configured provider and
model registries, applies the reasoning level, and fails before inference if
the known combination is invalid. The Lua extension never receives provider
credentials.
The resolved model reference and reasoning label are recorded on each child
turn. On continuation, omitted overrides keep the child's last effective
values; an explicit `model` or `reasoning` changes that value for the new turn
and for later continuations.
## Conversation construction
A new child receives a fresh `Conversation` containing:
1. the primary's effective system and project context;
2. a fixed child-role instruction;
3. the selected profile's Markdown body as a separate system message; and
4. the tool's `prompt` as its only initial user message.
The parent dialogue is not copied. The primary must put task-specific context
in the user prompt.
The profile system message carries opaque, non-model-visible message metadata
recording the immutable subagent manifest: its owning primary session ID and
profile name. Each user message carries the full model reference and reasoning
label effective for that turn. This avoids a mutable sidecar manifest: resume
reads identity from the first system message and defaults from the latest user
message. The existing filesystem-store load path must preserve per-message
metadata when rebuilding a `Conversation`.
The stored conversation is canonical on resume. Profile edits affect new
children, not an existing child ID.
Every child sees the parent's normal registered tools except `subagents.*`.
Tools still run through the shared extension runtime. Children share the
workspace, so concurrent writers can race or conflict; the primary must
delegate independent work.
## Durable child sessions
Subagent conversations are ordinary `FileSystemJSONLStore` sessions, not an
in-memory `id -> Conversation` map. The public subagent ID is the actual Panto
session UUID and the JSONL filename stem.
Each primary session owns a separate child catalog below its already-resolved
per-cwd session directory:
```text
<session-dir>/
├── <primary-session-id>.jsonl
└── subagents/
└── <primary-session-id>/
├── <subagent-id>.jsonl
└── <subagent-id>.jsonl
```
This layout automatically follows `PANTO_SESSION_DIR` and the normal XDG
fallback. The main store's `list` and `resolve` operations examine only direct
`.jsonl` children, so nested subagent files never appear in `panto sessions`
or the `/resume` picker.
The primary session ID is the ownership boundary. After panto restarts and
the user resumes a primary conversation, extension activation derives the
same child-catalog path from that primary ID. A referenced child ID therefore
resolves again. A different primary uses a different directory and cannot
resolve it. There is no global child lookup and no cross-primary continuation.
Starting and resuming use the ordinary session lifecycle:
```text
new:
session = child_store.create()
agent = Agent.init(session, no prior conversation)
seed system/profile messages
run prompt
resume:
session = child_store.resolve(id)
conversation = session.load()
agent = Agent.init(session, conversation)
run prompt
```
The Agent appends through its `Session` handle, and the filesystem store syncs
completed entries normally. The Agent may be destroyed after a turn; a later
turn reconstructs the conversation from JSONL. Only active job handles,
progress, and cancellation state remain in memory.
## Foreground progress and cancellation
Silent foreground waiting is not acceptable. Each child job has its ID and
profile before inference starts and emits tagged progress events to the TUI.
The user can see the child's assistant stream, tool calls, and tool results
while the primary model remains blocked on the tool call. Concurrent children
remain visually distinguishable.
These nested events are presentation data, not partial tool results: they are
not inserted into the primary model's conversation. `subagents.run` returns
only the settled result, while the full child conversation is persisted under
its ID for inspection and continuation.
Escape cancels every still-running child belonging to the current foreground
tool operation. Completed siblings remain successful. Cancellation targets
the child streams and the protocol streams those turns opened, then lets
every affected tool call settle coherently as `cancelled` rather than
abandoning the parent's batch.
## Generic pantograph child-job seam
libpantograph remains unaware of Lua, extensions, and subagents. Its `Agent`
and `SessionStore` abstractions already provide the conversation and
persistence machinery, and no subagent scheduler or tree policy lives
anywhere in Zig. The seam above it has three layers: a Lua binding
(libpanto-lua) that adds generic job, metadata, and tool-control primitives
usable by any embedder; a thin surface in pantograph itself (`panto.ext`) for
the few things that need the running process or its credentials; and this
rock, which is Lua policy written entirely on those two layers. Nothing
subagent-specific exists below the rock.
The binding's async job is the generic replacement for a hand-rolled worker
thread:
```lua
local job = agent:run_async {
prompt = "...", -- or blocks, mirroring agent:run
metadata = { ... }, -- optional user-message metadata, a JSON
-- object (array-shaped tables are refused)
dispatch_tools = false, -- optional, default true: false ends the
-- turn at the first assistant response
-- instead of dispatching its tool calls
wake_fd = fd, -- optional: one byte is written on every
-- event and on settle
}
job:next_event() -- -> event table | nil (non-blocking; owned copy)
job:result() -- -> settled result table | nil while running
job:request_cancel()
job:close() -- joins the pump and frees the settled result; a
-- caller must read and cache job:result() first
```
A pump thread owned by the job, not by the caller, drives the blocking turn
to completion, copies each event off the stream before the next pull frees
it, and buffers it under a mutex. The `wake_fd` contract is deliberately
loop-agnostic — a luv consumer arms `uv.new_poll(fd)`, any other reactor
selects on it — so no loop dependency reaches into the binding. Tool dispatch
inside the turn is unchanged libpantograph behavior: when the job's agent
carries tools registered through pantograph's Lua tool source (the primary's
own extension tools, copied over via `agent:set_tools`), `invoke_batch` posts
to the Lua owner thread through the same multiplexed executor a primary's
batch uses (below), bound to that job's agent as its lane. `dispatch_tools =
false` is the generic knob that makes a one-shot structured worker possible
without any host involvement: the settled result carries the assistant's
tool calls (id, name, and raw input JSON) unresolved, and no second model
round runs.
Two more binding primitives complete the generic surface. Message metadata —
`conv:message_metadata(i)` / `conv:set_message_metadata(i, tbl)`, plus an
optional `metadata` argument on `add_system_message`/`add_user_message` —
reads and writes the same JSON-object metadata the disk format already
round-trips, on owned and borrowed conversations alike; the rock uses it for
both the subagent manifest and the per-turn model/reasoning stamp, with no
separate sidecar record. Tool control — `agent:tools()` returns a mutable
copy of an agent's declarations, `agent:set_tools(decls)` replaces them, and
`agent:set_config` additionally accepts `tool_choice` to force a named tool —
lets the rock copy the primary's tools onto a child and drop `subagents.*`,
or hand a child exactly one synthetic, call-refusing declaration for a
one-shot worker's output tool. Dispatch is name-keyed on the shared runtime
tool source, so a copied declaration reaches the same handler regardless of
which agent it is registered on.
pantograph adds only what requires the running process or its credentials.
`panto.ext.resolve_model { model = "provider:alias", reasoning = label,
tool_choice = ... }` returns an **opaque config userdata** accepted by
`panto.agent { config = ... }` and `agent:set_config`; resolution reuses the
existing provider/model registries and reasoning pipeline, fails before
inference, and the userdata exposes only `model`/`reasoning`/`style`/
`wire_model` — credentials never reach Lua. This is the one piece of the seam
that could not be a binding API. It, `panto.ext.session_info()`, and
`panto.ext.models` all read from one feature-neutral, read-only session
record: the provider and model registries, the primary's already-credentialed
live provider config, the current model label, registered extension
protocols, and the session's id and directory. `panto.ext.on("turn_start" |
"turn_interrupt" | "turn_end", fn)` fires around every turn on the primary
session — interrupt before the pump parks on Escape or Ctrl+C, end on every
exit path with a reason — generic and observe-only; the rock is one
subscriber among any number that could exist, cancelling every live child job
on interrupt and closing them on end. `event:set_component(tbl)` returns a
handle (`h:invalidate()`, `h:alive()`) so a component that mutates after it is
set — a progress card gaining a line — can ask for a repaint instead of
rendering once and going stale.
Everything else — the concurrency gate and queue, child store layout and
directory creation on top of `SessionStore`, manifest and resume-default
extraction from message metadata, tool filtering, one-shot worker
construction, cancellation propagation, and progress rendering — is Lua
policy in the rock, built entirely on the primitives above. A different
extension could build an unrelated concurrent-job feature on exactly the same
seam.
## Shared Lua runtime executor
All agents in one primary session share its Lua state, activated extensions,
and libuv loop. Children do not create Lua states, reload rocks, or
reactivate extensions.
The runtime multiplexes tool batches rather than tracking one global
in-flight batch — the primary's and one per in-flight child agent can be live
at once, all executing on the single Lua owner thread:
1. Parent tool handlers start child jobs and yield.
2. Child workers drive ordinary libpantograph streams.
3. Built-in providers run directly on those workers.
4. A child Lua tool call is posted to a thread-safe runtime queue, waking the
shared loop through a pantograph-owned `uv_async_t`. A Lua protocol call
made on behalf of a child travels the same queue.
5. The runtime executes a tool callback as a coroutine on the sole Lua owner
thread, where async extension code may yield normally. A protocol callback
is posted the same way but runs to completion under `pcall` on that
thread: it cannot yield.
6. Completion returns to the waiting child worker, while unrelated batches
keep making progress.
Tool batches carry explicit identity, so result recording always addresses
the right batch rather than one global slot. Each batch is bound to the agent
that raised it, and `panto.ext.agent` resolves to that Agent while the
batch's coroutine runs. Protocol sources are not bound this way — one
registered protocol serves every agent in the session, and its streams keep
the turns apart. Module globals remain shared intentionally. A
child's tool declarations are exactly whatever its own `agent:set_tools` call
put there — there is no host-side filtered view to keep in sync.
## Extension-provided protocol concurrency
A registered protocol is process-wide, not per-child: the primary and every
child job reach it through the one `ProtocolSource` the session installed.
What keeps concurrent turns apart is the stream, not a per-job lane — each
`open` returns its own. This remains a pantograph implementation detail
rather than a libpantograph or workflow concept.
Each call to an extension-provided protocol's `open` creates an independently
managed stream, conceptually:
```lua
panto.ext.register_protocol {
name = "external-runtime",
open = function(request)
local transport = open_transport(request)
return {
next = function() return transport:next() end,
cancel_turn = function() transport:cancel_turn() end,
close = function() transport:close() end,
}
end,
close = function() -- runtime-wide teardown
end,
}
```
Mutable turn state belongs to the returned stream or its closure, never a
module-global "current session." Multiple streams from one registered
protocol may be open concurrently and interleave between calls. A protocol
body — `open`, or a stream's `next`, `cancel_turn`, or `close` — runs to
completion on the loop thread under `pcall`: it cannot yield, and it must not
block, because that thread is the one every other stream and tool batch needs
back. Awaiting belongs in tool handlers, which do run as coroutines and may
park on luv work; the shared pantograph scheduler remains the sole event-loop
owner.
Cancellation and compaction are scoped to the stream, not the registration.
Abandoning a turn calls that stream's own `cancel_turn`; a protocol that
defines none falls back to the registration-level `cancel_turn`, which is
process-wide by construction. A child compacting its own conversation does
not reset protocol sessions the primary and its siblings are streaming on;
only the session's own teardown runs a protocol's registration-level
`close`.
Every child turn, including a resumed child, receives a fresh protocol stream.
The loaded Panto JSONL conversation is canonical and is present in the open
request; extension protocols cannot depend on private transport history for
continuation. A protocol may serialize the structured messages directly. If
its transport only accepts a textual bootstrap, it can use the existing
generic un-summarized transcript serializer, taking care not to duplicate
system context supplied separately in the request.
## Lua workflow API
Workflows build on the same Agent jobs after v0. The canonical Lua API is
callback- and await-based so a workflow can branch and fan out from structured
child output:
```lua
return subagents.workflow(function(ctx, input)
local split = ctx:agent {
agent = "splitter",
prompt = input,
output = {
description = "Return the independent work items.",
schema = {
type = "object",
required = { "items" },
properties = {
items = {
type = "array",
items = { type = "string" },
},
},
},
},
}:await()
local jobs = {}
for _, item in ipairs(split.output.items) do
jobs[#jobs + 1] = ctx:agent {
agent = "worker",
prompt = "Process this item:\n" .. item,
}
end
local results = ctx:await(jobs, "all")
return results
end)
```
`ctx:agent` starts immediately and returns a job handle. `handle:await()`
waits for one. `ctx:await(handles, "all")` returns settled results in input
order. `ctx:await(handles, "first")` returns the first settled result and the
remaining handles. Child failures are result values so the callback can
decide whether to continue, retry differently, or return an error. All jobs
share pantograph's global concurrency bound.
When `output` is present, the child is a one-shot structured worker:
- it receives only one synthetic output tool;
- tool choice is forced to that tool;
- its first model response must call the tool exactly once;
- the tool input is validated against `output.schema`;
- no tool result is sent back and no second model round runs; and
- `result.output` is the decoded tool input, not parsed assistant prose.
One-shot structured workers are ephemeral and not resumable conversations.
They exist to make reliable reducers, classifiers, planners, and dynamic
fan-out inputs without inventing another structured-output protocol.
The module is available directly to human-authored Panto extensions, which
can register their own commands with `panto.ext.register_command`.
## Model-authored transient workflows
A later model-facing tool executes a transient Lua workflow without writing a
definition to disk:
```lua
subagents.lua {
prompt = "Review the changed subsystems.",
source = "...Lua returning subagents.workflow(function(ctx, input) ... end)...",
}
```
The source runs as a coroutine in Panto's existing Lua state, but under a
restricted `_ENV` containing the workflow API and safe standard libraries.
It cannot access `os`, `io`, `debug`, `package`, `require`, raw Panto runtime
objects, or extension globals. An instruction budget between yields and a
bounded number of jobs prevent generated Lua from wedging the owner thread or
creating unbounded inference work. Human-authored extensions are trusted Lua
and use the module directly without this restricted environment.
No separate workflow-authoring skill ships initially. The tool schema and
description are sufficient until actual traces show that longer guidance is
needed.
## TOML workflows and slash commands
Persistent TOML workflows are the smaller, fully pre-specified DAG surface.
They are discovered recursively from:
1. `${XDG_CONFIG_HOME:-$HOME/.config}/panto/workflows/**/*.toml`
2. `<cwd>/.panto/workflows/**/*.toml`
Project workflows shadow user workflows by resolved name. A workflow may
define independent roots, fixed dependencies, and per-step call overrides:
```toml
name = "review-chain"
description = "Inspect a change from two angles, then synthesize."
[[steps]]
id = "correctness"
agent = "reviewer"
prompt = "Review for correctness and regressions."
[[steps]]
id = "tests"
agent = "reviewer"
prompt = "Review test coverage and validation gaps."
reasoning = "high"
[[steps]]
id = "synthesis"
agent = "reviewer"
prompt = "Synthesize the findings and remove duplicates."
needs = ["correctness", "tests"]
```
The parser validates duplicate IDs, unknown dependencies, and cycles before
starting work, then lowers the definition onto the same Lua job/await
primitives. Every step receives the original workflow input. A dependent also
receives its dependencies' outputs, clearly labeled and ordered by `needs`.
All ready steps start concurrently. A failed node skips its dependents while
unrelated branches finish. Terminal-node results and failures are returned in
declaration order.
Every discovered workflow registers `/workflow:<name>`. The command tail—the
equivalent of `$ARGUMENTS` in prompt commands—becomes the user prompt supplied
to the DAG's head nodes. Human-authored Lua workflows register any desired
slash command themselves.
The model-facing `subagents.workflow` tool runs either a discovered workflow
by name or a transient static step definition. Output-dependent branches and
dynamic fan-out remain Lua features; TOML does not grow into a programming
language.
## Deferred model-facing background control
Foreground tool batching and workflow-internal awaits cover the initial
parallelism requirements. Background control can be added without changing
the job model:
```lua
subagents.run {
agent = "researcher",
prompt = "Investigate this in the background.",
await = false,
}
-- { id = "0198...", status = "running" }
subagents.await {
ids = { "0198...", "0199..." },
mode = "first", -- or "all"
}
```
`first` means the first settled result, successful or not; `all` waits for
every named child. IDs are explicit so a primary never waits on unrelated
work. Results are not consumed by awaiting them. Adding this surface also
requires background result retention, targeted cancellation/status, and TUI
lifecycle behavior, so it is not part of v0.
## Validation
Pantograph checks must prove:
- independent child Agents make concurrent progress under the global bound;
- Lua tool batches from multiple children cannot corrupt results or enter the
Lua state concurrently;
- built-in and Lua protocol children can run together;
- lane-local `panto.ext.agent` resolves to the correct child;
- progress events remain tagged to the correct child;
- cancellation settles every affected stream and tool batch coherently;
- one failed child does not cancel successful siblings; and
- child tool declarations omit `subagents.*` while shared extension
activation happens exactly once.
Session checks must prove:
- successful child turns persist as normal JSONL sessions;
- the child ID is the persisted session ID;
- restarting and resuming a primary can continue its referenced child;
- another primary cannot resolve that ID;
- nested child files never appear in the primary session picker or listing;
- the subagent manifest and full conversation round-trip through persistence;
and
- incomplete first turns do not falsely report durable resumability.
Extension checks must cover profile discovery and shadowing, portable
frontmatter parsing, independent model/reasoning precedence, catalog query
bounding, new-versus-resume validation, and tool-batch concurrency.
Workflow checks, when those phases land, must cover callback awaiting,
structured-tool validation, output-driven fan-out, DAG validation, dependency
prompt assembly, branch-local failure, deterministic terminal ordering, and
generated slash-command registration.
Extension-protocol checks must run multiple mocked streams concurrently and
prove that startup, events, tool calls, cancellation, transcript bootstrap,
and closure stay scoped to the stream that opened them — including that
cancelling one turn leaves its siblings' streams untouched.
## Delivery order
1. Add generic concurrent Agent jobs, global bounding, multiplexed Lua
dispatch, per-stream protocol concurrency, nested progress, and foreground
cancellation.
2. Add layered Markdown profiles, model/reasoning resolution, bounded catalog
queries, durable tree-scoped child stores, continuation, and
`subagents.run`/`subagents.models`.
3. Add canonical-conversation bootstrap support for extension protocols whose
transports start without history.
4. Add the callback-based Lua workflow API and one-shot structured workers.
5. Add the restricted model-authored Lua workflow tool.
6. Add TOML DAG loading, `subagents.workflow`, and generated
`/workflow:<name>` commands.
7. Add model-facing background start/await/status/cancellation only when the
foreground behavior is proven.
## Not in v0
- cross-primary subagent lookup or continuation;
- recursive subagents;
- background jobs or model-facing await/status tools;
- worktree creation, merge orchestration, or write-conflict protection;
- durable workflow-run state or artifact management;
- agent/profile CRUD tools;
- a workflow-authoring skill; or
- Lua/TOML condition syntax beyond the callback and fixed-DAG surfaces above.
|