External renderers can produce complete canonical Agent Specs, but publishing
those bytes safely into a live catalog currently requires every renderer to
reimplement st2-specific validation, identity/path resolution, concurrency, and
watcher-safe filesystem ordering.
compile-agent does not close this gap: it is explicitly experimental,
harness-specific, and writes templates plus agent.kdl directly with
fs::write. It is a generator, not a transactional installation primitive.
The concrete use case is a policy-aware seat publisher:
bounded request
-> downstream authorization and persona/harness resolution
-> complete native Agent Spec
-> publish exact accepted bytes
-> st2 reconciles them normally
The final KDL—not the request or renderer—is the desired-state authority.
Scenario and current hazards
The accompanying minimal reproduction demonstrates two adjacent constraints:
https://github.com/schickling-repros/2026-07-st2-dynamic-agent-spec-lifecycle
- declaration inputs need a strict boundary, otherwise structured controller
resources can become phantom agents; and
- publishing new active bytes does not mean the running task realizes them.
The publisher additionally needs to prevent:
- two create-if-absent callers both claiming the same identity;
- a stale updater overwriting a newer declaration;
- malformed or duplicate-address candidates becoming visible;
- a crash exposing a partially written
agent.kdl; and
- a retry after an ambiguous timeout creating a second semantic generation.
These are policy-free catalog mechanics. Persona selection, grants,
delegatesTo, Nix integration, workspace authorization, and caller
authentication should remain downstream.
Proposed primitive
st2 agent publish \
--catalog <root> \
--spec <file-or-stdin> \
--host <host> \
--expect-absent | --expect-sha256 <digest> \
--json
Suggested contract:
-
Input bytes remain authoritative; parse and validate without reformatting.
-
Require exactly one top-level agent with explicit safe identity and host.
-
Derive the canonical target from content; the caller cannot choose an
arbitrary path.
-
Validate the candidate as a replacement overlay on the current catalog,
including duplicate bus/task IDs and render sources.
-
Under a host-local catalog/target lock, re-read current bytes and enforce
create-only or exact-digest CAS.
-
Write a hidden same-filesystem candidate, fsync, atomically rename it to
agent.kdl, then fsync the parent directory.
-
Retrying identical bytes is an idempotent unchanged.
-
Return stable JSON:
{
"status": "published",
"busId": "example-host.worker",
"beforeSha256": null,
"afterSha256": "...",
"path": "agents/example-host/worker/agent.kdl"
}
Publication means only that desired-state bytes committed. It must not claim
materialized, running, or ready.
Render inputs
The minimal v1 can require self-contained KDL or pre-published immutable,
content-addressed copy sources. Dependencies are installed first and
agent.kdl is the commit point.
A later --bundle convenience could install immutable inputs with
create-or-verify semantics before committing the declaration. Cross-filesystem
catalog/workspace ACID is neither required nor realistic; normal reconciliation
remains responsible for workspace materialization.
Concurrency boundary
CAS and the writer lock are host-local filesystem primitives, not distributed
consensus. Exactly one publisher must be authoritative for a given
<host>.<identity>. Remote catalog replicas may sync committed bytes afterward.
Non-goals
- no SeatIntent grammar in st2;
- no persona, harness, model, or permission flags;
- no automatic restart on a spec change;
- no claim that inert
managed-by metadata authenticates a caller;
- no distributed multi-writer consensus; and
- no promotion of
compile-agent into the policy renderer.
Related work
- #29: targeted per-agent
validation/materialization/reconciliation
- #40: desired-versus-observed
launch generation
- #39: canonical discovery
boundary for folder catalogs
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 |
External renderers can produce complete canonical Agent Specs, but publishing
those bytes safely into a live catalog currently requires every renderer to
reimplement st2-specific validation, identity/path resolution, concurrency, and
watcher-safe filesystem ordering.
compile-agentdoes not close this gap: it is explicitly experimental,harness-specific, and writes templates plus
agent.kdldirectly withfs::write. It is a generator, not a transactional installation primitive.The concrete use case is a policy-aware seat publisher:
The final KDL—not the request or renderer—is the desired-state authority.
Scenario and current hazards
The accompanying minimal reproduction demonstrates two adjacent constraints:
https://github.com/schickling-repros/2026-07-st2-dynamic-agent-spec-lifecycle
resources can become phantom agents; and
The publisher additionally needs to prevent:
agent.kdl; andThese are policy-free catalog mechanics. Persona selection, grants,
delegatesTo, Nix integration, workspace authorization, and callerauthentication should remain downstream.
Proposed primitive
Suggested contract:
Input bytes remain authoritative; parse and validate without reformatting.
Require exactly one top-level agent with explicit safe identity and host.
Derive the canonical target from content; the caller cannot choose an
arbitrary path.
Validate the candidate as a replacement overlay on the current catalog,
including duplicate bus/task IDs and render sources.
Under a host-local catalog/target lock, re-read current bytes and enforce
create-only or exact-digest CAS.
Write a hidden same-filesystem candidate,
fsync, atomically rename it toagent.kdl, thenfsyncthe parent directory.Retrying identical bytes is an idempotent
unchanged.Return stable JSON:
{ "status": "published", "busId": "example-host.worker", "beforeSha256": null, "afterSha256": "...", "path": "agents/example-host/worker/agent.kdl" }Publication means only that desired-state bytes committed. It must not claim
materialized,running, orready.Render inputs
The minimal v1 can require self-contained KDL or pre-published immutable,
content-addressed copy sources. Dependencies are installed first and
agent.kdlis the commit point.A later
--bundleconvenience could install immutable inputs withcreate-or-verify semantics before committing the declaration. Cross-filesystem
catalog/workspace ACID is neither required nor realistic; normal reconciliation
remains responsible for workspace materialization.
Concurrency boundary
CAS and the writer lock are host-local filesystem primitives, not distributed
consensus. Exactly one publisher must be authoritative for a given
<host>.<identity>. Remote catalog replicas may sync committed bytes afterward.Non-goals
managed-bymetadata authenticates a caller;compile-agentinto the policy renderer.Related work
validation/materialization/reconciliation
launch generation
boundary for folder catalogs
Version
0.1.0+a77776aa77776ac553af9b9b04149f2bc9f6c269a008b83Posted on behalf of @schickling
agent_nameagent_session_idagent_toolagent_tool_versionagent_runtimeagent_modelruntime_profileskills_manifestworktreemachinetooling_profile