Skip to content

The attribution pipeline

Venturi turns a raw AI invocation event into a resolved AttributionRecord in three stages. Each stage has one responsibility and one owner:

Stage Owner Responsibility
Stage A Venturi platform Deterministic resolution of every edge that facts can settle
Stage B RAIL Trained edge-existence inference for the eligible edges that Stage A leaves unresolved
Stage C Allocation subsystem Fractional split of genuinely shared cost

RAIL (Resource Attribution & Inference Layer) owns Stage B. It receives only the eligible ownership relationships that Stage A cannot resolve, builds the candidate set, applies its decision thresholds, and returns the most likely owner with an uncapped posterior confidence (cpost), the supporting evidence and the ranked alternatives. RAIL’s research and training machinery supplies the verified Stage B models. The Venturi platform runs canonical ingress and Stage A. Platform materialization then turns each result into the customer-facing operational confidence coper, capped at 0.95, and publishes the versioned AttributionRecord. Stage C belongs to a separate allocation subsystem.

Stage A sends resolved edges straight to platform materialization.

Evidence Path
Stage A resolves an edge. Bypass Stage B.
An unresolved edge is eligible for inference. Send it to RAIL Stage B, which returns cpost, evidence, and alternatives.
Evidence is insufficient or ineligible. Retain unresolved ownership, missing fields, and evidence lineage.

A Stage B path does not guarantee a selected owner. The AttributionRecord can preserve unresolved ownership and ranked alternatives; materialization never turns missing evidence into a resolved owner.

The diagram focuses on ownership resolution. Genuinely shared costs from Stage A or Stage B follow the separate Stage C allocation path before materialization. Stage C preserves ownership and conserves the invoice total.

A core principle runs through the whole pipeline: deterministic evidence always outranks inference, and inference always outranks allocation. Stage A overrides Stage B for any edge it can resolve; Stage C distributes cost but never changes who the candidate owners are. Precision degrades gracefully; it never collapses into a falsely confident guess.

Ownership Gaps

Insufficient or ineligible evidence leaves ownership unresolved. The result retains its missing fields and evidence lineage so the gap can be investigated. Eligible cases that reach RAIL retain calibrated confidence and ranked alternatives alongside any selected owner.

Unresolved cost can remain visible. Allocation uses invoice evidence and a declared method to split shared cost while conserving invoice totals and preserving ownership. Confidence, coverage, and invoice reconciliation answer different questions.

Stage A: deterministic resolution

The Venturi platform runs Stage A, which builds the attribution graph from facts. It populates all five node types from your source data and resolves every edge it can using exact join keys and rule-based matching. No machine learning is involved; Stage A is pure, repeatable logic over your own data.

Stage A applies five reconciliation methods:

Method How it resolves an edge
R1 · Direct key match An exact join (e.g. an account ID maps directly to an identity, or an API key to a service). The strongest evidence; can reach maximum posterior confidence.
R2 · Temporal proximity Events that line up in time are linked (e.g. a deployment immediately followed by invocations from that service).
R3 · Naming correlation Consistent naming across systems links records (e.g. a service name matching a repository name).
R4 · Historical patterns Prior resolved attributions inform new ones where the pattern is stable.
R5 · Service-account trace Following a service account or principal through the call chain to its owner.

Stage A also reports conflicts explicitly. Deterministic does not mean unambiguous: if two equally authoritative sources disagree (CODEOWNERS says Team A, deployment metadata says Team B), Stage A records a conflict state and preserves it for review rather than silently picking a winner. High-cost conflicts are surfaced for manual review.

Whatever Stage A resolves with certainty is marked deterministically_resolved and bypasses inference entirely. Only the genuinely ambiguous residual (the eligible edges Stage A cannot resolve from facts) flows to RAIL in Stage B.

Stage B: trained edge-existence inference

Stage B is RAIL. For the eligible edges that deterministic rules cannot resolve, RAIL infers the most likely relationship and attaches a calibrated confidence. This is where RAIL’s trained attribution model does its work.

Stage B runs an edge-existence model: for an unresolved edge, it scores how likely each candidate relationship is, given the available evidence, and returns the best candidate with a posterior confidence. That confidence is designed to be calibrated: a reported confidence of 0.85 is intended to correspond to a roughly 85% chance that the attribution is correct, and Venturi continuously checks whether emitted confidence still tracks real outcomes. RAIL returns this posterior uncapped as cpost; platform materialization turns it into the customer-facing operational score coper, capped at 0.95. Stage B always preserves the full set of ranked candidates alongside the selected answer, so a result can be inspected and challenged.

