Sendmux token-efficient usage
SkillSearchChoose the cheapest correct Sendmux surface and call. Use whenever a Sendmux task could be done through MCP, the sendmux CLI, an SDK, or direct HTTP and the user needs low-token, low-round-trip usage: batch sends, mailbox search/count/batch reads, sync deltas, cursor pagination, ETags, conditional requests, idempotency keys, attachment file transfer, or avoiding broad mailbox/log fetches.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Sendmux token-efficient usage skill
What this skill tells your AI
The instructions your AI receives, as published by sendmux/skills in skills/sendmux-token-efficient-usage/SKILL.md and read by ahel’s review.
Use this skill to choose the lowest-cost Sendmux route that still answers the task correctly.
Boundaries
- Do not ask the user to paste an API key.
- For API-key authentication, use send-capable
smx_mbx_*keys or owner-approved Sending-resourcesmx_agent_*tokens for Sending calls, andsmx_mbx_*keys for normal Mailbox calls. - For a self-registered agent, reuse one durable CLI profile for reads. Sending stays blocked until owner approval, then
sending:*commands exchange and cache a one-hour delegated token automatically. - Its inbox is capped at 500 MiB before approval. Owner-approved sending raises it to at least 5 GiB first. Revoking sending does not itself change the current inbox storage allocation.
- For API-key authentication, use
smx_root_*for Management calls. REST OAuth profiles can use their approved surfaces, scopes and mailboxes; route login and refresh tosendmux-cli. - Do not default to MCP for every task. MCP is best when the required tool is curated; CLI and SDK cover broader surfaces.
- Do not pipe real attachments through model context as base64. Route attachment transfer to
sendmux-attachments; preferfile_path, presigned URLs, CLI--attach, or SDK file helpers. Mailbox uploads cap each attachment at 7,500,000 bytes; Sending uploads cap each file at 18 MiB; MCP inline base64 caps at 32 KiB decoded. - Do not read full mailbox bodies, every message, or every log row unless the user asks for full content and narrower calls cannot answer.
Validate credentials with the selected surface's get-connection CLI operation or MCP mailbox_get_connection, management_get_connection, or sending_get_connection. These checks need no mailbox selector and send no email; public OpenAPI discovery does not validate credentials.
Surface choice
| Situation | Use | Why |
|---|---|---|
| Connected agent and curated tool exists | MCP tool | Small schema and no SDK boilerplate. |
| One-off terminal task | sendmux CLI with --json | Direct, scriptable, exposes the full generated operation set. |
| Application code or repeated workflow | SDK for the project already in use | Reuses client setup, pagination, headers, and retry helpers. |
| MCP lacks the needed operation | CLI for terminal work, SDK for code | Do not invent uncurated MCP tools. |
| No package/tooling available | Direct HTTP | Keep request bodies and headers aligned to OpenAPI. |
Cheapest-call map
| Task | Cheapest correct default |
|---|---|
| Send one outbound email | sending_send_email, CLI sending:send, SDK sendingSendEmail; include Idempotency-Key. |
| Send multiple outbound emails | sending_send_email_batch, CLI sending:send:batch, SDK sendingSendEmailBatch; do not loop single sends. |
| Send or read attachments | sendmux-attachments; use file_path, presigned upload/download URLs, CLI --attach, SDK file helpers, blob_id for mailbox sends, and attachment_id for Sending sends instead of inline base64. |
| Count matching mailbox messages | mailbox_count_messages, CLI mailbox:count-messages, SDK mailboxCountMessages. |
| Search mailbox text | mailbox_search_message_snippets, CLI mailbox:search-message-snippets, SDK mailboxSearchMessageSnippets; then fetch selected IDs. |
| Read several known messages | mailbox_batch_get_messages, CLI mailbox:batch-get-messages, SDK mailboxBatchGetMessages. |
| Update/delete several messages | Batch update/delete after explicit confirmation. |
| Resume broad mailbox sync | mailbox_get_changes, CLI mailbox:get-changes, SDK mailboxGetChanges. |
| Resume filtered mailbox sync | CLI/SDK mailbox:query-message-changes / mailboxQueryMessageChanges; MCP does not curate it yet. |
| Watch live mailbox events | CLI/SDK mailbox:stream-events / mailboxStreamEvents; MCP does not curate it yet. |
| Scan threads | List threads, then fetch one thread or its messages. |
| Manage domains/mailboxes/keys | Management MCP for curated create/list/get/update/suspend/resume/key tools; CLI/SDK for uncovered lifecycle work. |
| Manage sending accounts | CLI/SDK; MCP does not curate provider tools yet. |
| Manage webhooks | MCP for list/create/test; CLI/SDK for get/update/delete/rotate/delivery payloads. |
| Inspect spend, logs, metrics | Summary/metrics first; filter log lists with small limit, then fetch one selected row. |
For an agent with no key, avoid manual protocol calls and token copying:
sendmux agent:register my-agent --default --json
sendmux mailbox:me:get --profile my-agent --json
sendmux agent:invite-owner owner@example.com --profile my-agent --json
Register once, then reuse the durable profile across processes. After owner acceptance and sending approval, use the same profile with sending:*; the CLI handles the one-hour delegated token exchange and cache.
Read less
For mailbox questions, reduce the result set before reading content:
- Count when the user asks "how many" or when the query may be broad.
- Search snippets with a small
limitwhen the user needs examples. - Batch-get only selected message IDs.
- Request clean body/content only when message text affects the answer.
CLI:
sendmux mailbox:count-messages \
--query q=invoice \
--query is_unread=true \
--json
sendmux mailbox:search-message-snippets \
--query q=invoice \
--query is_unread=true \
--query limit=10 \
--json
sendmux mailbox:batch-get-messages \
--body '{
"ids": ["eml_abc", "eml_def"],
"body_mode": "clean_json",
"max_body_chars": 4000,
"strip_quotes": true,
"strip_signature": true,
"include_attachments": "metadata"
}' \
--json
Write fewer requests
Batch when there is more than one target.
sendmux sending:send:batch \
--idempotency-key "$IDEMPOTENCY_KEY" \
--body-file ./messages.json \
--json
sendmux mailbox:batch-update-messages \
--body '{
"ids": ["eml_abc", "eml_def"],
"seen": true,
"if_in_state": "state_from_prior_read"
}' \
--json
For batch sends, inspect every per-message result before reporting success. Batch can contain mixed outcomes.
Sync by delta
Use sync endpoints instead of re-listing stable data.
Broad mailbox sync:
sendmux mailbox:get-changes \
--query messages_since_state="$MESSAGES_STATE" \
--query folders_since_state="$FOLDERS_STATE" \
--query threads_since_state="$THREADS_STATE" \
--query limit=100 \
--json
Filtered message sync:
sendmux mailbox:query-message-changes \
--query since_query_state="$QUERY_STATE" \
--query q=invoice \
--query is_unread=true \
--query limit=100 \
--json
Store the returned state token. Continue with the same filters only while has_more is true and the next page is needed.
Transfer less
- Use small
limitvalues on list calls. - Follow
pagination.next_cursoronly until enough evidence has been gathered. - Prefer summary or metrics endpoints before log lists.
- Use
If-None-Matchfor repeated detail reads that previously returned anETag. - Use
If-Matchfor updates when the prior read returned anETag. - For inbound attachments, fetch metadata and use the short-lived
download_url; if it expires, re-fetch metadata instead of building URLs manually. - For outbound attachments, a file path or presigned URL is usually under 100 tokens, while base64 can burn thousands of tokens and corrupt large files.
CLI conditional examples:
sendmux management:get-email-log \
--path public_id=dlog_abc \
--if-none-match "$ETAG" \
--json
sendmux management:update-mailbox \
--path public_id=mbx_abc \
--if-match "$ETAG" \
--body '{"display_name":"Agent Inbox"}' \
--json
SDK helpers:
import {
conditionalHeaders,
idempotencyHeaders,
paginate,
responseEtag,
} from "@sendmux/core";
const headers = conditionalHeaders({ ifNoneMatch: priorEtag });
const writeHeaders = {
...conditionalHeaders({ etag: priorEtag }),
...idempotencyHeaders(operationKey),
};
Retry safely
Use Idempotency-Key on supported mutations so retrying does not create duplicate work.
Good candidates:
sending:sendandsending:send:batch.mailbox:send-message.- Management creates, mailbox key creation, suspend/resume, provider mutations, webhook create/rotate/test.
When retrying application code, prefer SDK retry helpers only for safe reads or idempotent writes. Non-idempotent writes should fail rather than risk duplicate side effects.
Routing
- Setup, key scopes, first call:
sendmux-getting-started. - Email send bodies and SMTP-vs-HTTP choice:
sendmux-send-email. - Attachment upload/download mechanics:
sendmux-attachments. - Mailbox read/search/sync/triage/reply details:
sendmux-mailbox-agent. - Management domains, mailboxes, webhooks, billing, logs:
sendmux-management. - CLI syntax and profiles:
sendmux-cli. - MCP installation and client config:
sendmux-mcp-setup.
Signals
- GitHub stars
- 20
- Forks
- 1
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
sendmux-token-efficient-usage- Source
- github.com/sendmux/skills