Skip to content

feat(missive): add Missive integration#371

Merged
TheRealAgentK merged 37 commits into
masterfrom
sj/missive-integration
Jun 22, 2026
Merged

feat(missive): add Missive integration#371
TheRealAgentK merged 37 commits into
masterfrom
sj/missive-integration

Conversation

@Shubhank-Jonnada

@Shubhank-Jonnada Shubhank-Jonnada commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a Missive integration to the autohive-integrations SDK (2.0.0).

Missive is a collaborative team inbox that unifies email, SMS, WhatsApp, and live chat. This integration covers conversations, messages, drafts, posts, contacts, analytics, and discovery helpers for resolving organization, user, team, and shared-label IDs.

Actions

Category Actions
Conversations list_conversations, get_conversation, update_conversation, merge_conversations, list_conversation_messages, list_conversation_comments, list_conversation_posts, list_conversation_drafts
Messages list_messages, get_message, create_message
Drafts & Posts create_draft, delete_draft, create_post
Contacts list_contacts, get_contact, create_contact, update_contact, list_contact_books, list_contact_groups
Analytics create_analytics_report, get_analytics_report
Discovery list_organizations, list_users, list_teams, list_shared_labels

Auth

Custom auth (type: custom) with a single api_token field (Bearer token). Token requires the Missive Productive plan or higher.

Testing

  • Unit tests — mocked request/response coverage for actions, request shapes, and non-2xx error paths
  • Integration tests — live API coverage requiring MISSIVE_API_TOKEN
  • Destructive tests (create_draft, delete_draft, create_post, create_contact, create_analytics_report) are marked with @pytest.mark.destructive and documented separately from the safe read-only run command

Notable API quirks discovered during testing

  • list_conversations uses the mailbox name as a boolean query param (all=true, not mailbox=all)
  • Team mailboxes require a UUID value: team_inbox={team_uuid}
  • list_messages is an exact lookup by email Message-ID, not a general search/list endpoint
  • create_message uses the documented custom-channel fields (account, from_field, to_fields, body) and maps conversation_id to conversation
  • create_draft uses draft fields such as from_field, to_fields, account, conversation, team, and add_assignees; it does not use channel_id
  • create_post requires a notification payload and maps assignment/label inputs to Missive wire keys (team, add_assignees, add_shared_labels)
  • Assignment and shared-label flows require the relevant organization_id
  • Minimum limit on paginated endpoints is 2

Files

missive/
├── missive.py
├── config.json
├── README.md
├── __init__.py
├── requirements.txt
├── icon.png
└── tests/
    ├── conftest.py
    ├── test_missive_unit.py
    └── test_missive_integration.py

Implements full Missive integration covering conversations, messages,
drafts, posts, contacts, and analytics — all actions live-tested against
the Missive API.
@github-actions

github-actions Bot commented Jun 15, 2026

Copy link
Copy Markdown

🔍 Integration Validation Results

Commit: 650c00efb69a9d3f7b7f06fa1221e8527c9f647e · fix(missive): adopt SDK 2.x ActionError pattern and finalize review fixes
Updated: 2026-06-22T11:47:29Z

Changed directories: missive

Check Result
Structure ✅ Passed
Code ⚠️ Passed with warnings
Tests ✅ Passed
README ✅ Passed
Version ✅ Passed
✅ Structure Check output
Validating 1 integration(s)...

============================================================
Integration: missive
============================================================
✅ All checks passed!

============================================================
SUMMARY
============================================================
Integrations validated: 1
Total errors: 0
Total warnings: 0

✅ All validations passed!
⚠️ Code Check output
----------------------------------------
Checking: missive
----------------------------------------

📦 Installing dependencies...

🐍 Checking Python syntax...
   ✅ Syntax OK

📥 Checking imports...
   ✅ Imports OK

📄 Checking JSON files...
   ✅ JSON files OK

🔍 Linting with ruff...
   ✅ Lint OK

🎨 Checking formatting with ruff...
   ✅ Formatting OK

🔒 Scanning for security issues with bandit...
   ✅ Security OK

🛡️ Checking dependencies for vulnerabilities with pip-audit...
   ✅ Dependencies OK

🔗 Checking config-code sync...
   ⚠️  Action 'list_organizations': parameter 'offset' defined in input_schema but never accessed in code
   ⚠️  Action 'list_organizations': parameter 'limit' defined in input_schema but never accessed in code
   ⚠️  Action 'list_users': parameter 'offset' defined in input_schema but never accessed in code
   ⚠️  Action 'list_users': parameter 'limit' defined in input_schema but never accessed in code
   ⚠️  Action 'list_teams': parameter 'offset' defined in input_schema but never accessed in code
   ⚠️  Action 'list_teams': parameter 'limit' defined in input_schema but never accessed in code
   ⚠️  Action 'list_shared_labels': parameter 'offset' defined in input_schema but never accessed in code
   ⚠️  Action 'list_shared_labels': parameter 'limit' defined in input_schema but never accessed in code
   ✅ Config-code sync OK