Where the model runs

Stage B runs in-process inside the attribution processor, in your data plane. There is no separate inference service and no network hop: the processor loads a hash-verified model artifact into its own runtime and answers one question well: for this ambiguous edge, which relationship is most likely, and how sure are we? It does not own your dashboards, billing, or controls.

Stage B degrades without stopping attribution

Stage B runs in the asynchronous processor and never enters your AI request path. The processor falls back to a deterministic heuristic baseline, a permanent, conservative fallback that resolves the edge with a transparent, lower-confidence heuristic instead of waiting on the model, when any of the Stage B fallback conditions occurs:

  • the call reaches its 20 ms timeout;
  • the model artifact is missing;
  • the model returns an invalid output;
  • Stage B is disabled for that edge by flag;
  • the call is shed because 8 calls are already in flight on that processor instance;
  • the circuit breaker is open because the timeout rate exceeds its configured threshold (default: 5% over a 100-call rolling window);
  • the edge’s readiness gate vetoes serving the trained model for that edge (a fail-closed, per-edge veto).

During a canary rollout, an increase in expected calibration error (ECE) greater than 0.02 rolls the new model back automatically, with no flag that can suppress it. Results answered by the fallback say so in their evidence metadata.

Where each latency budget applies

  • The decision-time interceptor on your live AI hot path performs a fast index lookup and runs no model inference. It works to a 50 ms P99 end-to-end budget, with a cooperative timeout against a cumulative deadline, and forwards the request unmodified on breach.
  • The asynchronous attribution processor, which handles the large majority of attribution volume off the hot path, works to its own 100 ms P99 budget, independent of customer traffic.
  • Inside that processor budget, each Stage B inference call carries a hard 20 ms timeout. If inference does not complete in time, the heuristic baseline answers.

Stage B can momentarily degrade while attribution processing keeps flowing. Separately, the interceptor forwards admitted requests unmodified on an exception or timeout within its 50 ms P99 end-to-end budget. A fallback result is marked as degraded so you always know when it happened.

A Stage B result is marked strongly_inferred when the model resolves the edge with high confidence, or bounded when the answer is uncertain enough that Venturi reports a constrained range rather than a single owner.

Stage C: fractional allocation

Some costs are genuinely shared and have no single owner: a shared API key, a shared endpoint, a platform service used by many teams. Stage C handles exactly these cases, in a separate allocation subsystem outside RAIL. It does not decide who the candidates are (Stage A and Stage B already established that); it decides how the cost is split among them.

  • Conservation. Allocations always sum to 100% of the cost. Nothing is lost, double-counted, or invented.
  • Fractional splits. Stage C distributes the cost across candidate owners proportionally, based on the available allocation signals.
  • The allocation prior (R6). Stage C is the only stage that uses the sixth reconciliation method, R6, an allocation prior used purely to split shared cost. R6 is refused outright as evidence for whether an edge exists, and it carries a hard 0.50 ceiling of its own, so allocated attributions are always clearly distinguished from directly resolved ones. An allocated line is capped at 0.70 where proportional allocation signals are present and at 0.50 where the split rests on no such signal. Both sit below the 0.80 chargeback floor, so shared-cost splits are transparently provisional rather than presented as certain ownership.

What comes out

Each stage stamps its result with a stage origin (stage_a, stage_b, or stage_c) and an output state, so you can always see how an attribution was reached. Platform materialization combines the output into an AttributionRecord and indexes it for your dashboards, exports, budgets, and the REST API.

Typical output states by stage:

Stage Job and scope Output state
A Deterministic resolution (R1 to R5); resolves facts and exact matches deterministically_resolved
B Trained edge-existence inference (heuristic-baseline fallback); resolves ambiguous residual strongly_inferred, bounded
C Fractional allocation (R6 prior); resolves shared cost allocated splits, conservation enforced

Where to go next

Give feedback on this page

Sign in to send feedback. Opens in a new tab.

Copy page details
Docs feedback: The attribution pipeline
Page: https://docs.venturi.systems/engine/rail-pipeline/