Problem
An agent graph currently has the same lifetime as its root Session:
agentGraphIdForRootSession(rootSessionId) deterministically maps one root Session to one graph ID.
- A
finish schedule update permanently closes that graph.
- Later schedule updates for the same root Session fail with
Agent graph schedule is already finished.
- There is no normal graph epoch/generation or "begin next graph" path.
This makes sense if a root Session represents one workflow execution, but Maka Sessions are long-lived conversations. A common flow is:
- Ask the supervisor to use swarm for a research task.
- The supervisor finishes the graph and selects its final result records.
- Continue the same conversation with a follow-up question.
- Ask for another swarm pass.
Step 4 cannot schedule new work because the root Session still resolves to the already-finished graph. We reproduced this in a normal conversation: after completing and finishing a six-item architecture-reading swarm, a follow-up add_work failed because the graph schedule was closed.
Relevant implementation points:
packages/runtime/src/stream-graph-coordinator.ts: agentGraphIdForRootSession() hashes only rootSessionId.
packages/storage/src/sqlite-session-metadata-store.ts: commitAgentGraphScheduleUpdate() rejects every update after hasClosedAgentGraphSchedule(graphId).
packages/runtime/src/stream-graph-supervisor-tools.ts: schedule projection rejects updates after finish.
The last two invariants are valuable: finish should remain a durable, irreversible admission boundary. The questionable part is binding that one graph's lifetime to the entire conversational Session.
There is a related data-continuity issue. A new graph should be able to consume immutable results published by a finished graph without reopening or mutating the old graph. Otherwise follow-up work must copy large outputs back into prompts, rely on lossy supervisor summaries, or repeat completed work.
Desired outcome
A root Session can run multiple sequential graph epochs while preserving the meaning of finish for each individual graph.
For example:
Root Session
|- Graph epoch 1 (finished)
|- Graph epoch 2 (finished)
`- Graph epoch 3 (active)
Desired semantics:
finish permanently closes the current graph epoch; it does not reopen later.
- A later supervisor turn can atomically create or bind a new graph epoch for the same root Session.
- Only one graph epoch is active for a root Session at a time, unless explicit parallel-root semantics are introduced later.
- Historical graphs remain readable and retain their selected final results.
- A new graph may explicitly consume committed outputs from an older graph.
- Cross-graph data references do not grant cross-graph control: the new graph cannot stop old activations, continue old claims, mutate old schedules, or implicitly reuse old operators.
One possible model is an explicit root-to-graph binding with an epoch:
graph_id = hash(rootSessionId, graphEpoch)
agent_graph_roots(
graph_id,
root_session_id,
epoch,
status,
created_at,
finished_at
)
Coordinator APIs would resolve the active graph rather than deriving a single permanent graph ID from the root Session. If no active graph exists, a new epoch could be created atomically, either automatically on the next graph operation or through an explicit begin_agent_graph operation.
For cross-graph inputs, a typed reference would make provenance and authorization clearer than a bare string:
type GraphInputRef =
| { kind: 'graph_result'; graphId: string; resultId: string }
| { kind: 'graph_record'; graphId: string; recordId: string }
| { kind: 'artifact'; artifactId: string; fingerprint: string };
At minimum, cross-graph inputs should be:
- immutable and committed;
- authorized for the current root Session/workspace;
- pinned against garbage collection while referenced;
- recorded as explicit lineage;
- resolved to a stable source identity/fingerprint at admission time.
It may be preferable to expose only results selected by the old graph's finish.resultIds as its public cross-graph interface, rather than allowing arbitrary internal records by default.
Most existing storage structures are already keyed by graph_id, so this appears primarily to require a lifecycle/binding change in the coordinator and recovery paths rather than a redesign of schedule, claim, wake, or projection semantics.
Alternatives or workarounds
- Start a new root Session for every swarm. This loses conversational continuity and makes follow-up research awkward.
- Never call
finish. This weakens the graph's terminal/admission invariant and leaves lifecycle management ambiguous.
- Reopen a finished graph. This would invalidate the current meaning of
finish, complicate wake recovery, and allow schedule revisions after a declared terminal boundary.
- Copy old outputs into the next prompt. This is expensive, lossy, and loses durable provenance.
- Reset/delete graph operational state. This is destructive and is not a normal lifecycle operation.
The proposed direction is therefore new graph epochs with immutable cross-epoch result references, not reopening an old graph.
Problem
An agent graph currently has the same lifetime as its root Session:
agentGraphIdForRootSession(rootSessionId)deterministically maps one root Session to one graph ID.finishschedule update permanently closes that graph.Agent graph schedule is already finished.This makes sense if a root Session represents one workflow execution, but Maka Sessions are long-lived conversations. A common flow is:
Step 4 cannot schedule new work because the root Session still resolves to the already-finished graph. We reproduced this in a normal conversation: after completing and finishing a six-item architecture-reading swarm, a follow-up
add_workfailed because the graph schedule was closed.Relevant implementation points:
packages/runtime/src/stream-graph-coordinator.ts:agentGraphIdForRootSession()hashes onlyrootSessionId.packages/storage/src/sqlite-session-metadata-store.ts:commitAgentGraphScheduleUpdate()rejects every update afterhasClosedAgentGraphSchedule(graphId).packages/runtime/src/stream-graph-supervisor-tools.ts: schedule projection rejects updates afterfinish.The last two invariants are valuable:
finishshould remain a durable, irreversible admission boundary. The questionable part is binding that one graph's lifetime to the entire conversational Session.There is a related data-continuity issue. A new graph should be able to consume immutable results published by a finished graph without reopening or mutating the old graph. Otherwise follow-up work must copy large outputs back into prompts, rely on lossy supervisor summaries, or repeat completed work.
Desired outcome
A root Session can run multiple sequential graph epochs while preserving the meaning of
finishfor each individual graph.For example:
Desired semantics:
finishpermanently closes the current graph epoch; it does not reopen later.One possible model is an explicit root-to-graph binding with an epoch:
Coordinator APIs would resolve the active graph rather than deriving a single permanent graph ID from the root Session. If no active graph exists, a new epoch could be created atomically, either automatically on the next graph operation or through an explicit
begin_agent_graphoperation.For cross-graph inputs, a typed reference would make provenance and authorization clearer than a bare string:
At minimum, cross-graph inputs should be:
It may be preferable to expose only results selected by the old graph's
finish.resultIdsas its public cross-graph interface, rather than allowing arbitrary internal records by default.Most existing storage structures are already keyed by
graph_id, so this appears primarily to require a lifecycle/binding change in the coordinator and recovery paths rather than a redesign of schedule, claim, wake, or projection semantics.Alternatives or workarounds
finish. This weakens the graph's terminal/admission invariant and leaves lifecycle management ambiguous.finish, complicate wake recovery, and allow schedule revisions after a declared terminal boundary.The proposed direction is therefore new graph epochs with immutable cross-epoch result references, not reopening an old graph.