OXYGENHUB
# 445ce913ba56 oxygen / docs / ai_native_agent_workflows.md
11.2 KiB · Markdown · last changed author.signer: an agent signs its owner's changes with its own key 1 month ago renderedsource blame history raw
b277870b Andy McCall ↶ 1
# Oxygen (`oxy`): AI-Native Agent Workflows Specification
2
3
| | |
4
|---|---|
5
| **Status** | Draft 1.1 |
6
| **Date** | 2026-10-03 |
7
| **Audience** | Implementers and AI tooling developers |
8
| **Depends on** | spec.md §6 (changes), §9 (conflicts), §12 (operation log, workspaces), §14 (identity, policy), revsets (`revset_query_language.md`) |
9
10
## 1. Overview and philosophy
11
12
Coding agents, such as Aider or Claude Code, or local LLM loops, commit
13
at machine speed. A version control system must let them work without
14
giving them the keys to the kingdom, and without burying the human's
15
history in micro-changes.
16
17
The guiding principle is **delegated, bounded, reversible autonomy**:
18
19
- **Delegated:** an agent acts under its human owner's identity, with its
20
  own key, so every change it makes is attributable to both.
21
- **Bounded:** an agent can record changes but cannot move protected
22
  bookmarks, approve, or seal, whatever its owner may do.
23
- **Reversible:** an agent works in its own workspace and bookmark, so
24
  discarding its session never touches the human's work.
25
26
None of this weakens what Oxygen already guarantees. The change graph is
27
immutable, every change is signed with Ed25519 and ML-DSA-65, policy is
28
verified on fetch and push, and the operation log records everything.
29
30
Each section says what **exists** today and what is **new**.
31
32
## 2. Agent identity and delegation
33
34
**Exists (§14.2):** an identity object has `delegates [8]: [KeyId]`.
35
These are keys allowed to sign or seal changes whose `author` is that
36
identity. Delegation is one level deep and not transitive, and
37
`oxy identity delegate add|remove` manages it. Any change to an identity
38
is a rotation: a successor object.
39
40
- **The agent's own key pair.** An agent generates its own Ed25519 and
41
  ML-DSA-65 key pair locally. Its identity object's `name` says what it
42
  is, for example `"aider 0.x on andy-laptop"`. An agent never holds the
43
  human's secret keys.
44
- **Authorship.** Changes the agent records set `author` to the human's
45
  `KeyId` and are signed with the agent's key. The signature's KeyId
46
  identifies the agent. **No marker is stored in the change:** `extra
47
  [9]` is reserved and must stay empty, and the signature already proves
ff1a64f8 Andy McCall ↶ 48
  which agent made the change, which a marker could not. In practice
49
  (implemented 2026-10-04): the agent's keys live in its own `$OXY_HOME`,
50
  and its user config (or `$OXY_SIGNER`) sets `author.signer` to its
51
  KeyId; the checkout's `author.key` stays the human's, so `oxy commit`
52
  run by the agent carries the human as author and the agent's
53
  signature, and `oxy log -r 'delegated()'` lists what the agent did.
b277870b Andy McCall ↶ 54
7ba155f2 Andy McCall ↶ 55
**Scoped delegation (§14.2, implemented 2026-10-04).** Before it, a
56
delegate moved references as far as its delegator may (§14.5). That is
57
right for a hub signing browser edits, and wrong for an agent. `delegates`
58
is a list of entries:
b277870b Andy McCall ↶ 59
60
```
61
delegates [8]: [{ key [0]: KeyId, scope [1]: ["changes" | "refs" | "seal"], expires [2]: u64? }]
62
```
63
64
- An agent is added with `--scope changes`. Its signature authenticates
65
  changes, but a reference or tag attestation, or a seal, signed by it is
66
  refused. **An agent can never land on a protected bookmark**, even
67
  when its owner could.
68
- A per-delegate `expires` limits an agent to a session or a day
69
  (`--expires 8h`), without rotating the human's own expiry.
70
- Hosts that sign for users keep the current behaviour with
71
  `--scope changes,refs`.
