Oxygen (oxy): AI-Native Agent Workflows Specification
| Status | Draft 1.1 |
| Date | 2026-10-03 |
| Audience | Implementers and AI tooling developers |
| Depends on | spec.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
namesays 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
authorto the human'sKeyIdand 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) setsauthor.signerto its KeyId; the checkout'sauthor.keystays the human's, sooxy commitrun by the agent carries the human as author and the agent's signature, andoxy 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
expireslimits 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:
- creates a workspace under
.oxy/agents/NAME/; - creates the bookmark
agents/NAME/<session>from the human's current heads; - 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 OPreturns 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 logshows a run of consecutive changes signed by the same agent key as one line: "aider: 37 changes, 4 files".--expandshows them all. The hub does the same. - New, adoption: when the human wants one change in history,
oxy fold -r REVSETfolds the selected changes into one new change. It uses the revset language, for exampleoxy 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 existingoxy squashfolds 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 --jsonlists each conflict: path, node, kind (order, name or tree), and the contributing ChangeIds.oxy cat PATH --at CHANGEgives 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 writesdepsby 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 NAMEwith anagentbadge: in history rows on the hub, as aviarow under the author on the change page (↳ Antigravity <…> · delegate for changes, until … · key …), under the author in Contributors ("via Antigravity 3"), asviain the API's change summaries, and the same inoxy log(via NAME) andoxy show(theviarow). 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 verifylist 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,refsinstead. 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 andoxy verifystill show every agent-signed change and every agent-signed bookmark move. - Per bookmark: the usual setup gates
mainandrelease/*and leavesagents/**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:
- Give the agent its own identity, not a delegate.
- List only human keys in the
mainrule, and the agent's key in anagents/**rule. - Policy checks each change a bookmark move adds, so the agent's changes
cannot reach
maindirectly 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
| Item | Spec 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 -r | CLI, hub |
| Agent-aware approvals and policy rules, optional human gate (§6a) | §14.5, hub spec |
| Agent-scoped hub tokens | hub spec (API tokens) |
oxy status --json conflict listing (check what exists) | §9, CLI |