About Projects Articles
Architecture · Web3 · DeSci · Agentic Systems

When the Chain Is Not Enough: Building a Full-Stack Agentic DApp

A DeSci peer-review case study, told as a user journey — where every step in the workflow introduces the piece of the stack that makes it possible.

Companion piece to the BioVerify project page.

Peer review is broken: opaque, unpaid, and riddled with conflicts of interest. What if we could make it verifiable, fair, and economically aligned?

I built BioVerify: a full-stack agentic DApp where authors stake ETH on their research, reviewers are selected by Chainlink VRF, every artifact is content-addressed on IPFS, and AI agents coordinate the rest — with humans making every verdict call. You can try it on the live demo (Base Sepolia and Ethereum Sepolia, no setup), and the architecture and source are open on GitHub.

This is a case study in trust-minimised coordination: the chain records what happened, and agents orchestrate what happens next. Having spent fifteen years in Molecular Biology and Civil/Environmental Engineering before software — and having been on the author side of peer review myself — I had a specific reason to care. Rather than describe the stack in the abstract, this article follows the system as a user experiences it, and introduces each piece of technology precisely at the moment the story needs it.

"Truth on-chain, orchestration off-chain — with humans making every verdict call."

Why decentralised peer review — and why now

Peer review is a coordination game with a trust deficit: opaque processes, inconsistent conflict disclosure, and reviewers who are rarely compensated. Blockchain cannot fix science, but it can make parts of the process verifiable — stakes and outcomes settle on-chain, participants can prove what they signed, and for one specific subproblem (selecting reviewers fairly) Chainlink VRF attaches a cryptographic proof to the randomness so the draw can be audited.

BioVerify is an experiment in the coordination patterns that matter here: long-running workflows, randomly selected participants from a staked pool, human-in-the-loop delays, economic accountability, and settlement back on-chain.

TL;DR
  • What it is — a DeSci peer-review case study: stake, verifiable reviewer selection, AI screening, human verdicts, on-chain settlement.
  • CQRS as a first principle — the contract emits events (writes); an off-chain Postgres projection handles all reads. The chain is truth, not a database.
  • Durable coordination — Inngest wraps agents in durable step.run with retries and crash-resume on serverless; LangGraph interrupt() pauses for human signatures, and Postgres checkpointers persist graph state between resumes.
  • Human-in-the-loop — AI agents coordinate the workflow, but reviewers make every verdict call; agents record and settle, they never override.

Author flow
Submitting a publication

Choosing a network

An author wishing to submit their work first chooses the network: Base Sepolia or Ethereum Sepolia. BioVerify deploys BioVerifyV3 independently on both testnets, each with its own contract address, reward and slash pools, and reviewer pool. The same Solidity source is deployed to both networks, producing the same ABI on each — only per-chain parameters such as the Chainlink VRF coordinator and subscription differ. This multi-chain design is deliberate: BioVerify is chain-agnostic across EVM-compatible networks; the same coordination patterns work without modifying application logic.

Building the submission: IPFS and content addressing

The author fills a form with the components of their research: title, abstract, authors, body content, and any supporting files. Before anything touches the blockchain, each of these components is uploaded to IPFS — the InterPlanetary File System.

IPFS addresses files by content, not location: a CID (Content IDentifier) is a cryptographic hash of the bytes. Change a single byte and the CID changes — once recorded on-chain, it is a commitment to exactly those bytes.

BioVerify uses Pinata as the IPFS pinning service. Each component is uploaded individually, producing its own CID. The frontend then assembles a final research manifest — a structured JSON object containing all the component CIDs — and pins that too. The manifest's CID becomes the single identifier for the whole submission.

Calling the contract: stake and submission fee

With the manifest CID in hand, the author calls submitPublication(cid) on the BioVerifyV3 contract — alongside two distinct ETH amounts:

  • A stake. The author puts skin in the game. If the publication is rejected for plagiarism or fails peer review, this stake is slashed. If it passes, the stake is returned plus a reputation boost. That alignment makes the incentive structure legible: the author is incentivised to submit only non-plagiarised work and only work they believe will survive human peer review.
  • A submission fee. This is not a platform fee — it funds Chainlink VRF (Verifiable Random Function). On-chain, the fee is msg.value minus the fixed publisher stake; callers may overpay so spikes in gas or VRF costs stay covered. When pickReviewers runs, the contract forwards paidSubmissionFee into the VRF subscription via fundSubscriptionWithNative, so each submission directly tops up the oracle budget. The frontend can estimate that fee in real time from current conditions while the contract enforces a minimum.

