An open API service indexing awesome lists of open source software.

https://github.com/codenamev/agentic

A simple Ruby command-line tool to build and run AI Agents in a plan-and-execute fashion.
https://github.com/codenamev/agentic

Last synced: about 2 months ago
JSON representation

A simple Ruby command-line tool to build and run AI Agents in a plan-and-execute fashion.

Awesome Lists containing this project

README

          

# Agentic

A Ruby gem for building and running AI agents in a [plan-and-execute](https://blog.langchain.dev/planning-agents/#plan-and-execute) fashion. Agentic provides a simple command-line tool and library to build, manage, deploy, and run purpose-driven AI agents using OpenAI's LLM API.

## What's New in v0.2.0

🚀 **Agent Self-Assembly System** - Agents can now dynamically construct themselves based on task requirements

🎯 **Capability System** - Rich specification and versioning system for agent capabilities

💾 **Persistent Agent Store** - Save and reuse agents across sessions

🔧 **Enhanced CLI** - Comprehensive command-line interface with agent and capability management

📊 **Learning System** - Agents improve over time through execution history analysis

🎨 **Real-time Feedback** - Progress bars, spinners, and colorized output for better user experience

## Demo Video



Agentic Gem v0.2.0 Release - Watch Video






## Installation

Install the gem and add to the application's Gemfile by executing:

```bash
$ bundle add agentic
```

If bundler is not being used to manage dependencies, install the gem by executing:

```bash
$ gem install agentic
```

## Usage

### Command-Line Interface

Agentic comes with a rich command-line interface featuring colored output, spinners for long-running tasks, and progress tracking:

```bash
# Display version information
$ agentic version

# Configuration Management
$ agentic config init # Initialize configuration
$ agentic config init --global # Initialize global configuration
$ agentic config list # List all configuration settings
$ agentic config get model # Get a specific configuration value
$ agentic config set api_token=your_openai_api_key # Set your OpenAI API token
$ agentic config set model=gpt-4o-mini # Configure the default model

# Plan Creation and Execution
$ agentic plan "Generate a market research report on AI trends" # Create a plan
$ agentic plan "Write a blog post about Ruby" --save plan.json # Save plan to file
$ agentic plan "Research quantum computing" --output json # Output in JSON format
$ agentic plan "Analyze market trends" --model gpt-4o # Use a specific model
$ agentic plan "Create documentation" --execute # Create and execute immediately
$ agentic plan "Research topics" --no-interactive # Skip interactive prompts

$ agentic execute --plan plan.json # Execute a saved plan
$ agentic execute --from-stdin # Read plan from stdin
$ agentic execute --max-concurrency 5 # Limit concurrent tasks
$ agentic execute --file results.json # Save results to specific file

# Agent Management
$ agentic agent list # List available agents
$ agentic agent list --detailed # List with detailed information
$ agentic agent create "ResearchAgent" \ # Create a new agent
--role="Research Assistant" \
--purpose="Conduct thorough research" \
--capabilities=text_generation,web_search
$ agentic agent show "ResearchAgent" # Show agent details
$ agentic agent build "ResearchAgent" # Build an agent from storage
$ agentic agent delete "ResearchAgent" # Delete an agent

# Capability Management
$ agentic capabilities list # List available capabilities
$ agentic capabilities show text_generation # Show capability details
$ agentic capabilities search generation # Search for capabilities
```

The CLI provides real-time feedback with spinners for long-running operations, colored status updates, and detailed progress tracking. It supports both global and project-specific configuration, allowing you to customize the behavior for different projects.

### Programmatic API

To use Agentic in your Ruby code:

#### Basic Usage

```ruby
require 'agentic'

# Configure your OpenAI API key
Agentic.configure do |config|
config.access_token = 'your_openai_api_key'
end

# Create a TaskPlanner instance with a goal
planner = Agentic::TaskPlanner.new("Write a blog post about Ruby on Rails")

# Generate the plan
plan = planner.plan

# Display the plan
puts plan.to_s

# Or access the structured data
plan.tasks.each do |task|
puts "Task: #{task.description}"
puts "Agent: #{task.agent.name}"
end
```

#### Working with Agents

```ruby
# Create an agent with specific configuration
agent = Agentic::Agent.build do |a|
a.name = "ResearchAgent"
a.role = "Research Assistant"
a.instructions = "Conduct thorough research on the given topic"
end

# Configure the LLM
config = Agentic::LlmConfig.new(
model: "gpt-4o-mini",
temperature: 0.7
)

# Create a task
task = Agentic::Task.new(
description: "Research the latest trends in Ruby on Rails",
agent_spec: {
"name" => "ResearchAgent",
"description" => "An agent that performs research",
"instructions" => "Research the given topic thoroughly"
}
)

# Execute the task with the agent
result = task.perform(agent)

# Check the result
if result.successful?
puts "Task completed successfully!"
puts result.output
else
puts "Task failed: #{result.failure.message}"
end
```

#### Plan Orchestration

```ruby
# Create an orchestrator
orchestrator = Agentic::PlanOrchestrator.new(
concurrency_limit: 5,
continue_on_failure: true
)

# Add tasks to the orchestrator
tasks.each do |task|
orchestrator.add_task(task)
end

# Create an agent provider
agent_provider = Agentic::DefaultAgentProvider.new

# Execute the plan
result = orchestrator.execute_plan(agent_provider)

# Process the results
if result.successful?
puts "Plan executed successfully!"
else
puts "Plan execution had issues: #{result.status}"
result.results.each do |task_id, task_result|
if task_result.failed?
puts "Task #{task_id} failed: #{task_result.failure.message}"
end
end
end
```

## Extension System

Agentic includes a powerful Extension System to help integrate with external systems and customize the framework's behavior. The Extension System consists of three main components:

### Domain Adapters

Domain Adapters let you customize Agentic's behavior for specific domains like healthcare, finance, or legal:

```ruby
# Create a domain adapter for healthcare
adapter = Agentic::Extension.domain_adapter("healthcare")

# Add domain-specific knowledge
adapter.add_knowledge(:terminology, {
terms: ["patient", "diagnosis", "treatment"],
specialty: "cardiology"
})

# Create a custom prompt adapter
prompt_adapter = ->(prompt, context) {
specialty = context[:domain_knowledge][:terminology][:specialty]
"#{prompt} [Adapted for #{context[:domain]} #{specialty}]"
}

# Register the adapter
adapter.register_adapter(:prompt, prompt_adapter)

# Apply adaptation to a prompt
adapted_prompt = adapter.adapt(:prompt, "Describe the symptoms")
# => "Describe the symptoms [Adapted for healthcare cardiology]"
```

### Protocol Handlers

Protocol Handlers standardize connections to external systems and APIs:

```ruby
# Get the protocol handler
handler = Agentic::Extension.protocol_handler(
default_headers: { "User-Agent" => "AgenticApp/1.0" }
)

# Create and register a protocol implementation
http_protocol = Object.new
def http_protocol.send_request(endpoint, options)
# Implement HTTP request logic
{ status: 200, body: "Response data" }
end

# Register the protocol
handler.register_protocol(:http, http_protocol, { timeout: 30 })

# Send a request
response = handler.send_request(:http, "/api/data", {
method: "GET",
headers: { "Accept" => "application/json" }
})
```

### Plugin Manager

The Plugin Manager handles third-party extensions and their lifecycle:

```ruby
# Get the plugin manager
manager = Agentic::Extension.plugin_manager

# Register a plugin
plugin = MyPlugin.new
manager.register("my_plugin", plugin, { version: "1.0.0" })

# Get and use a plugin
if plugin = manager.get("my_plugin")
result = plugin.call(arg1, arg2)
end

# Disable a plugin
manager.disable("my_plugin")
```

## Agent Specification and Task Definition

Agentic provides structured representations for agents and tasks through several key value objects:

### Agent Specification

The AgentSpecification defines the requirements for an agent:

```ruby
# Create an agent specification
agent_spec = Agentic::AgentSpecification.new(
name: "ResearchAgent",
description: "An agent that performs research",
instructions: "Research the given topic thoroughly"
)

# Convert to a hash representation
hash = agent_spec.to_h

# Create from a hash representation
agent_spec_from_hash = Agentic::AgentSpecification.from_hash(hash)
```

### Task Definition

The TaskDefinition defines a task to be performed by an agent:

```ruby
# Create a task definition
task_def = Agentic::TaskDefinition.new(
description: "Research AI trends",
agent: agent_spec
)

# Convert to a hash representation
hash = task_def.to_h

# Create from a hash representation
task_def_from_hash = Agentic::TaskDefinition.from_hash(hash)
```

### Execution Plan

The ExecutionPlan represents a plan with tasks and expected answer format:

```ruby
# Create an expected answer format
expected_answer = Agentic::ExpectedAnswerFormat.new(
format: "PDF",
sections: ["Summary", "Trends", "Conclusion"],
length: "10 pages"
)

# Create an execution plan
plan = Agentic::ExecutionPlan.new([task_def], expected_answer)

# Convert to a formatted string
puts plan.to_s

# Convert to a hash representation
hash = plan.to_h
```

### Agent Configuration

The AgentConfig provides a configuration object for agents:

```ruby
# Create an agent configuration
config = Agentic::AgentConfig.new(
name: "ResearchAgent",
role: "Research Assistant",
backstory: "You are an expert researcher with decades of experience",
tools: ["web_search", "document_processor"],
llm_config: Agentic::LlmConfig.new(model: "gpt-4o-mini")
)

# Access configuration properties
puts config.name
puts config.role

# Convert to a hash representation
hash = config.to_h
```

## Agent Capabilities System

Agentic features a powerful Capability System that enables dynamic agent composition, self-assembly, and persistence. The system allows agents to be constructed with precisely the capabilities they need for specific tasks, and to be stored for future reuse.

### Capability Registry

The capability registry manages capability specifications and providers:

```ruby
# Define a capability specification
text_gen_capability = Agentic::CapabilitySpecification.new(
name: "text_generation",
description: "Generates text based on a prompt",
version: "1.0.0",
inputs: {
prompt: { type: "string", required: true, description: "The prompt to generate text from" }
},
outputs: {
response: { type: "string", description: "The generated text" }
}
)

# Create a provider for the capability
text_gen_provider = Agentic::CapabilityProvider.new(
capability: text_gen_capability,
implementation: ->(inputs) { { response: "Generated text for: #{inputs[:prompt]}" } }
)

# Register the capability with the system
Agentic.register_capability(text_gen_capability, text_gen_provider)
```

### Agent Assembly Engine

The assembly engine dynamically constructs agents based on task requirements:

```ruby
# Define a task
task = Agentic::Task.new(
description: "Generate a report on AI trends",
agent_spec: Agentic::AgentSpecification.new(
name: "Report Generator",
description: "An agent that generates reports",
instructions: "Generate a comprehensive report on the topic"
),
input: {
topic: "AI trends in 2023",
format: "markdown"
}
)

# Assemble an agent for the task
agent = Agentic.assemble_agent(task)

# The agent will automatically have capabilities like "text_generation"
# based on the task requirements
```

### Agent Persistence

Agents can be stored and retrieved for future use:

```ruby
# Store an agent for future use
agent_id = Agentic.agent_store.store(agent, name: "report_generator")

# Later, retrieve the agent by name
stored_agent = Agentic.agent_store.build_agent("report_generator")

# Or retrieve by ID
stored_agent = Agentic.agent_store.build_agent(agent_id)

# List all stored agents
agents = Agentic.agent_store.all
```

### Capability Composition

Capabilities can be composed into higher-level capabilities:

```ruby
registry = Agentic.agent_capability_registry

# Compose multiple capabilities into a new one
registry.compose(
"comprehensive_report",
"Generates a comprehensive report with research and formatting",
"1.0.0",
[
{ name: "text_generation", version: "1.0.0" },
{ name: "data_analysis", version: "1.0.0" }
],
->(providers, inputs) {
# Implementation that uses both capabilities
analysis = providers[1].execute(data: inputs[:data])
report = providers[0].execute(prompt: "Generate a report on: #{analysis[:summary]}")
{ report: report[:response], analysis: analysis }
}
)

# Use the composed capability
agent.add_capability("comprehensive_report")
result = agent.execute_capability("comprehensive_report", { data: { ... } })
```

## Learning System

Agentic features a Learning System that enables agents to improve over time by capturing execution metrics, recognizing patterns, and optimizing strategies. The Learning System consists of three main components:

### Execution History Store

The ExecutionHistoryStore captures and stores execution metrics and performance data:

```ruby
# Create a history store
history_store = Agentic::Learning::ExecutionHistoryStore.new(
storage_path: "~/.agentic/history",
anonymize: true,
retention_days: 30
)

# Record task execution metrics
history_store.record_execution(
task_id: "task-123",
agent_type: "research_agent",
duration_ms: 1500,
success: true,
metrics: { tokens_used: 2000, quality_score: 0.85 }
)

# Query execution history
research_tasks = history_store.get_history(agent_type: "research_agent", success: true)

# Calculate metrics
avg_tokens = history_store.get_metric(:tokens_used, { agent_type: "research_agent" }, :avg)
```

### Pattern Recognizer

The PatternRecognizer analyzes execution history to identify patterns and optimization opportunities:

```ruby
# Create a pattern recognizer
recognizer = Agentic::Learning::PatternRecognizer.new(
history_store: history_store,
min_sample_size: 10
)

# Analyze agent performance
patterns = recognizer.analyze_agent_performance("research_agent")

# Analyze correlations between properties
correlation = recognizer.analyze_correlation(:duration_ms, :tokens_used)

# Get optimization recommendations
recommendations = recognizer.recommend_optimizations("research_agent")
```

### Strategy Optimizer

The StrategyOptimizer generates improvements for prompts, parameters, and task sequences:

```ruby
# Create a strategy optimizer
optimizer = Agentic::Learning::StrategyOptimizer.new(
pattern_recognizer: recognizer,
history_store: history_store,
llm_client: llm_client # Optional, for LLM-enhanced optimizations
)

# Optimize a prompt template
improved_prompt = optimizer.optimize_prompt_template(
"Research the topic: {topic}",
"research_agent"
)

# Optimize LLM parameters
improved_params = optimizer.optimize_llm_parameters(
{ temperature: 0.7, max_tokens: 2000 },
"research_agent",
optimization_strategy: :balanced
)

# Generate performance report
report = optimizer.generate_performance_report("research_agent")
```

### Integrating with Plan Orchestrator

The Learning System can be automatically integrated with the PlanOrchestrator:

```ruby
# Create the learning system
learning_system = Agentic::Learning.create(
storage_path: "~/.agentic/history",
llm_client: llm_client,
auto_optimize: false
)

# Create a plan orchestrator
orchestrator = Agentic::PlanOrchestrator.new

# Register the learning system with the orchestrator
Agentic::Learning.register_with_orchestrator(orchestrator, learning_system)

# The orchestrator will now automatically record execution metrics
```

## Configuration

### Setting up the OpenAI API Key

You can configure the OpenAI API key in several ways:

1. Environment variable:
```bash
export OPENAI_ACCESS_TOKEN="your_api_key"
```

2. Configuration file:
Create `.agentic.yml` in your project directory or home directory:
```yaml
api_token: "your_api_key"
model: "gpt-4o-mini"
```

3. In your Ruby code:
```ruby
Agentic.configure do |config|
config.access_token = "your_api_key"
end
```

### LLM Configuration

You can customize the LLM behavior:

```ruby
config = Agentic::LlmConfig.new(
model: "gpt-4o-mini",
max_tokens: 500,
temperature: 0.7,
top_p: 1.0,
frequency_penalty: 0,
presence_penalty: 0
)

# Use in TaskPlanner
planner = Agentic::TaskPlanner.new("Write a blog post", config)

# Or with LlmClient directly
client = Agentic::LlmClient.new(config)
```

## Development

After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.

### Running Tests

Agentic includes a comprehensive test suite with both unit tests and integration tests. To run all tests:

```bash
rake spec
```

To run specific test categories:

```bash
# Run just integration tests
rspec spec/integration/

# Run a specific integration test file
rspec spec/integration/plan_orchestrator_integration_spec.rb

# Run with verbose output
rspec spec/integration/ --format documentation
```

The integration tests cover real-world scenarios including:
- Complex orchestration patterns with dependencies
- Learning system's pattern recognition capabilities
- Agent specification and task definition interactions
- Timeout and retry behaviors
- Error handling in complex scenarios

To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).

## Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/codenamev/agentic. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/codenamev/agentic/blob/main/CODE_OF_CONDUCT.md).

## License

The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).

## Code of Conduct

Everyone interacting in the Agentic project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/codenamev/agentic/blob/main/CODE_OF_CONDUCT.md).