# ARP Agent

An LLM-powered agent that processes events from the ARP (Agent-native ERP) platform using the Model Context Protocol (MCP).

## Overview

The ARP Agent is an intelligent agent that:
- Connects to an ARP server via MCP over Server-Sent Events (SSE)
- Uses an OpenAI-compatible LLM for processing events
- Subscribes to ARP resources (taskCreated, taskUpdated, taskDeleted, messageAdded)
- Takes actions on the platform using GraphQL tools (introspect, query, mutate)
- Supports external MCP servers for additional capabilities

## Prerequisites

- Go 1.25 or later
- Access to an ARP server
- An OpenAI-compatible LLM endpoint (OpenAI, local LLM, vLLM, etc.)

## Quick Start

1. **Clone and navigate to the agent:**
   ```bash
   cd arp_agent
   ```

2. **Copy the example environment file:**
   ```bash
   cp .env.example .env
   ```

3. **Edit `.env` with your configuration** (see Configuration section below)

4. **Build and run:**
   ```bash
   go build -o arp_agent
   ./arp_agent
   ```

## Configuration

### Where to Put Config Files

The agent looks for configuration files in the following locations (in order of priority):

1. **Current working directory** - Where you run the agent from
2. **Same directory as the executable** - For production deployments
3. **Absolute paths** - If specified in environment variables

### Required: `.env` File

Copy `.env.example` to `.env` and configure:

```bash
# ARP Server Configuration (required)
ARP_URL=http://localhost:8080
ARP_USERNAME=mira@slang.com
ARP_PASSWORD=mira

# OpenAI API Configuration (required)
OPENAI_API_KEY=your-api-key-here
OPENAI_MODEL=openai/gpt-4
OPENAI_TEMPERATURE=0.5
OPENAI_MAX_TOKENS=4096

# OpenAI Base URL (optional - for local/custom LLMs)
# Default: https://api.openai.com/v1
OPENAI_BASE_URL=http://localhost:1234/v1
```

### Optional: `mcp.json` File

For external MCP servers, create a `mcp.json` file (copy from `mcp.json.example`):

```json
{
  "mcpServers": {
    "brave-search": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-brave-search"],
      "env": {
        "BRAVE_API_KEY": "your-api-key-here"
      }
    }
  }
}
```

To use the MCP config file, set the environment variable:
```bash
MCP_CONFIG_PATH=/path/to/mcp.json
```

### Environment Variables Reference

| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `ARP_URL` | Yes | - | ARP server URL (e.g., `http://localhost:8080`) |
| `ARP_USERNAME` | Yes | - | ARP login email |
| `ARP_PASSWORD` | Yes | - | ARP login password |
| `OPENAI_API_KEY` | Yes | - | OpenAI API key |
| `OPENAI_MODEL` | No | `gpt-4` | LLM model name |
| `OPENAI_TEMPERATURE` | No | `0.0` | LLM temperature (0.0-2.0) |
| `OPENAI_MAX_TOKENS` | No | `4096` | Max tokens for response |
| `OPENAI_BASE_URL` | No | OpenAI API | Base URL for LLM (supports local/custom endpoints) |
| `ARP_AGENT_NAME` | No | `AI Assistant` | Agent's display name |
| `ARP_AGENT_SPECIALIZATION` | No | `general assistance` | Agent's specialization |
| `ARP_AGENT_VALUES` | No | `helpfulness, accuracy, and collaboration` | Agent's values |
| `ARP_AGENT_GOALS` | No | `help teammates accomplish their goals` | Agent's goals |
| `ARP_MAX_QUEUE_SIZE` | No | `100` | Maximum events to queue |
| `ARP_MAX_ITERATIONS` | No | `10` | Max tool call iterations per event |
| `MCP_CONFIG_PATH` | No | - | Path to `mcp.json` |

## Running the Agent

### Basic Usage

```bash
# Build
go build -o arp_agent

# Run
./arp_agent
```

### With Custom Config Path

```bash
# Use custom .env location
cd /custom/path && ./arp_agent

# Or use absolute path for MCP config
MCP_CONFIG_PATH=/etc/arp/mcp.json ./arp_agent
```

### Docker (Example)

```dockerfile
FROM golang:1.25-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o arp_agent

FROM alpine:latest
COPY --from=builder /app/arp_agent .
COPY --from=builder /app/.env.example .env
RUN apk add --no-cache ca-certificates
ENTRYPOINT ["./arp_agent"]
```

## Agent Identity

The agent has a customizable identity that defines how it behaves on the platform:

```bash
# Example: HR Specialist
ARP_AGENT_NAME=HR Bot
ARP_AGENT_SPECIALIZATION=HR and people operations
ARP_AGENT_VALUES=empathy, privacy, and professionalism
ARP_AGENT_GOALS=help employees with HR questions and processes

# Example: Engineering Assistant
ARP_AGENT_NAME=Dev Assistant
ARP_AGENT_SPECIALIZATION=software development and DevOps
ARP_AGENT_VALUES=code quality, documentation, and continuous improvement
ARP_AGENT_GOALS=help developers ship reliable software efficiently
```

