feat: add MessagesResource (messaging primitive lifecycle)#28
Merged
Conversation
govindkavaturi-art
approved these changes
May 4, 2026
Member
govindkavaturi-art
left a comment
There was a problem hiding this comment.
MessagesResource port for the messaging-primitive lifecycle. Approve.
Wraps the `/v1/messages` surface (Phase 12.1.5). Closes the messages portion of the `Messaging primitive` `endpoints_missing` entry in cueapi-python #24's parity manifest. New resource: - `cueapi/resources/messages.py`: MessagesResource - .send(from_agent, to, body, subject=, reply_to=, priority=, expects_reply=, reply_to_agent=, metadata=, idempotency_key=) - .get(msg_id) - .mark_read(msg_id) # idempotent on already-read - .ack(msg_id) # terminal Client extension: - Same `_request(headers=...)` extension as PR #27 (AgentsResource). Independent commit on this branch since the two resources can land in either order; minor merge conflict on client.py is auto-resolvable (both PRs add the same kwarg in the same way). Design notes pinned by tests: - `from_agent` goes via `X-Cueapi-From-Agent` HEADER, NOT in body. The server's MessageCreate schema is extra="forbid" — putting `from` in the body would 400, but we want this caught at unit-test time. Pinned by test_minimal_body_and_from_header. - `expects_reply=False` (default) NOT sent in body. Server default is False; sending `expects_reply: false` is no-op + adds noise. Pinned by test_omits_expects_reply_when_default. - `idempotency_key` >255 chars raises ValueError client-side BEFORE any HTTP call. Matches server's hard limit. Pinned that no HTTP request is made when the validation fails. - `idempotency_key=None` omits the header entirely (no `Idempotency-Key: None` leakage). Pinned. Tests: 9 new (12 → 21 in this resource family; 38 total across all unit-test files). Server-side dedup-hit (200 response) and priority-downgrade signals (`X-CueAPI-Priority-Downgraded` header) are surfaced through the underlying httpx response — the SDK's `_handle_response` returns the data dict on 2xx, so callers see status_code 200 vs 201 only via the underlying client. A future enhancement could expose these signals explicitly via a richer return type; documented for follow-up. No hosted-PR dependency. All 4 endpoints already shipped on prod. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
e7899b6 to
f968e54
Compare
This was referenced May 4, 2026
mikemolinet
added a commit
that referenced
this pull request
May 9, 2026
…t recent ports (#36) Manifest was 3 days stale; many endpoints listed as missing have been ported since the last audit. Moved from endpoints_missing → endpoints_covered (with PR refs): - POST /v1/cues/{id}/fire (PR #23; in-flight kwargs in #33) - POST /v1/executions/{id}/replay (PR #25) - GET /v1/executions/claimable (PR #23) - POST /v1/executions/{id}/claim (PR #23) - POST /v1/executions/claim (PR #23) - GET /v1/workers + DELETE /v1/workers/{id} (PR #26) - GET /v1/usage (PR #26) - POST /v1/agents + GET/PATCH/DELETE /v1/agents/{ref} + GET /v1/agents/{ref}/webhook-secret + GET /v1/agents/{ref}/inbox + /sent (PR #27) - POST /v1/messages + GET/read/ack (PR #28) Added in-flight refs (open PRs): - GET /v1/agents/roster (in-flight PR #35; cueapi #630 parity) - GET /v1/agents/{ref}/presence (in-flight PR #35; cueapi #662 parity) - send_at + exit_criteria + idempotency_key kwargs on fire (PR #33) - send_at kwarg on messages.send (PR #34) New endpoints_missing items (post-audit): - POST /v1/agents/{ref}/webhook-secret/regenerate (destructive; tracked) - DELETE /v1/messages bulk (cueapi #650; bounded by cueapi-cli upstream) - POST /v1/executions/{id}/live-claim (cueapi #664; handler-runtime, not SDK) New "in_flight_ports_2026_05_07" section listing all 4 currently-open SDK PRs with PR-overlap notes (PR #30/#33 lane-flagged with cueapi-main). Bumped sdk_version_at_audit 0.1.3 → 0.2.x. This refresh closes the Backlog row "Refresh cueapi-python parity-manifest.json" filed earlier today (Self-flag 2026-05-07). Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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
Wraps the
/v1/messagessurface (Phase 12.1.5). Closes the messages portion of theMessaging primitiveendpoints_missingentry in cueapi-python #24's parity manifest. Pairs with PR #27 (AgentsResource) to close the entire messaging-primitive entry.Surface
client.messagesexposes:.send(from_agent, to, body, ...)X-Cueapi-From-Agentheader; idempotency viaIdempotency-Keyheader.get(msg_id).mark_read(msg_id).ack(msg_id)Design notes pinned by tests
from_agentgoes viaX-Cueapi-From-AgentHEADER, not in body. Matches the server's contract —MessageCreateschema isextra=\"forbid\", so a refactor puttingfromin the body would 400 at integration time. The test pins this so the failure is loud at unit-test time instead.expects_reply=False(default) NOT sent in body. Server default is False; sendingexpects_reply: falseis no-op + adds noise. Pinned:test_omits_expects_reply_when_default.idempotency_key>255 chars raisesValueErrorclient-side BEFORE any HTTP call. Matches server's hard limit; pinned that no HTTP request is made when the validation fails.idempotency_key=Noneomits theIdempotency-Keyheader entirely — no\"Idempotency-Key\": Noneleakage. Pinned.Client extension
This branch contains the same
_request(headers=...)extension as PR #27 (since both PRs need it independently). Minor merge conflict onclient.pywill auto-resolve when one lands first — both PRs add the kwarg in the same way.Tests
9 new (12 → 21 in this resource family; 38 total across all unit-test files).
Server-side signals not yet exposed
Two server-side signals exist but aren't yet surfaced richly through the SDK return type:
Idempotency-Key: server returns 200 (not 201) when same key + same body found within 24h. SDK's_handle_responsereturns the data dict on both 200 and 201 — callers can't easily tell which they got.X-CueAPI-Priority-Downgraded: trueresponse header when receiver-pair limits downgrade priority>3 to 3.Both could be surfaced via a richer return type (e.g. a
MessageResponsedataclass with status code + headers exposed) in a follow-up. Documented but not implemented in this PR — keeping scope tight on endpoint coverage.No hosted-PR dependency
All 4 endpoints already shipped on prod via Phase 12.1 messaging primitive.
Companion PRs from this session
mark_verifiedbug fix +replay()WorkersResource+UsageResourceAgentsResource🤖 Generated with Claude Code