Prefer the webhook body over refetching - #28
Merged
Merged
Conversation
message.received carries the plain-text body, so the inbound mail path no longer needs an API round-trip to read an email. It fetched on every inbound and fell back to the 200-char snippet whenever that call failed, leaving the agent with an email cut off mid-sentence and no indication anything was missing. Use the body from the payload when it is whole. Only a truncated or absent body is worth a fetch, and when that fetch fails the truncated body is delivered with a notice giving the character counts and the message id, rather than silently collapsing to the snippet.
The SDK announces itself in the User-Agent and accepts a caller token ahead of its own, but the plugin never set one, so an inbound request was indistinguishable from any other Python SDK caller. Without that there is no way to tell which plugin, or which version of it, a given agent is running. Pass user_agent_prefix from inkbox_client_kwargs, the single place client kwargs are built, sourced from installed package metadata so it cannot drift from the declared version. __version__ had already drifted to 0.1.0 against a 0.1.4 pyproject, which is exactly the failure the metadata lookup avoids. Version is realigned to 0.2.5, the shared number across the plugin fleet, so the token identifies a fleet release rather than a per-repo count.
alex-w-99
marked this pull request as ready for review
July 27, 2026 02:40
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two changes to the inbound mail path and one fleet-wide version alignment.
1.
_fetch_mail_bodypredatesmessage.receivedcarrying the body. It issued aget_messagecall on every inbound email and, on any exception, fell back tosnippet, the 200-char preview. So a transient API failure silently handed the agent an email cut off mid-sentence with nothing indicating content was missing, and the healthy path paid a round-trip for a body the webhook had already delivered.2. The plugin was anonymous to the API. The SDK announces itself in the
User-Agentand accepts a caller token ahead of its own, but the plugin never set one, so its requests were indistinguishable from any other Python SDK caller. There was no way to tell which plugin, or which version of it, an agent was running.What's here
Inbound body
body_state: "complete") is used as-is, so the common case does no network call at all.get_message, which is the only way to recover the remainder._webhook_mail_bodydelivers what the webhook did carry: the truncated body plus a notice line giving the included/total character counts and the message id, or the snippet when there was no body at all. Previously a failed fetch discarded a body the payload already had.Bounce and delivery-failure handlers are untouched, since
bodyis null by contract on non-receivedevents and the snippet is the only text available there.Plugin User-Agent
inkbox_client_kwargsnow passesuser_agent_prefix, yieldinginkbox-codex/<version> inkbox-python/<sdk version>. That helper is the single place client kwargs are built, so every construction site is covered by one change.__version__had already drifted to0.1.0against a0.1.4pyproject, which is exactly the failure the metadata lookup avoids; both are now consistent.User-Agentheader is already sent on every request. It fills in a field that was previously blank.Version
Realigned to 0.2.5, the shared number across the plugin fleet. Previously each repo counted independently (0.2.4 / 0.2.2 / 0.1.4 / 0.1.3 / 0.1.0), so a version told you nothing about which fleet release you were on. 0.2.5 is one above the previous fleet maximum, so every repo moves strictly up and no version number is reused for different content.
Behavior change
Inbound email turns get longer, and the steady-state inbound path makes one fewer API call. Anything downstream that assumed a mail turn was at most ~200 chars of body on the failure path will now see the whole email.
Tests
tests/test_gateway_inbound_mail_body.pycovers the body helper and the fetch policy: complete body skips the fetch, truncated body fetches the remainder, failed fetch keeps the truncated body with its notice, absent body falls through to the snippet.tests/test_user_agent.pycovers the token, its presence in the client kwargs, and the missing-distribution fallback. Full suite: 298 passed, 1 skipped.