Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ bundle add openai
# Anthropic
bundle add anthropic

# Atlas Cloud (uses OpenAI-compatible API)
bundle add openai

# Ollama (uses OpenAI-compatible API)
bundle add openai

Expand Down Expand Up @@ -119,6 +122,11 @@ development:
access_token: <%= Rails.application.credentials.dig(:anthropic, :access_token) %>
model: "claude-sonnet-4.5"

atlas_cloud:
service: "AtlasCloud"
api_key: <%= ENV["ATLASCLOUD_API_KEY"] %>
model: "qwen/qwen3.8-max"

ollama:
service: "Ollama"
model: "llama3.2"
Expand Down Expand Up @@ -156,7 +164,7 @@ free low-volume trial.
## Features

- **Agent-Oriented Programming**: Build AI applications using familiar Rails patterns
- **Multiple Provider Support**: Works with OpenAI, Anthropic, Ollama, RubyLLM, and more
- **Multiple Provider Support**: Works with OpenAI, Anthropic, Atlas Cloud, Ollama, RubyLLM, and more
- **Action-Based Design**: Define agent capabilities through actions
- **View Templates**: Use ERB templates for prompts (text, JSON, HTML)
- **Streaming Support**: Real-time response streaming with ActionCable
Expand Down
1 change: 1 addition & 0 deletions docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ export default defineConfig({
text: 'Providers',
items: [
{ text: 'Anthropic', link: '/providers/anthropic' },
{ text: 'Atlas Cloud', link: '/providers/atlas_cloud' },
{ text: 'Ollama', link: '/providers/ollama' },
{ text: 'OpenAI', link: '/providers/open_ai' },
{ text: 'OpenRouter', link: '/providers/open_router' },
Expand Down
7 changes: 7 additions & 0 deletions docs/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Providers connect your agents to AI services through a unified interface. Switch

<<< @/../test/dummy/app/agents/providers/anthropic_agent.rb#agent{ruby} [Anthropic]

<<< @/../test/dummy/app/agents/providers/atlas_cloud_agent.rb#agent{ruby} [Atlas Cloud]

<<< @/../test/dummy/app/agents/providers/ollama_agent.rb#agent{ruby} [Ollama]

<<< @/../test/dummy/app/agents/providers/open_ai_agent.rb#agent{ruby} [OpenAI]
Expand All @@ -33,6 +35,11 @@ end

## Choosing a Provider

### [Atlas Cloud](/providers/atlas_cloud)
**Best for:** OpenAI-compatible access to Atlas Cloud text models

Use Atlas Cloud model identifiers with Active Agent's chat, streaming, structured output, and tool-calling interfaces. The provider reads `ATLASCLOUD_API_KEY` and uses the Atlas Cloud endpoint automatically.

### [Anthropic](/providers/anthropic)
**Best for:** Complex reasoning, coding tasks, long context

Expand Down
50 changes: 50 additions & 0 deletions docs/providers/atlas_cloud.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
title: Atlas Cloud Provider
description: Use Atlas Cloud text models through its OpenAI-compatible Chat Completions API.
---
# {{ $frontmatter.title }}

The Atlas Cloud provider connects Active Agent to Atlas Cloud's OpenAI-compatible Chat Completions API. It supports the standard Active Agent chat features, including streaming, structured output, and tool calling when the selected model supports them.

## Installation

Atlas Cloud uses the `openai` gem:

```bash
bundle add openai
```

## Configuration

Set the API key in your environment:

```bash
ATLASCLOUD_API_KEY=your-api-key
```

Configure the provider in `config/active_agent.yml`:

```yaml
development:
atlas_cloud:
service: "AtlasCloud"
api_key: <%= ENV["ATLASCLOUD_API_KEY"] %>
model: "qwen/qwen3.8-max"
```

Then select it from an agent:

<<< @/../test/dummy/app/agents/providers/atlas_cloud_agent.rb#agent{ruby}

The provider defaults to `https://api.atlascloud.ai/v1`. You can override `base_url` in the provider configuration when routing through a compatible proxy.

## Model Selection

Atlas Cloud model identifiers use a `provider/model` format. Query the current catalog before selecting a model:

```bash
curl https://api.atlascloud.ai/v1/models \
-H "Authorization: Bearer $ATLASCLOUD_API_KEY"
```

Use the returned model ID as the `model` value. Model capabilities vary, so verify streaming, structured output, or tool support for the chosen model.
25 changes: 25 additions & 0 deletions lib/active_agent/providers/atlas_cloud/options.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# frozen_string_literal: true

require_relative "../open_ai/options"

module ActiveAgent
module Providers
module AtlasCloud
# Configuration options for the Atlas Cloud provider.
class Options < ActiveAgent::Providers::OpenAI::Options
attribute :base_url, :string, as: "https://api.atlascloud.ai/v1"

private

def resolve_api_key(kwargs)
kwargs[:api_key] ||
kwargs[:access_token] ||
ENV["ATLASCLOUD_API_KEY"]
end

def resolve_organization_id(_kwargs) = nil
def resolve_project_id(_kwargs) = nil
end
end
end
end
45 changes: 45 additions & 0 deletions lib/active_agent/providers/atlas_cloud_provider.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# frozen_string_literal: true

require_relative "_base_provider"

require_gem!(:openai, __FILE__)

require_relative "open_ai_provider"
require_relative "atlas_cloud/options"

module ActiveAgent
module Providers
# Provides access to Atlas Cloud's OpenAI-compatible Chat Completions API.
#
# Atlas Cloud uses provider/model identifiers such as +qwen/qwen3.8-max+.
# Request and response handling is shared with the OpenAI Chat provider;
# only the endpoint and API-key resolution are provider-specific.
class AtlasCloudProvider < OpenAI::ChatProvider
# @return [String]
def self.service_name
"AtlasCloud"
end

# @return [Class]
def self.options_klass
AtlasCloud::Options
end

# @return [ActiveModel::Type::Value]
def self.prompt_request_type
OpenAI::Chat::RequestType.new
end

protected

# @see BaseProvider#api_response_normalize
# @param api_response [OpenAI::Models::ChatCompletion]
# @return [Hash]
def api_response_normalize(api_response)
return api_response unless api_response

OpenAI::Chat::Transforms.gem_to_hash(api_response)
end
end
end
end
13 changes: 13 additions & 0 deletions test/dummy/app/agents/providers/atlas_cloud_agent.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

module Providers
# region agent
class AtlasCloudAgent < ApplicationAgent
generate_with :atlas_cloud, model: "qwen/qwen3.8-max"

def ask
prompt(message: params[:message])
end
end
# endregion agent
end
40 changes: 40 additions & 0 deletions test/providers/atlas_cloud/provider_loading_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# frozen_string_literal: true

require "test_helper"

class AtlasCloudProviderLoadingTest < ActiveSupport::TestCase
test "loads AtlasCloudProvider via atlas_cloud_provider path" do
require "active_agent/providers/atlas_cloud_provider"

assert defined?(ActiveAgent::Providers::AtlasCloudProvider)
assert defined?(ActiveAgent::Providers::AtlasCloud::Options)
end

test "provider concern loads AtlasCloud service correctly" do
provider_class = Class.new(ActiveAgent::Base).provider_load("AtlasCloud")

assert_equal ActiveAgent::Providers::AtlasCloudProvider, provider_class
end

test "Atlas Cloud options use the provider endpoint and API key" do
require "active_agent/providers/atlas_cloud_provider"

options = ActiveAgent::Providers::AtlasCloud::Options.new(api_key: "atlas-test")

assert_equal "https://api.atlascloud.ai/v1", options.base_url
assert_equal "atlas-test", options.api_key
end

test "Atlas Cloud options resolve ATLASCLOUD_API_KEY" do
require "active_agent/providers/atlas_cloud_provider"

previous_key = ENV["ATLASCLOUD_API_KEY"]
ENV["ATLASCLOUD_API_KEY"] = "atlas-env-test"

options = ActiveAgent::Providers::AtlasCloud::Options.new

assert_equal "atlas-env-test", options.api_key
ensure
ENV["ATLASCLOUD_API_KEY"] = previous_key
end
end