🔄 Checking fetch patterns...
   ✅ Fetch patterns OK

========================================
✅ CODE CHECK PASSED
========================================
✅ Tests Check output

Integration   Tests  Coverage        Status
-------------------------------------------
missive     45/45       82%      ✅ Passed
-------------------------------------------
Total       45/45            ✅ All passed

✅ Tests passed: missive
✅ README Check output
========================================
✅ README CHECK PASSED
========================================
✅ Version Check output
✅ missive: New integration with version 1.0.0

========================================
✅ VERSION CHECK PASSED
========================================

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d4ad6c40b2

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread missive/missive.py
Comment thread missive/missive.py Outdated
Comment thread missive/missive.py Outdated
Comment thread missive/missive.py Outdated
Comment thread missive/missive.py Outdated
Comment thread missive/missive.py Outdated
…tact, skip test when token lacks Operator role
… wrapper with id in body per Missive API spec
@TheRealAgentK

Copy link
Copy Markdown
Collaborator

💡 Suggestion: Consider adding a small shared request/response helper for Missive calls to centralize headers, status handling, and Missive error extraction. The current handlers repeat the same try/except/result pattern, which makes it easy for non-2xx responses to slip through as successes and harder to keep SDK v2 ActionError behavior consistent.

@TheRealAgentK

Copy link
Copy Markdown
Collaborator

💡 Suggestion: The unit tests are broad but shallow: they mostly assert result is True and do not verify request URLs, methods, query params, or payloads. Consider adding request-shape tests for the high-risk write actions (create_draft, create_post, update_conversation, create_contact) plus non-2xx/error-path tests. That would have caught several API-field mismatches and false-success paths in this PR.

@TheRealAgentK TheRealAgentK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Posted integration review findings: blockers and should-fixes are inline on the relevant code; suggestions are posted as general PR comments.

Comment thread missive/missive.py Outdated
Comment thread missive/missive.py Outdated
Comment thread missive/tests/test_missive_integration.py
Comment thread missive/missive.py Outdated
Comment thread missive/tests/test_missive_integration.py Outdated
Comment thread missive/tests/test_missive_integration.py Outdated
Comment thread missive/tests/test_missive_integration.py
Comment thread missive/tests/test_missive_integration.py Outdated
@TheRealAgentK

Copy link
Copy Markdown
Collaborator

💡 Suggestion: Avoid putting exact counts like “22 actions”, “16 integration tests”, etc. in PR descriptions and README copy unless the number is generated or otherwise maintained. These counts tend to drift as actions/tests are added or removed, making the docs stale. Prefer wording like “covers conversations, messages, drafts, contacts, and analytics” or “includes unit and integration coverage” without hard-coded totals.

…tch; fix create_draft field names to match Missive API (channel, conversation, team, add_assignees)
…ng; use resp.json(content_type=None) in real_fetch
@TheRealAgentK

Copy link
Copy Markdown
Collaborator

Follow-up on my earlier suggestion about centralizing Missive request/response handling: this is partially addressed by _check_response(), but not fully yet. Two handlers still bypass response checking and can return success for non-2xx responses:

  • merge_conversations
  • delete_draft

Please make sure those fetch responses are assigned and passed through _check_response(response) before returning success. That would satisfy the functional part of this suggestion.

@TheRealAgentK

Copy link
Copy Markdown
Collaborator

Follow-up on the exact-counts suggestion: this still looks unaddressed. The PR description/README copy still includes hard-coded counts such as “22 actions” / test totals. Please remove those exact numbers unless they are generated or otherwise maintained, and use wording like “covers conversations, messages, drafts, contacts, and analytics” / “includes unit and integration coverage” instead.

Shubhank-Jonnada and others added 2 commits June 17, 2026 14:10
…_draft, pass through _check_response; remove hard-coded action counts from README
@TheRealAgentK

Copy link
Copy Markdown
Collaborator

Two follow-ups from the re-review:

  1. Exact counts are still not fully addressed. The PR title still says “22 actions”, the PR body has fixed counts/categories, and root README.md still says “provides 22 actions”. Please remove hard-coded counts unless they’re generated/maintained automatically. Prefer wording like “covers conversations, messages, drafts, posts, contacts, and analytics.”

  2. Can you add evidence of live integration test runs after the latest fixes? The current validation comment shows 30/30 tests, which appears to be the unit test suite, not test_missive_integration.py.

