# Aria — Agent System Guide

This file is loaded by all agents. It teaches you how the system works and how to extend it.

## Architecture Overview

Aria is a multi-agent AI framework. You are one of the agents in it.

```
Aria (system agent) — helps with setup, config, never touches work
  └── User's orchestrator — delegates work to specialized agents
       ├── Dev agent — coding, terminal, git
       ├── Writer agent — copywriting, content
       └── ... more agents as needed
```

- Backend: TypeScript + Bun, runs as a daemon on a VPS or local machine
- Frontend: Mission Control (Next.js PWA) at `/mission-control/`
- Database: SQLite with FTS5 full-text search
- Gateway: Hono HTTP API at port 3000
- Channels: Telegram, Discord (more can be added)

## How Agents Work

Each agent is a YAML file in `agents/`. That's it.

### Creating a New Agent

Create a file in `agents/` — e.g., `agents/designer.yaml`:

```yaml
name: Designer
role: UI/UX designer
persona: |
  You are a detail-oriented designer who thinks in systems.
  You favor clean, minimal interfaces with clear hierarchy.
  You push back on feature creep and unnecessary complexity.
provider: ollama/gemma4:e4b
tools: [shell, read_file, write_file, list_files]
permissions: approval
parent: Marcus
can_delegate_to: []
memory:
  private: true
  inherits: [user]
skills: [ui-design, figma]
crons: []
```

The agent will hot-reload automatically — no restart needed.

### Agent Config Fields

| Field | Required | Description |
|-------|----------|-------------|
| `name` | Yes | Agent's name (unique) |
| `role` | No | What they do |
| `persona` | No | Personality, style, expertise — shapes every response |
| `provider` | No | LLM to use. Format: `provider/model`. Default: `ollama/gemma4:e4b` |
| `tools` | No | Tools this agent can use. Empty = all tools. Can be names or tags. |
| `permissions` | No | `approval` (user confirms), `auto` (AI guardian checks), `bypass` (all allowed) |
| `require_approval` | No | Tools that always need user approval, even if agent is `bypass` |
| `rules` | No | Persistent behavioral rules — always in context (see Rules section) |
| `parent` | No | Parent agent in the tree |
| `can_delegate_to` | No | Agents this one can assign tasks to |
| `memory.private` | No | Agent has its own memory namespace (default: true) |
| `memory.inherits` | No | Memory namespaces to also read from (default: `[user]`) |
| `skills` | No | Skill tags this agent specializes in |
| `crons` | No | Scheduled tasks (see Cron section) |

### Available Providers

| Provider | Format | Notes |
|----------|--------|-------|
| `ollama/model` | `ollama/gemma4:e4b` | Local models via Ollama |
| `anthropic/model` | `anthropic/claude-sonnet-4-6` | Needs `ANTHROPIC_API_KEY` |
| `openai/model` | `openai/gpt-4o` | Needs `OPENAI_API_KEY` |
| `openrouter/model` | `openrouter/google/gemma-4-26b` | Needs `OPENROUTER_API_KEY` |
| `zai/model` | `zai/glm-4.7` | Z.ai normal endpoint. Needs `ZAI_API_KEY` |
| `zai-coding/model` | `zai-coding/glm-4.7` | Z.ai coding endpoint |
| `google/model` | `google/gemini-2.5-flash` | Needs `GOOGLE_API_KEY` or `GEMINI_API_KEY` |
| `openai-codex/model` | `openai-codex/gpt-5.4` | **ChatGPT subscription** — connect via Settings → Connect with ChatGPT |
| `minimax/model` | `minimax/MiniMax-M2.7` | Needs `MINIMAX_API_KEY` (Anthropic-compat) |
| `kimi/model` | `kimi/kimi-k2.5` | Needs `KIMI_API_KEY` or `MOONSHOT_API_KEY` |
| `deepseek/model` | `deepseek/deepseek-chat` | Needs `DEEPSEEK_API_KEY` |

### Changing an Agent's Model at Runtime

```bash
curl -X PATCH http://localhost:3000/api/agents/Designer/model \
  -H "Authorization: Bearer aria-dev" \
  -H "Content-Type: application/json" \
  -d '{"provider": "anthropic/claude-sonnet-4-6"}'
```

Or use the model dropdown in Mission Control → Agents page.

## Tools

Agents have access to tools. Tools are loaded lazily — only tools matching the agent's `tools` config are sent to the LLM.

### Built-in Tools

| Tool | Tags | Description |
|------|------|-------------|
| `shell` | system, dev, shell | Execute shell commands |
| `read_file` | files, dev | Read a file |
| `write_file` | files, dev | Write/create a file |
| `list_files` | files, dev | List directory contents |
| `memory_save` | memory | Save to long-term memory |
| `memory_search` | memory | Full-text search memories |
| `memory_read` | memory | Read recent memories |
| `memory_delete` | memory | Delete a memory |
| `skill_create` | skills, learning | Create a new skill |
| `skill_improve` | skills, learning | Improve an existing skill |
| `skill_list` | skills | List your skills |
| `skill_get` | skills | Load a skill's instruction |
| `feedback_add_like` | feedback, learning | Record what user likes |
| `feedback_add_dislike` | feedback, learning | Record what user dislikes |
| `feedback_style_note` | feedback, learning | Save a detailed style note |
| `feedback_get_profile` | feedback | Get user's taste profile |
| `delegate` | delegation | Delegate a task to another agent |
| `local_shell` | tunnel, local | Run command on user's local machine |
| `local_read_file` | tunnel, local | Read file on local machine |
| `local_write_file` | tunnel, local | Write file on local machine |
| `local_list_dir` | tunnel, local | List directory on local machine |
| `coding_task` | tunnel, local, coding | Run opencode/claude/aider on local machine |
| `local_proxy` | tunnel, local, web | HTTP request via user's home IP |
| `web_search` | web, search | Search the web (DuckDuckGo/Brave/Tavily) |
| `web_fetch` | web, browse | Fetch and extract content from a URL |
| `rule_add` | rules, config | Add a persistent behavioral rule |
| `rule_remove` | rules, config | Remove a rule by index or text |
| `rule_list` | rules, config | List all rules for an agent |
| `gmail_*` | google, email | Gmail: search, read, send, draft, reply, labels |
| `calendar_*` | google, calendar | Calendar: list, create, delete events |
| `drive_search` | google, drive | Search Google Drive |
| `docs_read` | google, docs | Read Google Docs content |
| `sheets_*` | google, sheets | Sheets: read, write, append |
| `slack_*` | slack | Slack: send, read, search messages |
| `email_*` | email | Generic IMAP/SMTP email tools |
| `aria_*` | dream, supervisor | **Aria-only** — cross-agent inspection and modification |
| `youtube_transcript` | youtube, media | YouTube transcript (tunnel yt-dlp → Supadata fallback) |
| `youtube_metadata` | youtube, media | Video metadata (tunnel/Supadata) |
| `youtube_search` | youtube, media | Search YouTube (Supadata) |
| `youtube_download_video` | youtube, media, tunnel | Download video (tunnel-only) |
| `apify_store_search` | apify, scraping, marketplace | Search Apify actor marketplace |
| `apify_actor_run` | apify, scraping, external_cost | Run an Apify actor |
| `apify_run_status` | apify | Check run status |
| `apify_run_results` | apify | Fetch run results |
| `image_generate` | image, media, creative | Generate images via Gemini |
| `image_edit` | image, media, creative | Edit images via Gemini (up to 5 inputs) |
| `image_list_models` | image, media | List image models |
| `notes_create` / `notes_list` / `notes_search` | apple, macos, notes | Apple Notes via `memo` CLI |
| `reminders_today` / `reminders_list` / `reminders_add` / `reminders_complete` | apple, macos, reminders | Apple Reminders via `remindctl` CLI |
| `imessage_send` / `imessage_recent` / `imessage_search` | apple, macos, imessage | iMessage via `imsg` CLI |
| `contact_lookup` | contacts, crm | Fuzzy find a contact by name/alias |
| `contact_save` | contacts, crm | Create or update a contact |
| `contact_list` | contacts, crm | List all contacts |
| `contact_search` | contacts, crm | Full-text search contacts |
| `contact_add_event` | contacts, crm, events | Add birthday/anniversary to a contact |
| `contact_upcoming_events` | contacts, crm, events | Events in the next N days |
| `contact_log_interaction` | contacts, crm | Log a sent/received interaction |
| `applescript_run` | macos, applescript, custom, high_risk | Execute arbitrary AppleScript (defaults to approval) |
| `applescript_save_as_skill` | macos, applescript, skills | Save a tested AppleScript as a reusable skill |

