Guide

Build an OpenHands Email Agent

Build an OpenHands email agent with the CLI inside a sandboxed runtime, provisioning-time auth, Docker image setup, draft-only writes, and JSON commands.

Written by Prem Keshari Senior SRE

VerifiedCLI 3.1.20 · Gmail · last tested June 14, 2026

Command references used in this guide: nylas email list, nylas email read, and nylas email drafts create.

How do you give an OpenHands agent email?

You give an OpenHands agent email by putting the Nylas CLI on the sandbox path and treating email as one more shell action. OpenHands, from All Hands AI, executes actions inside a sandboxed runtime, so the CLI can be a normal binary instead of a custom tool class.

The OpenHands docs center the “Runtime” as the place where commands run, files change, and tests execute. That model is the integration. Install once, authenticate once, then the autonomous loop can list 20 messages, read 1 thread, or create 1 draft without adding provider SDK code to the agent.

That also keeps the mental model close to how OpenHands already works. If the agent can run a test command in 1 container, it can run an email command in the same place and receive structured output back through stdout.

How do you bake the CLI into the OpenHands runtime image?

Bake the Nylas CLI into the OpenHands runtime image so every agent task starts with the same binary on PATH. The image layer should install software only. Authentication belongs to provisioning, because a Docker layer can live for months and shouldn't carry an API key or grant.

Run the install script in the Dockerfile fragment to make the binary available before the 1st OpenHands task starts. OpenHands runtime images are Debian-based, so the curl … install.sh path is the right fit; see the getting started guide for the other official installation methods.

Keep the runtime image pinned through your normal container release process. If 5 OpenHands sandboxes serve the same queue, they should all start from the same image digest so command output and error handling don't drift between agents.

# Dockerfile fragment for the OpenHands runtime image (Debian-based)
RUN curl -fsSL https://cli.nylas.com/install.sh | bash
ENV PATH="/home/openhands/.config/nylas/bin:${PATH}"

How does the agent call email commands?

The OpenHands agent calls email commands the same way it calls git, pytest, or a project script: by spawning a subprocess in the runtime shell. The command returns JSON, so the agent can inspect 20 recent messages without importing a mail SDK or parsing provider-specific API responses.

Run nylas email list --json --limit 20 when the agent needs a bounded inbox snapshot. Run nylas email read MESSAGE_ID after selection so only 1 message body enters the prompt, then pipe list output through jq to keep the reasoning context small.

This is a good fit for OpenHands because the action transcript already records shell input and output. A reviewer can inspect the exact 2 commands that shaped the agent's decision.

# Read the 20 most recent messages for triage
nylas email list --json --limit 20

# Read exactly 1 selected message by ID (positional id)
nylas email read msg_123 --json

# Narrow output to subjects with jq before reasoning
nylas email list --json --limit 20 | jq '[.[] | {subject, from}]'

How should provisioning-time authentication work?

Provisioning-time authentication means the OpenHands runtime is authorized before the agent loop receives a task. The agent shouldn't run OAuth, paste tokens, or choose providers during execution. One setup phase on 2026-06-15 can create the stored grant, then later shell actions reuse it.

Run nylas auth config --api-key in a provisioning step, not inside an autonomous task prompt, so the agent never learns the secret value. Follow it with nylas auth whoami --json to verify 1 active account before OpenHands accepts work, and fail the sandbox startup if that check returns the wrong identity.

This split gives operations a clean rotation path. Rebuild the image when the binary changes, re-run provisioning when credentials change, and restart the task loop only after both checks succeed for the intended mailbox.

# Provision the sandbox once before the OpenHands task loop starts
nylas auth config --api-key

# Confirm the runtime has exactly the account you expect
nylas auth whoami --json

How do you scope the sandbox to draft-only writes?

Sandbox scoping for an OpenHands email agent means the container can read project files and mailbox data, but its only email write path creates drafts. The runtime file system should be read-only except for 1 drafts directory, and the environment should expose only the variables required for CLI auth.

Run nylas email drafts create when the agent proposes a reply, because the command creates a draft without sending mail. The 1 writable path can store review notes and generated bodies, while the human reviewer decides whether any draft moves to an actual send step.

In practice, mount source code and configuration read-only, pass a minimal environment, and reserve a writable /workspace/drafts folder for generated mail bodies. That gives OpenHands enough space to work without giving every shell command broad write access.

# Agent-visible write action: create a draft, not a sent message
nylas email drafts create \
  --to teammate@example.com \
  --subject "Proposed follow-up" \
  --body "Draft prepared by the OpenHands runtime for review." \
  --json

# Optional local audit trail inside the only writable workspace path
nylas email drafts create --to teammate@example.com --subject "Review needed" --body "See /workspace/drafts/reply.md" --json

What guardrails should the agent have?

OpenHands guardrails should treat runtime isolation as the safety story: the CLI runs inside the container, and credentials never leave the sandbox. That boundary matters because an autonomous coding agent can read private data, process untrusted email, and call external communication tools in the same 1 task loop.

That combination is the lethal trifecta: private data + untrusted content + external communication. Email bodies can carry prompt injection, and OWASP LLM01 (2025) names that class directly. Keep nylas email send and nylas email drafts send outside the agent's reachable actions; give it draft creation, bounded reads, and logs instead. For broader containment patterns, see stop an AI agent going rogue and build a human-in-the-loop email agent.

The review record should include the command transcript, the draft ID, and the 1 mailbox identity from provisioning. That gives a human enough context to approve, reject, or edit the draft without trusting the model's summary alone.

Next steps