cgcardona / muse public
agent-provenance.md markdown
89 lines 2.9 KB
9ee9c39c refactor: rename music→midi domain, strip all 5-dim backward compat Gabriel Cardona <gabriel@tellurstori.com> 1d ago
1 # Agent Provenance in Muse
2
3 ## Overview
4
5 As Muse hosts multiple autonomous agents editing the same repository
6 concurrently, attribution and audit trail become critical. Agent provenance
7 answers: **who wrote this commit, with which model, using which toolchain,
8 and can that attribution be verified cryptographically?**
9
10 ## Commit-level fields
11
12 `CommitRecord` in `muse/core/store.py` carries six new optional fields
13 (all optional — omit if not tracking agent identity):
14
15 | Field | Description |
16 |-------|-------------|
17 | `agent_id` | Stable identifier for the agent or human (`"counterpoint-bot"`, `"alice"`) |
18 | `model_id` | AI model version used (`"gpt-5-turbo"`, `"claude-4"`) |
19 | `toolchain_id` | Agent framework version (`"muse-agent-v2.1"`) |
20 | `prompt_hash` | SHA-256 of the system prompt (no raw text stored) |
21 | `signature` | HMAC-SHA256 hex digest of the commit ID under the agent's key |
22 | `signer_key_id` | Short fingerprint of the signing key (for key lookup) |
23
24 ## Signing and verification
25
26 `muse/core/provenance.py` provides:
27
28 ```python
29 # Generate a new 32-byte HMAC key.
30 key = generate_agent_key()
31
32 # Persist the key to .muse/keys/<agent_id>-<fingerprint>.key
33 write_agent_key(repo_root, agent_id, key)
34
35 # Sign a commit ID.
36 sig = sign_commit_hmac(commit_id, key)
37
38 # Verify.
39 ok = verify_commit_hmac(commit_id, sig, key) # uses hmac.compare_digest
40
41 # Convenience: sign a full CommitRecord in one call.
42 signed_commit = sign_commit_record(repo_root, commit_record)
43 ```
44
45 HMAC-SHA256 using Python's standard `hmac` module requires no new
46 dependencies. If stronger non-repudiation is needed in the future,
47 the `sign_commit_hmac` function can be upgraded to Ed25519 using the
48 `cryptography` package without changing any callers.
49
50 ## AgentIdentity
51
52 `make_agent_identity()` constructs an `AgentIdentity` TypedDict:
53
54 ```python
55 identity = make_agent_identity(
56 agent_id="counterpoint-bot",
57 model_id="gpt-5",
58 toolchain_id="muse-agent-v2",
59 prompt="system: you are a music composition agent",
60 execution_context={"env": "ci", "run_id": "1234"},
61 )
62 ```
63
64 Sensitive fields (`prompt`, `execution_context`) are hashed before storage —
65 the raw strings never appear in the identity record.
66
67 ## Key storage
68
69 Agent keys live at `.muse/keys/<agent_id>-<fingerprint>.key` as hex-encoded
70 files. Multiple agents can coexist; each has its own key file keyed by
71 `agent_id`. Key files should be added to `.museignore` and managed
72 separately from the repository content.
73
74 ## Querying provenance
75
76 The music query DSL supports provenance fields directly:
77
78 ```bash
79 muse midi-query "agent_id == 'counterpoint-bot' and note.pitch > 60"
80 muse midi-query "model_id == 'gpt-5'"
81 ```
82
83 ## Related files
84
85 | File | Role |
86 |------|------|
87 | `muse/core/provenance.py` | `AgentIdentity`, key I/O, HMAC signing |
88 | `muse/core/store.py` | `CommitRecord`, `CommitDict` — six new fields |
89 | `tests/test_provenance.py` | Unit tests |