Skip to contents

Overview

This vignette covers advanced tool use patterns:

  1. Tool Search: Dynamic tool discovery from large collections
  2. Programmatic Tool Calling: Orchestrate tools via code
  3. Token-Efficient Tools: Reduce tool response tokens by up to 70%

The Problem

Loading hundreds of tools upfront consumes massive context:

# This loads ALL 500 tool definitions into context
tools <- lapply(1:500, create_tool)
chat <- claude_new(tools = tools)
# Context exhausted before first message!

The Solution: Deferred Loading

Mark tools for deferred loading - Claude searches for needed tools on demand:

library(artclaude)

# Create 100 tools with deferred loading
tools <- lapply(1:100, function(i) {
  claude_tool_defer(claude_tool(
    fn = function() paste("Result from tool", i),
    name = paste0("tool_", i),
    desc = paste("Tool number", i)
  ))
})

chat <- claude_new(
  tools = tools,
  beta = beta_headers$BETA_TOOL_SEARCH
)

chat$chat("Use tool_42")
# Only tool_42 definition loaded into context

How It Works

  1. You mark tools with claude_tool_defer()
  2. Tool metadata goes to API, full definitions stay deferred
  3. Claude searches tool names/descriptions
  4. Only needed tools get loaded into context
  5. Massive context savings

Best Practices

Tool search works best when:

  • Clear names: calculate_tax, not calc_t
  • Descriptive: Good descriptions help Claude find the right tool
  • Organized: Group related tools with consistent naming
# Good: Clear names and descriptions
tax_tool <- claude_tool_defer(claude_tool(
  fn = calculate_tax,
  name = "calculate_sales_tax",
  desc = "Calculate sales tax for a purchase amount and state"
))

# Not ideal: Vague names
tool_1 <- claude_tool_defer(claude_tool(
  fn = calc,
  name = "calc",
  desc = "Does calculations"
))

Programmatic Tool Calling

The Problem

Calling tools individually wastes tokens:

# 3 separate API round-trips, all results in context
chat$chat("Search for 'impressionism'")
chat$chat("Search for 'baroque'")
chat$chat("Search for 'renaissance'")

The Solution

Claude writes code that orchestrates multiple tool calls:

search_tool <- claude_tool_programmatic(claude_tool(
  fn = function(query) search_database(query),
  name = "search",
  desc = "Search the art database",
  query = ellmer::type_string("Search query")
))

chat <- claude_new(
  tools = list(search_tool, claude_code_exec(type = "python")),
  beta = c(beta_headers$BETA_ADVANCED_TOOLS, beta_headers$BETA_CODE_EXEC_PYTHON)
)

chat$chat("Search for 'impressionism', 'baroque', and 'renaissance' and combine results")
# Claude writes Python that:
# 1. Calls search("impressionism")
# 2. Calls search("baroque")
# 3. Calls search("renaissance")
# 4. Combines and filters results
# 5. Returns only summary to context

Benefits

Programmatic tool calling provides:

  • 37%+ token reduction vs individual calls
  • Batch processing: Multiple calls in one execution
  • Filtered results: Only relevant data enters context
  • Aggregation: Combine/summarize before returning

Requirements

Programmatic tool calling requires:

  1. Beta header: beta_headers$BETA_ADVANCED_TOOLS
  2. Code execution: claude_code_exec(type = "python")
  3. Marked tools: Wrap with claude_tool_programmatic()

Example: Batch Processing

# Create programmatic tools
fetch_tool <- claude_tool_programmatic(claude_tool(
  fn = function(url) fetch_url(url),
  name = "fetch",
  desc = "Fetch content from URL",
  url = ellmer::type_string("URL to fetch")
))

analyze_tool <- claude_tool_programmatic(claude_tool(
  fn = function(text) analyze_sentiment(text),
  name = "analyze",
  desc = "Analyze sentiment",
  text = ellmer::type_string("Text to analyze")
))

chat <- claude_new(
  tools = list(fetch_tool, analyze_tool, claude_code_exec(type = "python")),
  beta = c(beta_headers$BETA_ADVANCED_TOOLS, beta_headers$BETA_CODE_EXEC_PYTHON)
)

chat$chat("Fetch these 10 URLs and analyze sentiment of each:
  url1, url2, url3, url4, url5, url6, url7, url8, url9, url10")
# Claude writes Python to:
# - Loop through URLs
# - Fetch each
# - Analyze sentiment
# - Return summary statistics only

Token-Efficient Tools

Enable Globally

Reduce all tool response tokens:

chat <- claude_new(
  tools = list(claude_web_search()),
  token_efficient = TRUE
)

chat$chat("Search for R package best practices")
# Uses more compact tool response format

Impact

Token-efficient tools:

  • Average reduction: 14%
  • Maximum reduction: 70% (some cases)
  • No quality loss: Same information, more compact format

Combine with Other Features

# Maximum efficiency: token-efficient + context editing
chat <- claude_new(
  tools = list(claude_web_search()),
  token_efficient = TRUE,
  context_edit = claude_context_edit(),
  beta = beta_headers$BETA_CONTEXT_MGMT
)

# Can run extremely long sessions
for (i in 1:200) {
  chat$chat(paste("Search topic", i))
}

Complete Example: Research Assistant

Combining all advanced features:

library(artclaude)

# Setup
memory_dir <- "~/agents/research_assistant"
fs::dir_create(memory_dir)

# Create comprehensive research agent
agent <- claude_new(
  tools = list(
    claude_memory(memory_dir),
    claude_web_search(),
    claude_web_fetch(),
    claude_code_exec(type = "python")
  ),
  context_edit = claude_context_edit(
    trigger_tokens = 50000L,
    keep_tool_uses = 10L,
    exclude_tools = c("memory")
  ),
  token_efficient = TRUE,
  beta = c(
    beta_headers$BETA_CONTEXT_MGMT,
    beta_headers$BETA_CODE_EXEC_PYTHON
  )
)

# Day 1: Initial research
agent$chat("Research the history of Impressionism and save key facts to memory")

# Day 2: Expand research
agent$chat("Research Post-Impressionism and compare with Impressionism from memory")

# Day 3: Deep dive (many tool calls)
agent$chat("For each Impressionist artist in memory, search for their biography")
# Context editing prevents exhaustion
# Token-efficient keeps responses compact

# Day 4: Generate report
agent$chat("Create a comprehensive report from all research in memory")

Performance Comparison

Configuration 100-turn Session Notes
No optimizations Fails at ~30 turns Context exhaustion
Context editing 84% less tokens Completes successfully
+ Token-efficient 90%+ less tokens Maximum efficiency
+ Programmatic tools 95%+ less tokens With batch operations

API References