# Agenai

[![PyPI version](https://badge.fury.io/py/agenai.svg)](https://pypi.org/project/agenai/)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)

A modular, extensible AI agent system built around a core loop of **perceive -> reason -> act**.

## Features

- **Modular Architecture**: Build specialized agents with custom tools
- **Multiple LLM Providers**: Anthropic Claude, Ollama (local, free)
- **Web Interface**: FastAPI backend with WebSocket chat
- **Built-in Agents**: Teaching Assistant for teaching Python programming
- **Hooks System**: Full observability into agent behavior

## Installation

```bash
# From PyPI
pip install agenai

# With web server support (for chat UI)
pip install agenai[server]

# For development (editable install)
pip install -e ".[dev]"
```

## Quick Start

### Option 1: Using Ollama (Free, Local)

No API key required! Uses local LLMs.

```bash
# 1. Install Ollama from https://ollama.ai

# 2. Pull a model
ollama pull llama3.1

# 3. Start the web server
agenai-server

# 4. Open http://localhost:8000 in your browser
```

### Option 2: Using Claude API

```bash
# Set your API key
export ANTHROPIC_API_KEY="your-key"

# Run CLI
agenai run "Explain Python for loops" -v

# Or interactive chat
agenai chat
```

## Web Chat Interface

Start the server with WebSocket support:

```bash
# Install server dependencies
pip install -e ".[server]"

# Start server
agenai-server --port 8000

# Or with auto-reload for development
agenai-server --reload
```

Open http://localhost:8000 for the chat UI.

## API Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| `/` | GET | Web chat interface |
| `/health` | GET | Health check + Ollama status |
| `/chat` | POST | REST chat endpoint |
| `/ws/{client_id}` | WebSocket | Real-time chat |

## Creating Custom Agents

```python
from agenai.agent import SpecializedAgent, OllamaProvider
from agenai.agent.tools import Tool, ToolResult

class MyTool(Tool):
    @property
    def name(self) -> str:
        return "my_tool"

    @property
    def description(self) -> str:
        return "Does something useful"

    @property
    def parameters(self) -> dict:
        return {"type": "object", "properties": {}}

    def execute(self) -> ToolResult:
        return ToolResult.ok("Done!")

class MyAgent(SpecializedAgent):
    name = "my_agent"
    description = "My custom agent"

    def get_system_prompt(self) -> str:
        return "You are a helpful assistant..."

    def get_tools(self) -> list:
        return [MyTool()]

# Use with Ollama (free, local)
agent = MyAgent(llm=OllamaProvider(model="llama3.1"))
result = agent.run("Hello!")
```

## Built-in Agents

### Teaching Assistant

Teaching assistant for Python programming:

```python
from agenai.agents.teaching_assistant import TeachingAssistantAgent

agent = TeachingAssistantAgent(difficulty_level="beginner")
result = agent.run("Explain what a for loop is")
```

Tools: `run_code`, `review_code`, `create_exercise`, `create_quiz`

## Architecture

```
┌─────────────┐     WebSocket      ┌─────────────┐              ┌─────────────┐
│   Frontend  │ <================> │   Backend   │ <==========> │   Ollama    │
│  (Web Chat) │                    │  (FastAPI)  │              │ (Local LLM) │
└─────────────┘                    └──────┬──────┘              └─────────────┘
                                          │
                                          ▼
                                   ┌─────────────┐
                                   │   Agenai    │
                                   │   Agents    │
                                   └─────────────┘
```

See `AI-AGENT-ARCHITECTURE.md` for full details.

## Development

```bash
# Install dev dependencies
pip install -e ".[dev]"

# Run tests
pytest tests/ -v

# Format code
ruff check --fix .
```

## Publishing to PyPI

### Local Publishing

```bash
# Build only
./scripts/publish.sh --build-only

# Publish to TestPyPI
TEST_PYPI_TOKEN=xxx ./scripts/publish.sh --test

# Publish to PyPI
PYPI_TOKEN=xxx ./scripts/publish.sh
```

### Automated Publishing (GitHub Actions)

The repo includes a GitHub Actions workflow that auto-publishes using [Trusted Publisher](https://docs.pypi.org/trusted-publishers/) (OIDC - no API tokens needed).

**How it works:**
- Create a **GitHub Release** → auto-publishes to PyPI
- **Manual dispatch** → choose testpypi or pypi target

#### Step 1: Setup Trusted Publisher on PyPI

1. Go to https://pypi.org/manage/project/agenai/settings/publishing/
2. Click **"Add a new publisher"**
3. Fill in:

   | Field | Value |
   |-------|-------|
   | Owner | `tautobot` |
   | Repository | `agenai` |
   | Workflow name | `publish.yml` |
   | Environment name | `pypi` |

#### Step 2: Setup Trusted Publisher on TestPyPI

1. Go to https://test.pypi.org/manage/project/agenai/settings/publishing/
2. Same fields as above, but **Environment name**: `testpypi`

#### Step 3: Setup GitHub Environments

1. Go to https://github.com/tautobot/agenai/settings/environments
2. Create environment `pypi`
3. Create environment `testpypi`
4. (Optional) Add protection rules like required reviewers

#### Releasing a New Version

1. Update version in `pyproject.toml`
2. Commit and push
3. Create a GitHub Release with tag `v0.x.x`
4. GitHub Actions auto-publishes to PyPI

## License

MIT
