DEV Community

Aleksander Sekowski
Aleksander Sekowski

Posted on

ADJUST_DEAL_FLOOR on /imp/imp-1 Parses. ARTF Still Needs /imp/{id}/pmp/deals/{deal id}.

IAB Tech Lab's milestone on ARTF v1.0 says the Agentic Real Time Framework is final and running on live bidstreams. Hosts are wiring GPU agents beside the auction, container health checks pass, and gRPC returns OK. That is the week to stop treating "parsed" as "applied."

A publisher agent can return a mutation that looks like every sample in the repo, complete with enum names and a rooted path, and still aim at the wrong entity. The orchestrator receives a legal protobuf JSON document and has nothing on the wire to patch.

Intent and path are a matched pair

ARTF v1.0 does not use JSON Pointer. Each Mutation carries a semantic path: a rooted string that names a business entity inside the carried OpenRTB object, not a field walk.

The v1.0 reference documents four shapes:

  • /user/data/segment for segment and identity intents
  • /imp/{imp id} for impression-scoped deal activation, suppression, and metrics
  • /imp/{imp id}/pmp/deals/{deal id} for per-deal floor and margin proposals
  • /seatbid/{seat}/bid/{bid id} for bid shading on a concrete bid

Each Intent enum value is tied to one of those shapes. ACTIVATE_DEALS, SUPPRESS_DEALS, and ADD_METRICS stop at the impression. ADJUST_DEAL_FLOOR and ADJUST_DEAL_MARGIN must name both the impression and the deal id, because OpenRTB stores bidfloor on the Deal object under imp[].pmp.deals[], not on Imp itself.

Copy a path template from an ADD_METRICS example and swap the intent to ADJUST_DEAL_FLOOR without extending the path:

{
  "intent": "ADJUST_DEAL_FLOOR",
  "op": "OPERATION_REPLACE",
  "path": "/imp/imp-1",
  "adjust_deal": { "bidfloor": 12.5 }
}
Enter fullscreen mode Exit fullscreen mode

Protobuf JSON parsing succeeds. The path resolves to impression imp-1, which exists in the bid request. The payload oneof is populated. Transport is green.

The coherence check is where ARTF stops being syntax. Impression paths accept ACTIVATE_DEALS, SUPPRESS_DEALS, and ADD_METRICS. They do not accept ADJUST_DEAL_FLOOR. RTBlint reports artf.mutation.path_intent_mismatch: the intent targets an impression, but deal-floor intents belong on /imp/{imp id}/pmp/deals/{deal id}.

The symmetric mistake is pointing an impression intent at a deal path. ACTIVATE_DEALS on /imp/imp-1/pmp/deals/deal-premium parses the deal segment correctly, then fails the same rule because activation is an impression-level operation, not a single row in deals[].

Why agents copy the wrong path

Model-generated mutations often reuse the last path that validated in context. Metrics enrichment at /imp/imp-1 is a common template. Floor changes feel like "another number on the same imp," so the path stays short.

applicable_intents does not fix this. The host may declare ADJUST_DEAL_FLOOR in the envelope and still receive a mutation whose path never names a deal. artf.mutation.intent_not_applicable is a different failure: the intent string was never offered. Here the intent is allowed; the path is wrong.

Relative paths fail earlier with artf.mutation.path_not_absolute. Unknown intent strings in the envelope's applicable_intents fail with artf.intent.unknown before the agent runs. Path-intent mismatch is the class of bug that survives those checks.

Margin is legal ARTF with no OpenRTB field

Even when the path is correct, one intent has no column to write. ADJUST_DEAL_MARGIN is valid ARTF, but OpenRTB 2.6 Deal has no margin field. The orchestrator applies margin out of band. RTBlint flags artf.mutation.no_openrtb_target as a warning so you do not expect pass-three OpenRTB validation to prove margin landed.

How you catch it

I run three passes on every ARTF hop: envelope and carried OpenRTB as protobuf JSON, the mutation set against applicable_intents and semantic paths, then apply accepted mutations and revalidate OpenRTB on the object the exchange will see.

The ARTF simulator runs the same engine in a browser: paste an RTBRequest, paste mutations, watch apply-then-revalidate. The primer on lifecycle, paths, and permissioning is ARTF explained. The longer walkthrough of independent acceptability is ARTF mutations and bid request validation.

CLI:

$ rtblint validate --type artf-response --request rtb-request.json rtb-response.json
FAILED (OpenRTB 2.6-202606 ARTF mutation set): …
  mutations[1].path: Intent ADJUST_DEAL_FLOOR targets "/imp/imp-1", which names an impression.
    Paths that carry ADJUST_DEAL_FLOOR look like /imp/{imp id}/pmp/deals/{deal id}.
  (artf.mutation.path_intent_mismatch)
Enter fullscreen mode Exit fullscreen mode

MCP tools validate_artf_request and validate_artf_response (with apply when you need post-patch OpenRTB) exist so an agent implementing AdCP, ARTF, or AAMP-style patches can call the check on its own output. The RPC can still return OK; the wire contract for OpenRTB inside the envelope does not move. rtblint (cargo install rtblint, npm install rtblint-core, MCP rtblint-mcp) is the deterministic check on that object and mutation set. It is independent of IAB Tech Lab and of AAO; the spec does not require it, and nothing in v1.0 replaces pass two before you forward.

Where to go next

Treat path templates as intent-specific types, not shared strings. When you add deal-floor agents, unit-test the full path including pmp/deals/{deal id} against the deals the sample bid request actually carries.

For rule-level detail, see path intent mismatch, intent not applicable, and no OpenRTB target for margin.

Production ARTF means production path bugs. gRPC success is transport; semantic paths are still the contract that decides whether a floor change ever touches a deal row.

Top comments (0)