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 often opaque, reviewers are rarely paid, and conflicts of interest are hard to see. I wanted to find out which parts of it could be made verifiable and fairly paid.
I built BioVerify: a full-stack agentic DApp where authors stake ETH on their research, reviewers are selected by Chainlink VRF, the submission and its final verdict are content-addressed on IPFS, and AI agents coordinate the rest, with people writing the reviews and Gemini or a senior reviewer setting the verdict. You can try it on the live demo (Base Sepolia and Ethereum Sepolia, no local setup), and the architecture and source are open on GitHub.
This is a case study in on-chain coordination: the chain records what happened, and agents orchestrate what happens next. One agent key still settles every outcome, so it is not yet trust-minimised. 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 involved in verdict calls."
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, reviewers sign their reviews, which are checked off-chain, and for one specific subproblem (drawing reviewers at random) 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.
- What it is: a DeSci peer-review case study with stakes, verifiable reviewer selection, AI screening, signed human reviews and on-chain settlement.
- CQRS as a first principle: the contract emits events (writes); an off-chain Postgres projection serves the reads of publications and members. The chain is truth, not a database.
- Durable coordination: Inngest starts each agent run and retries it if it fails (all of the screening, and the review agent up to its first pause); LangGraph
interrupt()pauses for human signatures, and Postgres checkpointers persist graph state between resumes, which run in a server action with no retry. - Human-in-the-loop: human reviewers sign the peer verdicts and the senior reviewer has the final word after an escalation; an agent records and settles them. The plagiarism screen, the call to escalate and the verdict when there is no escalation are Gemini's.
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. The two networks are hardcoded in the app, though: adding a chain means a new deployment plus changes in several places.
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, these components go to IPFS, the InterPlanetary File System.
IPFS addresses files by content, not location: a CID (Content IDentifier) is derived from a cryptographic hash of the content. Change a single byte and the CID changes, so a CID recorded on-chain is a commitment to exactly those bytes.
BioVerify uses Pinata as the IPFS pinning service. The title, abstract, body and each attached file are uploaded individually, each with its own CID. The server then pins a research manifest, a JSON object with those CIDs plus the authors and the license. 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, with one payment that covers two 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 pass review.
- A submission fee. It funds Chainlink VRF (Verifiable Random Function). On-chain, the fee is
msg.valueminus the fixed publisher stake; callers may overpay so spikes in gas or VRF costs stay covered. WhenpickReviewersruns, the contract forwardspaidSubmissionFeeinto the VRF subscription viafundSubscriptionWithNative, so each submission that passes screening tops up the oracle budget. An early-slashed submission never reaches that call: its fee stays in the contract, outside both pools, and nothing in the normal flow moves it. The frontend estimates that fee from the current gas price and a fixed gas budget, and sends the larger of that and the minimum the contract enforces.
The contract records the author's address, the publication CID, and the paid submission fee, transitions the publication to SUBMITTED status, and emits SubmitPublication.
From on-chain event to off-chain intelligence
Getter-light 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 and a smaller surface to audit (every write emits events, so writes cost a little more gas, not less). The frontend benefits: the UI reads a fast Postgres projection rather than orchestrating dozens of eth_call requests against the chain (the chain is not built for product lists), while Drizzle queries filter the list by network and status and page through it, newest first. 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, filtered in Alchemy's dashboard to the deployed BioVerifyV3 address, so Alchemy POSTs a signed payload containing the event logs that contract emitted in each new block; the route itself does not re-check which contract emitted a log. Two such webhooks run in parallel, one for Base Sepolia and 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 about three seconds after the event is mined (a delay that gives the webhook time to update Postgres), so open lists update without polling.
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 sixteen of them into three Drizzle-backed tables: protocol, member, publication. Claim, MemberLockedStakeOnPubId and Agent_RequestVRF are not projected.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 of the submission's abstract; 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 an Inngest step.run.
Why Inngest: Vercel serverless functions have tight per-invocation time limits and no guaranteed in-memory state between invocations. Inngest starts each agent run and retries it if it fails. The screening agent runs entirely inside one step.run, so a retry re-runs all of it, and it still has to finish within one function call. The review agent runs there only until its first interrupt(); every later step, settlement included, runs in the server action that resumes it, with no retry. The commands read state before writing where they can. 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.
- 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
Plagiarism check, then pick or slash
The submission agent runs a linear sequence of nodes, with 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 fetches the manifest by its CID, then the abstract it points to. This is the same content the author uploaded, addressed by its CID. The agent fetches it through the Pinata gateway without re-hashing it, so this relies on trusting the gateway.
Plagiarism check with Exa. The agent passes the abstract to Exa AI, a neural web search API, limited to its "research paper" category. Exa returns up to five similar papers, each with its text and a relevance score.
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. 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, 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 checks msg.sender against the immutable agent address.
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).
Verifiable 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 also puts a price on Sybil attacks: each fake reviewer account has to keep a reviewer stake deposited to stay in the pool (0.001 test ETH on the current deployments), 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, which is not enough 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 Chainlink VRF coordinator verifies that proof on-chain before calling back the consumer contract. The draw is verifiable. Think of it as a public lottery that anyone can re-check afterward. One caveat: the contract owner can change the VRF coordinator, so the draw is only as neutral as the coordinator it points to (listed under known edge cases).
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 same event pipeline (Alchemy Notify, the HMAC-verified webhook, the Neon Postgres projection), closing the loop through the same webhook and projector.
Demo: Submitting a publication (success path). Split view: BioVerify Telegram bot (left) and DApp (right).
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 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 one of the reviewers drawn for 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.
A Telegram bot also posts an alert to one chat at each step (screening, review and settlement, on both networks); the split-view demos show it.
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 the drawn reviewer with the highest on-chain reputation, or the first one drawn on a tie):
- Peer reviewers. The non-senior members of the VRF draw. They submit independent pass/fail verdicts, and Gemini reads them and returns pass, fail or escalate. When it settles (
publishPublicationon pass,slashPublicationon fail), each peer whose verdict matches Gemini's is honest and gets their stake back, the reviewer reward and a reputation bump; a peer who disagrees is negligent and is slashed. The senior reviewer is not asked. - Senior reviewer. Drawn alongside peers but designated as the highest-reputation reviewer of the three (the first drawn on a tie). If Gemini escalates (its prompt asks for that when the peers split or one flags a fraud risk the others missed, but the code does not force it), the senior reviewer signs a binding verdict: the code enforces it, and Gemini only rewrites the reasoning. Each peer whose verdict matches the senior's is honest; a peer who disagrees is negligent and is slashed (stake to the slash pool, reputation drop). Settlement always counts the senior as honest, with or without escalation: their locked stake unlocks and they get the reviewer reward for standing by as the escalation authority, so the senior is never slashed.
Possible outcomes and what triggers settlement
The review agent settles the publication once the binding verdict is established: Gemini's verdict or, after escalation, the senior reviewer's. It calls one of two contract functions through the agent address:
publishPublication(pubId, honest, negligent, verdictCid)→PUBLISHED. The publisher's locked stake unlocks back intoavailableStakeand 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.
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; Gemini escalates, the senior reviewer breaks the tie, and settlement flips the publication to PUBLISHED.
- 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 →
earlySlashPublicationorpickReviewers pickReviewers→ Chainlink VRF →Agent_PickReviewers→ the same webhook + projector pipeline → Review Agent- Review Agent: LangGraph
interrupt()while reviewers sign EIP-712 payloads → Gemini verdict or escalation →publishPublication/slashPublication - Settlement: rewards honest actors and/or slashes negligent ones; pull payments credit internal balances on-chain, and each party calls
claim()themselves
Incentives: making honesty the rational choice
The economic mechanics aim to make careful reviewing pay: a reviewer who matches the binding verdict gets their stake back plus a reward, and one who does not is slashed. The contract never sees the reviews; it applies the outcome and the honest and negligent lists the agent sends.
| Outcome | Trigger | Publisher | Honest reviewers | Negligent reviewers |
|---|---|---|---|---|
| Early Slashed | Plagiarism detected pre-review | Stake slashed · rep penalty | None selected | N/A |
| Published | Final verdict: pass | Stake returned · rep boost | Stake + reward + rep boost | Stake slashed · rep penalty |
| Slashed | Final verdict: fail | Stake slashed · rep penalty | Stake + reward + rep boost | Stake slashed · rep penalty |
| Honesty means matching the binding verdict (Gemini's, or the senior's after escalation), pass or fail. The senior reviewer is always classified as honest at settlement. | ||||
Honesty means matching the binding verdict, whichever way it goes. Without escalation, Gemini's verdict is binding: each peer who matches it is rewarded, and a peer who disagrees is negligent. After escalation, the senior reviewer's verdict is binding: each peer who matches it is honest, and each peer who does not is negligent. The senior is always credited as honest at settlement so their standby stake and reward settle cleanly. The system is intentionally simple, with clear limitations: without escalation, Gemini's reading of the reviews decides who is slashed, and after escalation a wrong or compromised senior reviewer gets the final word. The roadmap replaces the senior tie-break with voting weighted by on-chain reputation; Gemini's role without escalation has no planned fix yet.
Security as a first-class concern
claim and transferSlashPoolToTreasury, the two functions that send ETH to members or the treasury, follow the CEI pattern (Checks–Effects–Interactions) and carry OpenZeppelin nonReentrant. pickReviewers stores the VRF request ID after calling the coordinator, because the coordinator returns it.
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 has 50 Foundry tests in 12 suites, across 11 test files; forge coverage on 24 October 2026 shows 100% of the lines (240/240), branches (37/37) and functions of src/BioVerifyV3.sol. VRF flows use VRFCoordinatorV2_5Mock with deterministic fulfillment overrides and log assertions, including edge cases such as colliding random words. Only the contract has tests; the agents, the read model and the frontend have none.
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 shared process, with verifiable selection, long-running human-in-the-loop steps, and on-chain settlement.
I have not validated these. 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.
These domains share a verifiable draw, stakes and long human pauses. In BioVerify the draw is verifiable; the verdict still rests on the agent.
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:
- Less trust in the agent: separate the agent, the treasury and the owner, and record each review's signature on-chain so the contract can check who voted what.
- 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, so no single reviewer has the final word.
- ZK reputation via Reclaim Protocol: lets reviewers prove off-chain credentials (for example h-index or affiliation) without doxxing themselves, enabling credentialed review without exposing identity.
- Encrypted access (Lit Protocol) and monetisation (x402): manuscript confidentiality during review; micropayments to open datasets and supplementary material, closing the privacy and monetisation gaps.
- Internal corpus + RAG (Neon + pgvector): Exa searches research papers for text close to the abstract; an internal pgvector index would compare submissions with BioVerify's own past publications.
- Known edge cases: empty or malformed IPFS payloads can leave a publication stuck in
SUBMITTED; after the review agent's first pause, nothing is retried, so if a later step or the settlement transaction fails, for example on a gas spike, the publication staysIN_REVIEW.pickReviewerschecksstatus != IN_REVIEWinstead of== SUBMITTED, so the agent could re-open a finished publication; if the reviewer pool shrinks or rewards run out between the VRF request and the callback, the callback reverts and the publication staysIN_REVIEW; and linear probing on collisions slightly biases the draw. The webhook compares its HMAC with===, not in constant time, and the projection follows the chain tip with no confirmation depth. One agent key, which is also the treasury and the owner on both deployments, settles every outcome, and as owner it can change the VRF coordinator. Reviewers also have no deadline: one who never answers leaves the paperIN_REVIEW, with every stake locked. The README covers the rest, including agent transactions that use simulate-then-write with no gas bump or nonce recovery.
Tech stack at a glance
- Blockchain & contracts: Foundry, Solidity, Chainlink VRF v2.5
- Infrastructure: Alchemy Notify (contract-scoped webhooks), Vercel serverless functions
- Agents & orchestration: LangGraph (graph state + HITL interrupts), Inngest (starts and retries the agent runs that chain events trigger; the review agent only up to its first pause)
- Data & storage: Neon Postgres (CQRS read model + LangGraph checkpointer), Drizzle ORM, IPFS via Pinata
- LLM & search: Gemini, Exa AI
- Frontend: Next.js, TypeScript, wagmi, viem, Reown AppKit, TanStack Query, TanStack Table, nuqs, EIP-712 signing (checked on the server)
- 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 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, and between server-checked EIP-712 reviews and the settlement the agent sends on chain. It also lives in the contract incentives: 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.