Paybond does not ship a dedicated OTLP exporter for agent receipts. When you already emit OpenTelemetry traces from agent middleware, map signed paybond.agent_receipt_v1 fields to span attributes so observability backends can correlate tool calls with authorization, evidence, and payment proof.
This mapping is optional and additive: existing Paybond trace events (spend_authorized, tool_executed, evidence_submitted) remain the primary run timeline. Agent receipt attributes are most useful on the tool execution span (or a child span closed after evidence submit).
Recommended attributes
Use the paybond.receipt.* and paybond.agent.* namespaces to avoid collisions with generic http.* or vendor SDK attributes.
| OTLP attribute | Receipt source | Notes |
|---|---|---|
paybond.receipt.id | receipt_id | Action scope: deterministic sha256(intent_id + tool_call_id). |
paybond.receipt.kind | kind | Always paybond.agent_receipt_v1. |
paybond.receipt.scope | scope | action or intent_terminal. |
paybond.receipt.issued_at | issued_at | RFC3339 string. |
paybond.receipt.message_digest_sha256_hex | message_digest_sha256_hex | Canonical signing digest; omit raw signature bytes from spans. |
paybond.receipt.verifier_id | Gateway trust registry | When known; otherwise omit. |
paybond.intent.id | references.intent_id | Also on parent run spans. |
paybond.tool_call.id | execution.tool_call_id | Action scope only. |
paybond.tool.name | execution.tool_name | |
paybond.tool.operation | execution.operation | Harbor allowed-tool operation. |
paybond.agent.model_family | authorization.agent.model_family | Never emit raw prompts. |
paybond.agent.config_hash_sha256_hex | authorization.agent.config_hash_sha256_hex | |
paybond.agent.prompt_hash_sha256_hex | authorization.agent.prompt_hash_sha256_hex | Hash-only; required when tenant policy mandates prompt attestation. |
paybond.authorization.decision_id | authorization.decision_id | Spend verify decision UUID. |
paybond.authorization.audit_id | authorization.audit_id | Harbor audit correlation when present. |
paybond.policy.template_id | authorization.policy.template_id | |
paybond.policy.content_digest_sha256_hex | authorization.policy.content_digest_sha256_hex | |
paybond.evidence.preset_id | evidence.completion_preset_id | |
paybond.evidence.payload_digest_sha256_hex | evidence.payload_digest_sha256_hex | |
paybond.evidence.predicate_passed | evidence.predicate_passed | Boolean. |
paybond.payment.settlement_rail | payment.settlement_rail | When funded intent. |
paybond.payment.funding_reference | payment.funding_reference | Provider reference only; no PAN or bank numbers. |
paybond.outcome.harbor_state | outcome.harbor_state | |
paybond.external_attestation.count | len(external_attestations) | Integer count only on spans; store digests in receipt JSON, not span arrays. |
Span placement
sequenceDiagram
participant Agent as Agent runtime
participant Kit as Paybond middleware
participant OTEL as OTLP backend
Agent->>Kit: wrapExecute(tool)
Kit->>Kit: spend_authorized trace
Kit->>Agent: execute tool
Kit->>Kit: evidence_submitted trace
Kit->>OTEL: set paybond.receipt.* on tool span
Kit->>Agent: receiptDraft / getReceipt- Start a span when
wrapExecutebegins (or reuse the framework tool span). - Set authorization attributes after spend verify succeeds (
decision_id,audit_id, policy digests). - Set execution attributes after the tool returns (
tool_call_id, argument/result digests if your backend allows hash-only fields). - Set receipt attributes after evidence submit when a signed receipt is fetched or a local draft is composed.
- End the span with
paybond.outcome.harbor_stateandpaybond.evidence.predicate_passed.
Privacy and cardinality
- Never put raw tool arguments, tool results, prompts, or evidence payloads on spans.
- Prefer digests and IDs over free-text vendor fields.
paybond.external_attestation.countis safer than exporting each partner digest as span attributes (high cardinality).tenant_idon receipts is tenant realm text; scope OTLP export pipelines per tenant when exporting to shared observability vendors.
Example (TypeScript)
After fetching a signed receipt:
import { trace } from "@opentelemetry/api"; const span = trace.getActiveSpan(); if (span && receipt) { span.setAttribute("paybond.receipt.id", receipt.receipt_id); span.setAttribute("paybond.receipt.kind", receipt.kind); span.setAttribute("paybond.intent.id", receipt.references.intent_id); span.setAttribute("paybond.tool_call.id", receipt.execution?.tool_call_id ?? ""); span.setAttribute("paybond.agent.model_family", receipt.authorization.agent.model_family); span.setAttribute("paybond.authorization.decision_id", receipt.authorization.decision_id); span.setAttribute("paybond.evidence.payload_digest_sha256_hex", receipt.evidence?.payload_digest_sha256_hex ?? ""); span.setAttribute("paybond.external_attestation.count", receipt.external_attestations.length); }