The contract records the author's address, the publication CID, and the paid submission fee, transitions the publication to SUBMITTED status, and emits SubmitPublication.


Infrastructure
From on-chain event to off-chain intelligence

Getter-less contract: CQRS as a first principle

BioVerifyV3 is deliberately getter-light. It emits a granular event for every state transition and avoids exposing view functions for UI queries. This is CQRS — Command Query Responsibility Segregation — applied at the chain boundary: the contract is the write model; an off-chain Postgres projection is the read model.

The contract benefits: smaller bytecode means cheaper deployment, lower ongoing interaction gas where it matters, and a smaller attack surface to audit. The frontend benefits: the UI reads a fast Postgres projection rather than orchestrating dozens of eth_call requests against the chain — work the EVM is not optimised for product lists — while Drizzle-backed queries support rich filtering, sorting, and pagination. The chain is the source of truth; Postgres reflects that truth and is the source of responsiveness, lowering UI latency.

Alchemy Notify: from block to webhook

Alchemy Notify is Alchemy's webhook service. For each network, BioVerify configures one webhook scoped to a single contract address — the deployed BioVerifyV3 — so Alchemy POSTs a signed payload containing the event logs that contract emitted in each new confirmed block. Two such webhooks run in parallel — one for Base Sepolia, one for Ethereum Sepolia — both reacting to the same set of BioVerifyV3 events and both POSTing to the Next.js API route at /api/webhooks/alchemy/all-events.

That route runs as a Vercel serverless function. The first thing it does is verify the webhook's HMAC-SHA256 signature: Alchemy and the server share a per-network secret key, and any payload that does not match is rejected immediately. This prevents spoofed events from triggering agent actions or corrupting the read model.

The Neon Postgres read model: OCC projection

Once the signature is verified, the raw log is decoded with viem and dispatched to processContractEvent() — the core projector in the @packages/cqrs layer. This function translates on-chain events into typed updates and writes them into Neon Postgres.

The correctness mechanism is Optimistic Concurrency Control (OCC): each event carries a position stamp from the blockchain — its block number and log index. The projector only applies an update if the incoming event is more recent than what it has already stored. Late webhook deliveries can repeat; they cannot roll the read model backward. A viem WebSocket subscription to NewPublicationStatus invalidates the matching TanStack Query keys the moment the event is mined, so open lists update without polling.

Optimistic concurrency (OCC)
Webhooks can replay or arrive out of chronological order — that is intrinsic to networked indexers and retries. BioVerify attaches a deterministic ordering stamp from Ethereum — block number plus log index — to each upsert. An update applies only when the inbound event sorts strictly newer than what is already stored. Duplicates converge idempotently; stale deliveries cannot rewind fresher projections. That guards the projection against duplication and reorder chaos that webhook pipelines naturally introduce.
Figure 1 — Event pipeline: from contract event to read model and agents
Figure 1 — Event pipelineBioVerifyV3· writes· emits granular eventsAlchemy Notifycontract-scoped · signed webhookNext.js serverless handlerHMAC-SHA256 verify → decode → routeNeon Postgres· reads· OCC on (block, logIndex)Inngest· Durable execution· wraps LangGraph agentstriggered for 2 events only:· SubmitPublication· Agent_PickReviewersUI read model· fast and rich queries· no eth_call
Every event from the contract flows through the same pipeline — decoded, verified, projected to Postgres. Only two specific contract events also dispatch an Inngest event that wraps a LangGraph agent.
Event families on BioVerifyV3
Pools: RewardPool, SlashPool; members / stakes: RewardMember, SlashMember, IsAvailableReviewer, MemberReputation, MemberAvailableStake, MemberLockedStake, MemberLockedStakeOnPubId, Claim; publications: SubmitPublication, LockedStakeOnPubId, NewPublicationStatus; agent + VRF: Agent_RequestVRF, Agent_PickReviewers, Agent_RecordReview, Agent_FinalizePublication, treasury moves (Agent_TransferSlashPoolToTreasury, Agent_MoveSlashPoolToRewardPool). The projector in @packages/cqrs folds these into three Drizzle-backed tables: protocol, member, publication.