7ba155f2 Andy McCall ↶ 72
- A bare KeyId in an older identity means every scope.
b277870b Andy McCall ↶ 73
7ba155f2 Andy McCall ↶ 74
**Revocation by the delegator (implemented 2026-10-04).** Before it,
75
only the revoked key itself or a policy root key could sign `revoke`. An agent's key may be lost on a
b277870b Andy McCall ↶ 76
compromised machine, and the policy root is often someone else, so the
77
identity that delegated a key may also revoke it. Removing a delegate in
78
a successor identity stops future use. Revoking it also marks the changes
79
the agent already signed as *valid but revoked* in `oxy verify` and on
80
the hub, so they get a second look.
81
82
## 3. Isolation: one workspace and bookmark per session
83
84
**Exists:** `oxy workspace add` creates an extra checkout that shares the
85
repository, each with its own current bookmark.
86
87
**New:** `oxy agent start NAME` does three things:
88
1. creates a workspace under `.oxy/agents/NAME/`;
89
2. creates the bookmark `agents/NAME/<session>` from the human's current
90
   heads;
91
3. records a session operation carrying the agent's KeyId.
92
93
The agent works only there. This replaces a session marker in the
94
human's operation log:
95
96
- **The human's working copy is never touched.** Changes commute, so the
97
  human keeps working on the same files at the same time, and merging
98
  the agent's bookmark later is an ordinary `oxy merge`.
99
- **Discarding a session** is `oxy agent drop NAME`: delete the
100
  bookmark and the workspace. Nothing the human did is undone, unlike an
101
  undo in a shared workspace would.
102
- **Undo within a session** is the agent's own operation log (§12),
103
  scoped to its workspace. The new `oxy undo --to OP` returns to any
104
  earlier operation of that workspace.
105
106
## 4. Micro-changes: keep them, show them folded
107
108
Agents produce many small changes. Oxygen keeps them, because each is
109
signed, cheap, and commutes with everything that does not touch the same
110
lines. The noise is a display problem first.
111
112
- **New, display folding:** `oxy log` shows a run of consecutive changes
113
  signed by the same agent key as one line: "aider: 37 changes, 4
114
  files". `--expand` shows them all. The hub does the same.
115
- **New, adoption:** when the human wants one change in history,
116
  `oxy fold -r REVSET` folds the selected changes into one new change.
117
  It uses the revset language, for example
118
  `oxy fold -r 'signed_by(aider) & main..agents/aider/s1'`. The folded
119
  change is authored and signed by the human's own key. It records the
120
  folded changes' hashes in its description footer, so the trail to the
121
  agent's work stays verifiable while those changes remain stored.
122
  The existing `oxy squash` folds one change into a dependency and stays
123
  as it is.
124
- **Folding is optional.** Unfolded agent changes stay valid history.
125
  Folding is for when a team's convention wants one reviewed change.
126
127
## 5. Conflicts as data, for agents
128
129
**Exists:** conflicts are recorded in states, not raised as errors (§9).
130
A conflicted state can be committed and built on, and `oxy resolve`
131
reports which conflicts the current files resolve.
132
133
- **Reading conflicts:** `oxy status --json` lists each conflict: path,
134
  node, kind (order, name or tree), and the contributing ChangeIds.
135
  `oxy cat PATH --at CHANGE` gives each side's text for the agent's
136
  context.
137
- **Resolving:** the agent writes the resolved files and runs
138
  `oxy commit`. **Oxy computes the resolution's dependencies**: a
139
  resolution must depend on every change that contributed an atom to
140
  the conflict. An agent never writes `deps` by hand. Correctness of the
141
  graph is Oxygen's job, not the model's.
142
- **A valid resolution is not necessarily a right one.** The graph will
143
  be well-formed; the code may still be wrong. A policy rule for
144
  protected bookmarks can require that a resolution signed by an agent
145
  has a passing Flow receipt and a human approval before it lands.
146
147
## 6. Review and policy on the hub
148
149
- **Badges:** changes signed by a delegate with `changes` scope show
150
  "agent: NAME on behalf of HUMAN" on the hub and in `oxy log`.
151
- **Approvals:** approvals count only signatures by keys that are not
152
  agent-scoped delegates, so an agent cannot approve its own work or
