Skip to content

Commit 32bf2b3

Browse files
simonovic86claude
andauthored
Elevate liquidation demo as canonical, sharpen terminal UX (#31)
* feat(agent): elevate liquidation demo as canonical, sharpen terminal experience Lead README with the visceral continuity story ("this agent did not stay alive — it stayed continuous") instead of platform claims. Make demo-liquidation the canonical demo with prominent DID banners on run/resume, visual gap detection separators, and cross-node identity verification in the demo script. Reconcile OVERVIEW.md to match current project state. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: print effective resume budget, guard DID parsing in demo script Move the resume banner after the budget override logic so it displays the actual budget used, not always the checkpoint value. Add || true to DID grep pipelines in the demo script so a missing "Agent DID" line doesn't abort under set -euo pipefail. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 237af6b commit 32bf2b3

5 files changed

Lines changed: 119 additions & 195 deletions

File tree

README.md

Lines changed: 37 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,32 @@
11
# Igor
22

3-
**Runtime for Portable, Immortal Software Agents**
3+
**This agent did not stay alive. It stayed continuous.**
44

5-
Igor makes any WASM program into a sovereign agent with its own identity, memory, and verifiable life history. The checkpoint file IS the agent — copy it anywhere, run `igord resume`, it continues exactly where it left off. No infrastructure lock-in.
5+
An agent monitors a DeFi position for liquidation risk. Node A dies. The price keeps moving. The threshold is breached while the agent is absent. Node B picks up the checkpoint, detects the gap, replays the missed time slots, and discovers what happened during downtime. Same DID identity. Cryptographic proof of the entire life history. No state lost.
66

7-
---
7+
```bash
8+
make demo-liquidation # See it happen in 60 seconds
9+
```
810

9-
## About This Repository
11+
---
1012

11-
**What:** Runtime for portable, infrastructure-independent agents
12-
**Status:** Product Phase 1 complete. Agents have DID identity, checkpoint/resume across machines, and cryptographic lineage verification. Built on a research foundation (Phases 2–5) of WASM sandboxing, P2P migration, budget metering, replay verification, and signed checkpoint lineage.
13-
**Purpose:** Give software agents identity, memory, and continuity — independent of any machine, cloud, or operator
13+
Igor is a runtime for portable, continuous software agents. The checkpoint file IS the agent — copy it anywhere, run `igord resume`, it continues exactly where it left off. Every agent has a DID identity (`did:key:z6Mk...`), and a signed checkpoint lineage providing cryptographic proof of its entire life history.
1414

15-
**Read first:**
16-
- [ANNOUNCEMENT.md](./ANNOUNCEMENT.md) - Public project introduction
17-
- [docs/philosophy/OVERVIEW.md](./docs/philosophy/OVERVIEW.md) - Introduction to Igor concepts and status
18-
- [docs/philosophy/VISION.md](./docs/philosophy/VISION.md) - Why autonomous software needs survival
19-
20-
**Contribute:**
21-
- [CONTRIBUTING.md](./CONTRIBUTING.md) - Guidelines and workflow
22-
- [docs/governance/DEVELOPMENT.md](./docs/governance/DEVELOPMENT.md) - Developer setup
23-
24-
---
15+
**Status:** Early product stage. Agents have DID identity, checkpoint/resume across machines, gap-aware catch-up, and cryptographic lineage verification. Not production-ready for value-critical workloads.
2516

2617
## Why Igor Exists
2718

28-
Agents today are tied to their infrastructure. Kill the server, the agent dies. Restart it, and it has to start from scratch — losing in-memory state, execution history, and continuity.
29-
30-
Kubernetes restarts processes but loses state. Temporal forces you into a workflow programming model. AO replays entire message histories from Arweave. An LLM with a wallet can rent a server but can't survive dying on it.
19+
Agents today are tied to their infrastructure. Kill the server, the agent dies. Restart it, and it starts from scratch — losing state, execution history, and continuity.
3120

3221
Igor gives agents three things nothing else provides together: **identity** (DID), **memory** (checkpointed state that survives infrastructure failure), and **verifiable continuity** (cryptographic proof of the agent's entire life history). The agent is a portable digital object — not a deployment tied to specific infrastructure.
3322

34-
## Technical Domains
35-
36-
Igor addresses challenges in:
37-
38-
* **Autonomous agent infrastructure** - Runtime for self-managing software entities
39-
* **Survivable distributed systems** - Execution persistence across infrastructure failure
40-
* **WASM sandbox runtimes** - Portable deterministic agent execution (wazero)
41-
* **Peer-to-peer compute mobility** - Agent migration over libp2p networks
42-
* **Runtime economic accounting** - Budget-based execution metering and enforcement
43-
* **Self-hosting autonomous software** - Agents that pay for their own compute
44-
* **Distributed systems research** - Experimental infrastructure for agent survival
45-
46-
## Related Ecosystem Areas
47-
48-
Igor occupies a lower-level runtime infrastructure layer, distinct from agent reasoning or orchestration frameworks.
49-
50-
Relevant adjacent domains:
51-
* Autonomous AI agent infrastructure and runtimes
52-
* Distributed compute execution environments
53-
* WebAssembly execution engines and sandbox runtimes
54-
* Peer-to-peer service fabrics and distributed protocols
55-
* DeFi solver network infrastructure
56-
* Oracle and economic automation service infrastructure
57-
* Mobile code and process migration research
58-
59-
Igor provides execution survival primitives that these higher-level systems could build upon.
60-
6123
## Core Guarantees
6224

25+
- **Continuous:** Agents detect gaps in their history and reconstruct what they missed
6326
- **Portable:** The checkpoint file IS the agent — copy it anywhere, resume it
6427
- **Identity:** Every agent has a DID (`did:key:z6Mk...`) derived from its Ed25519 keypair
6528
- **Verifiable:** Signed checkpoint lineage — cryptographic proof of entire life history
66-
- **Survival:** Agents checkpoint state and resume after infrastructure failure
67-
- **Sandboxing:** WASM isolation, 64MB memory limit, no filesystem/network access
68-
- **Migration:** Agents transfer between nodes over libp2p streams (research foundation)
69-
70-
## What Igor Does Not Provide
71-
72-
Igor is **not**:
73-
74-
- An AI reasoning framework
75-
- An agent marketplace or discovery protocol
76-
- A blockchain or consensus system
77-
- A multi-agent coordination platform
78-
- A general-purpose orchestration system
79-
80-
Igor is a minimal runtime for portable, sovereign agents. It provides identity, checkpointing, and verifiable continuity. Nothing more.
29+
- **Sandboxed:** WASM isolation, 64MB memory limit, no filesystem/network access
8130

8231
## Architecture Overview
8332

@@ -127,39 +76,13 @@ The checkpoint file IS the agent. It contains everything needed to resume:
12776

12877
Every checkpoint is archived to `history/{agentID}/{tickNumber}.ckpt` for full lineage verification.
12978

130-
## Current Capabilities
131-
132-
**Product Phase 1 (Portable Sovereign Agent) - Complete**
133-
134-
- Agent runs with DID identity (`did:key:z6Mk...`)
135-
- Agent checkpoints and resumes on any machine — same DID, continuous tick count
136-
- Signed checkpoint lineage — cryptographic proof of entire life history
137-
- Checkpoint history archival for lineage verification
138-
- CLI subcommands: `igord run`, `resume`, `verify`, `inspect`
139-
140-
**Research Foundation (Phases 2–5) - Complete**
141-
142-
- WASM sandboxing, P2P migration, budget metering, replay verification
143-
- Capability membranes, lease-based authority, signed lineage, migration failure recovery
144-
14579
## Project Status
14680

147-
**Maturity:** Product Phase 1 complete. Built on research foundation (Phases 2–5).
148-
**Production:** Not yet production-ready — early product stage.
149-
**Security:** Ed25519 signed checkpoint lineage with DID identity.
150-
151-
**Known limitations:**
152-
- Local filesystem storage only (no permanent archival yet)
153-
- No HTTP or payment hostcalls (agents can't call external APIs yet)
154-
- No self-provisioning (agents can't deploy themselves yet)
155-
- Minimal security hardening
81+
Early product stage. Not production-ready for value-critical workloads.
15682

157-
**Suitable for:**
158-
- Building and running portable agents
159-
- Experimenting with agent identity and continuity
160-
- Understanding infrastructure-independent agent patterns
83+
What works today: DID identity, checkpoint/resume across machines, gap-aware catch-up, signed checkpoint lineage, CLI (`igord run/resume/verify/inspect`). Built on a research foundation of WASM sandboxing, P2P migration, budget metering, and replay verification.
16184

162-
See [SECURITY.md](./SECURITY.md) for complete security model.
85+
See [SECURITY.md](./SECURITY.md) for the complete security model and known limitations.
16386

16487
## Quick Start
16588

@@ -169,39 +92,45 @@ See [SECURITY.md](./SECURITY.md) for complete security model.
16992
- TinyGo 0.40.1+ (for agents)
17093
- golangci-lint (for development)
17194

172-
### Build and Run
95+
### The Canonical Demo
96+
97+
```bash
98+
make demo-liquidation
99+
```
100+
101+
This runs the full continuity proof: agent starts on Node A monitoring a simulated ETH position, Node A dies during a critical price drawdown, Node B resumes from checkpoint, detects the gap, replays missed time slots, discovers the threshold was breached during downtime, and verifies the cryptographic lineage across both nodes.
102+
103+
### Manual Usage
173104

174105
```bash
175-
# Build runtime and heartbeat agent
106+
# Build runtime and agent
176107
make build
177-
make agent-heartbeat
108+
make agent-liquidation
178109

179-
# Run agent (creates identity, starts ticking)
180-
./bin/igord run --budget 1.0 agents/heartbeat/agent.wasm
181-
# [heartbeat] tick=1 age=1s
182-
# [heartbeat] tick=2 age=2s
183-
# Ctrl+C → checkpoint saved
110+
# Run agent (creates DID identity, starts monitoring)
111+
./bin/igord run --budget 100.0 agents/liquidation/agent.wasm
184112

185113
# Resume on same or different machine
186-
./bin/igord resume checkpoints/heartbeat/checkpoint.ckpt agents/heartbeat/agent.wasm
187-
# [heartbeat] tick=3 age=3s ← continues where it left off
114+
./bin/igord resume --checkpoint checkpoints/liquidation/liquidation.checkpoint \
115+
--wasm agents/liquidation/agent.wasm
188116

189117
# Verify the agent's entire life history
190-
./bin/igord verify checkpoints/heartbeat/history/
118+
./bin/igord verify checkpoints/liquidation/history/
191119

192120
# Inspect a checkpoint
193-
./bin/igord inspect checkpoints/heartbeat/checkpoint.ckpt
121+
./bin/igord inspect checkpoints/liquidation/liquidation.checkpoint
194122
```
195123

196-
### Portable Agent Demo
124+
### Other Demos
197125

198126
```bash
199-
# Full demo: run → stop → copy → resume → verify
200-
make demo-portable
127+
make demo-portable # Basic portable resume (heartbeat agent)
128+
make demo-pricewatcher # Price tracking across resume
129+
make demo-sentinel # Effect-safe crash recovery
130+
make demo-x402 # Payment with crash reconciliation
131+
make demo-deployer # Multi-step deployment with crash recovery
201132
```
202133

203-
The demo shows an agent running on "Machine A", checkpoint copied to "Machine B", resuming with the same DID identity and continuous tick count, then verifying the cryptographic lineage across both machines.
204-
205134
## Specification Overview
206135

207136
Igor's specification is organized into layered authority domains. See the full [Specification Index](./docs/SPEC_INDEX.md) for cross-references.

agents/liquidation/main.go

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,15 @@ func (w *LiquidationWatcher) Tick() bool {
112112
// Detect gap.
113113
if currentSlot > w.LastProcessedSlot+1 {
114114
gap := currentSlot - w.LastProcessedSlot - 1
115-
igor.Logf("[resume] restored checkpoint from slot %d", w.LastProcessedSlot)
116-
igor.Logf("[resume] current slot is %d", currentSlot)
117-
igor.Logf("[resume] gap detected: %d missed slots (%d..%d)",
115+
igor.Logf("")
116+
igor.Logf("────────────────────────────────────────────────────")
117+
igor.Logf(" GAP DETECTED")
118+
igor.Logf(" Last processed: slot %d", w.LastProcessedSlot)
119+
igor.Logf(" Current time: slot %d", currentSlot)
120+
igor.Logf(" Missed: %d slots (%d..%d)",
118121
gap, w.LastProcessedSlot+1, currentSlot-1)
122+
igor.Logf(" Replaying missed history...")
123+
igor.Logf("────────────────────────────────────────────────────")
119124

120125
// Remember whether warning was already known before catch-up.
121126
warningBefore := w.FirstWarningSlot
@@ -126,9 +131,16 @@ func (w *LiquidationWatcher) Tick() bool {
126131
}
127132

128133
// Summary after catch-up.
134+
igor.Logf("────────────────────────────────────────────────────")
129135
if w.FirstWarningSlot != 0 && warningBefore == 0 {
130-
igor.Logf("[catch-up] ⚠ WARNING first occurred at slot %d (during downtime)", w.FirstWarningSlot)
136+
igor.Logf(" ⚠ THRESHOLD BREACHED AT SLOT %d (DURING DOWNTIME)", w.FirstWarningSlot)
137+
igor.Logf(" The agent was dead. The world kept moving.")
138+
igor.Logf(" Catch-up reconstructed %d missed slots.", gap)
139+
} else {
140+
igor.Logf(" Catch-up complete: %d missed slots replayed.", gap)
131141
}
142+
igor.Logf("────────────────────────────────────────────────────")
143+
igor.Logf("")
132144
}
133145

134146
// Process current slot as live.

cmd/igord/main.go

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -212,10 +212,9 @@ func runStandalone(wasmPath, agentID string, budgetVal float64, manifestPath, ch
212212
os.Exit(1)
213213
}
214214

215-
logger.Info("Agent identity",
216-
"did", agentIdent.DID(),
217-
"did_short", agentIdent.DIDShort(),
218-
)
215+
fmt.Fprintf(os.Stdout, "\n Agent: %s\n", agentID)
216+
fmt.Fprintf(os.Stdout, " DID: %s\n", agentIdent.DID())
217+
fmt.Fprintf(os.Stdout, " Budget: %s\n\n", budget.Format(budget.FromFloat(budgetVal)))
219218

220219
manifestData := runner.LoadManifestData(wasmPath, manifestPath, logger)
221220
budgetMicrocents := budget.FromFloat(budgetVal)
@@ -240,16 +239,9 @@ func runStandalone(wasmPath, agentID string, budgetVal float64, manifestPath, ch
240239

241240
// Try to load existing checkpoint.
242241
if loadErr := instance.LoadCheckpointFromStorage(ctx); loadErr != nil {
243-
logger.Info("No existing checkpoint, starting fresh")
242+
logger.Debug("No existing checkpoint, starting fresh")
244243
}
245244

246-
logger.Info("Agent started",
247-
"agent_id", agentID,
248-
"did", agentIdent.DIDShort(),
249-
"budget", budget.Format(budgetMicrocents),
250-
"tick", instance.TickNumber,
251-
)
252-
253245
runTickLoop(ctx, instance, logger)
254246
}
255247

@@ -307,19 +299,18 @@ func resumeFromCheckpoint(checkpointPath, wasmPath, agentID string, budgetVal fl
307299
}
308300
}
309301

310-
logger.Info("Resuming agent",
311-
"did", agentIdent.DID(),
312-
"from_tick", hdr.TickNumber,
313-
"checkpoint", checkpointPath,
314-
)
315-
316302
manifestData := runner.LoadManifestData(wasmPath, manifestPath, logger)
317303

318304
b := budget.FromFloat(budgetVal)
319305
if b == 0 {
320306
b = hdr.Budget
321307
}
322308

309+
fmt.Fprintf(os.Stdout, "\n Resuming: %s\n", agentID)
310+
fmt.Fprintf(os.Stdout, " DID: %s\n", agentIdent.DID())
311+
fmt.Fprintf(os.Stdout, " From: tick %d\n", hdr.TickNumber)
312+
fmt.Fprintf(os.Stdout, " Budget: %s\n\n", budget.Format(b))
313+
323314
instance, err := agent.LoadAgent(
324315
ctx, engine, wasmPath, agentID, storageProvider,
325316
b, hdr.PricePerSecond,
@@ -343,13 +334,6 @@ func resumeFromCheckpoint(checkpointPath, wasmPath, agentID string, budgetVal fl
343334
os.Exit(1)
344335
}
345336

346-
logger.Info("Agent resumed",
347-
"agent_id", agentID,
348-
"did", agentIdent.DIDShort(),
349-
"tick", instance.TickNumber,
350-
"budget", budget.Format(b),
351-
)
352-
353337
runTickLoop(ctx, instance, logger)
354338
}
355339

0 commit comments

Comments
 (0)