Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Email

Two email channels depending on how you want inbound messages delivered.

Who can talk to the agent

Inbound senders are gated against the peer set resolved for the bound agent, drawn from the peer_groups config the agent belongs to. Matching strips a leading @ and is case-insensitive against the channel’s native sender identifier. An empty set denies everyone; a set containing "*" accepts anyone; otherwise only the listed external peers (and peer agents) are accepted. This is separate from gateway pairing (gateway.require_pairing), which authenticates HTTP/WebSocket clients, not chat-channel senders.

A peer group for email sets channel to email, lists the allowed senders in external_peers (for email, the sender’s email address; ["*"] accepts anyone), optionally names peer agents for cross-agent dispatch, an ignore blocklist, and an output_modality (mirror, voice, or text). See Peer Groups for the field reference.

Where to set this:

Gateway dashboard

Open /config/peer_groups in the web dashboard.

zerocode

In the Config pane, under Peer groups.

IMAP + SMTP (email_channel)

The general-purpose email channel. Polls IMAP for new messages and, when SMTP is configured, sends via SMTP. Works with Gmail, Outlook, Fastmail, self-hosted Postfix, and anything else that speaks IMAP/SMTP.

default_subject string · default "Re: Message"

Set it on any surface:

Gateway dashboard

Open /config/channels/email and set the channels.email.<alias>.default_subject field.

zerocode

In the Config pane, set the channels.email.<alias>.default_subject field.

zeroclaw config

zeroclaw config set channels.email.<alias>.default_subject <value>

Environment variable

Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:

export ZEROCLAW_channels__email__<alias>__default_subject=
excluded_tools string[] · default []

Tools excluded from this channel’s tool spec. When set, these tools are not exposed to the model when responding via this channel.

Set it on any surface:

Gateway dashboard

Open /config/channels/email and set the channels.email.<alias>.excluded_tools field.

zerocode

In the Config pane, set the channels.email.<alias>.excluded_tools field.

zeroclaw config

zeroclaw config set channels.email.<alias>.excluded_tools <value>

Environment variable

Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:

export ZEROCLAW_channels__email__<alias>__excluded_tools=
from_address string? · default null

From identity for outbound mail. Optional for the same reason as smtp_host: outbound sending requires both, and inbound-only channels never build an outbound message.

Set it on any surface:

Gateway dashboard

Open /config/channels/email and set the channels.email.<alias>.from_address field.

zerocode

In the Config pane, set the channels.email.<alias>.from_address field.

zeroclaw config

zeroclaw config set channels.email.<alias>.from_address <value>

Environment variable

Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:

export ZEROCLAW_channels__email__<alias>__from_address=
html_body bool · default true

When true (default), outbound emails are rendered as HTML via Markdown conversion. Set to false to send plain-text emails instead.

Set it on any surface:

Gateway dashboard

Open /config/channels/email and set the channels.email.<alias>.html_body field.

zerocode

In the Config pane, set the channels.email.<alias>.html_body field.

zeroclaw config

zeroclaw config set channels.email.<alias>.html_body <value>

Environment variable

Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:

export ZEROCLAW_channels__email__<alias>__html_body=
idle_timeout_secs integer · default 1740

Set it on any surface:

Gateway dashboard

Open /config/channels/email and set the channels.email.<alias>.idle_timeout_secs field.

zerocode

In the Config pane, set the channels.email.<alias>.idle_timeout_secs field.

zeroclaw config

zeroclaw config set channels.email.<alias>.idle_timeout_secs <value>

Environment variable

Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:

export ZEROCLAW_channels__email__<alias>__idle_timeout_secs=
imap_folder string · default "INBOX"

Set it on any surface:

Gateway dashboard

Open /config/channels/email and set the channels.email.<alias>.imap_folder field.

zerocode

In the Config pane, set the channels.email.<alias>.imap_folder field.

zeroclaw config

zeroclaw config set channels.email.<alias>.imap_folder <value>

Environment variable

Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:

export ZEROCLAW_channels__email__<alias>__imap_folder=
imap_host* string · default —

Set it on any surface:

Gateway dashboard

Open /config/channels/email and set the channels.email.<alias>.imap_host field.

zerocode

In the Config pane, set the channels.email.<alias>.imap_host field.

zeroclaw config

zeroclaw config set channels.email.<alias>.imap_host <value>

Environment variable

Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:

export ZEROCLAW_channels__email__<alias>__imap_host=
imap_port integer · default 993

Set it on any surface:

Gateway dashboard

Open /config/channels/email and set the channels.email.<alias>.imap_port field.

zerocode

In the Config pane, set the channels.email.<alias>.imap_port field.

zeroclaw config

zeroclaw config set channels.email.<alias>.imap_port <value>

Environment variable

Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:

export ZEROCLAW_channels__email__<alias>__imap_port=
max_attachment_bytes integer · default 26214400

Set it on any surface:

Gateway dashboard

Open /config/channels/email and set the channels.email.<alias>.max_attachment_bytes field.

zerocode

In the Config pane, set the channels.email.<alias>.max_attachment_bytes field.

zeroclaw config

zeroclaw config set channels.email.<alias>.max_attachment_bytes <value>

Environment variable

Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:

export ZEROCLAW_channels__email__<alias>__max_attachment_bytes=
oauth2 EmailOAuth2Config · default —

Set it on any surface:

Gateway dashboard

Open /config/channels/email and set the channels.email.<alias>.oauth2 field.

zerocode

In the Config pane, set the channels.email.<alias>.oauth2 field.

zeroclaw config

zeroclaw config set channels.email.<alias>.oauth2 <value>

Environment variable

Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:

export ZEROCLAW_channels__email__<alias>__oauth2=
observer_mode bool · default false

When true, the daemon observes new mail but never modifies any IMAP flag.

Set it on any surface:

Gateway dashboard

Open /config/channels/email and set the channels.email.<alias>.observer_mode field.

zerocode

In the Config pane, set the channels.email.<alias>.observer_mode field.

zeroclaw config

zeroclaw config set channels.email.<alias>.observer_mode <value>

Environment variable

Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:

export ZEROCLAW_channels__email__<alias>__observer_mode=
password* string · default —

Set it on any surface:

Gateway dashboard

Open /config/channels/email and set the channels.email.<alias>.password field.

zerocode

In the Config pane, set the channels.email.<alias>.password field.

zeroclaw config

zeroclaw config set channels.email.<alias>.password <value>

Environment variable

Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:

export ZEROCLAW_channels__email__<alias>__password=
poll_interval_secs integer · default 60

Polling interval used when the IMAP server does not advertise the IDLE capability (RFC 2177). Ignored when IDLE is available.

Set it on any surface:

Gateway dashboard

Open /config/channels/email and set the channels.email.<alias>.poll_interval_secs field.

zerocode

In the Config pane, set the channels.email.<alias>.poll_interval_secs field.

zeroclaw config

zeroclaw config set channels.email.<alias>.poll_interval_secs <value>

Environment variable

Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:

export ZEROCLAW_channels__email__<alias>__poll_interval_secs=
smtp_host string? · default null

SMTP relay host. Optional: when omitted (or blank) the channel stays read-write on IMAP (inbound processing, flag updates) but refuses to send, so an operator can grant mailbox access without outbound email.

Set it on any surface:

Gateway dashboard

Open /config/channels/email and set the channels.email.<alias>.smtp_host field.

zerocode

In the Config pane, set the channels.email.<alias>.smtp_host field.

zeroclaw config

zeroclaw config set channels.email.<alias>.smtp_host <value>

Environment variable

Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:

export ZEROCLAW_channels__email__<alias>__smtp_host=
smtp_password string? · default null

Set it on any surface:

Gateway dashboard

Open /config/channels/email and set the channels.email.<alias>.smtp_password field.

zerocode

In the Config pane, set the channels.email.<alias>.smtp_password field.

zeroclaw config

zeroclaw config set channels.email.<alias>.smtp_password <value>

Environment variable

Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:

export ZEROCLAW_channels__email__<alias>__smtp_password=
smtp_port integer · default 465

Set it on any surface:

Gateway dashboard

Open /config/channels/email and set the channels.email.<alias>.smtp_port field.

zerocode

In the Config pane, set the channels.email.<alias>.smtp_port field.

zeroclaw config

zeroclaw config set channels.email.<alias>.smtp_port <value>

Environment variable

Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:

export ZEROCLAW_channels__email__<alias>__smtp_port=
smtp_tls bool · default true

Set it on any surface:

Gateway dashboard

Open /config/channels/email and set the channels.email.<alias>.smtp_tls field.

zerocode

In the Config pane, set the channels.email.<alias>.smtp_tls field.

zeroclaw config

zeroclaw config set channels.email.<alias>.smtp_tls <value>

Environment variable

Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:

export ZEROCLAW_channels__email__<alias>__smtp_tls=
smtp_username string? · default null

Set it on any surface:

Gateway dashboard

Open /config/channels/email and set the channels.email.<alias>.smtp_username field.

zerocode

In the Config pane, set the channels.email.<alias>.smtp_username field.

zeroclaw config

zeroclaw config set channels.email.<alias>.smtp_username <value>

Environment variable

Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:

export ZEROCLAW_channels__email__<alias>__smtp_username=
username* string · default —

Set it on any surface:

Gateway dashboard

Open /config/channels/email and set the channels.email.<alias>.username field.

zerocode

In the Config pane, set the channels.email.<alias>.username field.

zeroclaw config

