Somnia Agents / Invoking agents

Receipts

The per-validator execution log every agent request produces, and how to view or fetch it.

Every agent invocation produces an execution receipt: a per-validator log of what happened during execution. Receipts provide transparency and auditability for agent operations.

Note. Receipts are currently stored on centralized infrastructure (a public Google Cloud Storage bucket). We plan to migrate to decentralized storage in the future to make receipts tamper-proof and permanently available.

Understanding receipts

Consensus vs. receipts

It's important to understand the distinction:

  • Result: the final output of the agent is what validators reach consensus on. All nodes must agree on this value for it to be accepted.
  • Receipt: the execution steps are subjective and may vary slightly between nodes. Receipts are for transparency and debugging, not consensus.

This means:

  • You can trust the result completely: it has been verified by multiple validators.
  • Each receipt shows what one node did to compute that result.
  • Different nodes may have different receipts (timing, network paths) but still agree on the final result.

One request, one receipt per subcommittee member

A single agent request is processed by every member of its subcommittee (default size 3, configurable via createAdvancedRequest). Each member produces its own receipt, so a default request yields 3 receipts. The receipts service exposes them as a manifest keyed by (contractAddress, requestId).

Viewing receipts

In the Somnia Explorer

Browse recent invocations or look up a request by ID on the Requests page of the Somnia Explorer:

https://somnia-platform-explorer.vercel.app/agents/requests

Use the chain selector to pick Global (mainnet) or Global testnet. This is useful when you don't have the request URL handy or want to scan recent activity.

If you already know the request ID, go straight to its page:

https://somnia-platform-explorer.vercel.app/agents/requests/<requestId>

Replace <requestId> with the numeric request ID returned by createRequest. The request page shows the on-chain request state plus each validator's signed receipt from the receipts service. See Using the explorer.

From the Agent Explorer app

