Source: https://cli.nylas.com/guides/anthropic-tool-use-email

# Anthropic Tool Use for Email (CLI)

Anthropic's tool use lets Claude request a named tool with structured input, then continue once you return the result. It's the clean way to give Claude email without an MCP server: define a few tool schemas and dispatch each call to the Nylas CLI. Claude decides what to do; the CLI does it across six providers and returns JSON. This guide builds the tool-use loop and keeps sends behind a human review step.

Written by [Caleb Geene](https://cli.nylas.com/authors/caleb-geene) Director, Site Reliability Engineering

Updated June 8, 2026

> **TL;DR:** Define Anthropic tool schemas for list, search, and draft, then run the tool-use loop: when Claude returns `stop_reason: tool_use`, run the matching Nylas CLI command and send the result back as a `tool_result`. The CLI returns JSON across six providers with no SDK. Expose a draft tool, not a send tool, so a misread message can't fire mail unattended.

Command references used in this guide: [`nylas email list`](https://cli.nylas.com/docs/commands/email-list), [`nylas email search`](https://cli.nylas.com/docs/commands/email-search), and [`nylas email drafts create`](https://cli.nylas.com/docs/commands/email-drafts-create).

## How do you give Claude email with tool use?

You give Claude email by declaring tools on the Messages API and dispatching each request to the Nylas CLI. A tool is a name, a description, and an `input_schema`; when Claude returns a `tool_use` block, your code runs the matching command and replies with a `tool_result`. Because `nylas email list --json` emits structured data, Claude receives clean JSON to reason over rather than HTML.

Authenticate the CLI once with `nylas auth login`; the stored grant is reused on every subprocess call, so your dispatcher never handles credentials. This is a lighter alternative to running an MCP server when you only need a few actions. Anthropic's tool-use contract — tool schemas in, `tool_use` out, `tool_result` back — is documented in the [Anthropic tool use docs](https://docs.anthropic.com/en/docs/build-with-claude/tool-use).

## How do you define the tool schemas?

Define one tool per action with a precise description, since Claude selects tools from those descriptions. A `list_unread` tool takes an integer limit; a `search_email` tool takes a query string. Keep the set small — two read tools and a draft tool handle most inbox work — because a narrow toolset is easier for the model to use correctly and easier for you to audit.

The `input_schema` is standard JSON Schema, so required fields and types are enforced before your code runs. That validation, plus a thin dispatcher, means every action is one CLI command with explicit arguments you can log. Claude never sees a provider name — it calls `search_email`, and your code runs `nylas email search`.

```python
tools = [
    {
        "name": "list_unread",
        "description": "List unread emails as JSON across the connected mailbox.",
        "input_schema": {
            "type": "object",
            "properties": {"limit": {"type": "integer"}},
        },
    },
    {
        "name": "search_email",
        "description": "Search the mailbox with a provider-agnostic query, return JSON.",
        "input_schema": {
            "type": "object",
            "properties": {"query": {"type": "string"}},
            "required": ["query"],
        },
    },
]
```

## How do you run the tool-use loop?

Run the loop: send the message with the tools, and when the response's `stop_reason` is `tool_use`, run the requested command and append a `tool_result` block, then call the API again. Repeat until `stop_reason` is `end_turn`. A triage request usually completes in two or three round trips, with Claude reading JSON between each.

Use a current model such as `claude-sonnet-4-6` for the loop. The dispatcher maps each tool name to a CLI command and returns stdout; that indirection is what lets one integration work across Gmail, Outlook, and four more providers without provider-specific code in your agent.

```python
import subprocess, anthropic
client = anthropic.Anthropic()

def run_tool(name, args):
    if name == "list_unread":
        cmd = ["nylas", "email", "list", "--unread", "--json",
               "--limit", str(args.get("limit", 10))]
    elif name == "search_email":
        cmd = ["nylas", "email", "search", args["query"], "--json", "--limit", "20"]
    else:
        return "unknown tool"
    return subprocess.run(cmd, capture_output=True, text=True, check=True).stdout

msgs = [{"role": "user", "content": "Summarize my unread mail."}]
resp = client.messages.create(
    model="claude-sonnet-4-6", max_tokens=1024, tools=tools, messages=msgs)
# While resp.stop_reason == "tool_use": run_tool() each block,
# append a tool_result, and call messages.create again.
```

## How do you keep sends safe?

Keep outbound actions behind a human. Expose a draft tool that runs `nylas email drafts create` — composing a message without sending it and returning a draft ID — instead of a send tool. A person reviews and sends, so a misclassification can't reach a customer. This is the single most important guardrail for a Claude email agent.

Claude reads untrusted content, and a prompt injection in a message body can try to inject an unwanted `tool_use`. Containment outside the model's reasoning — a review step, or connector-level rules — holds even when injected text tries to talk past it. For deterministic enforcement at the connector, see [stopping a rogue agent at the connector layer](https://cli.nylas.com/guides/stop-ai-agent-going-rogue).

## Next steps

- [Connect Claude to email](https://cli.nylas.com/guides/connect-claude-to-email) — the MCP path instead of raw tool use
- [OpenAI assistants email tools](https://cli.nylas.com/guides/openai-assistants-email-tools) — function calling dispatched to the CLI
- [Human-in-the-loop email agent](https://cli.nylas.com/guides/build-human-in-loop-email-agent) — draft-and-approve guardrails
- [MCP email server setup](https://cli.nylas.com/guides/mcp-email-server-setup) — expose the same actions as MCP tools
- [Semantic Kernel email agent](https://cli.nylas.com/guides/semantic-kernel-email-agent) — the CLI as a native plugin
- [Full command reference](https://cli.nylas.com/docs/commands) — every flag and subcommand documented