Why Inngest, and why only two events trigger agents

Almost every BioVerify contract event exists to update the Postgres read model. Only two events also mean new long-running off-chain work must begin: SubmitPublication kicks off plagiarism screening for a manuscript; Agent_PickReviewers means VRF has finished, reviewers for that submitted publication have been picked, and human verdict collection must start. Everything else — stake movements, status transitions after settlement, treasury plumbing — is bookkeeping the projector already knows how to fold into Drizzle tables.

Those two moments map to Inngest events CHAIN_SUBMISSION_RECEIVED (submission agent) and CHAIN_PICKED_REVIEWERS_RECEIVED (review agent). Each handler wraps a LangGraph invocation inside a durable Inngest step.run.

Why Inngest? Vercel serverless functions have tight per-invocation time limits and no guaranteed in-memory state between invocations. Inngest wraps each agent run in a durable execution shell: automatic retries, step isolation so successful steps are not replayed, and clean crash-recovery if a worker dies mid-run. It is not the mechanism that waits days for a reviewer — that pause lives in LangGraph.

Why LangGraph? Human review needs real suspension inside the graph: interrupt() stops execution until a verified EIP-712 payload arrives, while the Postgres checkpointer remembers partial progress (who already reviewed, whether escalation opened). When a Next.js server action resumes the thread with Command({ resume }), the checkpointer reloads that state so the agent continues without replaying completed nodes.

Recap — what has happened so far
  • Author submits: manuscript uploaded to IPFS, CID + stake + submission fee recorded on-chain
  • Contract emits SubmitPublication → Alchemy Notify → Next.js webhook (HMAC-verified)
  • Projector writes to Neon Postgres read model with OCC (no event can roll the state back)
  • Inngest triggers the Submission Agent via a wrapped LangGraph call

Agent 1 — Submission screening
Plagiarism check, then pick or slash

The submission agent runs a linear sequence of nodes — no branching until the very end, which keeps the logic easy to follow. Here is what it does, step by step.

Fetch from IPFS. The agent retrieves the full publication manifest by its CID. This is the same content the author uploaded — content-addressed, so the agent is guaranteed to read exactly what was submitted, unchanged.

Plagiarism check with Exa. The agent passes the abstract to Exa AI — a semantic web search API optimised for research literature. Exa returns a ranked list of potentially similar publications from across the public web and academic databases.

LLM synthesis with Gemini. The raw Exa results are passed to a Gemini language model, which synthesises the similarity signals and produces a structured verdict inside the graph: pass (continue to review) or fail (plagiarism). The LLM node itself never touches the chain — no contract calls happen inside that step. Crucially, the output is schema-constrained; after the graph finishes, agent-start.ts maps pass/fail to exactly one CQRS command path.

Branch: plagiarism detected → earlySlashPublication(). On fail, the agent invokes earlySlashPublicationCommand: the AI verdict is pinned to IPFS, then earlySlashPublication(pubId, verdictCid) is called through the agent's immutable wallet. The contract slashes the author's stake and transitions the publication to EARLY_SLASHED. The workflow ends here for this publication.

Branch: clean → pickReviewers(). On pass, pickReviewersCommand calls pickReviewers(pubId) on the contract. This triggers the Chainlink VRF request — which is where the randomness story begins.

Access control: agent-gated transitions

Only the agent's immutable wallet address — set once at contract deployment and unchangeable afterwards — can call earlySlashPublication, pickReviewers, recordReview, publishPublication, slashPublication, and pool-management moves guarded by onlyAgent. Arbitrary callers cannot trigger those transitions — the contract simply checks msg.sender against the immutable agent address.

Figure 2 — Submission agent: linear screening → branch to earlySlash or pickReviewers
Figure 2 — Submission agentSUBMISSION AGENT (Inngest + LangGraph)1. Fetch IPFSretrieve manifestby CID2. Exa plagiarismsemantic web search3. Gemini LLMschema-constrainedverdict4. DecisionearlySlash orpickReviewersplagiarismearlySlashPublication()cleanpickReviewers()
The submission agent's nodes run in sequence; only the final command branches. Schema-constraining the LLM output ensures only two valid on-chain actions are possible.

