Skip to main content

AI agents for agentic workflows deployable to multiple chatbot platforms

Project description

aw-agents

AI Agents for Agentic Workflows - Easily deploy AI agents to multiple chatbot platforms (Claude, ChatGPT, and more).

Overview

aw-agents provides a unified framework for building AI agents and deploying them to different chatbot platforms with minimal boilerplate. Write your agent once, deploy everywhere.

Key Features

  • ๐ŸŽฏ Write Once, Deploy Everywhere: Single agent implementation works with Claude, ChatGPT, and future platforms
  • ๐Ÿ”Œ Pluggable Adapters: MCP for Claude, OpenAPI for ChatGPT
  • ๐Ÿ“ฆ Batteries Included: Built-in download agent with smart features
  • ๐Ÿ› ๏ธ Easy to Extend: Simple base class for creating new agents
  • ๐ŸŽจ Clean Architecture: Separation of agent logic and platform adapters
  • ๐Ÿš€ Run as Script: Each agent can run directly as a server with built-in setup instructions

Documentation

Installation

# From source (recommended for development)
git clone https://github.com/thorwhalen/aw_agents.git
cd aw_agents
pip install -e .

# With Claude Desktop support (MCP)
pip install -e .[mcp]

# With ChatGPT Custom GPT support (FastAPI)
pip install -e .[api]

# With all features
pip install -e .[all]

# For development
pip install -e .[dev]

Verify Installation

# Test the installation
python -c "from aw_agents.agents.download import DownloadAgent; agent = DownloadAgent(); print('โœ“ Installation successful!')"

Quick Start

Easiest Way: Run Agent as Server

Each agent can be run directly as a server with built-in instructions:

# For Claude Desktop (MCP server)
python -m aw_agents.agents.download.agent --mcp

# For ChatGPT (FastAPI server)
python -m aw_agents.agents.download.agent --api

# With ngrok for remote access
python -m aw_agents.agents.download.agent --api --server-url https://your-ngrok-url.ngrok.io

The agent will print:

  • โœ… Configuration snippets (copy-paste ready)
  • ๐Ÿ“ Exact file locations for configs
  • ๐Ÿ“‹ Step-by-step setup instructions
  • ๐Ÿš€ Everything you need to get started
  • ๐ŸŒ Proper OpenAPI schema with server URLs (fixes ChatGPT import issues)

Using the Download Agent

The package includes a smart download agent out of the box:

from aw_agents.agents.download import DownloadAgent

agent = DownloadAgent()

# Get available tools
tools = agent.get_tools()
print([t['name'] for t in tools])
# ['download_content', 'download_multiple', 'list_downloads']

# Execute a tool
result = agent.execute_tool('download_content', {
    'url': 'https://arxiv.org/pdf/2103.00020.pdf',
    'context': 'Important ML Paper'
})

print(result['data']['path'])  # ~/Downloads/Important_ML_Paper.pdf

Deploy to Claude Desktop (MCP)

Quick Start - Run the agent directly:

# The agent will automatically configure Claude Desktop for you!
python -m aw_agents.agents.download.agent --mcp

# Or run directly:
python aw_agents/agents/download/agent.py --mcp

The agent will:

  • Automatically add itself to your Claude Desktop config
  • Start the MCP server
  • Give you step-by-step instructions
  • You just need to restart Claude Desktop!

Managing Claude Desktop Configuration:

The agent uses claude_desktop_config() from the aw package to automatically manage your Claude Desktop configuration:

from aw.util import claude_desktop_config

# View all configured MCP servers
mcp = claude_desktop_config()
list(mcp)  # ['download', 'other_server', ...]

# Add a new server manually
mcp['my_agent'] = {
    'command': 'python',
    'args': ['/path/to/my_agent.py']
}

# Remove a server
del mcp['old_server']

# View a server's config
print(mcp['download'])

Manual Setup (Alternative):

If you prefer to create your own script and manage configuration manually:

Step 1: Create MCP Server Script

from aw_agents.agents.download import DownloadAgent
from aw_agents.adapters import MCPAdapter

agent = DownloadAgent()
adapter = MCPAdapter(agent, "download-agent")

# This starts an MCP server for Claude Desktop
if __name__ == "__main__":
    adapter.run_sync()

Save this as mcp_download.py or use the deployment script:

python scripts/deploy_mcp.py DownloadAgent --output mcp_download.py

Step 2: Configure Claude Desktop

Using claude_desktop_config():

from aw.util import claude_desktop_config

mcp = claude_desktop_config()
mcp['download'] = {
    'command': 'python',
    'args': ['/absolute/path/to/mcp_download.py']
}

Or manually edit the config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
  • Linux: ~/.config/Claude/claude_desktop_config.json

Important: Use absolute paths, not ~/ or relative paths.

Step 3: Restart Claude Desktop

Completely quit and restart Claude Desktop.

Step 4: Test It

Ask Claude:

Download this paper for me: https://arxiv.org/pdf/2103.00020.pdf
Context: "Attention is All You Need"

Troubleshooting:

  • Check logs: ~/Library/Logs/Claude/ (macOS)
  • Verify Python path in config
  • Ensure dependencies are installed in the correct Python environment

Deploy to ChatGPT Custom GPT (FastAPI)

Quick Start - Run the agent directly:

# The agent will print setup instructions for you
python -m aw_agents.agents.download.agent --api

# Or specify a custom port:
python aw_agents/agents/download/agent.py --api --port 8080

The agent will:

  • Start the FastAPI server
  • Print the server URLs (API, docs, OpenAPI schema)
  • Show you exactly how to configure ChatGPT Custom GPT
  • Provide ngrok instructions for remote access

Manual Setup (Alternative):

Step 1: Create and Start API Server

from aw_agents.agents.download import DownloadAgent
from aw_agents.adapters import OpenAPIAdapter

agent = DownloadAgent()
adapter = OpenAPIAdapter(agent, title="Download Agent API")

# This starts a FastAPI server
if __name__ == "__main__":
    adapter.run(port=8000)

Save this as api_download.py or use the deployment script:

python scripts/deploy_api.py DownloadAgent --output api_download.py
python api_download.py  # Start the server

The server will be available at http://localhost:8000

Step 2: Create Custom GPT

  1. Go to https://chat.openai.com/gpts/editor
  2. Click "Create a GPT"
  3. Name it (e.g., "Download Assistant")
  4. Add instructions:
    You help users download files from URLs. Use the download_content 
    action when users provide URLs. Always ask for context to generate 
    good filenames. You can download multiple files at once and list 
    previously downloaded files.
    

Step 3: Add Actions

  1. In the GPT editor, go to "Configure" โ†’ "Actions"
  2. Click "Create new action"
  3. Import schema from: http://localhost:8000/openapi.json
  4. Click "Add Action"

Step 4: Test Your GPT

Ask your Custom GPT:

Download this dataset: https://github.com/user/repo/blob/main/data.csv
Context: "Sales Data Q4"

Important Notes:

  • Local Testing: ChatGPT servers can't access localhost from OpenAI's infrastructure
  • For Remote Access:
    • Use ngrok: ngrok http 8000 (provides a public URL)
    • Deploy to cloud service (AWS, GCP, Azure, Heroku)
    • Use local network IP if on the same network

Production Deployment:

  1. Deploy to cloud service with HTTPS
  2. Add authentication (API keys, OAuth)
  3. Update Custom GPT actions with public URL

Architecture

aw_agents/
โ”œโ”€โ”€ base.py              # AgentBase, ToolExecutionResult
โ”œโ”€โ”€ adapters/
โ”‚   โ”œโ”€โ”€ mcp.py          # MCPAdapter for Claude
โ”‚   โ””โ”€โ”€ openapi.py      # OpenAPIAdapter for ChatGPT
โ””โ”€โ”€ download/           # Download agent implementation
    โ”œโ”€โ”€ agent.py        # DownloadAgent (AgentBase subclass)
    โ””โ”€โ”€ download_core.py # Core download logic

