OXYGENHUB
◆ switch-says oxygen / docs / ai_native_agent_workflows.md
11.8 KiB · Markdown · last changed Who did the work: via AGENT in log and show, delegates by name 1 month ago renderedsource blame history raw

Oxygen (oxy): AI-Native Agent Workflows Specification

StatusDraft 1.1
Date2026-10-03
AudienceImplementers and AI tooling developers
Depends onspec.md §6 (changes), §9 (conflicts), §12 (operation log, workspaces), §14 (identity, policy), revsets (revset_query_language.md)

1. Overview and philosophy

Coding agents, such as Aider or Claude Code, or local LLM loops, commit at machine speed. A version control system must let them work without giving them the keys to the kingdom, and without burying the human's history in micro-changes.

The guiding principle is delegated, bounded, reversible autonomy:

  • Delegated: an agent acts under its human owner's identity, with its own key, so every change it makes is attributable to both.
  • Bounded: an agent can record changes but cannot move protected bookmarks, approve, or seal, whatever its owner may do.
  • Reversible: an agent works in its own workspace and bookmark, so discarding its session never touches the human's work.

None of this weakens what Oxygen already guarantees. The change graph is immutable, every change is signed with Ed25519 and ML-DSA-65, policy is verified on fetch and push, and the operation log records everything.

Each section says what exists today and what is new.

2. Agent identity and delegation

Exists (§14.2): an identity object has delegates [8]: [KeyId]. These are keys allowed to sign or seal changes whose author is that identity. Delegation is one level deep and not transitive, and oxy identity delegate add|remove manages it. Any change to an identity is a rotation: a successor object.

  • The agent's own key pair. An agent generates its own Ed25519 and ML-DSA-65 key pair locally. Its identity object's name says what it is, for example "aider 0.x on andy-laptop". An agent never holds the human's secret keys.
  • Authorship. Changes the agent records set author to the human's KeyId and are signed with the agent's key. The signature's KeyId identifies the agent. No marker is stored in the change: extra [9] is reserved and must stay empty, and the signature already proves which agent made the change, which a marker could not. In practice (implemented 2026-10-04): the agent's keys live in its own $OXY_HOME, and its user config (or $OXY_SIGNER) sets author.signer to its KeyId; the checkout's author.key stays the human's, so oxy commit run by the agent carries the human as author and the agent's signature, and oxy log -r 'delegated()' lists what the agent did.

Scoped delegation (§14.2, implemented 2026-10-04). Before it, a delegate moved references as far as its delegator may (§14.5). That is right for a hub signing browser edits, and wrong for an agent. delegates is a list of entries:

delegates [8]: [{ key [0]: KeyId, scope [1]: ["changes" | "refs" | "seal"], expires [2]: u64? }]
  • An agent is added with --scope changes. Its signature authenticates changes, but a reference or tag attestation, or a seal, signed by it is refused. An agent can never land on a protected bookmark, even when its owner could.
  • A per-delegate expires limits an agent to a session or a day (--expires 8h), without rotating the human's own expiry.
  • Hosts that sign for users keep the current behaviour with --scope changes,refs.
  • A bare KeyId in an older identity means every scope.

Revocation by the delegator (implemented 2026-10-04). Before it, only the revoked key itself or a policy root key could sign revoke. An agent's key may be lost on a compromised machine, and the policy root is often someone else, so the identity that delegated a key may also revoke it. Removing a delegate in a successor identity stops future use. Revoking it also marks the changes the agent already signed as valid but revoked in oxy verify and on the hub, so they get a second look.

3. Isolation: one workspace and bookmark per session

Exists: oxy workspace add creates an extra checkout that shares the repository, each with its own current bookmark.

New: oxy agent start NAME does three things:

  1. creates a workspace under .oxy/agents/NAME/;
  2. creates the bookmark agents/NAME/<session> from the human's current heads;
  3. records a session operation carrying the agent's KeyId.

The agent works only there. This replaces a session marker in the human's operation log:

  • The human's working copy is never touched. Changes commute, so the human keeps working on the same files at the same time, and merging the agent's bookmark later is an ordinary oxy merge.
  • Discarding a session is oxy agent drop NAME: delete the bookmark and the workspace. Nothing the human did is undone, unlike an undo in a shared workspace would.
  • Undo within a session is the agent's own operation log (§12), scoped to its workspace. The new oxy undo --to OP returns to any earlier operation of that workspace.

4. Micro-changes: keep them, show them folded

Agents produce many small changes. Oxygen keeps them, because each is signed, cheap, and commutes with everything that does not touch the same lines. The noise is a display problem first.

  • New, display folding: oxy log shows a run of consecutive changes signed by the same agent key as one line: "aider: 37 changes, 4 files". --expand shows them all. The hub does the same.
  • New, adoption: when the human wants one change in history, oxy fold -r REVSET folds the selected changes into one new change. It uses the revset language, for example oxy fold -r 'signed_by(aider) & main..agents/aider/s1'. The folded change is authored and signed by the human's own key. It records the folded changes' hashes in its description footer, so the trail to the agent's work stays verifiable while those changes remain stored. The existing oxy squash folds one change into a dependency and stays as it is.
  • Folding is optional. Unfolded agent changes stay valid history. Folding is for when a team's convention wants one reviewed change.