Demo — AI plagiarism detection and early slashing. Dual-device view: User A (left, mobile, no wallet) on /publications; User B (right, tablet, wallet on Base Sepolia).

Step 1 — User B submits on Base Sepolia
User B on tablet submits a publication that duplicates existing literature; transaction confirmed on Base Sepolia
User B submits a publication that duplicates existing literature.
Step 2 — Realtime list → EARLY_SLASHED
User A on mobile sees the new publication row appear in real time over WebSocket without a wallet; status ends at EARLY_SLASHED
User A sees the row appear in real time over WebSocket — no wallet, no refresh. The publication ends at EARLY_SLASHED with the AI verdict loaded from IPFS.

Verifiable randomness
Fair reviewer selection via Chainlink VRF

The reviewer pool: anyone can join by staking

Any user can register as a reviewer by depositing a reviewer stake into the contract. This stake is the reviewer's skin in the game: if a reviewer delivers a verdict that is later deemed negligent (more on this below), their stake is slashed. Staking is also what makes Sybil attacks expensive: each fake reviewer account costs real ETH, and VRF only draws a handful of reviewers per publication, so the probability that any given fake account is drawn falls as the honest pool grows.

Why VRF, and why it matters when stakes are real

Blockchains are deterministic. Any randomness derived from public on-chain fields (blockhash, block.timestamp) is predictable or influenceable in principle — not sufficient when selection has economic consequences.

Chainlink VRF v2.5 follows the usual hybrid smart-contract pattern: random words are produced off-chain together with a cryptographic proof; the consumer contract verifies that proof on-chain before consuming the words. The draw is not merely opaque — it is verifiable. Think of it as a public lottery where you do not have to trust the organiser: anyone can re-check the draw afterward.

In BioVerify's flow: the agent calls pickReviewers() → the contract calls requestRandomWords() → Chainlink fulfills via fulfillRandomWords() → the callback selects reviewers from the staked pool and emits Agent_PickReviewers. That event re-enters the exact same event pipeline — Alchemy Notify, HMAC-verified webhook, Neon Postgres projection — closing the loop without any special-casing.

Figure 3 — Chainlink VRF: verifiable reviewer selection
Figure 3 — Chainlink VRFAgentpickReviewers()BioVerifyV3requestRandomWords()CHAINLINK VRFRandom words+ cryptographic proofBioVerifyV3fulfillRandomWords()Agent_PickReviewers event→ pipeline
Random words come back with a cryptographic proof; the contract verifies the proof on-chain before drawing reviewers from the staked pool.

Demo — Submitting a publication (success path). Split view: BioVerify Telegram bot (left) and DApp (right).

Step 1 — Fill the publication form
Author fills the publication form on the DApp with metadata and IPFS manifest, ready to submit
The author fills in the publication form (metadata and IPFS manifest) and prepares to submit.
Step 2 — Submitted → In Review
Author confirms the on-chain submitPublication transaction; the Telegram bot mirrors SUBMITTED then IN_REVIEW as the events are mined
The author confirms the on-chain transaction. The bot receives status notifications as the publication moves from SUBMITTED to IN_REVIEW.
Step 3 — VRF reviewers on the publication detail
Publication detail page on the DApp showing IN_REVIEW status and the Chainlink VRF–selected reviewer addresses
The publication detail page shows IN_REVIEW and the Chainlink VRF–selected reviewers.

Agent 2 — Human-in-the-loop review
Verdicts, escalation, and settlement

After projection, Agent_PickReviewers fires CHAIN_PICKED_REVIEWERS_RECEIVED into Inngest, which kicks off the second LangGraph agent. This agent is the most complex part of the system — it manages a workflow that can pause for days, handles human escalation, and ultimately settles the publication on-chain.

Human-in-the-loop (HITL): what pausing actually means