Please paste the commands and output for at least:

pytest missive/tests/test_missive_integration.py -m "integration and not destructive" -v

And, if destructive tests were run:

pytest missive/tests/test_missive_integration.py -m "integration and destructive" -v

If destructive tests were intentionally not rerun, please say that explicitly.

@TheRealAgentK TheRealAgentK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Integration review using the Autohive integration skills. Requesting changes for the inline blockers and should-fix items.

Comment thread missive/config.json Outdated
Comment thread missive/README.md Outdated
Comment thread missive/missive.py Outdated
Comment thread missive/tests/test_missive_integration.py
Comment thread missive/tests/test_missive_integration.py Outdated
Comment thread missive/missive.py Outdated
Make the Missive integration API-correct and agent-usable, validated
against the live REST API with a PAT token.

API correctness fixes (missive.py + config.json):
- create_message: drop invalid channel_id; map conversation_id -> conversation
- create_post: require notification (live API 400s without it); map
  assignee_id -> add_assignees, team_id -> team,
  shared_label_ids -> add_shared_labels; parse posts[].conversation;
  output conversation_id
- create_draft/create_post/update_conversation: require organization_id
  for assignee/shared-label flows (live API 400s without it)
- update_conversation: closed:false -> reopen:true, closed:true -> close:true
- create_analytics_report: fix wire keys (time_zone, teams, users,
  shared_labels)
- list_contact_groups: kind is required by the API (HTTP 400 without it)
- fix contacts schema: infos[].kind/label/value; remove bogus top-level kind

Agent usability:
- add discovery actions: list_organizations, list_users, list_teams,
  list_shared_labels so agents can resolve required IDs
- list_conversations: add email/domain/contact_organization_id/organization_id
  filters (mutually exclusive) to find conversations by contact
- redescribe list_messages as exact Message-ID lookup (not a search)

Tests:
- expand unit coverage to 43 tests (request-shape + error paths)
- add live coverage for discovery actions, contact filters, and message
  endpoint contract tests (synthetic IDs) so message paths are verified
  without real email data

Validated: validate_integration + check_code pass; 43 unit pass;
23 live integration pass (2 data-only skips).
@ProRedCat

Copy link
Copy Markdown
Member

Review changes pushed — Missive integration now API-correct & agent-usable

Worked through the open review feedback and validated every action against the live Missive REST API (PAT auth). Summary of what changed:

API correctness fixes

  • create_message: removed invalid channel_id; map conversation_idconversation.
  • create_post: notification is now required (live API returns HTTP 400 without it); map assignee_idadd_assignees, team_idteam, shared_label_idsadd_shared_labels; parse posts[].conversation and output conversation_id.
  • create_draft / create_post / update_conversation: require organization_id for assignee/shared-label flows (live API 400s without it).
  • update_conversation: closed: falsereopen: true, closed: trueclose: true.
  • create_analytics_report: corrected wire keys → time_zone, teams, users, shared_labels.
  • list_contact_groups: kind is required by the API (HTTP 400 without it) — found and fixed during live contacts testing.
  • Contacts schema: infos[].kind/label/value; removed a bogus top-level kind.

Agent usability

  • Added discovery actions so agents can resolve required IDs: list_organizations, list_users, list_teams, list_shared_labels.
  • list_conversations: added email / domain / contact_organization_id / organization_id filters (mutually exclusive) so conversations can be found by contact.
  • Redescribed list_messages as an exact Message-ID lookup (not a general search).

Tests & validation

  • Unit tests expanded to 43 passing (request-shape + error paths).
  • Live integration: 23 passing, 2 data-only skips. Added contract tests for the message endpoints using synthetic IDs, so GET /messages and GET /messages/:id are verified live without needing a connected email account.
  • validate_integration.py ✅ (0 errors, 0 warnings) and check_code.py ✅.

Contacts were also verified live after creating a contact book (list/get/create/update + list_contact_groups all pass).

…ixes

Address review feedback from PR #371.

Blocker: non-2xx responses no longer look successful.
- Every handler now returns ActionError(message=...) on failure instead of
  success-shaped {"result": false, "error": ...} data.
- Success returns drop the "result" field; output schemas in config.json
  drop "result"/"error". update_conversation/merge_conversations/delete_draft
  now echo the relevant id.
- Input-validation guards (org required, mutually exclusive filters) return
  ActionError too.

Blocker: list_contacts now requires contact_book and sends it.
- contact_book_id is required in config and mapped to the contact_book query
  param; non-2xx is surfaced as ActionError. Added a non-2xx unit test.

Tests refactored to SDK 2.x semantics.
- Unit + integration tests assert ResultType.ACTION / ResultType.ACTION_ERROR
  and result.result.message instead of data["result"].