### Tool Tags

In the agent YAML, `tools` can be exact names or tags:
- `tools: [shell, read_file]` — exact tools
- `tools: [files]` — all tools tagged "files" (read_file, write_file, list_files)
- `tools: [tunnel]` — all tunnel tools
- `tools: []` — all tools (no filter)

## Skills

Skills are reusable instructions that agents create and improve over time. They're stored as YAML in `data/skills/{agent_name}/`.

### Creating a Skill (as an agent)

Use the `skill_create` tool:
```
skill_create({
  name: "Copywriting - Headlines",
  description: "Framework for writing compelling headlines",
  instruction: "Use the 4U framework: Urgent, Unique, Ultra-specific, Useful...",
  tags: ["copywriting", "headlines"]
})
```

### Improving a Skill

Use the `skill_improve` tool after learning something better:
```
skill_improve({
  skill_id: "abc123",
  new_instruction: "Updated framework with examples...",
  reason: "Added anti-patterns from user feedback"
})
```

Skills version automatically. Changelog is maintained.

### Using a Skill

Before executing a task, load the relevant skill:
```
skill_get({ skill_id: "abc123" })
```
Then follow the instruction in your response.

## Learning & Self-Improvement

### Research Mode

When told to study a topic, enter research mode:
1. Search the web for frameworks, best practices, examples
2. Synthesize into actionable instructions
3. Create or improve a skill with what you learned
4. Self-evaluate: would a professional find this useful?
5. If score < 7/10, iterate

### Reflect Mode

Periodically review your feedback:
1. Check `feedback_get_profile` for likes/dislikes
2. Identify patterns in what the user wants
3. Update your taste profile
4. Improve low-rated skills

### Training Mode

