Gmail
The io.b3os/gmail pack: 6 actions with call snippets, fixture outputs, connection setup and error codes, generated from version 1.0.0.
io.b3os/gmail 1.0.0 · email, productivity · MIT
Search and read mail, send plain-text messages, create drafts and change labels (read, starred, archived) in a Gmail mailbox with your own Google OAuth token. Reading gives headers, labels and a snippet; full bodies arrive base64-encoded from Gmail, which declarative actions cannot decode, so they are not included. Needs gmail.readonly, gmail.send, gmail.compose or gmail.modify depending on the actions you use.
Every call's result carries upstream_status and timing: validate_ms, inject_ms, render_ms, upstream_ms, map_ms and total_ms. upstream is the service's time; the others are B3OS's own (call actions). The snippets below show no timing values, because a fixture records none.
Connection
google, type oauth2: Google account (Gmail).
An OAuth access token for your Google account from your own Google Cloud OAuth client, with the scopes listed here. Store the refresh_token, client_id and client_secret with it so the vault can refresh the token (access tokens last an hour); B3OS never uses a Google client of its own.
How to get one: developers.google.com.
Scopes the pack's actions use: https://www.googleapis.com/auth/gmail.readonly, https://www.googleapis.com/auth/gmail.send, https://www.googleapis.com/auth/gmail.compose, https://www.googleapis.com/auth/gmail.modify. The manifest names them per connection, not per action.
The credential is sent only to gmail.googleapis.com.
Store the credential once as a vault connection for this pack and key, then name its id in a call's connections. Leave the key out and B3OS uses the project's newest connection for the pack and key without a subject (connections).
Hosts it reaches: gmail.googleapis.com.
Actions
| Action | Effect | MCP tool | Title |
|---|---|---|---|
list-messages | read | gmail__list-messages | Search messages |
get-message | read | gmail__get-message | Get message |
send-email | write | gmail__send-email | Send email |
create-draft | write | gmail__create-draft | Create draft |
modify-labels | write | gmail__modify-labels | Change message labels |
list-labels | read | gmail__list-labels | List labels |
list-messages
Search messages. Message and thread ids matching a Gmail search (the same syntax as the search box: from:alice is:unread newer_than:7d has:attachment label:work), newest first. Read each with get-message. Page with page_token.
Ref io.b3os/gmail/list-messages@1.0.0 · effect read · connection google · MCP tool gmail__list-messages
bashcurl -s https://beta-api.b3os.org/v1/actions/call \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "ref": "io.b3os/gmail/list-messages@1", "input": { "query": "from:releases@example.com newer_than:7d", "max_results": 2 }, "connections": {"google": "conn_01m5t6cbgdjs1ketgcqwa2sne8"} }'
tsimport { B3OS } from "@b3os/sdk";const b3os = new B3OS();const result = await b3os.actions.call({ ref: "io.b3os/gmail/list-messages@1", input: { query: "from:releases@example.com newer_than:7d", max_results: 2 }, connections: { google: "conn_01m5t6cbgdjs1ketgcqwa2sne8" },});console.log(result.output);
pythonfrom b3os import B3OSb3os = B3OS()result = b3os.actions.call({ "ref": "io.b3os/gmail/list-messages@1", "input": { "query": "from:releases@example.com newer_than:7d", "max_results": 2, }, "connections": {"google": "conn_01m5t6cbgdjs1ketgcqwa2sne8"},})print(result["output"])
json{ "method": "tools/call", "params": { "name": "gmail__list-messages", "arguments": { "query": "from:releases@example.com newer_than:7d", "max_results": 2 } }}
Expose the pack as tools with --packs gmail on the local server or ?packs=gmail on the remote URL, and the agent calls gmail__list-messages with the action's input. The tool uses your newest connection for each key without a subject. Without exposing the pack, actions_call takes the same input with ref.
Output, labeled fixture: Search messages (documented response shape, example values). From the bundle's fixtures/list-messages.json, not a live call.
json{ "messages": [ {"id": "18c9a2b3d4e5f6a7", "thread_id": "18c9a2b3d4e5f6a7"}, {"id": "18c99f0e1d2c3b4a", "thread_id": "18c99f0e1d2c3b4a"} ], "next_page_token": "09876543210987654321", "result_size_estimate": 12}
When the service answers with an error, the call fails with upstream_error and pack_error.code is one of:
pack_error.code | Service status | Retryable | Message |
|---|---|---|---|
not_found | 404 | no | built from the service's response |
connection_unauthorized | 401 | no | Google rejected the access token (expired or revoked); refresh or reconnect it. |
rate_limited | 429, 403 | yes | built from the service's response |
forbidden | 403 | no | built from the service's response |
invalid_request | 400 | no | built from the service's response |
conflict | 409 | no | built from the service's response |
get-message
Get message. One message's From, To, Cc, Subject, Date and Message-ID headers, labels, a text snippet, size and receive time. The body is not included (see the pack description).
Ref io.b3os/gmail/get-message@1.0.0 · effect read · connection google · MCP tool gmail__get-message
bashcurl -s https://beta-api.b3os.org/v1/actions/call \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "ref": "io.b3os/gmail/get-message@1", "input": {"id": "18c9a2b3d4e5f6a7"}, "connections": {"google": "conn_01m5t6cbgdjs1ketgcqwa2sne8"} }'
tsimport { B3OS } from "@b3os/sdk";const b3os = new B3OS();const result = await b3os.actions.call({ ref: "io.b3os/gmail/get-message@1", input: { id: "18c9a2b3d4e5f6a7" }, connections: { google: "conn_01m5t6cbgdjs1ketgcqwa2sne8" },});console.log(result.output);
pythonfrom b3os import B3OSb3os = B3OS()result = b3os.actions.call({ "ref": "io.b3os/gmail/get-message@1", "input": {"id": "18c9a2b3d4e5f6a7"}, "connections": {"google": "conn_01m5t6cbgdjs1ketgcqwa2sne8"},})print(result["output"])
json{ "method": "tools/call", "params": { "name": "gmail__get-message", "arguments": {"id": "18c9a2b3d4e5f6a7"} }}
Expose the pack as tools with --packs gmail on the local server or ?packs=gmail on the remote URL, and the agent calls gmail__get-message with the action's input. The tool uses your newest connection for each key without a subject. Without exposing the pack, actions_call takes the same input with ref.
Output, labeled fixture: Get message (documented response shape, example values). From the bundle's fixtures/get-message.json, not a live call.
json{ "id": "18c9a2b3d4e5f6a7", "thread_id": "18c9a2b3d4e5f6a7", "labels": ["UNREAD", "IMPORTANT", "CATEGORY_PERSONAL", "INBOX"], "snippet": "The release is live; the changelog has the details.", "from": "Releases <releases@example.com>", "to": "mona@acme.example", "cc": null, "subject": "Release v2.4.0", "date": "Mon, 26 Oct 2026 07:56:40 +0000", "message_id": "<CAB3OSexample123@mail.gmail.com>", "internal_date_ms": "1792999000000", "size_estimate": 5012}
When the service answers with an error, the call fails with upstream_error and pack_error.code is one of:
pack_error.code | Service status | Retryable | Message |
|---|---|---|---|
not_found | 404 | no | built from the service's response |
connection_unauthorized | 401 | no | Google rejected the access token (expired or revoked); refresh or reconnect it. |
rate_limited | 429, 403 | yes | built from the service's response |
forbidden | 403 | no | built from the service's response |
invalid_request | 400 | no | built from the service's response |
conflict | 409 | no | built from the service's response |
send-email
Send email. Send a plain-text email from the connected mailbox to one or more recipients, with optional Cc and Bcc. Returns the sent message id and thread id. Not idempotent: two calls send two emails.
Ref io.b3os/gmail/send-email@1.0.0 · effect write · connection google · MCP tool gmail__send-email
bashcurl -s https://beta-api.b3os.org/v1/actions/call \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H "Idempotency-Key: 7c1e2f6a-1d43-4a8e-b2a5-3f0c9d5e8b11" \ -H "Content-Type: application/json" \ -d '{ "ref": "io.b3os/gmail/send-email@1", "input": { "to": "ops@example.com", "cc": "mona@acme.example", "subject": "Deploy finished", "text": "v2.4.0 is live.\r\nRollback plan: redeploy v2.3.9." }, "connections": {"google": "conn_01m5t6cbgdjs1ketgcqwa2sne8"} }'
tsimport { B3OS } from "@b3os/sdk";const b3os = new B3OS();const result = await b3os.actions.call({ ref: "io.b3os/gmail/send-email@1", input: { to: "ops@example.com", cc: "mona@acme.example", subject: "Deploy finished", text: "v2.4.0 is live.\r\nRollback plan: redeploy v2.3.9.", }, connections: { google: "conn_01m5t6cbgdjs1ketgcqwa2sne8" },}, { idempotencyKey: crypto.randomUUID() });console.log(result.output);
pythonimport uuidfrom b3os import B3OSb3os = B3OS()result = b3os.actions.call({ "ref": "io.b3os/gmail/send-email@1", "input": { "to": "ops@example.com", "cc": "mona@acme.example", "subject": "Deploy finished", "text": "v2.4.0 is live.\r\nRollback plan: redeploy v2.3.9.", }, "connections": {"google": "conn_01m5t6cbgdjs1ketgcqwa2sne8"},}, idempotency_key=str(uuid.uuid4()))print(result["output"])
json{ "method": "tools/call", "params": { "name": "gmail__send-email", "arguments": { "to": "ops@example.com", "cc": "mona@acme.example", "subject": "Deploy finished", "text": "v2.4.0 is live.\r\nRollback plan: redeploy v2.3.9." } }}
Expose the pack as tools with --packs gmail on the local server or ?packs=gmail on the remote URL, and the agent calls gmail__send-email with the action's input. The tool uses your newest connection for each key without a subject. Without exposing the pack, actions_call takes the same input with ref.
Output, labeled fixture: Send email (documented response shape, example values). From the bundle's fixtures/send-email.json, not a live call.
json{ "id": "18c9b0c1d2e3f4a5", "thread_id": "18c9b0c1d2e3f4a5", "labels": ["SENT"]}
When the service answers with an error, the call fails with upstream_error and pack_error.code is one of:
pack_error.code | Service status | Retryable | Message |
|---|---|---|---|
not_found | 404 | no | built from the service's response |
connection_unauthorized | 401 | no | Google rejected the access token (expired or revoked); refresh or reconnect it. |
rate_limited | 429, 403 | yes | built from the service's response |
forbidden | 403 | no | built from the service's response |
invalid_request | 400 | no | built from the service's response |
conflict | 409 | no | built from the service's response |
create-draft
Create draft. Save a plain-text email as a draft in the connected mailbox for a person to review and send. Returns the draft id and message id. Not idempotent.
Ref io.b3os/gmail/create-draft@1.0.0 · effect write · connection google · MCP tool gmail__create-draft
bashcurl -s https://beta-api.b3os.org/v1/actions/call \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H "Idempotency-Key: 7c1e2f6a-1d43-4a8e-b2a5-3f0c9d5e8b11" \ -H "Content-Type: application/json" \ -d '{ "ref": "io.b3os/gmail/create-draft@1", "input": { "to": "customer@example.com", "subject": "Your refund", "text": "Hi, your refund was processed today." }, "connections": {"google": "conn_01m5t6cbgdjs1ketgcqwa2sne8"} }'
tsimport { B3OS } from "@b3os/sdk";const b3os = new B3OS();const result = await b3os.actions.call({ ref: "io.b3os/gmail/create-draft@1", input: { to: "customer@example.com", subject: "Your refund", text: "Hi, your refund was processed today.", }, connections: { google: "conn_01m5t6cbgdjs1ketgcqwa2sne8" },}, { idempotencyKey: crypto.randomUUID() });console.log(result.output);
pythonimport uuidfrom b3os import B3OSb3os = B3OS()result = b3os.actions.call({ "ref": "io.b3os/gmail/create-draft@1", "input": { "to": "customer@example.com", "subject": "Your refund", "text": "Hi, your refund was processed today.", }, "connections": {"google": "conn_01m5t6cbgdjs1ketgcqwa2sne8"},}, idempotency_key=str(uuid.uuid4()))print(result["output"])
json{ "method": "tools/call", "params": { "name": "gmail__create-draft", "arguments": { "to": "customer@example.com", "subject": "Your refund", "text": "Hi, your refund was processed today." } }}
Expose the pack as tools with --packs gmail on the local server or ?packs=gmail on the remote URL, and the agent calls gmail__create-draft with the action's input. The tool uses your newest connection for each key without a subject. Without exposing the pack, actions_call takes the same input with ref.
Output, labeled fixture: Create draft (documented response shape, example values). From the bundle's fixtures/create-draft.json, not a live call.
json{ "draft_id": "r-1234567890123456789", "message_id": "18c9b1d2e3f4a5b6", "thread_id": "18c9b1d2e3f4a5b6"}
When the service answers with an error, the call fails with upstream_error and pack_error.code is one of:
pack_error.code | Service status | Retryable | Message |
|---|---|---|---|
not_found | 404 | no | built from the service's response |
connection_unauthorized | 401 | no | Google rejected the access token (expired or revoked); refresh or reconnect it. |
rate_limited | 429, 403 | yes | built from the service's response |
forbidden | 403 | no | built from the service's response |
invalid_request | 400 | no | built from the service's response |
conflict | 409 | no | built from the service's response |
modify-labels
Change message labels. Add and remove labels on a message: remove UNREAD to mark it read, remove INBOX to archive it, add STARRED to star it, or add a user label. Returns the labels after the change.
Ref io.b3os/gmail/modify-labels@1.0.0 · effect write · connection google · MCP tool gmail__modify-labels
bashcurl -s https://beta-api.b3os.org/v1/actions/call \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H "Idempotency-Key: 7c1e2f6a-1d43-4a8e-b2a5-3f0c9d5e8b11" \ -H "Content-Type: application/json" \ -d '{ "ref": "io.b3os/gmail/modify-labels@1", "input": {"id": "18c9a2b3d4e5f6a7", "remove": ["UNREAD", "INBOX"]}, "connections": {"google": "conn_01m5t6cbgdjs1ketgcqwa2sne8"} }'
tsimport { B3OS } from "@b3os/sdk";const b3os = new B3OS();const result = await b3os.actions.call({ ref: "io.b3os/gmail/modify-labels@1", input: { id: "18c9a2b3d4e5f6a7", remove: ["UNREAD", "INBOX"] }, connections: { google: "conn_01m5t6cbgdjs1ketgcqwa2sne8" },}, { idempotencyKey: crypto.randomUUID() });console.log(result.output);
pythonimport uuidfrom b3os import B3OSb3os = B3OS()result = b3os.actions.call({ "ref": "io.b3os/gmail/modify-labels@1", "input": {"id": "18c9a2b3d4e5f6a7", "remove": ["UNREAD", "INBOX"]}, "connections": {"google": "conn_01m5t6cbgdjs1ketgcqwa2sne8"},}, idempotency_key=str(uuid.uuid4()))print(result["output"])
json{ "method": "tools/call", "params": { "name": "gmail__modify-labels", "arguments": {"id": "18c9a2b3d4e5f6a7", "remove": ["UNREAD", "INBOX"]} }}
Expose the pack as tools with --packs gmail on the local server or ?packs=gmail on the remote URL, and the agent calls gmail__modify-labels with the action's input. The tool uses your newest connection for each key without a subject. Without exposing the pack, actions_call takes the same input with ref.
Output, labeled fixture: Change message labels (documented response shape, example values). From the bundle's fixtures/modify-labels.json, not a live call.
json{ "id": "18c9a2b3d4e5f6a7", "labels": ["IMPORTANT", "CATEGORY_PERSONAL"]}
When the service answers with an error, the call fails with upstream_error and pack_error.code is one of:
pack_error.code | Service status | Retryable | Message |
|---|---|---|---|
not_found | 404 | no | built from the service's response |
connection_unauthorized | 401 | no | Google rejected the access token (expired or revoked); refresh or reconnect it. |
rate_limited | 429, 403 | yes | built from the service's response |
forbidden | 403 | no | built from the service's response |
invalid_request | 400 | no | built from the service's response |
conflict | 409 | no | built from the service's response |
list-labels
List labels. The mailbox's labels: system labels (INBOX, SENT, UNREAD, STARRED, ...) and user labels with their ids, which search and modify-labels use.
Ref io.b3os/gmail/list-labels@1.0.0 · effect read · connection google · MCP tool gmail__list-labels
bashcurl -s https://beta-api.b3os.org/v1/actions/call \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "ref": "io.b3os/gmail/list-labels@1", "input": {}, "connections": {"google": "conn_01m5t6cbgdjs1ketgcqwa2sne8"} }'
tsimport { B3OS } from "@b3os/sdk";const b3os = new B3OS();const result = await b3os.actions.call({ ref: "io.b3os/gmail/list-labels@1", input: {}, connections: { google: "conn_01m5t6cbgdjs1ketgcqwa2sne8" },});console.log(result.output);
pythonfrom b3os import B3OSb3os = B3OS()result = b3os.actions.call({ "ref": "io.b3os/gmail/list-labels@1", "input": {}, "connections": {"google": "conn_01m5t6cbgdjs1ketgcqwa2sne8"},})print(result["output"])
json{ "method": "tools/call", "params": {"name": "gmail__list-labels", "arguments": {}}}
Expose the pack as tools with --packs gmail on the local server or ?packs=gmail on the remote URL, and the agent calls gmail__list-labels with the action's input. The tool uses your newest connection for each key without a subject. Without exposing the pack, actions_call takes the same input with ref.
Output, labeled fixture: List labels (documented response shape, example values). From the bundle's fixtures/list-labels.json, not a live call.
json{ "labels": [ {"id": "INBOX", "name": "INBOX", "type": "system"}, {"id": "UNREAD", "name": "UNREAD", "type": "system"}, {"id": "Label_12", "name": "Customers", "type": "user"} ]}
When the service answers with an error, the call fails with upstream_error and pack_error.code is one of:
pack_error.code | Service status | Retryable | Message |
|---|---|---|---|
not_found | 404 | no | built from the service's response |
connection_unauthorized | 401 | no | Google rejected the access token (expired or revoked); refresh or reconnect it. |
rate_limited | 429, 403 | yes | built from the service's response |
forbidden | 403 | no | built from the service's response |
invalid_request | 400 | no | built from the service's response |
conflict | 409 | no | built from the service's response |