Skip to content

Commit 5203b62

Browse files
OpsKernclaude
andcommitted
docs: add README with real API, correct import path, v0 agent scope
- Import path: github.com/opskernel-io/writ (not vanity URL — not set up yet) - Quick start: uses actual writ.New(), client.Messages.New(), client.Audit() API - "Supported agents" section: v0 targets Go agents using anthropic-sdk-go directly; Devin/Cursor deferred to integration guides (OQ-5 unresolved) - Roadmap: writ verify CLI marked done; Devin/Cursor listed as roadmap item - Remove all references to non-existent client.Authorize() and DefaultDispatch() Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 35ee0c4 commit 5203b62

1 file changed

Lines changed: 188 additions & 0 deletions

File tree

README.md

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
# writ
2+
3+
**Codification gate and Merkle audit chain for Go agents.**
4+
5+
```
6+
go get github.com/opskernel-io/writ
7+
```
8+
9+
---
10+
11+
## The problem
12+
13+
Autonomous coding agents run with whatever permissions you gave them at setup time. There is no runtime gate that asks "is this call within policy?" before the LLM acts, and standard observability logs can be edited after the fact.
14+
15+
---
16+
17+
## What writ does
18+
19+
- **Blocks unauthorized agent calls before execution** — the codification gate intercepts every outbound LLM API call at the process level and evaluates it against your OPA policy before it leaves
20+
- **Logs every agent decision in a tamper-evident chain** — SHA-256-linked Merkle chain; altering any entry breaks verification from that point forward
21+
- **Routes tasks to the cheapest model tier that can handle them** — Ollama (free/local) → Claude Sonnet → Claude Opus, enforced by policy
22+
- **Reloads policy without restarting** — OPA hot-reload via file watch; policy changes take effect on the next call
23+
24+
---
25+
26+
## How it's different
27+
28+
| | writ | Asqav | Snyk Agent Guard | Microsoft AGT |
29+
|---|---|---|---|---|
30+
| Pre-execution gate | **** ||||
31+
| Tamper-evident audit | Merkle chain | Hash chain + RFC 3161 | Mutable session logs ||
32+
| OPA policy enforcement | **** || private preview ||
33+
| Tiered dispatch | **** ||||
34+
| Language | Go | Python | N/A | TypeScript |
35+
| License | Apache 2.0 + commercial | MIT | Commercial | MIT |
36+
37+
**The key distinction from Asqav:** Asqav logs what happened after execution. writ controls what is allowed to happen before execution. These are different architectural positions: authorize-then-enforce vs. observe-and-record. In a regulated environment you need both; writ's gate is the piece no other tool ships.
38+
39+
**The key distinction from Microsoft AGT:** The Agent Governance Toolkit has OPA enforcement and Ed25519 signing. It has no tamper-evident audit log. writ's Merkle chain fills that specific gap.
40+
41+
---
42+
43+
## EU AI Act Article 12
44+
45+
EU AI Act Article 12 requires automatic, technical, tamper-evident logging over the lifetime of high-risk AI systems. Enforcement begins August 2, 2026.
46+
47+
**Three requirements met in full:**
48+
- Automatic logging — the gate emits chain entries without human action per call
49+
- Technical logging — machine-generated, structured, SHA-256-linked
50+
- Traceability — every gate decision links to its chain entry by AuditID
51+
52+
**Three requirements partially met (remediation paths defined, days not weeks):**
53+
- Tamper-evident — SHA-256 chain detects alteration; filesystem-level write protection (`chattr +a` + `writ.ChainProtected()`) closes the gap
54+
- Lifetime coverage — chain is append-only within a process run; cross-restart hash linking closes the gap
55+
- Granularity — input hashes logged by default; `StoreFullInputs: true` opt-in logs the full input data
56+
57+
**Two named gaps:**
58+
- **RFC 3161 timestamping** — chain timestamps are machine-generated but not externally signed. Integration roadmap: `github.com/digitorus/timestamp`. Commercial tier: hosted eIDAS-compliant timestamping.
59+
- **6-month retention management** — the open-source core writes to local storage with no managed expiry. Commercial-tier feature.
60+
61+
writ-core is suitable for teams building toward Article 12 compliance. The three partial requirements close with days of engineering. The commercial tier closes the two named gaps.
62+
63+
---
64+
65+
## Quick start
66+
67+
```go
68+
import (
69+
"github.com/opskernel-io/writ"
70+
"github.com/anthropics/anthropic-sdk-go"
71+
)
72+
73+
// Initialize — wraps your anthropic.Client with gate + audit.
74+
// One-line change at construction time; the rest of your agent code stays the same.
75+
client, err := writ.New(writ.Config{
76+
PolicyPath: "/etc/writ/policy.rego", // OPA Rego bundle directory
77+
AuditPath: "/var/writ/audit.chain", // Merkle chain JSONL file
78+
CallerID: "myagent-v1", // optional stable agent identifier
79+
})
80+
if err != nil {
81+
log.Fatal(err)
82+
}
83+
84+
// LLM calls go through the gate automatically.
85+
// Allowed calls are audited and dispatched; denied calls return *writ.DenialError.
86+
msg, err := client.Messages.New(ctx, anthropic.MessageNewParams{
87+
Model: anthropic.ModelClaude_Sonnet_4_6,
88+
MaxTokens: 1024,
89+
Messages: anthropic.F([]anthropic.MessageParam{
90+
anthropic.NewUserMessage(anthropic.NewTextBlock("refactor the auth module")),
91+
}),
92+
})
93+
if err != nil {
94+
var denial *writ.DenialError
95+
if errors.As(err, &denial) {
96+
log.Printf("blocked by policy: %s (audit_id=%s)", denial.Reason, denial.AuditID)
97+
}
98+
}
99+
100+
// Streaming calls work the same way.
101+
stream, err := client.Messages.NewStreaming(ctx, params)
102+
if err != nil { ... }
103+
defer stream.Close() // writes the streaming-complete audit entry
104+
105+
// For tool use and other non-LLM events:
106+
client.Audit(writ.AuditEvent{
107+
ActionType: "write_file",
108+
Actor: writ.ActorAgent,
109+
InputHash: writ.HashInput([]byte(filePath)),
110+
Result: "success",
111+
})
112+
113+
// Verify the chain (run in CI or on-demand audits):
114+
err = writ.Verify("/var/writ/audit.chain")
115+
```
116+
117+
**Helm (Kubernetes):** writ-core is a library dependency of your agent process, not a sidecar. Add to your agent container's Go dependencies. See `docs/helm/` for a reference values.yaml with policy ConfigMap mounting.
118+
119+
---
120+
121+
## Supported agents
122+
123+
v0 targets **Go agents that call `anthropic.Client` directly** — any agent built with `github.com/anthropics/anthropic-sdk-go`. Drop `writ.New()` in at the client construction site.
124+
125+
Agents that proxy the Anthropic API through their own server (rather than calling the SDK directly from your Go process) require an alternative integration path. Integration guides for specific agents are on the roadmap.
126+
127+
---
128+
129+
## Architecture
130+
131+
```
132+
┌─────────────────────────────────────────────────────────┐
133+
│ Agent Process │
134+
│ │
135+
│ task ──► [writ codification gate] ──► LLM API call │
136+
│ │ │ │
137+
│ DENY (blocked) ALLOW (proceed) │
138+
│ │ │ │
139+
│ structured error [Merkle audit] │
140+
│ │ │
141+
│ [tiered dispatch] │
142+
│ │ │
143+
│ Ollama / Sonnet / Opus │
144+
└─────────────────────────────────────────────────────────┘
145+
│ │
146+
[OPA policy] [audit chain]
147+
file watch append-only
148+
hot-reload tamper-evident
149+
│ │
150+
/etc/writ/policy.rego /var/writ/audit.chain
151+
```
152+
153+
The gate sits between your agent's code and the LLM API call — not between your machine and the internet. It intercepts at the call site in-process.
154+
155+
---
156+
157+
## License
158+
159+
The writ-core SDK is Apache 2.0. Use it, fork it, embed it, build commercial products on top of it.
160+
161+
**What's in the commercial tier** ([writ.opskernel.io](https://writ.opskernel.io)):
162+
- Compliance dashboard — Article 12 audit report export (PDF + JSON)
163+
- Hosted RFC 3161 timestamping — eIDAS-compliant, third-party signed timestamps
164+
- 6-month retention management — cloud storage backend with compliance attestation
165+
- Multi-agent audit chains — cross-agent tracing across chained agent calls
166+
167+
---
168+
169+
## Roadmap
170+
171+
- [ ] RFC 3161 timestamping integration (closes Article 12 gap 1)
172+
- [ ] 6-month retention management, commercial tier (closes Article 12 gap 2)
173+
- [ ] Multi-agent audit chains — single verifiable chain spanning Agent A → Agent B calls
174+
- [ ] Agent integration guides — Devin, Cursor, and other agents (requires OQ-5 investigation)
175+
- [x] `writ verify` CLI — standalone chain verification for CI pipelines
176+
177+
---
178+
179+
## Related
180+
181+
- **[hookd](https://opskernel.io)** — governs external AI traffic: MCP server verification, replay detection, per-source audit. writ governs what agents do internally; hookd governs what external servers agents call.
182+
- **[opskern-policy](https://github.com/OpsKern/opskern-policy)** — shared OPA Rego policy templates for hookd + writ.
183+
- **[Asqav](https://github.com/jagmarques/asqav-sdk)** — MIT Python SDK for agent audit trails with RFC 3161 timestamps. Complementary to writ (observe-and-record layer); writ adds the pre-execution gate that Asqav does not have.
184+
- **[EU AI Act Article 12 text](https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32024R1689)** — the specific requirement writ's architecture addresses.
185+
186+
---
187+
188+
*writ is built by [OpsKern](https://opskern.io). Early access: [writ.opskernel.io](https://writ.opskernel.io)*

0 commit comments

Comments
 (0)