Skip to content

Proposal: exact-byte CAS publication for canonical Agent Specs #41

Description

@schickling-assistant

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:

  1. Input bytes remain authoritative; parse and validate without reformatting.

  2. Require exactly one top-level agent with explicit safe identity and host.

  3. Derive the canonical target from content; the caller cannot choose an
    arbitrary path.

  4. Validate the candidate as a replacement overlay on the current catalog,
    including duplicate bus/task IDs and render sources.

  5. Under a host-local catalog/target lock, re-read current bytes and enforce
    create-only or exact-digest CAS.

  6. Write a hidden same-filesystem candidate, fsync, atomically rename it to
    agent.kdl, then fsync the parent directory.

  7. Retrying identical bytes is an idempotent unchanged.

  8. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions