otto-agent 0.6.2
Otto — AI agent platform
Requires Python: >=3.12
Keywords: agent, automation, cli, tools

<p align="center">
  <img src="docs/otto-logo.png" alt="Otto" width="180" />
</p>

<h1 align="center">Otto</h1>

<p align="center">
  <strong>Self-hosted AI agent platform. Telegram bot, MCP tools, scheduled jobs, persistent memory.</strong>
</p>

<p align="center">
  <a href="https://pypi.org/project/otto-agent/"><img src="https://img.shields.io/pypi/v/otto-agent" alt="PyPI" /></a>
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green" alt="License" /></a>
  <a href="#"><img src="https://img.shields.io/badge/python-3.12+-yellow" alt="Python" /></a>
</p>

---

Otto is a personal AI agent that runs on your machine and talks to you through Telegram. It connects to any LLM via LiteLLM, exposes tools through MCP, runs scheduled jobs, and remembers context across conversations.

No cloud platform. No vendor lock-in. Just `pip install otto-agent` and go.

## Install

```bash
pip install otto-agent
```

Or with uv:

```bash
uv tool install otto-agent
```

## Setup

```bash
otto setup
```

The wizard walks you through:
- Choosing a model (`provider/model-name` format — Anthropic, OpenAI, Google, Ollama, OpenRouter, etc.)
- Connecting your Telegram bot token (from [@BotFather](https://t.me/botfather))
- Setting an owner ID so only you can use it

Config lives in `~/.otto/`.

## Usage

Start the Telegram bot:

```bash
otto start        # daemonized
otto run          # foreground (for debugging)
```

Manage the process:

```bash
otto status       # check if running
otto stop         # stop the daemon
otto logs         # tail recent logs
```

Configure the model:

```bash
otto config model get
otto config model set openai/gpt-4o
otto config model list
```

## Telegram Commands

| Command | What it does |
|---------|-------------|
| `/model` | Switch LLM model |
| `/tools` | List available tools |
| `/memory` | Search stored memories |
| `/stop` | Cancel a running response |
| `/session` | Start a fresh conversation |

## Features

**Multi-backend LLM** — Any model supported by LiteLLM: Anthropic, OpenAI, Google, Ollama, OpenRouter, and more. Switch models mid-conversation with `/model`. Supports **OAuth-authenticated models** (Claude Code, Google Code, OpenAI Codex).

**MCP Tool Gateway** — Tools are MCP servers defined in `~/.otto/tools.yaml`. Otto connects to them at startup and exposes them to the agent. Includes **Workspace Policies** for sandboxed file operations (default vs. strict modes).

**Persistent Memory** — Stores and retrieves context across sessions. Memory is searchable and can persist identity/personality rules.

**Agent Orchestration** — Otto can delegate tasks to async sub-agents running in parallel. Delegation is fire-and-forget: Otto returns immediately and notifies you via Telegram when the job is done. Sub-agents run with the same tools and model access as the main session. Delegation is contract-based — specify deliverables, constraints, and optional validation commands so results are verified before delivery.

Built-in delegation tools:
- `delegate_task` — spawn a background sub-agent with a structured contract
- `list_jobs` — inspect status of all delegated jobs
- `cancel_job` — cancel a running sub-agent

**Scheduled Jobs** — Cron-style scheduling built in, with background prompt execution.

**Web UI** — Built-in dashboard for monitoring status, viewing logs, and managing configuration (default: http://localhost:7070).

**Telegram UX** — Interactive commands, inline controls, status cards, and chunked delivery for long responses.

**File Sending** — Send files (PDFs, images, documents) directly to Telegram.

## Architecture

```
You (Telegram / Web)
      │
      ▼
┌─────────────┐
│ Telegram Bot │──── Commands (/model, /tools, /stop, ...)
└──────┬──────┘
       │
┌──────▼──────┐
│   Web UI    │──── Dashboard, monitoring, config
└──────┬──────┘
       ▼
┌─────────────┐
│  Chat Layer  │──── Sessions, memory, system prompt
└──────┬──────┘
       ▼
┌─────────────┐
│    Agent     │──── Tool-calling loop (LiteLLM → any LLM)
└──────┬──────┘
       ▼
┌─────────────┐
│ MCP Gateway  │──── Connects to tool servers defined in tools.yaml
└─────────────┘
```

## Configuration

All config is in `~/.otto/`:

| File | Purpose |
|------|---------|
| `config.yaml` | Model, Telegram token, owner ID, web/workspace settings |
| `tools.yaml` | MCP tool server definitions |
| `skills/` | Custom skill modules |
| `memory.db` | Persistent memory store |
| `sessions/` | Conversation history |
| `logs/` | Structured logs |
| `credentials/` | OAuth provider tokens |

## Development

```bash
git clone https://github.com/1broseidon/otto.git
cd otto
uv sync --dev
make check         # lint + test
otto web           # start web UI for development
```

## License

MIT