v0.1Pinned · latest at /spec

Open Agent Spend Attribution (OASA) Specification

Version 0.1 · Initial public draft · 2026-09-14 · CC BY 4.0

Abstract

OASA defines a canonical record format that attributes AI-agent resource consumption and spend to agent identity, task, and cost object, and joins runtime telemetry, normalized billing, and payment settlement into a single auditable ledger row. It is designed to interoperate with OpenTelemetry GenAI semantic conventions (telemetry), the FOCUS specification (billing), and x402 payment-rail records (settlement). It is not a payment protocol and not a billing format; it is the join between them.

Partial records are valid. Every field outside the envelope is optional so adapters can emit what they know and reconcile later. Within a major version, the schema is additive-only.

Design principles

  • Hub-and-spoke: canonical middle, adapters at the edges.
  • Settlement-agnostic: invoice, card, wire, and on-chain rails reconcile into the same spine.
  • Additive to FOCUS and OpenTelemetry — never competing with them.
  • Envelope required; all other groups optional so partial records remain valid.
  • Versioned; additive-only within a major version.

The three-layer model

TelemetryOTel GenAIAttributionOASA (canonical)BillingFOCUS+ Settlement (x402)trace_idinvoice_id + source_record_idsettlement_refHub-and-spoke: one canonical middle, adapters at the edges
Join keys on the edges; attribution in the middle.

Record schema v0.1

Group 1 — Envelope (required)

FieldTypeRequiredDescription
record_idstring (UUIDv7)YesGlobally unique record identifier.
record_typeenum: usage | charge | settlement | allocation | outcomeYesOne row = one event class.
schema_versionstringYesSchema version string; "0.1" for this draft.
occurred_attimestamp (RFC 3339, UTC)YesWhen the event happened.
recorded_attimestamp (RFC 3339, UTC)YesWhen the record was ingested.
source_systemstringYese.g. otel-collector, openai-billing, x402-facilitator.
source_record_idstringYesKey in the source system.
currencystringYesISO 4217, or CAIP-19 asset ID for on-chain assets.

Group 2 — Agent identity

FieldTypeRequiredDescription
agent_idstringNoStable internal agent ID.
agent_namestringNoHuman-readable agent name.
agent_versionstringNoAgent build or prompt version.
agent_ownerstringNoTeam or principal accountable.
parent_agent_idstringNoParent in a sub-agent chain.
agent_frameworkstringNoe.g. langgraph, crewai, custom.
identity_schemeenum: internal | erc8004 | otherNoHow external identity is named.
external_identity_refstringNoe.g. ERC-8004 registration reference.

Group 3 — Task & session context

FieldTypeRequiredDescription
session_idstringNoRuntime session identifier.
trace_idstringNoW3C Trace Context / OpenTelemetry trace id.
span_idstringNoSpan id within the trace.
task_idstringNoOrg-defined task identifier.
task_typestringNoFree taxonomy; org-defined.
workflow_idstringNoWorkflow or pipeline id.
triggerenum: human | scheduled | agent | eventNoWhat started the run.
initiating_principalstringNoHuman or agent that authorized the run.

Group 4 — Consumption

FieldTypeRequiredDescription
providerstringNoModel or API provider.
servicestringNoService product name.
modelstringNoModel identifier.
operationenum: chat | completion | embeddings | tool_call | inference | storage | api_call | otherNoOperation class.
input_tokensintegerNoInput token count.
output_tokensintegerNoOutput token count.
cached_tokensintegerNoCached / reused tokens when reported.
reasoning_tokensintegerNoReasoning tokens when reported.
unit_typeenum: tokens | requests | seconds | gb | customNoUnit of consumption.
units_consumeddecimalNoQuantity in unit_type.
tool_namestringNoTool invoked, if any.
request_countintegerNoRequest count for the event.

Group 5 — Cost

FieldTypeRequiredDescription
list_costdecimalNoList price; mirrors FOCUS ListCost semantics.
billed_costdecimalNoBilled amount; mirrors FOCUS BilledCost.
effective_costdecimalNoEffective cost after discounts; mirrors FOCUS EffectiveCost.
cost_sourceenum: measured | rated | invoicedNoHow cost was derived.
pricing_refstringNoPrice-sheet row ID.
invoice_idstringNoVendor invoice identifier.
focus_charge_refstringNoPointer into a FOCUS dataset row.

Group 6 — Allocation

FieldTypeRequiredDescription
cost_centerstringNoCost center or department.
project_idstringNoProject identifier.
customer_idstringNoCustomer or account identifier.
product_linestringNoProduct line.
environmentenum: prod | staging | dev | otherNoRuntime environment.
tagsmap<string,string>NoFree-form tags.
allocation_methodenum: direct | rule | splitNoHow cost was allocated.
allocation_rule_idstringNoRule that produced the allocation.
split_fractiondecimal (0–1)NoShare of a split allocation.

Group 7 — Settlement join

FieldTypeRequiredDescription
settlement_railenum: invoice | card | ach | wire | x402 | other_onchainNoHow money moved.
settlement_networkstringNoCAIP-2 chain ID where applicable.
settlement_assetstringNoCAIP-19 asset identifier.
settlement_amountdecimalNoSettled amount.
settlement_refstringNoTx hash, statement line, or remittance ID.
settled_attimestampNoSettlement timestamp.
reconciliation_statusenum: unmatched | matched | partial | disputedNoJoin status against billing/telemetry.

