paybondpaybond
Sign in

Agent receipt OpenTelemetry mapping

Recommended span attribute mapping from paybond.agent_receipt_v1 to OTLP traces.

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).

Use the paybond.receipt.* and paybond.agent.* namespaces to avoid collisions with generic http.* or vendor SDK attributes.

OTLP attributeReceipt sourceNotes
paybond.receipt.idreceipt_idAction scope: deterministic sha256(intent_id + tool_call_id).
paybond.receipt.kindkindAlways paybond.agent_receipt_v1.
paybond.receipt.scopescopeaction or intent_terminal.
paybond.receipt.issued_atissued_atRFC3339 string.
paybond.receipt.message_digest_sha256_hexmessage_digest_sha256_hexCanonical signing digest; omit raw signature bytes from spans.
paybond.receipt.verifier_idGateway trust registryWhen known; otherwise omit.
paybond.intent.idreferences.intent_idAlso on parent run spans.
paybond.tool_call.idexecution.tool_call_idAction scope only.
paybond.tool.nameexecution.tool_name
paybond.tool.operationexecution.operationHarbor allowed-tool operation.
paybond.agent.model_familyauthorization.agent.model_familyNever emit raw prompts.
paybond.agent.config_hash_sha256_hexauthorization.agent.config_hash_sha256_hex
paybond.agent.prompt_hash_sha256_hexauthorization.agent.prompt_hash_sha256_hexHash-only; required when tenant policy mandates prompt attestation.
paybond.authorization.decision_idauthorization.decision_idSpend verify decision UUID.
paybond.authorization.audit_idauthorization.audit_idHarbor audit correlation when present.
paybond.policy.template_idauthorization.policy.template_id
paybond.policy.content_digest_sha256_hexauthorization.policy.content_digest_sha256_hex
paybond.evidence.preset_idevidence.completion_preset_id
paybond.evidence.payload_digest_sha256_hexevidence.payload_digest_sha256_hex
paybond.evidence.predicate_passedevidence.predicate_passedBoolean.
paybond.payment.settlement_railpayment.settlement_railWhen funded intent.
paybond.payment.funding_referencepayment.funding_referenceProvider reference only; no PAN or bank numbers.
paybond.outcome.harbor_stateoutcome.harbor_state
paybond.external_attestation.countlen(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
  1. Start a span when wrapExecute begins (or reuse the framework tool span).
  2. Set authorization attributes after spend verify succeeds (decision_id, audit_id, policy digests).
  3. Set execution attributes after the tool returns (tool_call_id, argument/result digests if your backend allows hash-only fields).
  4. Set receipt attributes after evidence submit when a signed receipt is fetched or a local draft is composed.
  5. End the span with paybond.outcome.harbor_state and paybond.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.count is safer than exporting each partner digest as span attributes (high cardinality).
  • tenant_id on 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);
}