Worked integration

A verified outcome in the loop

See how a LangGraph agent checks delivered work, reads the earned value from a signed Spoolis Outcome Receipt, and uses that result to gate its own payment step.

Updated August 14, 2026

An agent framework can stop before a payment tool runs. It still needs a trustworthy answer to a different question: what did the provider earn? In the LangGraph and Spoolis example, the graph gets that answer from a signed Outcome Receipt, then applies its own policy before resuming its payment step.

The distinction matters. LangGraph gates its own payment step. Spoolis doesn't pause the graph or authorize payment. It doesn't submit settlement before its verdict. Spoolis turns the agreed criteria into checks, verifies the submitted evidence, calculates earned value, and signs the result.

The loop in one line. The graph requests verification, reads receipt.amounts.earned, checks the receipt under buyer policy, then resumes its own payment step with that amount.

Why an interrupt is not a verdict

LangGraph's interrupt() gives a graph a clean place to stop before a consequential tool call. It doesn't decide whether the work passed or how much was earned. A person can make that decision for an exception, but requiring one for every routine agent purchase defeats the point of an automated workflow.

The example separates those jobs. A verification node sends the agreement and evidence through Spoolis. A later payment-gate node interrupts with the receipt ID, result, and earned amount. The runner checks its policy and sends a resume command bound to that receipt. Only then can the graph reach its payment tool.

The worked example

The public example uses the account-free Spoolis sandbox to model a $10.00 task: 10 records at $1.00 each. Ten records arrive. Eight contain both required fields, while two omit status. Deterministic checks accept eight records, reject two, and produce a signed sandbox receipt with $8.00 earned.

The graph saves the receipt and carries receipt.amounts.earned forward. The payment tool receives that decimal amount as its input. In this example the tool is deliberately a stub. It prints what it would pay, so no real money moves.

You can inspect the code, notebook, and independent receipt verifier in the public repository. To see the same sandbox mechanics in the browser, walk from compilation to a verified receipt.

Keep verification outside the interrupted node

LangGraph restarts an interrupted node from the beginning when the graph resumes. That's why the example keeps the Spoolis network call in the preceding verification node and puts interrupt() in a separate payment-gate node. Resuming the graph doesn't rerun verification.

The example also uses a checkpointer and a stable thread ID. The runner resumes the same thread and binds the resume value to the saved receipt ID. Those details are framework mechanics, but they protect an important boundary: the value approved by buyer policy is tied to the receipt the graph actually received.

What the signature proves

The repository includes a separate Node.js verifier that checks the receipt against Spoolis's published trust set. A valid Ed25519 signature proves that the receipt came from a trusted published key and was not altered.

It doesn't prove that the underlying evidence was true, authorize payment, or establish that settlement happened. Those decisions stay with your application, payment authority, and rail. The Outcome Receipt specification defines these boundaries in detail.

What changes in production

This worked example is a sandbox integration, not a production payment system. The sandbox moves no real money. Its in-memory LangGraph checkpointer is suitable for a short example, not durable production state.

A production buyer would verify receipt authenticity before a consequential action and define explicit rules for identity, replay protection, amount limits, authorization scope, and settlement. For a PARTIAL result, the built-in settlement flow captures exactly the pro-rata amount in receipt.amounts.earned. FAIL and UNCERTAIN results move nothing.

The verification boundary is also intentionally plain about current capability. Deterministic checks and human-confirmed checks are live. AI-assisted verification is live for one checker, claim_cited, with code-verified citations.

The reusable pattern

LangGraph is the worked example, but the pattern belongs to any agent runtime that can separate verification from a consequential tool call:

  1. Fix the criteria and evidence requirements before evaluating the work.
  2. Ask Spoolis to verify the evidence and sign the resulting earned value.
  3. Verify the receipt's authenticity and apply the buyer's own policy.
  4. Let the runtime resume its payment step with receipt.amounts.earned as the input.

That puts a verified outcome in the loop without confusing the referee with the bank. Spoolis never receives the principal's signing key or payment credentials. The runtime decides whether its workflow continues, the payment authority decides whether spending is allowed, and the rail handles money movement.

A verified outcome in the loop · Spoolis