{"slug": "publisher-stage-artf-with-bid-response-on-the-envelope-stages-the-agent-wrong", "title": "Publisher-Stage ARTF With bid_response on the Envelope Stages the Agent Wrong", "summary": "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.", "body_md": "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.\n\nThat is not a deal-activation bug in the agent. It is a reused envelope whose lifecycle name and its OpenRTB members disagree.\n\nThe 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.\n\nPublisher-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.\n\n`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/):\n\n```\n{\n  \"id\": \"ep-1\",\n  \"tmax\": 120,\n  \"lifecycle\": \"LIFECYCLE_PUBLISHER_BID_REQUEST\",\n  \"bid_request\": { \"id\": \"a-1\", \"imp\": [{ \"id\": \"imp-1\", \"banner\": { \"w\": 300, \"h\": 250 } }] },\n  \"bid_response\": { \"id\": \"a-1\", \"seatbid\": [{ \"seat\": \"dsp-1\", \"bid\": [{ \"id\": \"bid-abc\", \"impid\": \"imp-1\", \"price\": 2.5 }] }] }\n}\n```\n\nThe 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.\n\nThe 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.\n\nReusing 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.\n\nARTF `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.\n\nThat 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`.\n\nI 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.\n\n``` bash\n$ rtblint validate --type artf-request rtb-request.json\nFAILED (OpenRTB 2.6-202606 ARTF request envelope): 0 error(s), 1 warning(s).\n- [warning] bid_response: lifecycle is LIFECYCLE_PUBLISHER_BID_REQUEST, which runs\n  before any DSP has answered, yet the envelope carries a bid_response.\n  (artf.lifecycle.payload_unexpected)\n```\n\nIf 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.\n\nPass 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.\n\nThe 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.\n\n[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.\n\nRTBlint 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.", "url": "https://wpnews.pro/news/publisher-stage-artf-with-bid-response-on-the-envelope-stages-the-agent-wrong", "canonical_source": "https://dev.to/aleksuix/publisher-stage-artf-with-bidresponse-on-the-envelope-stages-the-agent-wrong-1mig", "published_at": "2026-09-18 00:01:47+00:00", "updated_at": "2026-09-18 00:23:00.619706+00:00", "lang": "en", "topics": ["agent-protocols", "ai-agents", "developer-tools", "structured-data"], "entities": ["RTBlint", "IAB Tech Lab", "Agentic Real Time Framework", "OpenRTB", "gRPC"], "alternates": {"html": "https://wpnews.pro/news/publisher-stage-artf-with-bid-response-on-the-envelope-stages-the-agent-wrong", "markdown": "https://wpnews.pro/news/publisher-stage-artf-with-bid-response-on-the-envelope-stages-the-agent-wrong.md", "text": "https://wpnews.pro/news/publisher-stage-artf-with-bid-response-on-the-envelope-stages-the-agent-wrong.txt", "jsonld": "https://wpnews.pro/news/publisher-stage-artf-with-bid-response-on-the-envelope-stages-the-agent-wrong.jsonld"}}