Claude Duet Enters Research Preview: The Always-On Agent and Three Questions It Has to Answer
💡 Tool Tip: JSON Formatter, UUID Generator, Timestamp Converter
On October 21, 2026, Anthropic announced Claude Duet, a proactive agent for professionals and small business owners, launching as a research preview as a standalone app on iOS and Android and through Claude on the web. Per The Verge, it is built around Claude Opus 5.5. Each morning it sends a short brief on the most important items across your connected apps, keeps tabs on those apps during the day and messages you only when something needs attention, and takes on tasks ranging from scheduling meetings to building dashboards across dozens of tools, producing financial or sales forecasts, prototyping and building web apps. It carries a virtual machine with a browser so it can do the work itself, and it messages you for approval before big steps like sending a payment or deleting something. Anthropic is unusually direct about the limits: this is an early version that may misread a thread or miscalibrate what is urgent. That sentence is the important one, because the hard part of an always-on agent was never capability. It is judgment and permissions.
For a proactive agent, the permission boundary is the product
1. What Duet Actually Does
Four capabilities sit inside the description. The first is proactive summarizing: a morning brief across connected apps, which is the line between an agent and a chatbot, because it does not wait to be asked. The second is continuous watching: it tracks those apps all day and messages you only when something needs you, which means it has to decide what counts as needing you, and that is exactly where misjudgment happens. The third is doing the work: it does not just read, it writes, computes and calls tools, with examples from meeting scheduling to dashboards, forecasts, prototypes and web apps. The fourth is approval and safety: it pulls in memory, skills and connected apps from Claude, runs a virtual machine with a browser, requests approval before payments or deletions, and ships a dedicated classifier and safety system prompt designed to reject sharing the strictest tier of information such as credit card numbers. Availability is a research preview with a waitlist, currently for Pro or Max subscribers in the US.
# 1) Classify actions by consequence, not by prompt wording.
# The model decides WHAT it wants; this table decides whether it may.
POLICY = {
# read-only: safe to run unattended, still logged
"list_messages": {"class": "read", "approval": False},
"search_files": {"class": "read", "approval": False},
# reversible writes: run, but require an undo record
"create_draft": {"class": "write", "approval": False, "undo": "delete_draft"},
"schedule_event": {"class": "write", "approval": True},
# irreversible or money-moving: always human
"send_payment": {"class": "destructive", "approval": True, "hard_block": True},
"delete_record": {"class": "destructive", "approval": True, "hard_block": True},
"share_contact": {"class": "destructive", "approval": True, "hard_block": True},
}
def may_execute(action: str, approved: bool) -> tuple:
rule = POLICY.get(action)
if rule is None:
return False, "unknown action" # default deny, always
if rule.get("hard_block") and not approved:
return False, "requires explicit approval"
if rule["approval"] and not approved:
return False, "requires approval"
return True, "ok"2. Three Failure Modes of an Always-On Agent
The first is misreading: it understands a thread incorrectly and then advises, or acts, on the wrong understanding. Anthropic states this risk explicitly. The second is miscalibrated urgency: a daily brief that lists twenty urgent items gets filtered into a folder by day three. That does not cause an incident immediately, but it destroys the reason the product exists, because an ignored proactive agent is indistinguishable from no agent. The third is the dangerous one: out-of-scope action. Its authority comes from apps you connected, and connecting once grants standing access; an always-on agent keeps holding that access long after you have forgotten the grant. The first two failures are observable and correctable. The third is often irreversible, because it involves money, data leaving your control, or deletion. That inverts how you should evaluate a product like this: look first at how it constrains the third failure, then at how it mitigates the first two.
# 2) An approval request must state the blast radius, or people rubber-stamp it.
def approval_request(action: str, params: dict, preview: dict) -> dict:
return {
"action": action,
"summary": preview["summary"], # one line, human language
"target": preview["target"], # which record, which account
"reversible": preview.get("reversible", False),
"undo_window_minutes": preview.get("undo_window", 0),
"evidence": preview["evidence"], # the exact source it acted on
"deadline": preview.get("deadline"), # when it expires unanswered
}
# Three rules that keep approval meaningful:
# 1. Never batch unrelated approvals into one tap.
# 2. Expire the request instead of re-asking louder.
# 3. If evidence is missing, refuse rather than ask a vague question.
# An approval dialog with no evidence trains people to tap yes.3. Approvals Keyed to Consequence, Not to Prompting
A common design lets the model decide whether an operation is dangerous and therefore whether to ask a human. That has a structural flaw: judging danger is precisely the part the model gets wrong, so you cannot use it to catch its own errors. The workable version encodes the classification in code, by consequence, in three classes. Read-only actions may run unattended but are logged. Reversible writes may run, but only alongside an undo record and an undo window. Irreversible actions, or anything moving money or sending data outward, always require a human and default to deny: if an action is not on the allowlist, refuse rather than assume it is fine. The first snippet is that table: action, class, whether approval is required, whether it is hard-blocked. It is short, and it is the only part of the system that does not depend on the model's judgment.
# 3) Log every decision with its inputs. This is the only defense after
# the fact, and the only way to debug an agent that "felt wrong".
import json, time, uuid
def audit(event: dict) -> None:
row = {
"id": str(uuid.uuid4()),
"ts": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
"agent": event["agent"],
"action": event["action"],
"class": POLICY.get(event["action"], {}).get("class", "unknown"),
"inputs_hash": event["inputs_hash"], # hash, not the payload
"target": event.get("target"),
"approved_by": event.get("approved_by"), # human id, or None
"approved_at": event.get("approved_at"),
"result": event.get("result"),
"undo_available": event.get("undo_available", False),
}
with open("agent_audit.jsonl", "a") as f:
f.write(json.dumps(row, ensure_ascii=False) + chr(10))
# Store a hash of the inputs, not the inputs. You need to prove what it
# acted on, not to keep a second copy of everything it read.4. Code: Classes, Approvals, Audit, Scopes, Ranking
The first snippet is the policy table and the execution check: unknown actions are denied, hard-blocked ones need explicit approval. The second is the shape of an approval request: a one-line human summary, the target, reversibility, an undo window, the evidence it acted on, and an expiry. Three rules keep approvals meaningful. Never batch unrelated approvals into one tap. Let the request expire rather than re-asking louder. And if the evidence is missing, refuse instead of asking a vague question, because an approval dialog without evidence only trains people to tap yes. The third snippet is the audit log, storing a hash of the inputs rather than the inputs: you need to prove what it acted on, not keep a second copy of everything it read. The fourth is scope inventory, comparing what an app requests against what you defined as necessary and refusing the surplus.
# 4) Inventory the scopes behind every connected app before you connect them.
SCOPES = {
"mail": ["read:inbox", "send:draft"],
"calendar": ["read:events", "write:events"],
"banking": ["read:balance"], # read only. no payments. none.
"crm": ["read:contacts", "write:notes"],
}
def too_broad(granted: list, needed: list) -> list:
return [s for s in granted if s not in needed]
for app, granted in connect_requests.items():
extra = too_broad(granted, SCOPES.get(app, []))
if extra:
print("refuse:", app, "requests scopes you never defined:", extra)
# Rule: if an app offers "full access" and you only need reads, request
# reads. An always-on agent accumulates permissions silently; the only
# audit that works is the one that runs before the grant.5. Do the Arithmetic Before You Connect Anything
An always-on agent's permissions accumulate, and they are usually set during one hasty authorization. So the action that comes before every connect button is writing a table: for each app, which scopes you actually need. The rules are boring and effective. If an app offers full access and you only need reads, request reads. For banking and payments, allow reading balances and nothing that moves money. For contacts, grant no export, because a contact list leaving your control is irreversible. The fourth snippet implements the check, comparing granted scopes against defined ones and refusing the connection when there is a surplus. This can feel excessive for personal use until you notice the setup: you have connected a proactive agent to mail, calendar and finance, its misjudgments happen inside those systems, and you granted the access once. Ten minutes before the grant is cheaper than ten hours after it.
# 5) A daily brief is a ranking problem. Make the thresholds explicit.
URGENT = {"deadline_hours": 24, "mentions_me": True, "money_above": 0}
MAX_ITEMS = 5
def score(item: dict) -> int:
s = 0
if item.get("deadline_hours", 999) <= URGENT["deadline_hours"]:
s += 3
if item.get("mentions_me") and URGENT["mentions_me"]:
s += 2
if item.get("money", 0) > URGENT["money_above"]:
s += 3
if item.get("from") == "boss":
s += 2
return s
brief = sorted(items, key=score, reverse=True)[:MAX_ITEMS]
# Anything the model wants to include but scores 0 goes to "nothing urgent".
# An agent that reports everything urgent teaches you to ignore it, and
# that habit is the actual failure: it does not cost accuracy, it costs trust.6. A Practical Path for a Research Preview
Three stages. Stage one is read-only: mail, calendar and documents, all read-only, for two weeks, while you judge how many items in the daily brief were useful and how many were misreads. This measures judgment with no downside. Stage two adds reversible writes: drafts, calendar holds, notes, while every outbound send still requires your hand. This measures execution and, just as importantly, your review load, because if supervising it costs more than doing the work, the value is negative. Stage three is where irreversible actions become thinkable, and only with the narrowest scope: one account, one payee, one amount ceiling. Never hand it a master account that can do anything. And keep Anthropic's own sentence in view: this is an early version that may misread a thread or miscalibrate urgency. That is not marketing boilerplate. It is the operating manual.
An action you can undo is the only action you can ship
📌 Frequently Asked Questions
Is Claude Duet available now?
It launched as a research preview with a waitlist, currently for Pro or Max subscribers in the US, as a standalone app on iOS and Android and through Claude on the web, per The Verge.
Which model does it run on?
The Verge reports that Claude Duet is built around Claude Opus 5.5.
Does it ask before taking actions?
Per Anthropic's description, it messages you for approval before big steps such as sending a payment or deleting something, and it ships a dedicated classifier and safety system prompt designed to reject requests to share the strictest tier of information, including credit card numbers.
What limitations has Anthropic acknowledged?
Anthropic describes it as an early version that may misread a thread or miscalibrate what is urgent, and says it is not as strong at personal errands such as booking tickets. Those are operating limits, not footnotes.
How much access should I give it?
Start read-only for two weeks and judge the brief quality, then allow reversible writes with manual sending, and only then grant the narrowest irreversible scope with account, payee and amount limits. Do not authorize with a master account, and do not accept full access when reads are enough.
🔧 Recommended Tools
📚 Sources
- The Verge — Anthropic takes on Muse with Claude Duet, its new AI agent (October 21, 2026)
- CNBC — Anthropic previews Claude Duet, its personal AI agent (October 21, 2026)
- Business Insider — Anthropic answers Meta and OpenAI with Claude Duet
- VentureBeat — Claude Duet, a mobile and desktop agent that takes actions proactively