**Important:** The agent IS a user on the platform (not an assistant helping a user). When it creates tasks, notes, or messages, it does so as itself.

## Available Tools

The agent has access to these ARP tools via MCP:

### `introspect`
Discover the GraphQL schema structure.

```graphql
# Get full schema
introspect()

# Get specific type
introspect(typeName: "Task")

# Get mutation fields
introspect(typeName: "Mutation")
```

### `query`
Execute GraphQL queries (read operations).

```graphql
query {
  tasks(status: "open") {
    id
    title
    assignee {
      email
    }
  }
}
```

### `mutate`
Execute GraphQL mutations (create/update/delete operations).

```graphql
# Create a task
mutation {
  createTask(input: {
    title: "Review PR"
    content: "Please review PR #123"
    priority: "high"
    serviceId: "service-123"
  }) {
    id
    title
  }
}

# Update a task
mutation {
  updateTask(id: "task-123", input: {
    statusId: "status-done"
  }) {
    id
    status {
      label
    }
  }
}
```

## External MCP Servers

Add external MCP servers to extend the agent's capabilities:

### Brave Search

```json
{
  "mcpServers": {
    "brave-search": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-brave-search"],
      "env": {
        "BRAVE_API_KEY": "your-api-key"
      }
    }
  }
}
```

### GitHub

```json
{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_TOKEN": "your-github-token"
      }
    }
  }
}
```

### Filesystem

```json
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/allowed/directory"]
    }
  }
}
```

External tools are prefixed with the server name (e.g., `brave-search.search`, `github.list_pull_requests`).

## Architecture

```
┌─────────────────────────────────────────────────────────────┐
│                        ARP Agent                             │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────┐    ┌─────────────┐    ┌───────────────┐  │
│  │   LLM       │    │   Agent     │    │  MCP Manager  │  │
│  │ (OpenAI)    │◄───│  Processor  │───►│               │  │
│  └─────────────┘    └─────────────┘    └───────┬───────┘  │
│                                                  │          │
│  ┌──────────────────────────────────────────────┼────────┐ │
│  │                    Event Queues              │        │ │
│  │  ┌──────────────┐    ┌──────────────────┐  │        │ │
│  │  │ Task Events  │    │ Message Events   │  │        │ │
│  │  │ (taskCreated │    │ (messageAdded)   │  │        │ │
│  │  │  taskUpdated │    │                  │  │        │ │
│  │  │  taskDeleted)│    │                  │  │        │ │
│  │  └──────────────┘    └──────────────────┘  │        │ │
│  └─────────────────────────────────────────────┴────────┘ │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                      External MCP Servers                    │
├─────────────────────────────────────────────────────────────┤
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐     │
│  │ brave-search │  │   github     │  │ filesystem   │     │
│  └──────────────┘  └──────────────┘  └──────────────┘     │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                        ARP Server                            │
├─────────────────────────────────────────────────────────────┤
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐     │
│  │   GraphQL    │  │     MCP      │  │   Database   │     │
│  │   (query)    │  │   (SSE)      │  │              │     │
│  └──────────────┘  └──────────────┘  └──────────────┘     │
└─────────────────────────────────────────────────────────────┘
```

### Components

- **LLM**: OpenAI-compatible language model for processing events
- **Agent Processor**: Processes events with the LLM, handles tool calls
- **MCP Manager**: Aggregates tools from ARP server and external MCP servers
- **Event Queues**: Non-blocking queues for task and message events
- **MCP Client**: SSE-based connection to ARP server
- **MCP Stdio Client**: stdio-based connection to external MCP servers

## Troubleshooting

### Connection Issues

**"Failed to connect to OpenAI API"**
- Verify `OPENAI_API_KEY` is correct
- Check `OPENAI_BASE_URL` if using a custom endpoint
- Ensure network connectivity to the LLM provider

**"Failed to login"**
- Verify `ARP_URL`, `ARP_USERNAME`, and `ARP_PASSWORD` are correct
- Check that the ARP server is running and accessible

**"Failed to connect to SSE"**
- Ensure the ARP server has the MCP endpoint enabled
- Check network/firewall settings

### Configuration Issues

**"ARP_URL environment variable is required"**
- Copy `.env.example` to `.env` and fill in the values
- Ensure the file is in the correct location

**"OPENAI_API_KEY environment variable is required"**
- Add your OpenAI API key to the `.env` file

### MCP Server Issues

**External MCP server fails to start**
- Check that Node.js and npx are installed
- Verify the server command and arguments in `mcp.json`
- Check that required API keys are set in the `env` section

**"Unknown tool" errors**
- External tools are prefixed with the server name (e.g., `brave-search.search`)
- Check the tool name matches what's available in `mcp.json`

### Performance Issues

**"Max iterations reached"**
- Increase `ARP_MAX_ITERATIONS` in `.env` (default: 10)
- Simplify the task or break it into smaller steps

**"Queue is full, dropping event"**
- Increase `ARP_MAX_QUEUE_SIZE` in `.env` (default: 100)
- Check for a backlog of events

**"Response truncated: model hit token limit"**
- Increase `OPENAI_MAX_TOKENS` in `.env` (default: 4096)
- Consider using a model with higher token limits

## License

MIT
