Skip to content

feat(agentd): change an agent's instructions and skills in place - #366

Open
elsand wants to merge 2 commits into
mainfrom
feat/mutable-skills
Open

elsand wants to merge 2 commits into
mainfrom
feat/mutable-skills

Conversation

@elsand

@elsand elsand commented Oct 29, 2026 •

Copy link
Copy Markdown

Summary

Applying a manifest that adds, removes or renames instruction files or skills now updates the Agent in place. Until now agentd refused it as an immutable change, so the only way through was to create the Agent again, which deletes its disk. That is the change an agent most often makes when it improves its own definition.

agentd already rewrote instructions and skills on every pass. What kept them immutable was that it could not take back what it had placed:

  • Skills. A dropped skill stayed in the harness's skill folder. agentd now records the skills it placed in status.sandbox.skills, beside the harnesses convergence installed, and a later pass removes those the Agent no longer declares. Skills the image ships are not in the record, so they stay. The record belongs to the sandbox it was made in, so a new sandbox starts with only its image's skills.
  • Instructions. Once an Agent had no instructions of its own, the ones placed earlier were read back as the image's or the home overlay's, and kept. A marker now opens the Agent's own instructions below the Agent sandbox section, so a later pass knows the rest of the file is agentd's to replace. This one stays in the file rather than in status: the home overlay may restore the file between passes, so only the file can say whose text it holds.

Evidence

  • platform_linux::linux_setup_removes_the_skills_and_instructions_an_agent_no_longer_declares runs setup, then renames one skill and drops another and every instruction file. It checks that the dropped and renamed skills are removed, that the image's skill stays, that the instruction file keeps only the sandbox section, and that a record made for another sandbox removes nothing.
  • control_plane::the_skills_setup_placed_are_recorded_in_the_agents_status checks that the reconciler stores what setup placed with the sandbox.
  • control_plane::repeated_apply_is_idempotent_and_immutable_fields_are_rejected now applies an added instruction file and skill as a mutable change.

Risk

  • A pass that fails inside platform setup keeps the record of the last pass that succeeded. A skill that failed pass placed, and that the Agent drops before a pass succeeds, stays until removed by hand.
  • An Agent created before this change has no record and no marker yet. Skills it dropped before then stay until removed by hand. If the first pass after the upgrade also drops all of its own instructions, the old ones are kept once, as before. Every later pass behaves as described.

🤖 Generated with Claude Code

Adding, removing or renaming an instruction file or skill no longer takes
creating the agent again, which deleted its disk. agentd already rewrote both on
every pass. What it could not do was take back what it had placed: a dropped
skill stayed in the harness's skill folder, and once an agent had no
instructions of its own, the ones placed before read as the image's.

agentd now records, in each skill folder, the skills it placed there, and
removes those no longer declared, leaving the image's skills alone. A marker
ahead of the agent's own instructions tells a later pass the rest of the file
is agentd's to replace.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@elsand
elsand requested a review from martinothamar as a code owner October 29, 2026 18:38
@coderabbitai

coderabbitai Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: e41beef7-b327-4234-8a32-054762d6245c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@martinothamar

Copy link
Copy Markdown
Collaborator

Yeah this makes a ton of sense 👍 I essentially went with immutability by default to just keep the complexity down initially.

Wondering about the statekeeping here though, should we consider putting it in status_json column in the db instead? Something like this:

status:
  sandbox:
    harnesses: [claude]
    skills: [...] # bookkeeping matching manifest desired state to persisted/reconciled state

I guess harnesses would be the prior art to align with. Most of the "control theory" stuff in the agent layer is really inspired from k8s where stuff like this is typically kept in status. One example is flux Kustomization keeping its inventory of child manifests.

The record of which skills setup placed in the harnesses' skill folders moves
from a file in the sandbox to status.sandbox.skills, beside the harnesses
convergence installed. agentd owns its status, so the agent can no longer
write names into the record that a later pass removes. The record belongs to
the sandbox it was made in, so a new sandbox starts with only its image's
skills.

The marker ahead of the agent's own instructions stays in the instruction
file: the home overlay may restore that file between passes, so only the file
can say whose text it holds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@bdl-agent

Copy link
Copy Markdown

Wondering about the statekeeping here though, should we consider putting it in status_json column in the db instead? Something like this:

Good call, done in e0fa8df. The skills setup placed now live in status.sandbox.skills, next to harnesses, scoped to the sandbox they were placed in. That also means the sandbox user can no longer write into the record. The instructions marker stays in the file, since the home overlay may restore that file between passes, and only the file can tell whose text it holds.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants