A running task is adopted solely because its stable task ID is alive. If its
Agent Spec changes under that same ID, the catalog can describe generation g2
while the process is still executing g1. No machine-readable surface exposes
that disagreement.
This behavior is deterministic on current main.
Minimal reproduction
https://github.com/schickling-repros/2026-07-st2-dynamic-agent-spec-lifecycle
git clone https://github.com/schickling-repros/2026-07-st2-dynamic-agent-spec-lifecycle
cd 2026-07-st2-dynamic-agent-spec-lifecycle
./repro.sh
The second half:
- publishes a synthetic
worker whose command writes g1 and sleeps;
- runs one reconciliation pass and observes
g1;
- replaces
agent.kdl with the same identity/task ID but a command that writes
g2;
- runs another reconciliation pass.
The second pass reports:
and the running process still reports:
Before declaration update: running generation = g1
After declaration update: running generation = g1
Why this matters
Adoption is the right default for st2's nomadic control-plane contract: replacing
or restarting st2 up must not destroy a long-lived interactive session.
The missing distinction is between:
- adopting a task which realizes the current launch definition; and
- adopting an older task merely because its stable ID matches.
An external Agent Spec publisher cannot honestly report running or ready
after publishing new bytes. The same ambiguity affects hand-edited declarations:
command, cwd, environment, or rendered harness inputs may say one thing while
the live process remains on another.
Automatic restart on every KDL change would be worse: comments, metadata, and
non-launch-affecting changes should not destroy interactive work.
Expected
st2 should expose desired-versus-observed launch-definition identity. A live
task with an older effective launch definition should be observable as drift,
not silently indistinguishable from convergence.
Possible directions
A. st2-computed task generation (preferred long-term)
Compute a fingerprint over the lowered spawn-affecting task contract, persist it
in PTY/exec runtime metadata, and expose per-task desired/observed generations.
Values would include task kind/ID, command, cwd, effective environment, and
other spawn-affecting fields. Declaration-only comments or inert metadata would
not change the task generation.
Reconciliation remains nondestructive by default:
same task ID + same task generation -> adopt
same task ID + different task generation -> report drift
Replacement should be a later explicit operation, not an automatic consequence
of observation.
B. Publisher-authored opaque rollout revision
Allow an opaque declaration/task revision to be persisted and compared by st2.
This is smaller, but makes correctness depend on every renderer choosing the
right hash scope.
C. Exact declaration-byte digest only
Useful for CAS and audit, but insufficient by itself: comments and inert metadata
would appear to require a new process even though the spawn contract is
unchanged.
A machine-readable agent inspect/agents --json result should eventually
include the desired and observed identities plus an honest state such as
converged, drifted, or unknown.
Related
Version
- st2
0.1.0+a77776a
- source
a77776ac553af9b9b04149f2bc9f6c269a008b83
- Linux
Posted on behalf of @schickling
| field |
value |
agent_name |
co2-pine |
agent_session_id |
cdd15622-c01a-4731-bbfe-ab8cce0cad54 |
agent_tool |
Codex CLI |
agent_tool_version |
0.145.0 |
agent_runtime |
Codex CLI 0.145.0 |
agent_model |
unknown |
runtime_profile |
/nix/store/ph8rlhdj25mg71v81jsfzy6dq4xpcs9m-coding-agent-runtime-profile/share/coding-agents/profile.json |
skills_manifest |
/nix/store/lsykz8x5481xrpbgk280xh3pypk1c5jy-agent-skills-corpus/share/agent-skills/manifest.json |
worktree |
tmp |
machine |
dev3 |
tooling_profile |
dotfiles@3649b53 |
A running task is adopted solely because its stable task ID is alive. If its
Agent Spec changes under that same ID, the catalog can describe generation g2
while the process is still executing g1. No machine-readable surface exposes
that disagreement.
This behavior is deterministic on current main.
Minimal reproduction
https://github.com/schickling-repros/2026-07-st2-dynamic-agent-spec-lifecycle
git clone https://github.com/schickling-repros/2026-07-st2-dynamic-agent-spec-lifecycle cd 2026-07-st2-dynamic-agent-spec-lifecycle ./repro.shThe second half:
workerwhose command writesg1and sleeps;g1;agent.kdlwith the same identity/task ID but a command that writesg2;The second pass reports:
and the running process still reports:
Why this matters
Adoption is the right default for st2's nomadic control-plane contract: replacing
or restarting
st2 upmust not destroy a long-lived interactive session.The missing distinction is between:
An external Agent Spec publisher cannot honestly report
runningorreadyafter publishing new bytes. The same ambiguity affects hand-edited declarations:
command, cwd, environment, or rendered harness inputs may say one thing while
the live process remains on another.
Automatic restart on every KDL change would be worse: comments, metadata, and
non-launch-affecting changes should not destroy interactive work.
Expected
st2 should expose desired-versus-observed launch-definition identity. A live
task with an older effective launch definition should be observable as drift,
not silently indistinguishable from convergence.
Possible directions
A. st2-computed task generation (preferred long-term)
Compute a fingerprint over the lowered spawn-affecting task contract, persist it
in PTY/exec runtime metadata, and expose per-task desired/observed generations.
Values would include task kind/ID, command, cwd, effective environment, and
other spawn-affecting fields. Declaration-only comments or inert metadata would
not change the task generation.
Reconciliation remains nondestructive by default:
Replacement should be a later explicit operation, not an automatic consequence
of observation.
B. Publisher-authored opaque rollout revision
Allow an opaque declaration/task revision to be persisted and compared by st2.
This is smaller, but makes correctness depend on every renderer choosing the
right hash scope.
C. Exact declaration-byte digest only
Useful for CAS and audit, but insufficient by itself: comments and inert metadata
would appear to require a new process even though the spawn contract is
unchanged.
A machine-readable
agent inspect/agents --jsonresult should eventuallyinclude the desired and observed identities plus an honest state such as
converged,drifted, orunknown.Related
per-agent inspection surface would compose with that work.
Version
0.1.0+a77776aa77776ac553af9b9b04149f2bc9f6c269a008b83Posted on behalf of @schickling
agent_nameagent_session_idagent_toolagent_tool_versionagent_runtimeagent_modelruntime_profileskills_manifestworktreemachinetooling_profile