HITL is wired directly into the LangGraph itself. When the review workflow reaches humanReviewsNode, the graph calls interrupt() and stops. The Inngest step that wrapped the agent invocation finishes normally — the work is paused, not blocked — and LangGraph's Postgres checkpointer persists the partial graph state in Neon. Days later, when a reviewer signs their verdict, a Next.js server action verifies the EIP-712 payload and calls resumeReviewersAgent, which issues Command({ resume }). LangGraph reloads the thread state from the checkpointer, applies the new review, records recordReview on-chain once the payload checks out, and continues until the next interrupt or settlement.

How reviewers submit verdicts: EIP-712 gasless signing

Reviewers are not push-notified by the system — they check the reviewer dashboard at /publications/assignments, find the publication they have been assigned to review, and step through the flow from there. They read the manuscript and submit their verdict — without paying gas for the review transaction itself. Instead, they sign using EIP-712: typed structured data that yields a standard cryptographic signature without broadcasting a transaction.

The signed payload is posted to the backend off-chain. After viem verifies the signature and confirms the signer is exactly the reviewer assigned to this publication, the agent calls recordReview(pubId, reviewer) through the agent wallet. On-chain, that call only records that this reviewer has submitted their review for this publication; the qualitative verdict stays in LangGraph until settlement encodes honest versus negligent addresses.

Anyone can also follow the public BioVerify Telegram bot, which broadcasts contract state transitions in real time across both Base Sepolia and Ethereum Sepolia.

Peer reviewers, senior reviewers, and the escalation path

BioVerify distinguishes two reviewer roles within a publication cycle (current Base Sepolia and Ethereum Sepolia deployments draw I_VRF_NUM_WORDS = 3 candidates so there are two explicit peers plus one senior; the senior is whichever drawn reviewer has the highest on-chain reputation):

  • Peer reviewers. The non-senior members of the VRF draw. They submit independent pass/fail verdicts. When both agree, the graph routes straight to settlement — publishPublication if the shared verdict is pass, slashPublication if it is fail; in that branch the settlement helper classifies both peers as honest: each gets their stake back, the reviewer reward, and a reputation bump — the senior reviewer is not invoked.
  • Senior reviewer. Drawn alongside peers but designated as the highest-reputation reviewer of the three. If peers disagree, the workflow escalates to the senior reviewer (tie-break assisted by Gemini), who signs a binding verdict. The peer who aligned with the senior is honest; the dissenting peer is negligent and is slashed (stake to the slash pool, reputation drop). Even when peers agree, the senior remains economically aligned: settlement code unconditionally credits them as honest — their locked stake unlocks and they still receive the reviewer reward, on the grounds that they served as the standby escalation authority.

Possible outcomes and what triggers settlement

The review agent settles the publication once the binding verdict is established — either by peer reviewer consensus or senior reviewer decision. It calls one of two contract functions through the agent address:

  • publishPublication(pubId, honest, negligent, verdictCid) PUBLISHED. The publisher's locked stake unlocks back into availableStake and their reputation increases. Every address listed as honest (peers who matched the decision plus the senior reviewer) unlocks stake, receives the configured reviewer reward, and gains reputation. Negligent reviewers lose their locked stake to the slash pool and take a reputation penalty.
  • slashPublication(pubId, honest, negligent, verdictCid) SLASHED. The publisher is slashed the same way as other failure paths. Honest reviewers — including those who caught the failure — still receive stake, reward, and reputation; negligent reviewers are slashed.

Settlement deliberately uses a pull payment pattern: instead of pushing ETH to every participant inside the settlement transaction — where one malicious or buggy receive() hook could revert and grief the entire cohort (a denial-of-service against honest actors) — the contract moves value into internal balances and lets each party call claim() on their own schedule. Gas isolates per claimant; failures stay local.

Figure 4 — Review agent: HITL, escalation, and settlement
Figure 4 — Review agentREVIEW AGENT (Inngest + LangGraph — HITL)LangGraph rehydrates statefrom Neon Postgres checkpointerHuman-in-the-loop pauseLangGraph interrupt() — Inngest step exitsResume via Command({ resume }) when reviewer signs EIP-712 (may take days)Peer reviewers agree?consensus or conflictconflictSenior reviewerbreaks tie → bindingconsensusBinding verdictpass or failfailslashPublication()passpublishPublication()
The review agent runs under Inngest for durable step.run boundaries while LangGraph owns human pauses: the checkpointer restores state after each interrupt() so the graph knows both what it last knew and what must happen next.