Creating Your Own Agent

from aw_agents.base import AgentBase, ToolExecutionResult, create_json_schema

class MyAgent(AgentBase):
    """My custom agent."""
    
    def get_tools(self):
        return [
            {
                'name': 'my_tool',
                'description': 'Does something useful',
                'parameters': create_json_schema(
                    properties={
                        'input': {
                            'type': 'string',
                            'description': 'Input text'
                        }
                    },
                    required=['input']
                )
            }
        ]
    
    def execute_tool(self, name, arguments):
        if name == 'my_tool':
            # Your logic here
            result = self._process(arguments['input'])
            
            return ToolExecutionResult.success_result(
                data={'output': result},
                message="Processed successfully"
            ).to_dict()
        
        return ToolExecutionResult.error_result(
            message=f"Unknown tool: {name}"
        ).to_dict()
    
    def _process(self, input_text):
        # Your implementation
        return input_text.upper()

Then deploy it:

# For Claude
from aw_agents.adapters import MCPAdapter
adapter = MCPAdapter(MyAgent(), "my-agent")
adapter.run_sync()

# For ChatGPT
from aw_agents.adapters import OpenAPIAdapter
adapter = OpenAPIAdapter(MyAgent())
adapter.run(port=8001)

Included Agents

Download Agent

Smart content downloader with:

  • Landing page detection: Automatically finds actual download links
  • Context-aware file naming: Uses conversation context for meaningful filenames
  • Special handling for:
    • GitHub (converts blob URLs to raw)
    • HuggingFace (handles dataset downloads)
    • Kaggle datasets
    • Academic papers (arXiv, etc.)
  • Support for: PDFs, datasets, CSV, JSON, and more

Tools:

  • download_content - Download a single URL with smart handling
  • download_multiple - Download multiple URLs at once
  • list_downloads - List downloaded files

Examples:

from aw_agents.agents.download import DownloadAgent

agent = DownloadAgent()

# Download with context-aware naming
result = agent.execute_tool('download_content', {
    'url': 'https://github.com/user/repo/blob/main/data.csv',
    'context': 'Dataset for analysis'
})
# Automatically converts to raw.githubusercontent.com
# Saves as: Dataset_for_analysis.csv

# Download multiple files
result = agent.execute_tool('download_multiple', {
    'urls': [
        'https://arxiv.org/pdf/2103.00020.pdf',
        'https://arxiv.org/pdf/1706.03762.pdf'
    ],
    'contexts': [
        'Attention Paper',
        'Transformer Original'
    ]
})

# List downloaded PDFs
result = agent.execute_tool('list_downloads', {
    'pattern': '*.pdf'
})

Smart Features:

  1. Intelligent Extension Detection:

    # Priority-based routing handles edge cases correctly
    agent.execute_tool('download_content', {
        'url': 'https://arxiv.org/pdf/2103.00020.pdf',
        'context': 'ML Paper'
    })
    # Result: ML_Paper.pdf โœ“ (not .html despite Content-Type header)
    
    # Explicit extension override
    agent.execute_tool('download_content', {
        'url': 'https://example.com/ambiguous_file',
        'context': 'Data',
        'explicit_extension': 'csv'
    })
    # Result: Data.csv
    
  2. Landing Page Detection:

    # Input: Landing page URL
    agent.execute_tool('download_content', {
        'url': 'https://papers.nips.cc/paper/2017/hash/xxx-Abstract.html'
    })
    # Agent detects HTML, finds PDF link, downloads PDF, warns about redirect
    
  3. GitHub URL Handling:

    # Input: GitHub blob URL
    'https://github.com/user/repo/blob/main/data.csv'
    # Converts to: 
    'https://raw.githubusercontent.com/user/repo/main/data.csv'
    
  4. Context-Aware Naming:

    # Without context:
    # Filename: 2103.00020.pdf
    
    # With context:
    agent.execute_tool('download_content', {
        'url': 'https://arxiv.org/pdf/2103.00020.pdf',
        'context': 'Attention is All You Need - Transformer Paper'
    })
    # Filename: Attention_is_All_You_Need_Transformer_Paper.pdf
    

