This repository contains public examples of how to implement Google's Agent Development Kit (ADK) patterns in Ruby tools. These examples demonstrate enterprise-grade patterns for building LLM-powered agent tools with safety, state management, and efficiency features.
These tools show how to transform a sprawling collection of individual command-line tools into unified, enterprise-grade agent tools using Google's ADK architectural patterns. Instead of having separate tools for each operation (creating tasks, searching emails, enriching companies), you get single unified tools that handle multiple related operations with built-in safety, state management, and intelligent response formatting.
Based on comprehensive performance testing with real LLM usage:
- 41.2% LLM token reduction (p=0.01, statistically significant)
- 41.7% cost savings per operation
- 100% reliability improvement over legacy tool approaches
- 30 iterations per test for proper statistical validation
- Welch's t-test methodology for rigorous p-value calculation
Single tools with multiple actions instead of separate tools per operation.
Response formats optimized for different use cases:
concise: 70-85% token reduction for chaining operationsdetailed: Complete information for final displayids_only: 85-95% reduction for bulk operations
Input validation and guardrails before operations execute.
Persistent memory across operations with intelligent caching.
Smart routing and batch processing capabilities.
Demonstrates email operations with ADK patterns:
- Actions: draft, send, reply, read, search, archive
- Safety: Content filtering, rate limiting, blocked domains
- State: Contact management, usage tracking, caching
- Format control for token optimization
Shows research and enrichment workflows:
- Actions: company, person, validate, enrich, search, batch_enrich
- Safety: Domain validation, API rate limiting, sensitive data blocking
- State: Result caching, preference learning, usage analytics
- Multi-source integration patterns
Illustrates task management with enterprise features:
- Actions: create, list, search, complete, update, batch_create
- Safety: Keyword blocking, batch size limits, rate limiting
- State: Assignee preferences, operation history, search caching
- Batch processing with validation
# Email with format control
ruby unified_email_tool.rb --action search --from "sender" --format concise
# Research with caching
ruby unified_research_tool.rb --action company --domain "example.com" --format detailed
# Task management with safety
ruby unified_task_manager.rb --action create --title "Review" --assignee user1 --format ids_only# Batch email processing
ruby unified_email_tool.rb --action batch_archive --batch-file emails.json
# Batch research with validation
ruby unified_research_tool.rb --action batch_enrich --batch-file companies.json --format concise
# Batch task creation
ruby unified_task_manager.rb --action batch_create --batch-create tasks.jsonThe unified tools can be extended to support newsletter analysis & startup extraction:
# Process newsletters for VC opportunities
ruby newsletter_processor.rb --action analyze --source newsletter.html --format concise
# Extract & validate companies from newsletters
ruby newsletter_processor.rb --action extract_startups --batch-file newsletters.json
# Batch process multiple newsletters with CRM integration
ruby newsletter_processor.rb --action batch_process --auto-enrich --format ids_onlyNewsletter Processing Features:
- AI-powered startup identification
- Automatic company validation & enrichment
- CRM integration for promising companies
- Batch processing for efficiency
- Configurable filtering & scoring
All tools include:
- Blocked keyword detection
- Rate limiting (configurable per service)
- Input validation with helpful error messages
- Batch size limits for stability
- Domain/content filtering
Persistent state includes:
- Usage tracking and analytics
- Result caching with TTL
- User preference learning
- Rate limit tracking
- Operation history
- LLM Input Tokens: 41.2% reduction through structured outputs
- Cost Impact: 41.7% savings on API costs
- Context Management: Single tool calls replace multiple operations
- Error Recovery: Actionable suggestions and smart retry logic
- Validation: Comprehensive input checking before execution
- Consistency: Standardized JSON responses across all operations
- Safety: Multi-layer protection against sensitive data exposure
- Monitoring: Built-in usage analytics and performance tracking
- Scalability: Batch processing with configurable limits
- Caching: Intelligent result caching reduces redundant API calls
- Replace mock methods with actual API integrations
- Configure appropriate API keys and endpoints
- Adjust rate limits based on your service quotas
- Customize safety keywords for your domain
- Set up proper logging and monitoring
# Example environment variables to configure
export EMAIL_API_KEY="your_email_api_key"
export RESEARCH_API_KEY="your_research_api_key"
export TASK_API_KEY="your_task_api_key"- Ruby 2.7+
- Standard library gems: json, optparse, digest
- File system access for state management
The performance improvements were measured through rigorous testing:
- Sample Size: 30 iterations per test for statistical significance
- Methodology: Welch's t-test for unequal variances
- Real LLM Usage: Actual Claude API calls measuring input/output tokens
- Multiple Scenarios: Email workflows, research tasks, error handling
Tool output size doesn't predict LLM efficiency. While unified tools sometimes produce longer structured outputs, they enable the LLM to process information more efficiently, resulting in net token savings.
Before unifying, map out your existing tools:
- What operations do they perform?
- Which ones are related (email, tasks, research)?
- What are the common parameters?
- Where does data flow between tools?
Create a single tool that handles multiple related operations:
ACTIONS = %w[create read update delete search batch_process]
RESPONSE_FORMATS = %w[concise detailed ids_only]Add protection before any operation executes:
# Check for sensitive data
BLOCKED_KEYWORDS = ['password', 'secret', 'api_key']
# Rate limiting
RATE_LIMITS = {
api_service: { per_hour: 100, per_minute: 10 }
}
# Domain validation
BLOCKED_DOMAINS = ['example.com', 'test.com']Create persistent memory across operations:
STATE_FILE = File.join(ENV['HOME'], '.claude', 'tool_state.json')
# Track usage patterns
@state['usage']['total_operations'] += 1
@state['preferences']['last_successful_action'] = action
# Cache results
@state['cache'][cache_key] = { data: result, timestamp: Time.now }Optimize output for different use cases:
case @options[:response_format]
when 'concise'
# 70-85% token reduction for chaining
output_minimal_summary(data)
when 'ids_only'
# 85-95% token reduction for bulk ops
output_just_ids(data)
when 'detailed'
# Full information for final display
output_complete_data(data)
endYou may notice that these unified tools make calls to various mysterious functions that don't actually exist in this repository. Consider it like buying furniture from IKEA - we provide the instructions and the overall structure, but those little Allen wrenches and actual screws? That's on you, friend.
In unified_email_tool.rb:
mock_send_email()- Because actually sending emails would be presumptuousmock_archive_emails()- We trust you know where your archive folder ismock_search_emails()- Your search implementation is probably better anyway
In unified_research_tool.rb:
execute_ruby_tool()- Assumes you have Ruby tools lying around somewhereexecute_python_tool()- Because mixing languages is the spice of lifemock_company_research()- Returns placeholder data instead of real enrichmentmock_person_research()- Your CRM API goes here
In unified_task_manager.rb:
mock_create_task()- Creates imaginary tasks in the ethermock_search_tasks()- Searches through the void and finds sample datacomplete_task()- The eternal question: what IS completion, really?resolve_assignee()- Maps user1/user2/user3 to... something
These tools demonstrate the architecture and patterns, not the implementation details. Think of them as the blueprint for a house - we're showing you where the rooms go, how the plumbing connects, and where to put the safety features. Actually connecting to your specific email server, CRM, or task management system? That's where you get to be creative!
Each missing function represents an integration point with your actual infrastructure:
- Replace email functions with your mail server API
- Replace research functions with your data enrichment services
- Replace task functions with your project management system
- Or just use
puts "TODO: Implement this"like the rest of us
When adapting these tools for production:
- Replace all mock functions with actual API calls
- Configure your specific API endpoints and keys
- Implement the actual email operations (SMTP, IMAP, etc.)
- Connect to your task management system (Jira, Monday, Trello, etc.)
- Integrate with your CRM/research tools
- Set up proper error logging
- Add retry logic for failed API calls
- Implement circuit breakers for external services
- Add metrics collection for monitoring
- Create health check endpoints
- Add integration tests for all operations
- Set up proper secret management
- Add webhook support for real-time updates
- Implement async job processing for large batches
- Add GraphQL interface for flexible querying
- Create admin dashboard for monitoring
- Build automated testing pipeline
- Consistent JSON structure allows more efficient parsing
- Error states are clearly marked, reducing LLM confusion
- Metadata helps LLM understand context faster
- Structured data requires fewer LLM tokens to process than verbose text
- Safety-first design prevents issues before they occur
- State persistence enables personalization and optimization
- Format control optimizes for different use cases
- Unified interfaces reduce cognitive load for both agents and humans
During testing, we discovered that tool output size doesn't predict LLM efficiency. Unified tools produce MORE structured output than legacy tools, yet LLMs process them using FEWER tokens. Why? Because structured JSON with clear metadata is easier for LLMs to parse than unstructured text, even when the JSON is longer.
These are reference implementations. For production use:
- Actually implement those missing functions (please!)
- Add comprehensive error handling
- Include proper logging and monitoring
- Add unit tests for safety features
- Configure for your specific environment
- Share your implementations (minus the secrets!)
Public domain examples for educational and reference purposes. The missing functions are also public domain - you can't copyright nothingness!
For the full story of how we discovered these patterns (including the embarrassing part where we initially claimed 60% improvement without measuring), see: Modernizing Agent Tools with Google ADK Patterns