# CLAUDE.md - Project Guide for Claude Code

## Project Overview

**Agenai** is a modular, extensible AI agent framework built around a core loop of **perceive → reason → act**. It's designed for building specialized AI agents with custom tools and behaviors.

## Repository Relationship

```
~/github/agenai/              ← THIS REPO: Reusable agent library
    └── agenai/agents/
        └── teaching_assistant/   # First agent (used by pyrx.mentor)
        └── (future agents)       # More agents can be added here

~/github/pyrx.mentor/         ← CONSUMER: Learning platform product
    └── backend/              # Imports: from agenai.agents.teaching_assistant import ...
    └── frontend/
    └── docs/                 # Product docs (LEARNING_PATHS_CURRICULUM.md, etc.)
```

**Key distinction:**
- `agenai` = **Reusable agent framework/library** (generic, can be used by any project)
- `pyrx.mentor` = **Learning platform product** (specific application using agenai)

**Integration:** pyrx.mentor installs this package as editable:
```bash
cd ~/github/pyrx.mentor/backend
pip install -e ~/github/agenai
```

**What belongs where:**
- Agent code, tools, prompts → `agenai`
- Platform features, database, API, frontend, curriculum docs → `pyrx.mentor`

## Tech Stack

- **Language**: Python 3.10+
- **LLM SDK**: `anthropic` (primary)
- **HTTP**: `httpx`
- **CLI**: `typer` + `rich`
- **Validation**: `pydantic`
- **Testing**: `pytest`

## Project Structure

```
agenai/
├── agenai/
│   ├── agent/              # Core agent framework
│   │   ├── core.py         # Agent class with ReAct loop
│   │   ├── async_core.py   # AsyncAgent with streaming
│   │   ├── config.py       # AgentConfig (Pydantic)
│   │   ├── context.py      # AgentContext for state sharing
│   │   ├── hooks.py        # HookRegistry for observability
│   │   ├── llm.py          # LLM providers (Anthropic)
│   │   ├── memory.py       # ConversationMemory
│   │   ├── retry.py        # Retry logic with backoff
│   │   ├── specialized.py  # SpecializedAgent, ChainedAgent, RouterAgent
│   │   └── tools/          # Built-in tools
│   ├── agents/             # Specialized agents
│   │   └── teaching_assistant/    # Teaching Assistant teaching agent
│   └── main.py             # CLI entrypoint
├── examples/               # Usage examples
├── tests/                  # Test suite
└── pyproject.toml
```

## Key Patterns

### Creating a Specialized Agent

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

class MyAgent(SpecializedAgent):
    name = "my_agent"
    description = "What this agent does"

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

    def get_tools(self) -> list[Tool]:
        return [MyCustomTool()]
```

### Creating a Custom Tool

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

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

    @property
    def description(self) -> str:
        return "What this tool does"

    @property
    def parameters(self) -> dict:
        return {
            "type": "object",
            "properties": {
                "param": {"type": "string", "description": "..."}
            },
            "required": ["param"]
        }

    def execute(self, param: str) -> ToolResult:
        return ToolResult.ok("result")
```

## Common Commands

```bash
# Setup
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

# Run tests
pytest tests/ -v

# Run CLI
agenai --help
agenai tools
agenai run "prompt" -v

# Run specific agent
python -c "from agenai.agents.teaching_assistant import TeachingAssistantAgent; ..."
```

## Environment Variables

```bash
ANTHROPIC_API_KEY=...  # Required for Claude API
```

## Code Conventions

- Use `from __future__ import annotations` for type hints
- Tools return `ToolResult.ok(output)` or `ToolResult.fail(error)`
- Agents extend `SpecializedAgent` and implement `get_system_prompt()` and `get_tools()`
- Use hooks (`HookRegistry`) for observability, not print statements
- Tests use mock LLM providers to avoid API calls

## Important Files

| File | Purpose |
|------|---------|
| `agent/core.py` | Main Agent class with ReAct loop |
| `agent/specialized.py` | Base classes for specialized agents |
| `agent/tools/base.py` | Tool protocol and ToolRegistry |
| `agent/hooks.py` | Event system for observability |
| `agents/teaching_assistant/` | Example specialized agent |

## Testing

```bash
# Run all tests
pytest tests/ -v

# Run specific test file
pytest tests/test_teaching_assistant.py -v

# Run with coverage
pytest tests/ --cov=agenai
```

## Adding New Agents

1. Create directory: `agenai/agents/my_agent/`
2. Create tools in `tools/` subdirectory
3. Create agent class extending `SpecializedAgent`
4. Export from `__init__.py`
5. Add tests in `tests/test_my_agent.py`