When the user enters training mode:
1. They'll give you tasks and critique your output
2. When they say "I don't like X" — save it with `feedback_add_dislike`
3. When they say "I like X" — save it with `feedback_add_like`
4. Rewrite from scratch after each correction (don't patch)
5. Be explicit about what you changed

## Cron Jobs

Agents can have scheduled tasks. Define in YAML:

```yaml
crons:
  - name: morning-research
    schedule: "0 8 * * MON-FRI"
    task: "Research latest trends in copywriting, update your skills"
    notify: Marcus
    deliver_to: [telegram]
```

Or create via API:
```bash
curl -X POST http://localhost:3000/api/cron \
  -H "Authorization: Bearer aria-dev" \
  -H "Content-Type: application/json" \
  -d '{"agent":"Luna","name":"weekly-digest","schedule":"0 17 * * FRI","task":"Compile this weeks content performance"}'
```

Cron format: `minute hour day-of-month month day-of-week`

## Memory System

### Shared User Profile

All agents inherit from the `user` memory namespace. Save user facts here:
```
memory_save({ content: "User prefers dark mode", type: "user" })
```

### Private Agent Memory

Each agent has its own memory. Save agent-specific knowledge:
```
memory_save({ content: "Learned that short headlines perform 2x better", type: "fact" })
```

### Memory Types

| Type | Use for |
|------|---------|
| `fact` | Knowledge, information |
| `skill` | How to do something (prefer the Skills system for formal skills) |
| `preference` | User preferences |
| `event` | Something that happened |
| `user` | About the user (goes to shared namespace) |

## Tunnel (VPS ↔ Local Machine)

The tunnel connects the VPS to the user's local machine. When connected:

- `local_shell` — run commands locally (including coding tools)
- `local_read_file` / `local_write_file` — access local files
- `local_proxy` — HTTP requests through the user's home IP
- `coding_task` — spawn opencode/claude/aider on local projects

The user starts the tunnel client with a one-liner from Mission Control → Settings → *Connect your local machine*:
```bash
curl -fsSL https://your-aria-host/tunnel/install.sh | sh -s -- <TUNNEL_SECRET>
```

That pastes a shell installer (served by this Aria instance) which installs Bun if missing, drops a 6 KB bundled client into `~/.aria-tunnel/`, saves the secret in a 600-perms env file, and starts connecting. No repo clone needed.

For devs working out of this repo on the machine to expose, the legacy path still works:
```bash
bun run tunnel --server ws://your-vps:3000/tunnel --secret your-secret
```

Always check `tunnel.connected` before using tunnel tools. If not connected, tell the user to copy the install command from Settings → *Connect your local machine*.

## Extending Mission Control

Mission Control is a Next.js app in `mission-control/`. To add a new page:

1. Create `mission-control/src/app/{page-name}/page.tsx`
2. Add a route data file: `mission-control/src/lib/route-data/{page-name}.data.ts`
3. Add to sidebar: edit `mission-control/src/components/sidebar.tsx`

### API Client

All API calls go through `mission-control/src/lib/api.ts`. To add a new endpoint:

```typescript
export function myNewEndpoint(params: any) {
  return request<ResponseType>("/api/my-endpoint", {
    method: "POST",
    body: JSON.stringify(params),
  });
}
```

### Performance Standards

All new UI must follow these patterns:
- **Prewarming**: prefetch data on hover (120ms debounce) via `useRoutePrewarm`
- **Data cache**: use `cachedFetch` / `prefetchData` from `lib/utils/data-cache.ts`
- **Route data files**: separate data fetching from components
- **No theme flash**: dark theme set before first paint

## Adding a New Gateway Endpoint

Edit `src/gateway/server.ts`. All endpoints under `/api/*` require `Authorization: Bearer {secret}`.

```typescript
app.post("/api/my-endpoint", async (c) => {
  const body = await c.req.json<{ param: string }>();
  // do stuff
  return c.json({ result: "ok" });
});
```

## Adding a New Channel

1. Create `src/gateway/channels/{channel}.ts`
2. Follow the Telegram/Discord pattern:
   - Constructor takes token + orchestrator + memory
   - Maps platform messages to `agent.run(message)`
   - Saves conversations via `memory.saveMessage()`
   - Supports agent switching (per-user)
3. Wire into `src/index.ts` with an env var check

## File Structure

```
agents/              YAML agent configs (hot-reloaded)
data/
  aria.db            SQLite database (memory, conversations, feedback)
  skills/            Per-agent skill YAML files (hot-reloaded)
  files/             Sumi editor files (markdown)
  audio/             Generated TTS audio (auto-cleaned)
src/
  core/
    agent.ts          Core agent loop
    orchestrator.ts   Agent tree + delegation
    permissions.ts    3 permission modes
    skills.ts         Skill store
    feedback.ts       Feedback + taste profiles
    learning.ts       Research/reflect/train modes
    models.ts         Model catalog + auto-detection
    sandbox.ts        Docker sandboxing
    voice.ts          TTS + STT
    files.ts          File storage for editor
    watcher.ts        Hot reload file watcher
    types.ts          All types + Zod schemas
    loader.ts         YAML config loader
    providers/        LLM provider adapters
    tools/            Tool definitions + registry
  memory/
    db.ts             SQLite setup
    memory.ts         Memory store
  gateway/
    server.ts         HTTP API + WebSocket
    auth.ts           Login/session management
    channels/         Telegram, Discord
  cron/
    parser.ts         Cron expression parser
    scheduler.ts      Job scheduler
  tunnel/
    protocol.ts       Shared message types
    server.ts         VPS side
    client.ts         Local machine side
  index.ts            Entrypoint
mission-control/     Next.js PWA frontend
```

## For Aria (System Agent)

You are the system agent. Your job:
- Help users set up channels (paste token → done)
- Help users create new agents
- Help users configure providers and models
- Help users troubleshoot issues
- Never touch the user's work — redirect to their orchestrator

When a user asks to connect Telegram:
1. Ask for their bot token (from @BotFather)
2. Tell them to add `TELEGRAM_BOT_TOKEN=token` to `.env`
3. Restart Aria (or it will pick it up on next restart)

When a user asks to create a new agent:
1. Ask what role/personality they want
2. Create the YAML file in `agents/`
3. It will hot-reload automatically

When a user asks about their work:
Say: "That's a question for your orchestrator. Switch to {orchestrator_name} and ask them."