Demo — Peer review with human-in-the-loop conflict resolution. Two peer reviewers return conflicting verdicts; the senior reviewer breaks the tie and settlement flips the publication to PUBLISHED.

Step 1 — First peer reviewer: PASS (EIP-712 signature)
First peer reviewer signs an EIP-712 pass verdict off-chain in their wallet; the agent records the review on-chain
The first peer reviewer submits a pass verdict — signed off-chain via EIP-712 before the agent records it on-chain.
Step 2 — Second peer reviewer: FAIL → conflict, escalation
Second peer reviewer submits a fail verdict; the two reviews now conflict and the workflow escalates
The second peer reviewer submits a fail verdict. The two reviews now conflict, which triggers the escalation path.
Step 3 — Senior reviewer breaks the tie (PASS)
Split view: Telegram bot shows both peer reviews and the agent's escalation decision; the senior reviewer submits a tie-breaking pass
Split view: Telegram bot (left) and senior reviewer (right). The bot shows both peer reviews and the agent's decision to escalate. The senior reviewer submits a tie-breaking pass.
Step 4 — PUBLISHED with the verdict resolved from IPFS
Telegram bot shows PUBLISHED status; the publication detail page resolves the final verdict CID from IPFS after the senior reviewer's tie-break
After the senior review, Telegram reflects PUBLISHED and the detail page shows the final verdict resolved from IPFS.
Recap — full lifecycle
  • Author uploads to IPFS → calls submitPublication with stake + submission fee
  • SubmitPublication → pipeline → Neon DB + Inngest → Submission Agent
  • Submission Agent: IPFS fetch → Exa plagiarism check → Gemini verdict → earlySlashPublication or pickReviewers
  • pickReviewers → Chainlink VRF → Agent_PickReviewers → the same webhook + projector pipeline → Review Agent
  • Review Agent: LangGraph interrupt() while reviewers sign EIP-712 payloads → consensus or escalation → publishPublication / slashPublication
  • Settlement: rewards honest actors and/or slashes negligent ones; pull payments credit internal balances on-chain — each party calls claim() themselves

Incentives: making honesty the rational choice

The economic mechanics aim for honest participation to be the dominant strategy inside a trust-minimised system — not by assuming participants are virtuous, but by making dishonesty costly in every scenario the contract can observe.

OutcomeTriggerPublisherHonest reviewersNegligent reviewers
Early SlashedPlagiarism detected pre-reviewStake slashed · rep penaltyNone selected yetN/A
PublishedPeer review consensus: passStake returned · rep boostStake + reward + rep boostStake slashed · rep penalty
SlashedPeer review consensus: failStake slashed · rep penaltyStake + reward + rep boostStake slashed · rep penalty
Honesty is measured against the binding verdict (peer consensus or senior tie-break), not the paper's outcome. The senior reviewer is always classified as honest at settlement.

Honesty is measured against the binding verdict, not the paper's outcome. When peer reviewers agree, both peers aligned with that verdict are rewarded; the senior is always credited as honest at settlement so their standby stake and reward settle cleanly. When peers conflict, the senior reviewer's verdict is binding: the matching peer is honest; the dissenting peer is negligent. The system is intentionally simple, with a clear limitation: a wrong or compromised senior reviewer gets the final word — the roadmap addresses this with weighted majority voting based on on-chain reputation.


Security as a first-class concern

CEI pattern (Checks–Effects–Interactions) is applied consistently across external state-mutating functions in BioVerifyV3. OpenZeppelin nonReentrant additionally guards ETH-out paths: claim and transferSlashPoolToTreasury.

Pull payments. As described above, pushing ETH to every recipient in one transaction would concentrate griefing risk: the contract itself becomes the caller, and a single reverting receive() could deny service to the entire cohort. Crediting internal balances plus user-initiated claim() transfers isolates failure modes and caps settlement gas for the agent.

Contract test coverage. BioVerifyV3 ships with full coverage in Foundry: 50 tests across 12 suites — 100% lines, statements, branches, and functions. VRF flows use VRFCoordinatorV2_5Mock with deterministic fulfillment overrides and log assertions, including edge cases such as colliding random words.