zeroclaw config set channels.email.<alias>.username <value>

Environment variable

Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:

export ZEROCLAW_channels__email__<alias>__username=

password (and smtp_password if you use a separate relay) are secrets:

channels.email.<alias>.password is a secret. Stored encrypted, never in plain config.toml. Set it through one of these, which encrypt on write:

Gateway dashboard

Open /config/channels/email and set the channels.email.<alias>.password field there.

zerocode

In the Config pane, set the channels.email.<alias>.password field (input is masked).

zeroclaw config

zeroclaw config set channels.email.<alias>.password    # prompts for masked input, stores encrypted

Inbound-only mode (no SMTP)

imap_host is the only transport endpoint required. Leave smtp_host and from_address unset (or blank) to give the agent read-write access to the mailbox without the ability to send email:

  • When the alias is bound to an agent, IMAP still runs: new mail is delivered to the agent and read/flag updates are written unless observer_mode = true.
  • Every outbound send from this channel is refused with an outbound email is disabled error, so agent replies fail rather than leaving the mailbox. Surfaces that require real delivery (SOP approval routes, no-reply notices, escalations, text polls) treat the channel as unable to deliver and reject or skip it up front.
  • Set both smtp_host and from_address to enable sending again; either one alone keeps the channel inbound-only and raises an email_smtp_partially_configured config warning naming the missing field.

The restriction is outbound-only. Pair it with a peer group (above) to control who may address the agent, and with observer_mode if the mailbox must not be mutated at all.

Tools-only: enable it, don’t bind it

To use an IMAP mailbox as a pull-only tool, set enabled = true on the alias and leave it out of every agent’s channels list and out of every approval route that would name it. Enabling the alias registers the email_search and email_read tools. Binding it to an agent is one way to start the IMAP listener; an SOP approval request_route / escalation_route, or an enabled agent’s risk- profile approver_channel, also starts it. A route may name the bare channel type email; when exactly one email alias is enabled, that resolves to the alias. An alias that only an approval route names stays live so approval replies can be delivered, but it is not assigned to an agent for ordinary traffic.

The distinction matters for aliases with no SMTP configured (no smtp_host or from_address), which are inbound-only: they can receive mail, but send refuses to reply. If you bind such an alias, every inbound message from a sender your peer group admits dispatches an agent turn. The agent tries to reply, send refuses, and the reply fails, so you pay for a model turn on every email and get nothing back.

[channels.email.myserver]
enabled = true          # registers the read-only tools
imap_host = "imap.example.com"
username = "user"
password = "..."        # leave smtp_host / from_address unset

[agents.example]
channels = ["telegram.home"]   # any bound channel; email alias deliberately absent

Watch out for the fallback. The alias is only left unbound when at least one agent, anywhere in the config, declares a non-empty channels list. If no agent declares any bindings, ZeroClaw falls back to the legacy behavior: it starts every enabled channel under the default agent (the agent named default, otherwise the first alphabetically). In an email-only config, that means the IMAP listener starts anyway and you pay the per-email turn cost described above. To keep the alias tools-only, make sure some agent binds at least one other channel, as in the example where agents.example binds telegram.home, and also leave the alias out of SOP approval request_route / escalation_route values and every enabled agent’s risk-profile approver_channel (including a bare email route when only one email alias is enabled).

Gmail gotchas

  • App passwords required if 2FA is on. Regular account password is rejected.
  • “Less secure app access” is gone: app password is the only path.
  • Consider the Gmail Push channel below for real-time delivery instead of polling.

Outlook / Office 365

password (and smtp_password) are secrets:

channels.email.<alias>.password is a secret. Stored encrypted, never in plain config.toml. Set it through one of these, which encrypt on write:

Gateway dashboard

Open /config/channels/email and set the channels.email.<alias>.password field there.

zerocode

In the Config pane, set the channels.email.<alias>.password field (input is masked).

zeroclaw config

zeroclaw config set channels.email.<alias>.password    # prompts for masked input, stores encrypted

Gmail Push (gmail_push)

Real-time delivery via Google Cloud Pub/Sub, no polling.

excluded_tools string[] · default []

Tools excluded from this channel’s tool spec. When set, these tools are not exposed to the model when responding via this channel.

Set it on any surface:

Gateway dashboard

Open /config/channels/gmail_push and set the channels.gmail_push.<alias>.excluded_tools field.

zerocode

In the Config pane, set the channels.gmail_push.<alias>.excluded_tools field.

zeroclaw config

zeroclaw config set channels.gmail_push.<alias>.excluded_tools <value>

Environment variable

Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:

export ZEROCLAW_channels__gmail_push__<alias>__excluded_tools=
label_filter string[] · default ["INBOX"]

Set it on any surface:

Gateway dashboard

