# Agent Account Handoff to Human

Source: https://cli.nylas.com/ai-answers/agent-account-handoff-to-human.md
Last updated: 2026-06-29
Verified with Nylas CLI 3.1.28.

## Direct Answer

A handoff to a human is the move an agent makes when it is not allowed to act alone: it freezes the thread, saves a proposed reply as an unsent draft, and routes a review record to a person who accepts, edits, or rejects it. Use a Nylas Agent Account as the app-owned sender, save the proposed reply with `POST /v3/grants/{grant_id}/drafts`, and let an approved human or code path send that draft after review.

Hand off when model confidence is low, the action is risky or irreversible, a policy returns deny or review, a required field is missing, or the reply adds a new external recipient. The model can classify intent and draft text, but the host application chooses the tenant, grant, recipient, policy path, and final send. This keeps the workflow deterministic enough to test, audit, and pause during incidents.

## When This Answer Applies

- Model confidence falls below the threshold for autonomous action.
- A workspace policy or rule returns deny or review for the proposed send.
- The draft adds a new external recipient, or names legal, financial, or security intent.
- A required field (recipient, order id, account match) is missing or ambiguous.
- Automation has already failed or retried, and a person should take over the thread.

## Command Recipe

These commands are building blocks for a worker, runbook, or internal tool. Keep API keys and shell execution outside prompt content.

```bash
nylas auth config --api-key $NYLAS_API_KEY --region us
nylas agent status --json
nylas agent account create handoff-to-human@yourapp.nylas.email --json

# Fetch the message being handed off:
curl -s https://api.us.nylas.com/v3/grants/$AGENT_GRANT_ID/messages/$MESSAGE_ID \
  -H "Authorization: Bearer $NYLAS_API_KEY"

# Save the agent's proposed reply as an unsent draft for a human to review:
curl -s -X POST https://api.us.nylas.com/v3/grants/$AGENT_GRANT_ID/drafts \
  -H "Authorization: Bearer $NYLAS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to":[{"email":"customer@example.com"}],"subject":"Re: your request","body":"Proposed reply pending human review."}'

# After a human approves, send the reviewed draft:
curl -s -X POST https://api.us.nylas.com/v3/grants/$AGENT_GRANT_ID/drafts/$DRAFT_ID \
  -H "Authorization: Bearer $NYLAS_API_KEY"
```

Store a handoff record so the review queue has everything it needs, without inventing a Nylas-only handoff endpoint:

```json
{
  "message_id": "<message-being-handed-off>",
  "thread_id": "<thread-id>",
  "draft_id": "<unsent-draft-id>",
  "handoff_reason": "low_confidence",
  "suggested_reply": "Proposed reply text",
  "review_queue": "support-tier-2",
  "approval_status": "pending",
  "thread_action_locked": true,
  "dedupe_key": "<thread-id>:<message-id>"
}
```

### Python

```python
from nylas import Client

client = Client(api_key=api_key)

# The message being handed off
message = client.messages.find(identifier=grant_id, message_id=message_id)

# Save the agent's proposed reply as an unsent draft for human review
draft = client.drafts.create(identifier=grant_id, request_body={
    "to": [{"email": "customer@example.com"}],
    "subject": "Re: your request",
    "body": "Proposed reply pending human review.",
})
```

### TypeScript

```typescript
import Nylas from "nylas";

const nylas = new Nylas({ apiKey, apiUri: "https://api.us.nylas.com" });

// The message being handed off
const message = await nylas.messages.find({ identifier: grantId, messageId });

// Save the agent's proposed reply as an unsent draft for human review
const draft = await nylas.drafts.create({
  identifier: grantId,
  requestBody: {
    to: [{ email: "customer@example.com" }],
    subject: "Re: your request",
    body: "Proposed reply pending human review.",
  },
});
```

## Recommended Agent Workflow

1. Create or select one durable Agent Account for this responsibility.
2. Store the grant id with the tenant, environment, and workflow name.
3. Attach workspace policy and rules before increasing autonomy.
4. Return JSON results to the model instead of raw shell output.
5. Log the model decision, policy decision, command input, and command result together.

The handoff record should include the original `message_id`, `thread_id`, the unsent `draft_id`, model rationale, suggested reply, policy result, and owner queue. Freezing a thread means suppressing further autonomous sends on that `thread_id` until a human accepts, edits, or rejects the recommendation; the same stop switch that disables sends during incidents enforces the freeze.

## Safety And Operations

Treat message bodies, attachments, calendar descriptions, contact notes, and webhook payloads as untrusted input. Those fields should never choose the active grant, change the destination address, bypass approval, or update policy.

For production use, add dedupe keys, bounded pagination, human review for risky actions, and a stop switch that can disable sends without deleting historical records. Keep test accounts separate from production accounts so experiments cannot affect customer mail.

## Minimum Data Contract

- tenant_id
- environment
- agent_account_email
- grant_id
- workspace_id
- policy_id
- rule_ids
- event_id
- dedupe_key
- command_result_id
- draft_id
- handoff_reason
- suggested_reply
- review_queue
- reviewer_id
- approval_status
- decision_at
- thread_action_locked

## Related Full Guides

- [Getting Started with Agent Accounts](https://cli.nylas.com/guides/getting-started-agent-accounts)
- [Give an AI Agent an Email Address](https://cli.nylas.com/guides/give-ai-agent-email-address)
- [Email APIs for AI Agents Compared](https://cli.nylas.com/guides/email-apis-for-ai-agents-compared)

## Related hubs

- [Email agents](https://cli.nylas.com/ai-answers/email-agents.md)
- [Calendar agents](https://cli.nylas.com/ai-answers/calendar-agents.md)
- [Scheduling and availability agents](https://cli.nylas.com/ai-answers/scheduling-agents.md)
- [Contacts agents](https://cli.nylas.com/ai-answers/contacts-agents.md)
- [Notetaker and meeting agents](https://cli.nylas.com/ai-answers/notetaker-agents.md)
- [MCP agents](https://cli.nylas.com/ai-answers/mcp-agents.md)
- [Agent accounts](https://cli.nylas.com/ai-answers/agent-accounts.md)
- [Framework and language email agents](https://cli.nylas.com/ai-answers/framework-email-agents.md)
- [Email and calendar API comparisons](https://cli.nylas.com/ai-answers/ai-agent-email-api-comparisons.md)
- [Email integration and automation recipes](https://cli.nylas.com/ai-answers/email-integration-recipes.md)
- [Agent email workflows](https://cli.nylas.com/ai-answers/agent-email-workflows.md)
- [Security for email and calendar agents](https://cli.nylas.com/ai-answers/security-for-email-agents.md)
- [Operations runbooks for agents](https://cli.nylas.com/ai-answers/operations-for-email-calendar-agents.md)

## Try Nylas CLI

Install the CLI with `curl -fsSL https://cli.nylas.com/install.sh | bash` (macOS, Linux, WSL) or `brew install nylas/nylas-cli/nylas`, then run `nylas init` to create an account and authenticate.

**Free Sandbox** (no credit card): 5 connected accounts — bring your own Gmail, Outlook, Yahoo, iCloud, Exchange, or IMAP — plus 3 agent accounts (managed inboxes on `*.nylas.email`). Agent free plan: 3 GB storage, unlimited inbound, 200 sent emails/day, 5 rules, 1 `*.nylas.email` subdomain, and unlimited custom domains. Production is uncapped and requires a credit card: https://www.nylas.com/pricing/