153
  anyone else's.
154
- **Policy:** a policy rule may name agent rules, for example "agents may
155
  push `agents/**` bookmarks only" or "an agent-signed change needs a
156
  passing receipt to land".
157
- **Audit:** the trust page and `oxy verify` list agent-signed changes
158
  separately, with the delegation that authorized each.
159
160
## 6a. Optional: a human always lands AI work
161
162
Whether a human must land every AI-authored change is a **per-project
163
choice**. A regulated codebase may insist on it; a personal project or a
164
team that trusts its agents and tests may not. Oxygen's job is to make
165
the gate easy to turn on and impossible to bypass when it is on. It must
166
never impose the gate on everyone.
167
168
**With scoped delegation (this draft).** The agent is your delegate
169
with `--scope changes`, so its changes carry your authorship and its
170
signature. The policy decides whether it can land:
171
172
```
173
rules: [
174
  { pattern: "main",      keys: [andy, sam], threshold: 1, require: "signed" },
175
  { pattern: "release/*", keys: [andy, sam], threshold: 2, require: "signed" },
176
  { pattern: "agents/**",  keys: [andy, sam], threshold: 1 },
177
]
178
```
179
180
- **Gate on:** an agent-scoped delegate can never sign a reference
181
  attestation, so only Andy or Sam can move `main`. Approvals count only
182
  keys that are not agent-scoped, so a human approved and a human landed.
183
  The agent's changes keep their own signatures, so the landed history
184
  still shows which agent wrote what.
185
- **Gate off:** delegate the agent with `--scope changes,refs` instead.
186
  It then moves references as far as its owner may, and can land on its
187
  own where the policy allows. The project chooses this per agent, and
188
  the trust page and `oxy verify` still show every agent-signed change and
189
  every agent-signed bookmark move.
190
- **Per bookmark:** the usual setup gates `main` and `release/*` and
191
  leaves `agents/**` open, so agents push and move their own bookmarks
192
  freely while a human lands everything else. That needs refs scope
193
  that reaches only the open rules: a policy rule field naming agents
194
  explicitly, which is part of the §14.5 change.
195
196
**With today's spec (no scoped delegation).** A delegate moves
197
references as far as its owner, so the gate needs a different setup:
198
1. Give the agent its **own identity**, not a delegate.
199
2. List only human keys in the `main` rule, and the agent's key in an
200
   `agents/**` rule.
201
3. Policy checks each change a bookmark move adds, so the agent's changes
202
   cannot reach `main` directly at all. A human adopts the work by folding
203
   or re-committing it under their own key.
204
205
This gate is strict and works now. The cost is that the landed history
206
records the human as signer, not the agent.
207
208
**On the hub: agent-scoped tokens.** Policy governs keys, but landing on
209
the hub is done with an account's token. An agent using a human's token
210
lands *as that human*, and no policy can tell. The hub therefore needs
211
**agent tokens**:
212
- tied to an agent key and its human owner;
213
- allowed to push `agents/**`, open and update proposals, and comment;
214
- refused for landing, approving, changing settings or policy, and
215
  creating tokens, whatever the owner may do.
216
217
Hub actions taken with an agent token are recorded as "AGENT on behalf of
218
HUMAN" in the audit log and on the proposal. A project with the gate off
219
may still let agent tokens land, as a repository setting that mirrors the
220
policy, never by default.
221
222
## 7. Summary of new work
223
224
| Item | Spec section to change |
225
|---|---|
7ba155f2 Andy McCall ↶ 226
| Scoped, expiring delegates (done 2026-10-04) | §14.2 identity object, §14.4, §14.5 policy |
227
| Revocation by the delegator (done 2026-10-04) | §14.2 |
b277870b Andy McCall ↶ 228
| `oxy agent start` / `drop`, session operation | §12, CLI |
229
| `oxy undo --to OP` | §12, CLI |
230
| Display folding, `oxy fold -r` | CLI, hub |
231
| Agent-aware approvals and policy rules, optional human gate (§6a) | §14.5, hub spec |
232
| Agent-scoped hub tokens | hub spec (API tokens) |
233
| `oxy status --json` conflict listing (check what exists) | §9, CLI |