If you invoke agents from the standalone Agent Explorer app (https://agents.somnia.network for mainnet, https://agents.testnet.somnia.network for testnet):

  1. Invoke an agent.
  2. After execution completes, click View Receipt.
  3. Explore each step of the execution.

The app displays receipts in a readable format, showing:

  • Per-validator execution timelines
  • External calls made (URLs, responses)
  • Data transformations
  • Timing information

Fetching receipts programmatically

Fetching is a two-step flow:

  1. Hit the receipts service with the platform contractAddress and requestId — you get back a manifest of public Google Cloud Storage URLs.
  2. Fetch each URL directly to read the per-validator receipt JSON.
Network Receipts service base URL Platform contract
Mainnet https://receipts.mainnet.agents.somnia.host 0x5E5205CF39E766118C01636bED000A54D93163E6
Testnet https://receipts.testnet.agents.somnia.host 0x037Bb9C718F3f7fe5eCBDB0b600D607b52706776
const baseUrl   = 'https://receipts.testnet.agents.somnia.host';
const platform  = '0x037Bb9C718F3f7fe5eCBDB0b600D607b52706776';
const requestId = '<your-request-id>'; // returned by platform.createRequest

// Step 1 — manifest
const manifest = await (await fetch(
  `${baseUrl}/agent-receipts?contractAddress=${platform}&requestId=${requestId}`
)).json();
// → { contractAddress, requestId, receipts: [<gcs url>, ...], count }

// Step 2 — per-validator receipts
const receipts = await Promise.all(
  manifest.receipts.map(url => fetch(url).then(r => r.json()))
);
console.log(`${receipts.length} validator receipts for request ${requestId}`);

Both query parameters are required. Omitting contractAddress returns:

HTTP 400 { "error": "Missing contractAddress query parameter" }

Quick triage with type=minimal

For lightweight triage — "did this resolve, did the subcommittee agree, what was the error?" — the receipts service also exposes a type=minimal mode that returns all per-validator receipt JSON inline in a single call, with no second-step GCS fetch needed.

GET {baseUrl}/agent-receipts?contractAddress=<platform>&requestId=<id>&type=minimal

The minimal response:

  • Inlines every validator's receipt JSON in receipts[] (objects, not GCS URLs).
  • Caps long string fields (HTML page text, model output, raw responses) at 1024 characters with a <truncated, fetch the receipt URL for complete contents> marker.
  • Adds derived consensusType, requestDetails, and count at the top level for convenience.

Use it for triage and dashboards. If a field you need was truncated, fall back to the default (URL manifest) mode and fetch the receipt's GCS URL directly for the full content.

Receipt structure

Top-level fields

A single per-validator receipt looks like this:

{
  "requestId": "<requestId>",
  "agentId": "<agentId>",
  "contractAddress": "<platform address>",
  "agentRunnerAddress": "<validator address>",
  "consensusType": 0,
  "requestDetails": {
    "requester": "<caller address>",
    "callbackAddress": "<callback address>",
    "callbackSelector": "0x........",
    "threshold": 2,
    "subcommitteeSize": 3,
    "timeoutSeconds": 300
  },
  "status": "success",
  "startedAt": "2026-01-15T10:30:00.000Z",
  "completedAt": "2026-01-15T10:30:09.800Z",
  "elapsedMs": 9800,
  "agentImageUri": "https://storage.googleapis.com/somnia-agents-artifacts/agents/<agent>/<hash>.tar",
  "request": "0x...",
  "response": { "result": "0x..." },
  "agentReceipt": {
    "steps": [ /* see below */ ],
    "llmUsage": { "promptTokens": 0, "completionTokens": 0, "totalTokens": 0, "requests": 0, "streamingRequests": 0 },
    "bandwidthUsage": { "bytesIn": 0, "bytesOut": 0, "requests": 0 },
    "request": "0x...",
    "result": "0x..."
  }
}
Field Purpose
status success, failed, or timeout
elapsedMs End-to-end duration on this validator
agentRunnerAddress Which validator produced this receipt
agentImageUri Pinned artifact bundle the agent ran from (auditable)
requestDetails.subcommitteeSize / threshold Consensus config in force for this request
consensusType 0 = Majority, 1 = Threshold
agentReceipt.steps Per-agent execution stages (see below)
agentReceipt.llmUsage Token counts for cost analysis
agentReceipt.bandwidthUsage Outbound HTTP volume

Failed requests follow the same envelope but add a top-level errorMessage and omit agentReceipt and response. Always check status before reading agentReceipt.

Step names by agent

Step names live under agentReceipt.steps and vary by agent type:

Agent Step sequence
JSON API Request request_received → request_decoded → handler_started → handler_completed → response_encoded
LLM Inference request_received → request_decoded → handler_started → llm_response → handler_completed → response_encoded
LLM Parse Website request → fetch → convert → extract

Each step entry includes name, started_at, status, and an inputs object (and output where applicable). LLM-backed agents may also include auto-injected reasoning, answerable, and confidence_score (0–100) fields in the structured-extraction step. For LLM Inference requests where chain-of-thought was enabled (via the chainOfThought argument), the llm_response step also surfaces the model's thinking output.

Using receipts for debugging

Tracing failures

When a request fails or times out, check status and the top-level errorMessage. For successes that returned an unexpected result, walk agentReceipt.steps — each step's status and any embedded output show exactly where execution diverged. For HTTP-based agents (JSON API Request, Parse Website), bandwidthUsage.requests is a quick sanity check that an outbound call happened at all.

Checking LLM reasoning

For LLM agents, the agentReceipt.steps entry covering the model call carries the inputs and the structured output. When the request opted into chain-of-thought (chainOfThought = true), the thinking field on the llm_response step surfaces the model's intermediate reasoning. The auto-injected confidence_score is useful for understanding low-confidence answers.

Verifying external data (JSON API Request)

The handler_completed step records the upstream response payload and the value extracted via the selector path — useful for confirming that the JSON shape on the API hasn't changed underneath you.

Verifying scraped content (LLM Parse Website)

Parse Website's fetch step records the URL(s) loaded; the convert step records the markdown handed to the model; the extract step records the structured-output result. If extraction quality is low, the convert output usually shows why (collapsed structure, missing sections, dynamic content not rendered).

Monitoring cost

Both llmUsage and bandwidthUsage are aggregated per validator on every receipt. Summing across requests gives a reliable per-agent cost profile (especially for LLM Inference and Parse Website, where token usage drives the bulk of work).

Next steps

Edit this page