Customizing Extension Detection

The download agent uses configurable routing from the aw.routing module:

from aw.routing import ExtensionRouter
from aw_agents.agents.download import DownloadEngine

# Inspect default mappings
router = ExtensionRouter()
print(router.content_type_map)
print(router.priority_extensions)

# Customize mappings
router.content_type_map['text/x-log'] = '.log'

# Add custom detection strategy
def detect_special(ctx):
    if 'special' in ctx.url:
        return '.special'
    return None

custom_router = router.with_prepended_strategy(detect_special)

# Use in agent
engine = DownloadEngine(extension_router=custom_router)

See EXTENSION_ROUTING_SUMMARY.md for details.

Integration Guides

Claude Desktop Integration

Easiest Way - Automatic Configuration:

# Run the agent - it will automatically configure Claude Desktop!
python -m aw_agents.agents.download.agent --mcp

The agent automatically adds itself to your Claude Desktop config. Just restart Claude Desktop and you're done!

Alternative - Manual Configuration:

  1. Create MCP server script:

    python scripts/deploy_mcp.py DownloadAgent --output ~/mcp_download.py
    
  2. Add to Claude Desktop config using claude_desktop_config():

    from aw.util import claude_desktop_config
    
    mcp = claude_desktop_config()
    mcp['download'] = {
        'command': 'python',
        'args': ['/absolute/path/to/mcp_download.py']
    }
    
  3. Restart Claude Desktop

Managing Servers:

from aw.util import claude_desktop_config

mcp = claude_desktop_config()

# List all servers
list(mcp)  # ['download', 'other_server', ...]

# View a server's config
print(mcp['download'])

# Remove a server
del mcp['old_server']

Config file locations:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
  • Linux: ~/.config/Claude/claude_desktop_config.json

Usage Examples in Claude:

Download this paper: https://arxiv.org/pdf/2103.00020.pdf
Context: "Attention is All You Need paper"

I need these papers:
1. https://arxiv.org/pdf/2103.00020.pdf - "Attention Paper"
2. https://arxiv.org/pdf/1706.03762.pdf - "Transformer Original"

Show me what PDFs I've downloaded

ChatGPT Custom GPT Integration

  1. Create API server script:

    python scripts/deploy_api.py DownloadAgent --output ~/api_download.py
    python ~/api_download.py
    
  2. Create Custom GPT at https://chat.openai.com/gpts/editor

  3. Add actions using schema from: http://localhost:8000/openapi.json

  4. For remote access, deploy to cloud or use ngrok:

    ngrok http 8000
    

Usage Examples in ChatGPT:

Download this dataset: https://github.com/user/repo/blob/main/data.csv
Context: "Sales Data Q4 2024"

Can you download these research papers for me?
[List of URLs with contexts]

Troubleshooting

Installation Issues

Problem: Module not found errors

Solution:

# Update pip and reinstall
pip install --upgrade pip
pip uninstall aw-agents
pip install -e .[all]

Problem: Missing dependencies

Solution:

# Install specific feature sets
pip install -e .[mcp]    # For Claude
pip install -e .[api]    # For ChatGPT
pip install -e .[all]    # Everything

Claude Desktop Issues

Problem: Claude doesn't see the download tools

Solution:

  1. Verify config file location (see paths above)
  2. Use absolute path in config (not ~/ or ./)
  3. Check logs: ~/Library/Logs/Claude/ (macOS)
  4. Restart Claude Desktop completely (Quit, not just close window)
  5. Verify Python environment: which python

