Skip to content

Releases: tesserine/agentd

v0.1.1

23 Apr 05:21
22fe623

Choose a tag to compare

Daemon that runs autonomous AI agent sessions in ephemeral Podman containers.

This release introduces per-invocation work input, aligns with the shared commons exit-code convention, and tightens container isolation.

Added

  • Per-invocation work input. agentd run accepts one of three mutually-exclusive work surfaces without profile edits: --work-unit <id>, --request <text>, or --artifact-type <type> --artifact-file <path>. Request text is synthesized into .runa/workspace/request/operator-input.json; artifact-file input places validated JSON at .runa/workspace/<type>/<file-stem>.json. The runner enforces mutual exclusion and validates path components at the trust boundary regardless of caller.
  • Canonical request convention. --request depends on the configured methodology declaring support for the commons canonical request artifact type with a supported version (1.0.0 in v0.1.x). Unsupported or undeclared methodologies reject text input with an actionable error instead of silently materializing unchecked content.
  • Explicit audit_root in runner API. agentd_runner::SessionSpec requires an explicit audit_root field.

Changed

  • Shared exit-code convention. Session outcomes across agentd and agentd-runner carry semantic labels plus raw exit codes. Daemon and CLI surfaces report labels such as blocked and generic_failure. agentd run exits successfully for normal terminal states (success, blocked, nothing_ready). Timeout remains an agentd-layer outcome outside the shared exit-code vocabulary.
  • Linux-only platform contract. agentd-runner declares its platform contract at compile time. Non-Linux builds now fail explicitly instead of compiling dead fallback code.
  • Bind mount reservation scoping. Additional bind mounts reserve only runner-owned targets (/agentd/methodology, /home/{profile}, /home/{profile}/repo plus descendants), allowing supported read-only and read-write mounts elsewhere under $HOME without runner setup mutating host-backed data.
  • Profile bind-mount overlap detection. Profile-declared bind mounts reject overlapping container targets within the same profile before container startup.
  • Audit record defaults. Persistent audit records default to $XDG_STATE_HOME/tesserine/audit/<profile>/<session_id>/, falling back to $HOME/.local/state/tesserine/audit/<profile>/<session_id>/ for rootless installs. daemon.audit_root is available as an explicit override for root-owned system installs.
  • Audit sealing discipline. Completed audit records seal directories to 0555 and non-symlink entries to 0444, skip symlinks while sealing, and update agentd/session.json through atomic temp-file replacement.

Fixed

  • Session teardown skips audit finalization and sealing when cleanup fails, leaving agentd/session.json intentionally incomplete instead of marking a session complete while its audit bind mount may still be live.
  • Completed session outcomes remain caller-visible when only audit finalization fails after teardown cleanup succeeds.
  • Audit sealing refuses multi-linked entries before rewriting metadata, preventing host file mode changes through hard-linked audit aliases.
  • Allocation rollback failure preserves the incomplete audit-record signal instead of finalizing agentd/session.json after leaked cleanup state.

Dependencies

Requires runa v0.1.1 or later (uses the new .runa/workspace/ invariant) and commons v0.1.1 or later (uses the canonical request artifact spec).

Late additions (April 22, 2026 evening)

After the initial v0.1.1 work was tagged, integration testing surfaced a foundational gap that became #84: agentd run (the client subcommand) was reading the daemon's config file to find the socket path, coupling client and daemon to a shared file in a way that produced footguns at deployment. PR #85 decoupled the client from the daemon config:

  • agentd run now finds the daemon via well-known socket-path convention or explicit --socket-path override; never reads daemon config.
  • Default socket discovery walks $XDG_RUNTIME_DIR/agentd/agentd.sock/tmp/agentd-$UID/agentd.sock/run/agentd/agentd.sock, with each candidate verified by Ping/Pong handshake before being selected.
  • Default /tmp/agentd-$UID/ directory creation is now atomic via mkdir(2) with mode 0700, eliminating a TOCTOU race against symlink substitution.
  • Profile resolution moved entirely to the daemon side; client sends profile name and lets the daemon resolve repo defaults.
  • Bare agentd --config /path/to/agentd.toml still works as a daemon-mode shorthand for agentd daemon --config /path/to/agentd.toml.

This work was foundational enough to gate v0.1.1's tag on its completion; the tag now points at the post-#84 merge commit.

v0.1.0

11 Apr 15:05
5f6ad95

Choose a tag to compare

Daemon that runs autonomous AI agent sessions in ephemeral Podman containers.

Key capabilities:

  • Foreground daemon with single-instance enforcement via PID file
  • Unix socket operator interface for manual and scheduled session dispatch
  • Profile-based configuration: base image, methodology mount, credentials, session command
  • Ephemeral Podman containers with unprivileged execution, credential injection via secrets, and force-removal on teardown
  • Startup reconciliation of stale resources from prior runs
  • Cron-based profile scheduling through the daemon socket
  • Structured JSON logging with tracing
  • Two-signal shutdown: first SIGTERM drains, second force-exits