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):
- Invoke an agent.
- After execution completes, click View Receipt.
- 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:
- Hit the receipts service with the platform
contractAddressandrequestId— you get back a manifest of public Google Cloud Storage URLs. - 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, andcountat 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
- Gas fees: understand costs.
- Using the explorer: view requests and receipts in the Somnia Explorer.