Problem: "Module not found" when Claude tries to use agent

Solution:

# Install in the Python environment Claude uses
which python  # Check which Python Claude is using
# Use that Python to install dependencies
/path/to/python -m pip install mcp requests beautifulsoup4 graze

ChatGPT Custom GPT Issues

Problem: Actions can't connect to localhost

Solution:

  • ChatGPT servers can't access localhost from OpenAI's infrastructure
  • Options:
    1. For testing: Use ngrok to expose local server
      ngrok http 8000
      # Use the ngrok URL in your Custom GPT actions
      
    2. For production: Deploy to cloud service (AWS, GCP, Azure, Heroku)
    3. Same network: Use your local IP address

Problem: Schema import fails

Solution:

  1. Ensure server is running: curl http://localhost:8000/openapi.json
  2. Check for CORS issues (FastAPI handles this by default)
  3. Try manual schema paste instead of URL import

General Issues

Problem: Downloads failing

Solution:

  1. Check internet connection
  2. Verify URL is accessible: curl -I [URL]
  3. Some sites may block automated downloads
  4. Check download directory permissions

Problem: Import errors in Python

Solution:

# Verify installation
python -c "from aw_agents.agents.download import DownloadAgent; print('โœ“ Success')"

# Reinstall if needed
pip install -e .[all]

Development

Running Tests

pytest

Code Quality

# Format code
black aw_agents tests

# Lint
ruff aw_agents tests

# Type check
mypy aw_agents

Adding a New Agent

  1. Create a new directory in aw_agents/:

    aw_agents/myagent/
    โ”œโ”€โ”€ __init__.py
    โ”œโ”€โ”€ agent.py
    โ””โ”€โ”€ core.py (if needed)
    
  2. Implement AgentBase in agent.py

  3. Add to aw_agents/__init__.py:

    from aw_agents.myagent import MyAgent
    __all__.append('MyAgent')
    
  4. Create tests in tests/test_myagent.py

  5. Update documentation

Roadmap

  • Additional built-in agents (research, data prep, etc.)
  • Support for more platforms (Slack, Discord, etc.)
  • Agent composition and chaining
  • Persistent state management
  • Authentication and authorization
  • Web UI for agent management
  • CLI tools for deployment

Contributing

Contributions welcome! Please:

  1. Fork the repo
  2. Create a feature branch
  3. Add tests for new features
  4. Ensure all tests pass
  5. Submit a pull request

License

MIT License - see LICENSE file for details

Credits

Built with:

  • dol - Storage abstractions
  • graze - Download and caching
  • MCP - Model Context Protocol
  • FastAPI - Modern web framework

Part of the thorwhalen ecosystem.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aw_agents-0.1.2.tar.gz (42.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

aw_agents-0.1.2-py3-none-any.whl (30.6 kB view details)

Uploaded Python 3

File details

Details for the file aw_agents-0.1.2.tar.gz.

File metadata

  • Download URL: aw_agents-0.1.2.tar.gz
  • Upload date:
  • Size: 42.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for aw_agents-0.1.2.tar.gz
Algorithm Hash digest
SHA256 bf762feae5d7cd7712ad69e9951e4408e79439fd30908914921acc1fca20e604
MD5 3bdc4b56264db6d78961c92d4d0ef8fd
BLAKE2b-256 85a2511577f8563e0b04116f198cb8c15887aa5604352bc1ffc0b7c3b81cb2d6

See more details on using hashes here.

File details

Details for the file aw_agents-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: aw_agents-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 30.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for aw_agents-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 7998a69926a2c55caeda9042a0949862cddff69843a076cef229f7d2a183222f
MD5 8f194474ed9248530b64aa17381cbe1f
BLAKE2b-256 41dbd280ad34fe420f16c53ef6e7359b9ede69301961087fa239725d4816b2db

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page