Skip to main content
Use this tutorial after Quickstart with TypeScript SDK or Quickstart with MCP when you want to see the full Shodai agreement lifecycle work with a realistic agreement before authoring your own. You will run the service retainer example from authored agreement JSON through validation, deployment preflight, signed deployment, signed input submission, state reads, and input-history inspection. The service retainer is the teaching artifact for this tutorial. It is useful because it has participant roles, initialized business values, branching states, authorized inputs, EIP-712 signatures, state transitions, and an auditable history. You do not need to be building a retainer product to learn from it.

What you will learn

By the end of this workflow, you will have seen how:
  • authored agreement JSON defines variables, participants, states, inputs, issuers, and transitions
  • deployment context supplies live values such as participant wallets, chainId, and initialization data
  • deployment preflight normalizes the values that must be signed
  • EIP-712 permits authorize deployment and input submission
  • submitted inputs move an agreement through its authored state machine
  • state and input history provide receipts for what happened

Before you start

This tutorial has two equivalent paths. Use the MCP path when an agent is operating Shodai through MCP tools. Use the SDK path when you are building the workflow into a TypeScript integration. For setup details, see Quickstart with TypeScript SDK, Quickstart with MCP, TypeScript client reference, Authentication, and Complex Agreement.
Use testnet for a first run. Deployment and input submission are writes. They require signatures from eligible wallets, and successful submissions are not safe to retry blindly.

Choose a path

Both paths use the same lifecycle and the same underlying API model. The difference is the surface you operate through.

Run the workflow

1

Load the service retainer example

Read the complex-example-agreement MCP resource.The resource URI is:
MCP resources return JSON as text. Parse the returned contents[0].text value and keep the parsed object as agreement for the remaining MCP tool calls.This is the same agreement documented in Complex Agreement. It starts in AWAITING_PAYMENT, moves to WORK_IN_PROGRESS after initial payment proof, supports invoice review paths, can branch into top-up review, and can terminate through a final invoice flow.
2

Validate the authored agreement JSON

Call validate_agreement with environment: "testnet" and pass the parsed complex-example-agreement object as agreement.Review the validation result before continuing. The important evidence is the participant variable keys, state IDs, input IDs, and warnings. For this example, expect participant-backed variables such as serviceProviderRepresentative and clientRepresentative, and lifecycle inputs such as submitInitialPaymentProof and submitInvoice.Structural validation checks the agreement artifact only. It does not know which wallets or initialization values you will use for deployment.
3

Prepare deployment values

Choose deployment context for the first run.Keep participant wallet mappings and initialization values stable after preflight. If they change, regenerate the deployment typed data before signing.
4

Preflight deployment

Call preflight_deployment with the loaded agreement object, target chain, initialization values, and participant mappings.Use this deployment context with the loaded agreement:
Review the returned variables, participants, observers, contributors, and warnings before any signing step.
Preflight does not deploy the agreement. It assembles and validates the deployment request so you can sign the effective values rather than raw caller input.
5

Sign and deploy

For hosted MCP with external signing, call prepare_deployment_typed_data, sign the returned EIP-712 payload, then call deploy_agreement with the returned document link, normalized values, and permit fields.Call prepare_deployment_typed_data with:
  • environment: "testnet"
  • agreement: the loaded complex-example-agreement object
  • chainId: 59141
  • signerAddress: the wallet address that will sign and own the deployment
  • initValues: the same values used for preflight
  • participants: the same participant mappings used for preflight
Pass the same agreement, displayName, and chainId; the returned docUri and documentId when present; the normalizedInitValues, normalizedParticipants, and normalizedObservers returned by prepare_deployment_typed_data; and signer address, deadline, and signature fields into deploy_agreement.
Do not sign one deployment payload and submit another. Agreement JSON, initialization values, participant mappings, docUri, chain, factory context, nonce, and deadline are all part of the authorization boundary.
6

Read the deployed state

After deployment, call get_agreement_state.
The service retainer starts at AWAITING_PAYMENT. The current state tells you which authored inputs can move the lifecycle next.
7

Submit the first lifecycle input

Submit submitInitialPaymentProof to move the retainer from AWAITING_PAYMENT to WORK_IN_PROGRESS.First call prepare_input_typed_data with an eligible signer and the input values.
Sign the returned EIP-712 typed data externally, then call submit_input with the same agreementId, inputId, values, signer address, deadline, and signature fields.The submitInitialPaymentProof input can be issued by either representative in the service retainer example. Later inputs may be restricted to one role.
8

Inspect state and history

Reread current state and input history.
Use state to confirm the lifecycle position and input history to confirm that the submitted input appears with its status. Depending on transaction timing, an input may be PENDING, FINALIZED, or FAILED.

Try a branch

After the agreement reaches WORK_IN_PROGRESS, try one additional path to see why the complex example is useful.
Submit the submitInvoice input from WORK_IN_PROGRESS. The service provider representative must sign this input.Required values:
This path moves the agreement to INVOICE_SUBMITTED. From there, an authorized representative can approve, reject with feedback, or initiate termination.
Submit the submitInvoiceWithTopup input from WORK_IN_PROGRESS. The service provider representative must sign this input.Required values:
This path moves the agreement to INVOICE_SUBMITTED_WITH_TOPUP. The next step can approve with payment proof, reject with feedback, or initiate termination.

What happened under the hood

This tutorial uses one concrete agreement to exercise the core Shodai model.

If a step fails

Use Errors and troubleshooting for API errors, signing failures, and lifecycle diagnostics. Before retrying a write, reread state and input history so you do not sign or submit against a stale lifecycle position.

Next steps

Inspect the complex agreement

Study the complete service retainer JSON, lifecycle diagram, states, inputs, and transitions.

Author your own agreement

Turn a business workflow into agreement JSON after you have run the lifecycle once.

Build with the SDK

Use the TypeScript client reference for typed API calls, signing helpers, and diagnostics.

Quickstart with MCP

Configure the hosted MCP server and operate agreements through MCP tools.