Skip to main content

Getting Started

This walkthrough follows the lifecycle of an intent end-to-end. By the end you'll know how to submit a signed intent, receive its evaluation, and retrieve the resulting proof — enough to wire delta mandate into your platform. Examples use the mandate-orchestrator and mandate-verifier CLIs; see the API Guide for setup, or the Architecture for the system as a whole.

Before you start

  • A registered template — templates are reusable policy definitions; see Template Management to register one.
  • The mandate-orchestrator, mandate-verifier, and policy-engine CLIs installed — see Install.
  • A signing key for the user, or the operator's signing setup if signing on the user's behalf.

Intent Lifecycle

1. Submit a signed intent

An intent specifies what the user accepts. Either the user signs the intent themselves using their own key, or the operator signs it on their behalf.

The intent payload has three fields:

  • id — a UUID assigned by the caller
  • template_id — identifies the template that defines the rules for this intent
  • attrs — the input values that parameterize the template. Values sit under attrs.fields, keyed by field names declared in the template's intent schema.
{
"payload": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"template_id": "3mJr7AoLXfFj...",
"attrs": {
"fields": {
"max_price_cents": 5000,
"category": "pullover"
}
}
},
"signature": { "..." }
}

Once signed, the intent is submitted to the orchestrator — either directly by the user, or forwarded by the operator:

mandate-orchestrator intents submit --json-body signed_intent.json

2. Submit a proposal

The agent first discovers open intents — either by receiving them from the operator's platform or by querying the orchestrator directly (GET /intents/<intent_id>). It then submits a proposal for one of them, either directly or via the operator.

A proposal has two fields:

  • solution — an identifier of the proposed solution: a URL, a UCP product variant ID, or another identifier agreed between the template provider and the evidence layer.
  • metadata — an arbitrary JSON object passed along to the evidence layer. Its content is agreed between the template provider and the evidence layer.
{
"solution": "https://shop.example.com/products/pullover-xl",
"metadata": { "merchant": "shop.example.com" }
}
mandate-orchestrator intents propose \
--intent-id <intent_id> \
--json-body proposal.json

Once a proposal is received, the orchestrator sends its solution and metadata to the operator's evidence extraction server — which must implement the Evidence Extraction API (evidence-openapi.json) — to extract structured evidence. The orchestrator then evaluates that evidence against the template and intent and generates the proof.

3. Receive the outcome

The operator subscribes to the orchestrator's Server-Sent Events stream, which pushes an event the moment an intent reaches a terminal state:

mandate-orchestrator events stream
{
"type": "success",
"intent_id": "550e8400-e29b-41d4-a716-446655440000",
"proposal": { "solution": "https://shop.example.com/products/pullover-xl", "metadata": { "merchant": "shop.example.com" } },
"evidence": { "category": "pullover", "price_cents": 4200, "size": "XL" }
}

Each event carries a terminal type:

  • success — template evaluation and proof creation both succeeded; the proof is available via the verifier.
  • failure — the proposal did not satisfy the intent, or proof creation failed.
  • expired — no proposal arrived before the intent's TTL elapsed (default: 24 h).

Events for all intents arrive on one stream, so demultiplex by intent_id. See Streaming events for the failure and expiry payloads, the gRPC alternative, and the reconnect caveats.

If consuming a stream isn't an option, the operator can instead poll the verifier, whose response carries the same terminal states in its status field — see the API Guide for the response shapes:

mandate-verifier intents get --intent-id <intent_id>

On success, the operator retrieves the proof:

mandate-verifier proofs get --intent-id <intent_id>

The proof contains the signed intent, the proposal, the extracted evidence, and the zero-knowledge proof bytes — sufficient to independently verify that the proposal satisfied the intent:

{
"sp1_proof": "<base64 proof bytes>",
"evidence": { "fields": { "category": "pullover", "price_cents": 4200, "size": "XL" } },
"signed_intent": { "payload": { "..." }, "signature": { "..." } },
"proposal": { "solution": "https://shop.example.com/products/pullover-xl", "metadata": { "merchant": "shop.example.com" } }
}

The evidence.fields object contains the evidence extracted from the proposal and checked against the template's evidence schema.

Next steps

  • Template Management — register the templates your intents will reference.
  • API Guide — the full orchestrator and verifier API surface, with CLI setup.
  • Architecture — see how the components fit together end-to-end.