Group 8 — Control & governance

FieldTypeRequiredDescription
budget_idstringNoBudget that constrained or funded the spend.
policy_idstringNoPolicy identifier.
authorization_refstringNoMandate / verifiable-intent credential ID.
approval_typeenum: policy_auto | pre_authorized | human_approvedNoHow spend was authorized.

Group 9 — Outcome (optional, forward-looking)

Outcome capture is intentionally minimal in v0.1; it exists so cost-per-outcome queries have a landing zone.

FieldTypeRequiredDescription
outcome_event_idstringNoLinked outcome event.
outcome_typestringNoOutcome class (org-defined).
outcome_valuedecimalNoNumeric outcome value.
outcome_unitstringNoUnit for outcome_value.
business_metric_refstringNoPointer to a business metric definition.

Mapping tables

Verified against upstream docs on 2026-09-14. OpenTelemetry GenAI conventions are still experimental and may drift; re-check before treating attribute names as frozen. FOCUS token-economics columns track 1.4 (ratified) and 1.5 (scheduled). x402 V2 communicates requirements via PAYMENT-REQUIRED payloads (network, asset, amount, payTo).

OASA ↔ OpenTelemetry GenAI

OASAOTel
providergen_ai.provider.name
input_tokensgen_ai.usage.input_tokens
output_tokensgen_ai.usage.output_tokens
modelgen_ai.request.model
operationgen_ai.operation.name
agent_idgen_ai.agent.id
agent_namegen_ai.agent.name
trace_id / span_idW3C Trace Context / OTel trace_id, span_id

OASA ↔ FOCUS

FOCUS 1.4 added token-economics columns; FOCUS 1.5 (Dec 2026 target) adds native token tracking and a Price Sheet dataset. OASA tracks those columns as they ratify.

OASAFOCUS
list_costListCost
billed_costBilledCost
effective_costEffectiveCost
providerProviderName
serviceServiceName
tagsTags
charge rows (record_type=charge)ChargeCategory / charge rows

OASA ↔ x402

OASAx402
settlement_networkPaymentRequired.network (PAYMENT-REQUIRED)
settlement_assetPaymentRequired asset / token
settlement_amountPaymentRequired amount / price
settlement_refon-chain tx / SettlementResponse reference
(payee context)PaymentRequired.payTo

Worked example

One agent tool-call as a usage row, later joined by a charge row and an x402 settlement row sharing trace_id / settlement_ref.

1. Usage (telemetry)

{
  "record_id": "0193f0a0-0000-7000-8000-000000000001",
  "record_type": "usage",
  "schema_version": "0.1",
  "occurred_at": "2026-09-01T15:04:05Z",
  "recorded_at": "2026-09-01T15:04:06Z",
  "source_system": "otel-collector",
  "source_record_id": "span-9f2c",
  "currency": "USD",
  "agent_id": "agent-support-47",
  "agent_name": "Support Triage",
  "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
  "span_id": "00f067aa0ba902b7",
  "task_type": "ticket_resolve",
  "provider": "openai",
  "model": "gpt-4.1",
  "operation": "tool_call",
  "tool_name": "crm.lookup",
  "input_tokens": 1200,
  "output_tokens": 340,
  "unit_type": "tokens",
  "units_consumed": 1540,
  "cost_source": "measured"
}

2. Charge (billing)

{
  "record_id": "0193f0a0-0000-7000-8000-000000000002",
  "record_type": "charge",
  "schema_version": "0.1",
  "occurred_at": "2026-09-02T00:00:00Z",
  "recorded_at": "2026-09-02T06:12:00Z",
  "source_system": "openai-billing",
  "source_record_id": "inv_line_88421",
  "currency": "USD",
  "agent_id": "agent-support-47",
  "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
  "invoice_id": "INV-2026-09-01",
  "focus_charge_ref": "focus:row:88421",
  "list_cost": 0.042,
  "billed_cost": 0.038,
  "effective_cost": 0.038,
  "cost_source": "invoiced"
}

3. Settlement (x402)

{
  "record_id": "0193f0a0-0000-7000-8000-000000000003",
  "record_type": "settlement",
  "schema_version": "0.1",
  "occurred_at": "2026-09-01T15:04:07Z",
  "recorded_at": "2026-09-01T15:04:08Z",
  "source_system": "x402-facilitator",
  "source_record_id": "pay_0xabc…",
  "currency": "eip155:8453/erc20:0x…",
  "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
  "settlement_rail": "x402",
  "settlement_network": "eip155:8453",
  "settlement_asset": "eip155:8453/erc20:0x…",
  "settlement_amount": 0.038,
  "settlement_ref": "0xdeadbeef…",
  "settled_at": "2026-09-01T15:04:07Z",
  "reconciliation_status": "matched"
}

Changelog

  • v0.1 (2026-09-14) — initial public draft.

Contributing

This page is the pinned v0.1 draft. The specification is developed in the open at github.com/onaro-io/agent-spend-attribution; see /spec for the latest version.

General comments: hello@onaro.io

Cite this specification

Open Agent Spend Attribution (OASA) Specification, version 0.1. Onaro, 2026-09-14. https://www.onaro.io/spec/v0.1

Repository: https://github.com/onaro-io/agent-spend-attribution

License: CC BY 4.0. Attribution required; adaptations allowed.

Related: The Missing Ledger · Agent spend attribution · Agent payment data