5. Conflicts as data, for agents

Exists: conflicts are recorded in states, not raised as errors (§9). A conflicted state can be committed and built on, and oxy resolve reports which conflicts the current files resolve.

  • Reading conflicts: oxy status --json lists each conflict: path, node, kind (order, name or tree), and the contributing ChangeIds. oxy cat PATH --at CHANGE gives each side's text for the agent's context.
  • Resolving: the agent writes the resolved files and runs oxy commit. Oxy computes the resolution's dependencies: a resolution must depend on every change that contributed an atom to the conflict. An agent never writes deps by hand. Correctness of the graph is Oxygen's job, not the model's.
  • A valid resolution is not necessarily a right one. The graph will be well-formed; the code may still be wrong. A policy rule for protected bookmarks can require that a resolution signed by an agent has a passing Flow receipt and a human approval before it lands.

6. Review and policy on the hub

  • Badges (implemented 2026-10-04): a change signed by a delegate shows its author and, beside it, via NAME with an agent badge: in history rows on the hub, as a via row under the author on the change page (↳ Antigravity <…> · delegate for changes, until … · key …), under the author in Contributors ("via Antigravity 3"), as via in the API's change summaries, and the same in oxy log (via NAME) and oxy show (the via row). The author stays the human; the agent is the instrument, and a revoked or withdrawn delegation turns the badge red. The hub also links a rotated identity to its owner's account by itself when a push brings it, so delegating never breaks attribution.
  • Approvals: approvals count only signatures by keys that are not agent-scoped delegates, so an agent cannot approve its own work or anyone else's.
  • Policy: a policy rule may name agent rules, for example "agents may push agents/** bookmarks only" or "an agent-signed change needs a passing receipt to land".
  • Audit: the trust page and oxy verify list agent-signed changes separately, with the delegation that authorized each.

6a. Optional: a human always lands AI work

Whether a human must land every AI-authored change is a per-project choice. A regulated codebase may insist on it; a personal project or a team that trusts its agents and tests may not. Oxygen's job is to make the gate easy to turn on and impossible to bypass when it is on. It must never impose the gate on everyone.

With scoped delegation (this draft). The agent is your delegate with --scope changes, so its changes carry your authorship and its signature. The policy decides whether it can land:

rules: [
  { pattern: "main",      keys: [andy, sam], threshold: 1, require: "signed" },
  { pattern: "release/*", keys: [andy, sam], threshold: 2, require: "signed" },
  { pattern: "agents/**",  keys: [andy, sam], threshold: 1 },
]
  • Gate on: an agent-scoped delegate can never sign a reference attestation, so only Andy or Sam can move main. Approvals count only keys that are not agent-scoped, so a human approved and a human landed. The agent's changes keep their own signatures, so the landed history still shows which agent wrote what.
  • Gate off: delegate the agent with --scope changes,refs instead. It then moves references as far as its owner may, and can land on its own where the policy allows. The project chooses this per agent, and the trust page and oxy verify still show every agent-signed change and every agent-signed bookmark move.
  • Per bookmark: the usual setup gates main and release/* and leaves agents/** open, so agents push and move their own bookmarks freely while a human lands everything else. That needs refs scope that reaches only the open rules: a policy rule field naming agents explicitly, which is part of the §14.5 change.

With today's spec (no scoped delegation). A delegate moves references as far as its owner, so the gate needs a different setup:

  1. Give the agent its own identity, not a delegate.
  2. List only human keys in the main rule, and the agent's key in an agents/** rule.
  3. Policy checks each change a bookmark move adds, so the agent's changes cannot reach main directly at all. A human adopts the work by folding or re-committing it under their own key.

This gate is strict and works now. The cost is that the landed history records the human as signer, not the agent.

On the hub: agent-scoped tokens. Policy governs keys, but landing on the hub is done with an account's token. An agent using a human's token lands as that human, and no policy can tell. The hub therefore needs agent tokens:

  • tied to an agent key and its human owner;
  • allowed to push agents/**, open and update proposals, and comment;
  • refused for landing, approving, changing settings or policy, and creating tokens, whatever the owner may do.

Hub actions taken with an agent token are recorded as "AGENT on behalf of HUMAN" in the audit log and on the proposal. A project with the gate off may still let agent tokens land, as a repository setting that mirrors the policy, never by default.

7. Summary of new work

ItemSpec section to change
Scoped, expiring delegates (done 2026-10-04)§14.2 identity object, §14.4, §14.5 policy
Revocation by the delegator (done 2026-10-04)§14.2
oxy agent start / drop, session operation§12, CLI
oxy undo --to OP§12, CLI
Display folding, oxy fold -rCLI, hub
Agent-aware approvals and policy rules, optional human gate (§6a)§14.5, hub spec
Agent-scoped hub tokenshub spec (API tokens)
oxy status --json conflict listing (check what exists)§9, CLI