Publisher-Stage ARTF With bid_response on the Envelope Stages the Agent Wrong A developer maintaining RTBlint, an open-source OpenRTB and ARTF linter, has detailed a common publisher-stage ARTF misconfiguration in which an envelope labeled LIFECYCLE_PUBLISHER_BID_REQUEST still carries a bid_response member from an earlier hop, causing the agent to misread its position in the auction even though gRPC returns OK. The linter flags the case as artf.lifecycle.payload_unexpected, a warning rather than a hard error, and its inverse, a response-stage envelope missing bid_response, is flagged as artf.lifecycle.payload_mismatch. The developer also notes that ARTF tmax is a millisecond budget for the mutation RPC, with values above 1000 ms triggering artf.tmax.implausible. An SSP-side ARTF host labels the extension point LIFECYCLE PUBLISHER BID REQUEST , keeps yesterday's bid response on the envelope for debugging, and forwards ACTIVATE DEALS mutations against the publisher bid request . gRPC returns OK. The agent believes no buyer has answered yet. The orchestrator is staring at a seatbid it never told the agent existed. That is not a deal-activation bug in the agent. It is a reused envelope whose lifecycle name and its OpenRTB members disagree. The IAB Tech Lab Agentic Real Time Framework https://iabtechlab.com/standards/artf/ ARTF puts a containerized agent beside an SSP, exchange, or DSP. The host sends an RTBRequest with a lifecycle value, a tmax budget in milliseconds, the OpenRTB object under mutation, and applicable intents . The agent returns Mutation messages with semantic paths. The orchestrator applies what it accepts and only then forwards the auction. Publisher-stage calls run before any DSP has answered. Response-stage calls expect a bid response member when intents such as BID SHADE need seat and bid ids. The lifecycle enum names the stage. It does not delete extra members you left on the JSON from an earlier hop. LIFECYCLE PUBLISHER BID REQUEST means the extension point sits on the outbound publisher request. No DSP answer belongs on that wire yet. If bid response is present anyway, RTBlint reports artf.lifecycle.payload unexpected https://rtblint.org/docs/rule-reference/artf-lifecycle-payload unexpected/ : { "id": "ep-1", "tmax": 120, "lifecycle": "LIFECYCLE PUBLISHER BID REQUEST", "bid request": { "id": "a-1", "imp": { "id": "imp-1", "banner": { "w": 300, "h": 250 } } }, "bid response": { "id": "a-1", "seatbid": { "seat": "dsp-1", "bid": { "id": "bid-abc", "impid": "imp-1", "price": 2.5 } } } } The envelope declares publisher bid request stage and carries a full bid response . At that stage no DSP should have answered. The validator treats it as a warning, not a hard error, because a private host might deliberately pass prior context. For a default orchestrator, the warning is the point: the agent's model of where it sits in the auction is wrong even when protobuf JSON parses cleanly. The inverse failure, response stage without bid response , is artf.lifecycle.payload mismatch https://rtblint.org/docs/rule-reference/artf-lifecycle-payload mismatch/ . That one blocks shading paths that need a bid id the envelope never included. Together they are the same contract: lifecycle tells the agent which intents make sense; the carried OpenRTB members have to match that story. Reusing one JSON blob across hops is how both show up in production. A team logs the full auction state, copies the object into the next ARTF fixture, and forgets to drop bid response when the lifecycle moves back to publisher stage. gRPC still accepts the bytes. ARTF tmax is milliseconds budgeted for the mutation RPC inside the auction, not the OpenRTB bid timeout copied from bid request.tmax . Reference samples use roughly 120 to 150 ms. Values above 1000 ms trigger artf.tmax.implausible https://rtblint.org/docs/rule-reference/artf-tmax-implausible/ : the extension point runs inside an exchange timeout, and a budget measured in seconds usually means someone pasted an auction limit without converting units. That warning does not fail the envelope by itself. It pairs badly with a mislabeled lifecycle: you can burn seconds of agent time on a call that still carries the wrong stage label and a ghost bid response . I maintain RTBlint https://rtblint.org , an open source OpenRTB and ARTF linter. Envelope checks run before mutation checks because lifecycle and intents define what the response is allowed to propose. bash $ rtblint validate --type artf-request rtb-request.json FAILED OpenRTB 2.6-202606 ARTF request envelope : 0 error s , 1 warning s . - warning bid response: lifecycle is LIFECYCLE PUBLISHER BID REQUEST, which runs before any DSP has answered, yet the envelope carries a bid response. artf.lifecycle.payload unexpected If the document never parses, nothing downstream runs. Truncated fixtures and log line limits show up as artf.payload.invalid json https://rtblint.org/docs/rule-reference/artf-payload-invalid json/ before lifecycle logic executes. Pass two on responses pairs each mutation against applicable intents and semantic paths in the payloads actually carried. Pass three applies accepted mutations and revalidates OpenRTB so field-level damage appears on the request the exchange will see. The same rules run in the ARTF simulator https://rtblint.org/demo/artf/ , MCP tools, and gRPC on openadtech.rtblint.v1 . ARTF already mandates gRPC for the extension point; validating on that channel beats discovering stage skew only after deals activate against the wrong document. ARTF explained https://rtblint.org/guides/artf-explained/ walks the request and response members without assuming you read the PDF first. The docs index https://rtblint.org/docs/ links every ARTF rule id, including lifecycle, tmax, and mutation path checks, if you want stable ids in CI. RTBlint is independent of IAB Tech Lab. The rule ids above come from the public ARTF proto and the v1.0 document; they exist because lifecycle and payloads are contracts you can violate while the RPC still returns OK.