{"slug": "an-agent-s-life-on-the-chain-init-to-exodus-gitmark-workflow-for-llm-agents", "title": "An agent's life on the chain: init to exodus (gitmark workflow for LLM agents)", "summary": "A developer published a step-by-step workflow for running an LLM agent on Bitcoin testnet4 using gitmark, in which the agent is created and funded with 10,000 sats, anchors its commits to Bitcoin via `git mark`, announces its repository on Nostr as a signed NIP-34 kind 30617 event, and finally returns its remaining balance to the operator's voucher. Each step is a single command with a verification check, and the workflow requires explicit operator approval before any irreversible spend or public announcement.", "body_md": "A workflow for an LLM agent (or a person driving one). The agent gets a key, gets coins, anchors its commits to Bitcoin, announces the repo on Nostr, and when it is done hands the coin back and closes the trail. Every step is one command; every step has a check. Do the steps in order and stop at the first check that fails.\n\nTools: `npm init agent` (create-agent), `npx fund-agent`, `git mark` (gitmark ≥ 0.0.82). Chain used here: `txbt4`,\nthe BLAKE2b testnet4. Nothing below is mainnet.\n\n1. Never print, log, paste or commit the private key. It lives in `git config nostr.privkey` and nowhere else.\n2. One command at a time. Read its output before the next one.\n3. A mark is a real Bitcoin spend and cannot be undone. Announcing is public and signed. Exodus sends the whole balance. Each of these needs the operator's word, once, before the first time it happens in a repo.\n4. Never retry a spend blindly. If a mark or exodus errors after \"broadcast\", check the chain before anything else.\n5. Keep it light: one explorer call per check, no polling loops faster than a minute.\n\n```\nnode --version                  # 20 or newer\nnpm view gitmark version        # 0.0.82 or newer; else: npm install -g gitmark@latest\nls ~/.gitmark/faucet.txt        # the voucher file; if missing, see \"No voucher\" below\n```\n\nCheck: all three print something. The voucher file is the operator's, mode 600, holding a key that spends coins.\nNever read it aloud; `npx fund-agent status` is the only way to look at it.\n\n```\nmkdir my-agent && cd my-agent && git init -q\nnpm init agent\n```\n\nCheck: `git config --local nostr.privkey | wc -c` prints 65. `agent.did.json` exists. Nothing else to do with\nthe key.\n\n```\nnpx fund-agent\n```\n\nWhat happens: 10,000 sats go from the voucher to the agent's key; the change goes back to the voucher; the coin\nis written to `.well-known/txo/txo.json`.\n\nCheck: the output ends with `=== Agent funded successfully! ===` and a txid. Then:\n\n```\nnpx fund-agent balance          # Address: tb1p…, one coin of 10,000 sats (unconfirmed is fine)\n```\n\nIf it says the voucher has no coins, stop and tell the operator the address it printed. Do not look for coins elsewhere.\n\n```\ngit mark init --chain txbt4\n```\n\nWhat happens: gitmark finds the coin sitting at the key's base address and adopts it. No spend yet.\n\nCheck: `git config --local gitmark.txo` prints a `txo:txbt4:…` line, and `blocktrails.json` exists with\n`\"states\": []`.\n\n```\ngit add -A && git commit -qm \"what changed\"\ngit mark\n```\n\nWhat happens: one transaction, 300 sat fee, spending the trail coin to an address derived from this commit.\nOutput: `Marked: <commit> → <txid>`, the new balance, the new TXO.\n\nCheck: `git mark info` shows `Marks: 1`, `Last commit:` is HEAD, `Balance:` is 300 less than before. Status\nreads unconfirmed until the next block; that is normal on a testnet with few blocks.\n\nRules of thumb:\n\n- Mark commits worth proving, not every commit. 10,000 sats is about thirty marks.\n- `git mark` on a commit that is already the last mark is refused. That is correct; commit first.\n- An unknown word (`git mark anchor` ,`git mark commit` ) prints usage and exits 1. It never marks by accident.\n- Commit `blocktrails.json` after marking; it is the public trail. Or set`git config gitmark.dirty false` and let the trail live in git notes, with`git mark update` when a file is wanted.\n\nRepeat 4 for as long as the agent works.\n\nOnce, when the repo has a remote worth pointing at:\n\n```\ngit remote add origin <url>     # and any mirrors: git remote add forge <url>\ngit push -u origin HEAD\ngit mark announce\n```\n\nWhat happens: a NIP-34 repository announcement (kind 30617), signed with the agent's key, carrying the latest\nmark as `chain`, `txo` and `commit` tags and every remote as a `clone` tag. Relays come from\n`git config nostr.relays` (comma or space separated), or the defaults.\n\nCheck: the output ends `Announced: kind 30617 … (n/m relays)` with n ≥ 1. The repo then appears at\n[https://play-grounds.github.io/gitmark/](https://play-grounds.github.io/gitmark/) within a minute, agent shown as `did:nostr:<hex>`.\n\nIf n is 0: the relays refused or did not answer. Set `git config nostr.relays` to relays known to work and run\n`git mark announce` again. Nothing was spent.\n\nFrom here, `git mark --announce` marks and announces in one, or `git config gitmark.announce true` makes that\nthe default.\n\n```\ngit mark verify                 # every mark against the chain\ngit mark info                   # balance, marks, closed or not\n```\n\nAnyone with a clone can run these; they need no key.\n\nWhen the agent is finished, the coin goes back to the funder and the trail is closed.\n\n```\nnpx fund-agent status           # Address: tb1p… — the funder's address\ngit mark exodus <that address> --dry\n```\n\nRead the dry run: `Spend:` is the current TXO, `To:` is the funder's address, `Send:` is the balance less 300.\n`Raw:` is the transaction. Nothing was broadcast. Then:\n\n```\ngit mark exodus <that address>\n```\n\nCheck: output ends `Trail closed: git mark will not mark again.` Then `git mark info` shows `Closed: exodus …`\nand `Balance: 0 sats`, and `git config --local gitmark.txo` prints nothing. The agent's addresses hold no UTXOs.\nCommit `blocktrails.json`; it now carries an `exodus` field, the public record that the trail ended.\n\nAfter exodus, `git mark` refuses. That is the point. A new trail means a new repo and a new key.\n\n| Symptom | Meaning | Do | \n|---|---|---|\n| `fund-agent` : voucher has no coins | the operator's voucher is empty | stop, report the printed address | \n| `git mark init` : no coin found | funding not yet visible | wait one block, run init again | \n| `git mark` : already the last mark | nothing new to mark | commit first; `--force` only on the operator's word | \n| `git mark` : Trail is closed | exodus has run | nothing; a new repo if more work is wanted | \n| `announce` : 0/n relays | relay trouble, not a chain problem | change `nostr.relays` , announce again | \n| explorer errors | mempool.guide down or rate limited | `GITMARK_EXPLORER=<another esplora api>` and retry, once | \n| anything after \"broadcast\" | the spend may be on the chain | look the txid up before retrying | \n\nThe agent cannot make coins. If `~/.gitmark/faucet.txt` is missing, `npx fund-agent init` creates a key and prints\nan address; the operator sends testnet coins there (a faucet, a wallet), and `npx fund-agent status` shows them.\nThen step 2.\n\nEach mark spends the previous coin to an address derived from the commit hash, so the chain holds an ordered,\ntimestamped, unforgeable sequence of this agent's commits, verifiable from `blocktrails.json` alone. Exodus ends\nthe sequence in public: no coin, no further marks under this key.\n\nReferences: gitmark [https://github.com/solidpayorg/gitmark](https://github.com/solidpayorg/gitmark) (SKILL.md, BURN.md), fund-agent\n[https://github.com/blocktrails/fund-agent](https://github.com/blocktrails/fund-agent), create-agent [https://init-agent.com/SKILL.md](https://init-agent.com/SKILL.md), the console\n[https://play-grounds.github.io/gitmark/](https://play-grounds.github.io/gitmark/), git-mark.com.", "url": "https://wpnews.pro/news/an-agent-s-life-on-the-chain-init-to-exodus-gitmark-workflow-for-llm-agents", "canonical_source": "https://gist.github.com/melvincarvalho/69bc7991687d4182cb4de0090b5d16d9", "published_at": "2026-10-18 15:56:41+00:00", "updated_at": "2026-10-18 16:19:19.647493+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "ai-tools"], "entities": ["gitmark", "Nostr", "Bitcoin", "NIP-34", "npm"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/an-agent-s-life-on-the-chain-init-to-exodus-gitmark-workflow-for-llm-agents", "markdown": "https://wpnews.pro/news/an-agent-s-life-on-the-chain-init-to-exodus-gitmark-workflow-for-llm-agents.md", "text": "https://wpnews.pro/news/an-agent-s-life-on-the-chain-init-to-exodus-gitmark-workflow-for-llm-agents.txt", "jsonld": "https://wpnews.pro/news/an-agent-s-life-on-the-chain-init-to-exodus-gitmark-workflow-for-llm-agents.jsonld"}}