deputy keeps a provider-agnostic R runtime at its core and layers an opt-in Anthropic-compatible facade on top. This vignette shows what is covered by the compatibility layer, how the Anthropic-style entrypoints map to deputy, and where the current boundary remains intentionally narrower than Anthropic’s full ecosystem surface.
Compatibility Matrix
| Surface | Status | deputy mapping |
|---|---|---|
claude_sdk_query() / query()
|
Covered |
claude_sdk_query() and
ClaudeSDKClient$query()
|
| Session ids, resume, fork | Covered | Persisted snapshots plus resume() / CLI flags |
| Permission modes | Covered |
default, acceptEdits,
readonly, plan,
bypassPermissions
|
| Hook events | Covered | Existing hook system plus Notification
|
| Claude settings | Covered |
CLAUDE.md, .claude/skills,
.claude/commands, .claude/agents, tool policy
keys |
| Anthropic-style built-in tool names | Covered |
Read, Write, Edit,
MultiEdit, Glob, Grep,
LS, TodoRead, TodoWrite,
WebFetch, WebSearch, Task
|
| Native deputy runtime | Canonical |
Agent, LeadAgent,
Permissions, HookMatcher
|
| Plugin discovery / marketplace execution | Not in this wave | Track separately from the core compat facade |
| MCP resource subscriptions | Not in this wave | deputy exposes MCP tools, not Anthropic-specific resource flows |
Entry Points
Use claude_sdk_options() to express Anthropic-shaped
options and translate them into deputy internals:
library(deputy)
options <- claude_sdk_options(
chat = ellmer::chat_anthropic(model = "claude-sonnet-4-5-20250929"),
setting_sources = c("project", "user"),
permission_mode = "plan",
allowed_tools = c("Read", "Grep", "LS"),
max_turns = 15
)
result <- claude_sdk_query("Summarize the package structure", options = options)
result$session_idFor a stateful client:
client <- ClaudeSDKClient$new(options)
client$query("Inspect the R/ directory")Sessions, Resume, and Fork
The compatibility layer persists snapshots to:
tools::R_user_dir("deputy", "cache")Snapshots are enabled by default for the Claude-compatible APIs. Each
completed turn writes a new snapshot, and the latest snapshot path is
attached to AgentResult$snapshot_path.
result <- client$query("Create a high-level summary")
# Restore the latest snapshot for a session id
client$resume(result$session_id)
# Restore the newest snapshot at or before a point in time
client$resume(result$session_id, at = "2026-03-07 10:30:00")
# Clone the restored state into a new session id
client$resume(result$session_id, fork = TRUE)The CLI exposes the same behavior:
Permissions and Hooks
Anthropic’s planning behavior maps to deputy’s plan
mode:
plan allows only tools annotated with
read_only_hint = TRUE plus the approval tool named by
permission_prompt_tool_name (default:
"AskUserQuestion"). Write, execution, and unannotated tools
are denied by default.
Informational runtime events now use the existing hook system via
Notification:
hook <- HookMatcher$new(
event = "Notification",
callback = function(message, context) {
cli::cli_alert_info("[{context$code}] {message}")
NULL
}
)deputy emits Notification for cases such as session
restore or fork notices, permission-denied guidance, compaction
fallbacks, and cost warnings.
Settings, Agents, and Tool Aliases
claude_settings_load() and
claude_settings_apply() now understand:
-
CLAUDE.mdmemory blocks .claude/skills.claude/commands.claude/agents- Tool policy keys such as
allowedTools,disallowedTools, andpermissionPromptToolName
Custom agents from .claude/agents are converted to
AgentDefinition objects and registered automatically when
you use LeadAgent or ClaudeSDKClient.
Anthropic-style tool names resolve through the compatibility layer rather than changing deputy’s native tool names:
compat_tools <- claude_sdk_options(
custom_tools = list(),
allowed_tools = c("Read", "Edit", "TodoWrite")
)This keeps read_file, edit_file,
todo_write, and the rest of deputy’s snake_case tool
surface intact for native R users.
Design Boundary
deputy aims for behavioral compatibility, not a literal language-port of the Node or Python SDKs. The runtime model is intentionally R-native:
- R6 objects instead of Python or TypeScript classes
-
corogenerators for streaming - Base lists and data frames for snapshots and session indexes
- Existing deputy hooks and permissions reused by the compat facade
That boundary keeps the Anthropic surface available without making the rest of the package Anthropic-specific.