The pattern generalises

Peer review is the domain BioVerify is grounded in, but the coordination pattern is not specific to science. The same problems show up wherever multiple mutually untrusting actors need a trust-minimised process, with verifiable selection, long-running human-in-the-loop steps, and on-chain settlement.

These are not claims I have validated — they are domains where I see the same structural ingredients (verifiable selection, long-lived HITL, on-chain settlement) and think the coordination pattern could apply:

  • Legal arbitration — verifiable evidence submission, randomly selected arbitrators from a staked pool, durable multi-week deliberation, tamper-evident record of proceedings.
  • Insurance claims — multi-assessor processing where each step needs an audit trail and assessors have economic skin in the game.
  • DAO governance — proposal review with randomly drawn delegates, slashing for negligent voters, durable agent coordination across asynchronous human input.
  • Supply chain compliance — multi-party certification workflows where documents need content-addressed storage and auditor selection needs to be bias-resistant.
Verifiable fairness, economic accountability, durable coordination — the throughline is always the same trio. BioVerify is one instantiation.

What this build is, and what it is not

BioVerify is a case study, not a finished product. The current build covers the optimistic happy paths. The hardening backlog and roadmap include:

  • Author escalation path — today a plagiarism false positive from the submission agent (or a peer-review verdict the author believes is wrong) is terminal: settlement runs immediately and the author has no contractual recourse. The roadmap addresses this with an opt-in escalation: the author posts a larger escalation stake within a bounded window, which triggers a second review cycle restricted to humans only, drawn from a fresh VRF cohort that excludes the original reviewers. The second verdict is binding and reconciles the first — confirmed means an additional slash; overturned means prior rewards and slashes are reversed and recomputed. This implies that terminal settlement effects must be deferred or reversible until the escalation window closes.
  • Weighted majority voting — replaces the single-senior-reviewer tie-break with reputation-weighted consensus, removing the single point of failure.
  • ZK reputation via Reclaim Protocol — lets reviewers prove off-chain credentials (ORCID, h-index, institutional affiliation) without doxxing themselves, enabling credentialed review without exposing identity.
  • Encrypted access (Lit Protocol) and monetisation (x402) — manuscript confidentiality during review; post-publication micropayment gate routing revenue to researchers, closing the privacy and monetisation gaps.
  • Internal corpus + RAG (Neon + pgvector) — Exa handles general web plagiarism; an internal pgvector index compares submissions against BioVerify's own historical publications.
  • Known edge cases — empty or malformed IPFS payloads can leave a publication stuck in SUBMITTED; a gas spike during settlement can strand a publication in IN_REVIEW with no retry. The README documents these at the file level, including specific nodes and commands affected.

Tech stack at a glance

  • Blockchain & contracts — Foundry, Solidity, Chainlink VRF v2.5, EIP-712
  • Infrastructure — Alchemy Notify (contract-scoped webhooks), Vercel serverless functions
  • Agents & orchestration — LangGraph (graph state + HITL interrupts), Inngest (durable step.run, retries, crash recovery)
  • Data & storage — Neon Postgres (CQRS read model + LangGraph checkpointer), Drizzle ORM, IPFS via Pinata
  • LLM & search — Gemini, Exa AI
  • Frontend — Next.js, wagmi, viem, Reown AppKit, TanStack Query, TanStack Table, nuqs
  • Schema validation — Zod

Closing

What drew me into this build was the interplay between two layers with distinct responsibilities: the chain as the Truth layer — where stakes settle, agent-gated transitions execute, and VRF proofs are verified — and agents as the Orchestration layer — where multi-actor, multi-day workflows actually play out.

BioVerify is the case study I used to wire that idea end-to-end. The interesting work lives in the seams — between Inngest and LangGraph, between Alchemy webhooks and the OCC projector, between EIP-712 signatures and on-chain settlement — and in the contract incentives themselves: tuning staking, rewards, and slashing so that long-running review cycles stay economically coherent over days. That is what I want to keep building.

The contracts are deployed on Base Sepolia and Ethereum Sepolia, and the source is open.

The repo has the full architecture doc and a live demo.

The chain records what happened. Agents coordinate what happens next. And humans? They make the calls that matter.