Open /config/channels/gmail_push and set the channels.gmail_push.<alias>.label_filter field.

zerocode

In the Config pane, set the channels.gmail_push.<alias>.label_filter field.

zeroclaw config

zeroclaw config set channels.gmail_push.<alias>.label_filter <value>

Environment variable

Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:

export ZEROCLAW_channels__gmail_push__<alias>__label_filter=
oauth_token string · default ""

Set it on any surface:

Gateway dashboard

Open /config/channels/gmail_push and set the channels.gmail_push.<alias>.oauth_token field.

zerocode

In the Config pane, set the channels.gmail_push.<alias>.oauth_token field.

zeroclaw config

zeroclaw config set channels.gmail_push.<alias>.oauth_token <value>

Environment variable

Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:

export ZEROCLAW_channels__gmail_push__<alias>__oauth_token=
topic* string · default —

Set it on any surface:

Gateway dashboard

Open /config/channels/gmail_push and set the channels.gmail_push.<alias>.topic field.

zerocode

In the Config pane, set the channels.gmail_push.<alias>.topic field.

zeroclaw config

zeroclaw config set channels.gmail_push.<alias>.topic <value>

Environment variable

Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:

export ZEROCLAW_channels__gmail_push__<alias>__topic=
webhook_secret string · default ""

Set it on any surface:

Gateway dashboard

Open /config/channels/gmail_push and set the channels.gmail_push.<alias>.webhook_secret field.

zerocode

In the Config pane, set the channels.gmail_push.<alias>.webhook_secret field.

zeroclaw config

zeroclaw config set channels.gmail_push.<alias>.webhook_secret <value>

Environment variable

Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:

export ZEROCLAW_channels__gmail_push__<alias>__webhook_secret=
webhook_url string · default ""

Set it on any surface:

Gateway dashboard

Open /config/channels/gmail_push and set the channels.gmail_push.<alias>.webhook_url field.

zerocode

In the Config pane, set the channels.gmail_push.<alias>.webhook_url field.

zeroclaw config

zeroclaw config set channels.gmail_push.<alias>.webhook_url <value>

Environment variable

Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:

export ZEROCLAW_channels__gmail_push__<alias>__webhook_url=

oauth_token and webhook_secret are secrets:

channels.gmail_push.<alias>.oauth_token is a secret. Stored encrypted, never in plain config.toml. Set it through one of these, which encrypt on write:

Gateway dashboard

Open /config/channels/gmail_push and set the channels.gmail_push.<alias>.oauth_token field there.

zerocode

In the Config pane, set the channels.gmail_push.<alias>.oauth_token field (input is masked).

zeroclaw config

zeroclaw config set channels.gmail_push.<alias>.oauth_token    # prompts for masked input, stores encrypted

Setup

  1. Create a Google Cloud project, enable Gmail API and Pub/Sub API
  2. Create a Pub/Sub topic the Gmail service can publish to, set it as topic
  3. Authorize the agent’s Gmail access and store the resulting token via the secret path above
  4. The agent watches for new-mail notifications and routes them to the bound agent

Gmail Push sends through the Gmail API using its own oauth_token, independently of SMTP. Omitting smtp_host and from_address disables sending only for an IMAP+SMTP [channels.email.<alias>] block, not for Gmail Push.


Reply threading

Both email channels thread replies using In-Reply-To and References headers so conversations stay grouped in whatever client the sender uses.

Outbound body format

Agent replies are sent as multipart/alternative with both a plain-text and an HTML part by default. The HTML part is the Markdown-rendered body; the plain-text part is the raw body text. Mail clients that prefer plain text will select the plain-text alternative automatically.

To send plain text only (no HTML part, for clients or setups that prefer it), set the channel’s html_body field to false.

When attachments are present the body alternatives are wrapped in an outer multipart/mixed.

Attachment handling

Inbound attachments are stored under <workspace>/attachments/<conversation>/. The agent gets file paths in its context and can read them via the file_read tool. Filenames are taken from the Content-Disposition header first, falling back to the Content-Type name parameter.

Outbound attachments are sent from the bytes supplied with each attachment. The Email channel treats the attachment filename as display metadata, not as a local path. Integrations that intentionally send a local file must validate or constrain the path and load it explicitly with MediaAttachment::from_file before sending.

Rate and volume limits

Email isn’t optimised for conversational latency. Expect:

  • IMAP poll latency: poll_interval_secs (default 60 s). Lower at the cost of server load; some providers rate-limit aggressive polling.
  • SMTP send: subject to your provider’s daily-send quota (Gmail: 500/day for free accounts, 2000/day for Workspace).

Safety

Email has no auth at the protocol level beyond SMTP’s envelope; anyone can claim to be anyone. Gate inbound senders with a peer group (above) before exposing the agent to an inbox that receives public mail.