Docs: README output columns updated for the id-echo actions.

Already in place from earlier commits (verified): create_draft API shape,
.env.example MISSIVE_* entries, safe-first test docstring, destructive post
cleanup via DELETE /v1/posts/:id, and resp.json(content_type=None) in the
live fixture.

Validated: validate_integration, check_code, run_tests (45/45, 82% cov),
check_readme all pass; 23 live integration tests pass (2 data-only skips).
@ProRedCat

Copy link
Copy Markdown
Member

Integration PR review — feedback addressed

Applied sub-skills: building-integration, writing-unit-tests, writing-integration-tests, upgrading-sdk-v2.

All open review comments have been addressed in 650c00e (and earlier a63e3b6). Summary by reviewer:

🚫 Blockers (TheRealAgentK) — all fixed

  • missive.py non-2xx treated as success → Every handler now returns ActionError(message=...) on failure instead of success-shaped {"result": false, "error": ...}. Success returns drop the result field and config.json output schemas drop result/error, matching the SDK 2.x pattern. Input-validation guards also return ActionError. Added non-2xx unit tests across actions.
  • create_draft payload shape → Now sends Missive's documented draft fields: from_field, account, conversation, team, add_assignees, organization, to_fields/cc_fields/bcc_fields. channel_id removed. Request-shape unit test added (test_create_draft_request_shape).
  • list_contacts requires contact_bookcontact_book_id is now required in config.json and mapped to the contact_book query param; non-2xx surfaces as ActionError. Added test_list_contacts_non2xx_returns_error.

⚠️ Should-fix (TheRealAgentK) — all addressed

  • .env.example MISSIVE_ entries* → present (MISSIVE_API_TOKEN, MISSIVE_ORG_ID, MISSIVE_TEST_EMAIL).
  • Test docstring lists safe command first → done (read-only -m "integration and not destructive" first, destructive documented separately with a mutation warning).
  • Destructive post cleanuptest_create_post deletes the created post via DELETE /v1/posts/:id in a finally block.
  • resp.json(content_type=None) → used in the live fixture.

Codex bot items

  • post conversation_idconversation, merge target key, contact contact_book → all fixed.
  • PATCH /v1/conversations/:id → verified working against the live API (update_conversation integration test passes); kept as-is.

Validation

  • validate_integration.py missive ✅ (0 errors, 0 warnings)
  • check_code.py missive
  • run_tests.py missive ✅ — 45/45 unit, 82% coverage
  • check_readme.py missive
  • Live integration: 23 passed, 2 skipped (skips are data-only: no real email messages in the test workspace; the message endpoints are covered by synthetic-ID contract tests).

@ProRedCat ProRedCat requested a review from TheRealAgentK June 22, 2026 11:49
@TheRealAgentK TheRealAgentK changed the title feat(missive): add Missive integration with 22 actions feat(missive): add Missive integration Jun 22, 2026
@TheRealAgentK

Copy link
Copy Markdown
Collaborator

Follow-up from the latest re-review:

  1. I updated the PR body to remove stale counts and stale API notes, and checked the Missive README entries for the same issue.
  2. Accepting Reilly's posted live integration-test summary as evidence for this PR.
  3. The remaining config-code warning around limit/offset on the discovery actions is a tooling false positive caused by helper-based inputs access; we'll handle that separately in the tooling repo rather than treating it as a Missive integration blocker.

@TheRealAgentK

Copy link
Copy Markdown
Collaborator

⚠️ Code Check output

----------------------------------------
Checking: missive
----------------------------------------

🔗 Checking config-code sync...
⚠️ Action 'list_organizations': parameter 'offset' defined in input_schema but never accessed in code
⚠️ Action 'list_organizations': parameter 'limit' defined in input_schema but never accessed in code
⚠️ Action 'list_users': parameter 'offset' defined in input_schema but never accessed in code
⚠️ Action 'list_users': parameter 'limit' defined in input_schema but never accessed in code
⚠️ Action 'list_teams': parameter 'offset' defined in input_schema but never accessed in code
⚠️ Action 'list_teams': parameter 'limit' defined in input_schema but never accessed in code
⚠️ Action 'list_shared_labels': parameter 'offset' defined in input_schema but never accessed in code
⚠️ Action 'list_shared_labels': parameter 'limit' defined in input_schema but never accessed in code
✅ Config-code sync OK

I investigated the warnings and they are a tooling false positive that I'm addressing over there.

@TheRealAgentK TheRealAgentK merged commit cc91f3c into master Jun 22, 2026
5 checks passed
@TheRealAgentK TheRealAgentK deleted the sj/missive-integration branch June 22, 2026 16:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants