open-index/open-npm huggingface dataset:
npm package: @openvizai/shared-types
Description: Shared TypeScript contracts and chart constants for OpenVizAI packages.
Author: Jay Gajera
Latest version: 0.1.2

# @openvizai/shared-types

Shared TypeScript contracts and constants for OpenVizAI packages.

This package provides the canonical chart type constants used across backend prompts, validation schemas, and frontend rendering.

## Install

```bash
npm install @openvizai/shared-types
```

## Usage

```ts
import { SUPPORTED_CHART_TYPES } from "@openvizai/shared-types";
import type { ChartType } from "@openvizai/shared-types";
```

## Why this package exists

- Prevents chart type drift between packages
- Keeps core and react contracts aligned
- Improves type safety across package boundaries

For full context, see:
https://github.com/OpenVizAI/OpenVizAI
npm package: @openvole/paw-brain
Description: Unified Brain Paw — multi-provider LLM adapter for OpenVole
Latest version: 2.0.0

# @openvole/paw-brain

Unified Brain Paw for OpenVole — a single paw that supports multiple LLM providers.

## Supported Providers

| Provider | `BRAIN_PROVIDER` | API Key Env | Model Env | Default Model |
|----------|-----------------|-------------|-----------|---------------|
| Anthropic | `anthropic` | `ANTHROPIC_API_KEY` | `ANTHROPIC_MODEL` | `claude-sonnet-4-20250514` |
| OpenAI | `openai` | `OPENAI_API_KEY` | `OPENAI_MODEL` | `gpt-4o` |
| Google Gemini | `gemini` | `GEMINI_API_KEY` | `GEMINI_MODEL` | `gemini-2.5-flash` |
| xAI | `xai` | `XAI_API_KEY` | `XAI_MODEL` | `grok-3` |
| Ollama | `ollama` | — | `OLLAMA_MODEL` | `qwen3:latest` |

## Configuration

### Option 1: Generic env vars

```env
BRAIN_PROVIDER=gemini
BRAIN_API_KEY=your-api-key
BRAIN_MODEL=gemini-2.5-flash
```

### Option 2: Provider-specific env vars

```env
GEMINI_API_KEY=your-api-key
GEMINI_MODEL=gemini-2.5-flash
```

Provider-specific vars take precedence over generic `BRAIN_*` vars.

### Option 3: Auto-detect

If `BRAIN_PROVIDER` is not set, paw-brain auto-detects the provider from available API keys in this order: Anthropic, OpenAI, Gemini, xAI, Ollama.

### vole.config.json

```json
{
  "brain": "@openvole/paw-brain",
  "paws": [
    {
      "name": "@openvole/paw-brain",
      "allow": {
        "network": ["*"],
        "env": ["BRAIN_PROVIDER", "BRAIN_API_KEY", "BRAIN_MODEL", "BRAIN_BASE_URL",
                "ANTHROPIC_API_KEY", "ANTHROPIC_MODEL",
                "OPENAI_API_KEY", "OPENAI_MODEL",
                "GEMINI_API_KEY", "GEMINI_MODEL",
                "XAI_API_KEY", "XAI_MODEL",
                "OLLAMA_HOST", "OLLAMA_MODEL"]
      }
    }
  ]
}
```

## Switching providers

Just change `BRAIN_PROVIDER` and the corresponding API key — no config file changes needed:

```env
# Switch from Gemini to Claude
BRAIN_PROVIDER=anthropic
ANTHROPIC_API_KEY=sk-ant-...
```

## Fallback provider

If the primary provider errors (rate limit, timeout, outage), paw-brain can automatically retry with a fallback:

```env
BRAIN_PROVIDER=anthropic
ANTHROPIC_API_KEY=sk-ant-...

BRAIN_FALLBACK=openai
OPENAI_API_KEY=sk-...
BRAIN_FALLBACK_MODEL=gpt-4o          # optional
```

The fallback is only used when the primary throws an error — not for empty responses or tool narration.

## Cost tracking

paw-brain reports token usage (input/output tokens, model, provider) back to core via `AgentPlan.usage`. Core uses this for per-task cost estimation.

- Cloud providers are priced from a built-in pricing table
- Local Ollama models (no `:cloud` suffix) show as free in `auto` mode
- Ollama cloud models (e.g. `kimi-k2.5:cloud`) are priced
- Set `costTracking: "enabled"` in loop config to track all providers
npm package: @openvole/paw-browser
Description: Browser automation Paw using Puppeteer for web browsing, interaction, and screenshots
Latest version: 2.0.0

# @openvole/paw-browser

**Browser automation Paw using Puppeteer.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-browser)](https://www.npmjs.com/package/@openvole/paw-browser)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-browser
```

## Config

```json
{
  "name": "@openvole/paw-browser",
  "allow": {
    "network": ["*"],
    "env": ["VOLE_BROWSER_HEADLESS"]
  }
}
```

## Environment Variables

| Variable | Description |
|----------|-------------|
| `VOLE_BROWSER_HEADLESS` | Run browser in headless mode (`true`/`false`, default `true`) |

## Tools

| Tool | Description |
|------|-------------|
| `browser_navigate` | Navigate to a URL in the browser |
| `browser_click` | Click an element on the page by CSS selector |
| `browser_type` | Type text into an input element by CSS selector |
| `browser_screenshot` | Take a full-page screenshot (returns base64 PNG) |
| `browser_content` | Get page text content and accessibility tree |
| `browser_evaluate` | Run arbitrary JavaScript in the page context |

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-calendar
Description: Paw for managing Google Calendar events
Latest version: 2.0.0

# @openvole/paw-calendar

**Google Calendar event management.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-calendar)](https://www.npmjs.com/package/@openvole/paw-calendar)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-calendar
```

## Config

```json
{
  "name": "@openvole/paw-calendar",
  "allow": {
    "network": ["www.googleapis.com", "oauth2.googleapis.com"],
    "env": ["GOOGLE_CLIENT_ID", "GOOGLE_CLIENT_SECRET", "GOOGLE_REFRESH_TOKEN", "GOOGLE_CALENDAR_ID"]
  }
}
```

## Environment Variables

| Variable | Description |
|----------|-------------|
| `GOOGLE_CLIENT_ID` | Google OAuth client ID |
| `GOOGLE_CLIENT_SECRET` | Google OAuth client secret |
| `GOOGLE_REFRESH_TOKEN` | Google OAuth refresh token |
| `GOOGLE_CALENDAR_ID` | Calendar ID (default `primary`) |

## Tools

| Tool | Description |
|------|-------------|
| `calendar_list_events` | List upcoming events from Google Calendar |
| `calendar_create_event` | Create a new event on Google Calendar |
| `calendar_update_event` | Update an existing event on Google Calendar |
| `calendar_delete_event` | Delete an event from Google Calendar |

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-claude
Description: [DEPRECATED — use @openvole/paw-brain] Brain Paw powered by Anthropic Claude
Latest version: 2.0.0
Deprecated: Use @openvole/paw-brain instead. It supports all providers (Anthropic, OpenAI, Gemini, xAI, Ollama) in a single paw.

# @openvole/paw-claude

**Brain Paw powered by Anthropic Claude.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-claude)](https://www.npmjs.com/package/@openvole/paw-claude)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-claude
```

## Config

```json
{
  "name": "@openvole/paw-claude",
  "allow": {
    "network": ["api.anthropic.com"],
    "env": ["ANTHROPIC_API_KEY", "ANTHROPIC_MODEL", "ANTHROPIC_BASE_URL"]
  }
}
```

## Environment Variables

| Variable | Description |
|----------|-------------|
| `ANTHROPIC_API_KEY` | Anthropic API key |
| `ANTHROPIC_MODEL` | Model to use (e.g. `claude-sonnet-4-20250514`) |
| `ANTHROPIC_BASE_URL` | Custom API base URL (optional) |

## Brain

Implements the Think phase — receives the conversation context and registered tools, returns the next assistant message and any tool calls. Connects to the Anthropic API.

## BRAIN.md

The system prompt is loaded from `.openvole/paws/paw-claude/BRAIN.md`. On first startup, the paw scaffolds a default prompt there. Edit this file to customize how the Brain reasons and responds.

The old `.openvole/BRAIN.md` path is no longer used.

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-compact
Description: Default context compaction Paw for OpenVole — summarizes old messages to free context window
Latest version: 2.0.0

# @openvole/paw-compact

**Context compaction — heuristic trimming (default) + optional LLM summarization.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-compact)](https://www.npmjs.com/package/@openvole/paw-compact)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-compact
```

## Compaction Levels

### Level 0: Heuristic (default, free)

No LLM needed. Two-phase approach:
1. **Phase 1**: Shrink seen tool results in-place (works even with few messages)
2. **Phase 2**: Replace old messages with structured summary (tool calls, results, errors)

### Level 1: LLM Summarization (opt-in)

Uses a configurable LLM to produce structured summaries preserving task context, decisions, blockers, and next steps. Falls back to Level 0 if LLM unavailable.

```env
# Use a cheap local model
VOLE_COMPACT_MODEL=ollama/llama3.1:8b

# Or a cloud model
VOLE_COMPACT_MODEL=openai/gpt-4o-mini
VOLE_COMPACT_MODEL=gemini/gemini-2.0-flash
```

## Config

```json
{
  "name": "@openvole/paw-compact",
  "allow": {
    "network": ["*"],
    "env": ["VOLE_COMPACT_KEEP_RECENT", "VOLE_COMPACT_MODEL",
            "OLLAMA_HOST", "OPENAI_API_KEY", "GEMINI_API_KEY"]
  }
}
```

## Environment Variables

| Variable | Description |
|----------|-------------|
| `VOLE_COMPACT_KEEP_RECENT` | Number of recent messages to keep uncompacted (default: 10) |
| `VOLE_COMPACT_MODEL` | LLM for summarization in `provider/model` format. If not set, auto-detects or uses heuristic |

## How It Works

Runs in-process as part of the kernel's context management. When context exceeds 75% of `maxContextTokens`:

1. **Phase 1** always runs — shrinks large tool results the Brain has already seen
2. **Phase 2** runs if enough messages — LLM summarizes old messages (or heuristic if no LLM)
3. Result: first user message + summary + recent messages

The LLM client initializes lazily on first compaction, not at startup.

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-dashboard
Description: Web dashboard Paw for OpenVole — real-time agent monitoring
Latest version: 3.0.0

# @openvole/paw-dashboard

**Real-time web dashboard for agent monitoring.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-dashboard)](https://www.npmjs.com/package/@openvole/paw-dashboard)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-dashboard
```

## Config

```json
{
  "name": "@openvole/paw-dashboard",
  "allow": {
    "listen": [3001],
    "env": ["VOLE_DASHBOARD_PORT"]
  }
}
```

## Environment Variables

| Variable | Description |
|----------|-------------|
| `VOLE_DASHBOARD_PORT` | Port for the dashboard web server (default `3001`) |

## How It Works

Starts a local web server with a WebSocket connection for real-time streaming of agent activity. View conversations, tool calls, and system events in your browser.

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-database
Description: Database Paw for OpenVole — query PostgreSQL, MySQL, and SQLite databases
Latest version: 2.0.0

# @openvole/paw-database

**Query PostgreSQL, MySQL, and SQLite databases.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-database)](https://www.npmjs.com/package/@openvole/paw-database)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-database
```

## Config

```json
{
  "name": "@openvole/paw-database",
  "allow": {
    "network": ["*"],
    "filesystem": ["./"],
    "env": ["DATABASE_URL", "DATABASE_TYPE", "VOLE_DB_READONLY"]
  }
}
```

## Environment Variables

| Variable | Description |
|----------|-------------|
| `DATABASE_URL` | Connection string. SQLite: `/path/to/db.sqlite`, PostgreSQL: `postgres://user:pass@host/db`, MySQL: `mysql://user:pass@host/db` |
| `DATABASE_TYPE` | Force type: `sqlite`, `postgresql`, `mysql` (auto-detected from URL if not set) |
| `VOLE_DB_READONLY` | Set to `true` to block write operations (INSERT/UPDATE/DELETE) |

## Tools

| Tool | Description |
|------|-------------|
| `db_query` | Execute a read-only SQL query (SELECT/WITH/EXPLAIN). Auto-limited to 100 rows |
| `db_schema` | List all tables and their columns (name, type, nullable) |
| `db_execute` | Execute a write statement (INSERT/UPDATE/DELETE/CREATE). Blocked if read-only mode |

## Database Support

- **SQLite** — via better-sqlite3, in-process, no external service needed
- **PostgreSQL** — via `psql` CLI (must be installed)
- **MySQL** — via `mysql` CLI (must be installed)

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-discord
Description: Discord messaging channel Paw for OpenVole
Latest version: 2.0.0

# @openvole/paw-discord

**Discord bot channel for OpenVole.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-discord)](https://www.npmjs.com/package/@openvole/paw-discord)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-discord
```

## Config

```json
{
  "name": "@openvole/paw-discord",
  "allow": {
    "network": ["discord.com", "gateway.discord.gg"],
    "env": ["DISCORD_BOT_TOKEN", "DISCORD_ALLOW_FROM"]
  }
}
```

## Environment Variables

| Variable | Description |
|----------|-------------|
| `DISCORD_BOT_TOKEN` | Discord bot token |
| `DISCORD_ALLOW_FROM` | Comma-separated list of allowed channel IDs |

## Tools

| Tool | Description |
|------|-------------|
| `discord_send` | Send a message to a Discord channel |
| `discord_reply` | Reply to a message in Discord |
| `discord_get_channel` | Get information about a Discord channel |

Connects to Discord as a bot, forwarding incoming messages to the agent and exposing tools for sending replies.

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-email
Description: Paw for sending and reading emails via SMTP and IMAP
Latest version: 2.0.0

# @openvole/paw-email

**Email via SMTP and IMAP.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-email)](https://www.npmjs.com/package/@openvole/paw-email)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-email
```

## Config

```json
{
  "name": "@openvole/paw-email",
  "allow": {
    "network": ["*"],
    "env": ["EMAIL_HOST", "EMAIL_PORT", "EMAIL_USER", "EMAIL_PASS", "EMAIL_IMAP_HOST", "EMAIL_IMAP_PORT"]
  }
}
```

## Environment Variables

| Variable | Description |
|----------|-------------|
| `EMAIL_HOST` | SMTP server hostname |
| `EMAIL_PORT` | SMTP server port |
| `EMAIL_USER` | Email account username |
| `EMAIL_PASS` | Email account password |
| `EMAIL_IMAP_HOST` | IMAP server hostname |
| `EMAIL_IMAP_PORT` | IMAP server port |

## Tools

| Tool | Description |
|------|-------------|
| `email_send` | Send an email via SMTP |
| `email_search` | Search emails in a mailbox folder |
| `email_read` | Read a specific email by its message ID |
| `email_list_folders` | List available mailbox folders |

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-filesystem
Description: Filesystem Paw for reading, writing, editing, and searching files
Latest version: 2.0.0

# @openvole/paw-filesystem

**File system operations for reading, writing, editing, and searching files.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-filesystem)](https://www.npmjs.com/package/@openvole/paw-filesystem)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-filesystem
```

## Config

```json
{
  "name": "@openvole/paw-filesystem",
  "allow": {
    "filesystem": ["/app/workspace"],
    "env": ["VOLE_FS_ALLOWED_DIRS"]
  }
}
```

## Environment Variables

| Variable | Description |
|----------|-------------|
| `VOLE_FS_ALLOWED_DIRS` | Comma-separated list of directories the paw can access |

## Tools

| Tool | Description |
|------|-------------|
| `fs_read` | Read a file |
| `fs_write` | Write or create a file |
| `fs_edit` | Search and replace in a file |
| `fs_list` | List directory contents |
| `fs_search` | Search for text in files |
| `fs_mkdir` | Create a directory |

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-gemini
Description: [DEPRECATED — use @openvole/paw-brain] Brain Paw powered by Google Gemini
Latest version: 2.0.0
Deprecated: Use @openvole/paw-brain instead. It supports all providers (Anthropic, OpenAI, Gemini, xAI, Ollama) in a single paw.

# @openvole/paw-gemini

**Brain Paw powered by Google Gemini.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-gemini)](https://www.npmjs.com/package/@openvole/paw-gemini)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-gemini
```

## Config

```json
{
  "name": "@openvole/paw-gemini",
  "allow": {
    "network": ["generativelanguage.googleapis.com"],
    "env": ["GEMINI_API_KEY", "GEMINI_MODEL"]
  }
}
```

## Environment Variables

| Variable | Description |
|----------|-------------|
| `GEMINI_API_KEY` | Google Gemini API key |
| `GEMINI_MODEL` | Model to use (e.g. `gemini-pro`) |

## Brain

Implements the Think phase — receives the conversation context and registered tools, returns the next assistant message and any tool calls. Connects to the Google Gemini API.

## BRAIN.md

The system prompt is loaded from `.openvole/paws/paw-gemini/BRAIN.md`. On first startup, the paw scaffolds a default prompt there. Edit this file to customize how the Brain reasons and responds.

The old `.openvole/BRAIN.md` path is no longer used.

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-github
Description: Paw for interacting with GitHub via the Octokit REST API
Latest version: 2.0.0

# @openvole/paw-github

**GitHub API integration via Octokit.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-github)](https://www.npmjs.com/package/@openvole/paw-github)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-github
```

## Config

```json
{
  "name": "@openvole/paw-github",
  "allow": {
    "network": ["api.github.com"],
    "env": ["GITHUB_TOKEN"]
  }
}
```

## Environment Variables

| Variable | Description |
|----------|-------------|
| `GITHUB_TOKEN` | GitHub personal access token |

## Tools

| Tool | Description |
|------|-------------|
| `github_create_issue` | Create a GitHub issue in a repository |
| `github_list_issues` | List issues in a GitHub repository |
| `github_create_pr` | Create a pull request in a GitHub repository |
| `github_list_prs` | List pull requests in a GitHub repository |
| `github_search_repos` | Search GitHub repositories |
| `github_get_file` | Get file content from a GitHub repository |

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-image
Description: Image processing Paw for OpenVole — resize, crop, watermark, compress, convert
Latest version: 2.0.0

# @openvole/paw-image

**Resize, crop, watermark, compress, and convert images.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-image)](https://www.npmjs.com/package/@openvole/paw-image)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-image
```

## Config

```json
{
  "name": "@openvole/paw-image",
  "allow": {
    "filesystem": ["./"]
  }
}
```

## Tools

| Tool | Description |
|------|-------------|
| `image_info` | Get metadata: dimensions, format, channels, color space, file size |
| `image_resize` | Resize with aspect ratio preservation (fit modes: cover, contain, fill, inside, outside) |
| `image_crop` | Crop a region by pixel coordinates |
| `image_compress` | Reduce file size with configurable quality (1-100) |
| `image_convert` | Convert between formats: PNG, JPEG, WebP, AVIF, TIFF |
| `image_watermark` | Add text watermark with configurable position and opacity |

## Dependencies

Uses [sharp](https://sharp.pixelplumbing.com/) — high-performance image processing powered by libvips.

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-mcp
Description: MCP bridge Paw for OpenVole — connects MCP servers to the tool registry
Latest version: 2.0.0

# @openvole/paw-mcp

**MCP server bridge — connects MCP servers to OpenVole's tool registry.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-mcp)](https://www.npmjs.com/package/@openvole/paw-mcp)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-mcp
```

## Config

```json
{
  "name": "@openvole/paw-mcp",
  "allow": {}
}
```

Permissions are inherited from each MCP server's own configuration. Configure MCP servers in your `vole.config.json` under the `mcp` key.

## Environment Variables

No required environment variables. MCP server configs are in `.openvole/paws/paw-mcp/servers.json`.

## How It Works

This paw bridges any [Model Context Protocol](https://modelcontextprotocol.io/) server into OpenVole's tool registry. Tools provided by connected MCP servers appear alongside native paw tools — the Brain calls them by name without knowing the source.

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-memory
Description: Persistent memory Paw for OpenVole — markdown-based long-term and daily memory
Latest version: 2.0.0

# @openvole/paw-memory

**Persistent memory with hybrid semantic + keyword search.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-memory)](https://www.npmjs.com/package/@openvole/paw-memory)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-memory
```

## Features

- **Hybrid search**: BM25 keyword + vector semantic similarity with Reciprocal Rank Fusion (RRF)
- **Auto-detects embedding provider**: Ollama (local, free), OpenAI, Gemini — zero config needed
- **Temporal decay**: Older memories score lower (configurable half-life, default 30 days)
- **Source isolation**: Memories scoped by task source (user, paw, heartbeat, schedule)
- **Disposable index**: Vector index is rebuilt from markdown files — delete `vectors.db` anytime
- **Graceful degradation**: Falls back to BM25-only when no embedding provider available
- **Auto-extraction**: Extracts key facts before compaction, tool patterns on observe

## Config

```json
{
  "name": "@openvole/paw-memory",
  "allow": {
    "network": ["*"],
    "env": ["VOLE_MEMORY_DIR", "VOLE_EMBEDDING_PROVIDER", "VOLE_EMBEDDING_MODEL",
            "OLLAMA_HOST", "OPENAI_API_KEY", "GEMINI_API_KEY"]
  }
}
```

## Environment Variables

| Variable | Description |
|----------|-------------|
| `VOLE_MEMORY_DIR` | Directory for storing memory files |
| `VOLE_EMBEDDING_PROVIDER` | Embedding provider: `ollama`, `openai`, `gemini` (auto-detected if not set) |
| `VOLE_EMBEDDING_MODEL` | Embedding model name (default: `nomic-embed-text` for Ollama, `text-embedding-3-small` for OpenAI) |
| `VOLE_EMBEDDING_DIMS` | Embedding dimensions (default: 768 for Ollama/Gemini, 1536 for OpenAI) |

## Tools

| Tool | Description |
|------|-------------|
| `memory_read` | Read a memory file (MEMORY.md or a daily log) |
| `memory_write` | Write or append to a memory file (auto-indexes for vector search) |
| `memory_search` | Hybrid search — semantic + keyword with RRF fusion. Falls back to BM25-only |
| `memory_list` | List all memory files with dates |

## Search Modes

- **Hybrid** (when embedding provider available): Combines BM25 keyword matching with vector cosine similarity. Results fused via RRF for best of both.
- **BM25-only** (fallback): Standard keyword-based ranked retrieval. Always available.

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-msteams
Description: Microsoft Teams channel Paw for OpenVole
Latest version: 2.0.0

# @openvole/paw-msteams

**Microsoft Teams bot channel for OpenVole.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-msteams)](https://www.npmjs.com/package/@openvole/paw-msteams)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-msteams
```

## Config

Add the paw to your `vole.config.json`:

```json
{
  "name": "@openvole/paw-msteams",
  "allow": {
    "network": ["login.microsoftonline.com", "smba.trafficmanager.net", "*.botframework.com"],
    "listen": [3978],
    "env": ["MSTEAMS_APP_ID", "MSTEAMS_APP_PASSWORD", "MSTEAMS_TENANT_ID", "MSTEAMS_PORT", "MSTEAMS_ALLOW_FROM"]
  }
}
```

## Environment Variables

| Variable | Required | Description |
|----------|----------|-------------|
| `MSTEAMS_APP_ID` | Yes | Microsoft App ID from Azure Bot registration |
| `MSTEAMS_APP_PASSWORD` | Yes | Client secret from Azure Bot registration |
| `MSTEAMS_TENANT_ID` | No | Azure AD tenant ID (for single-tenant bots) |
| `MSTEAMS_PORT` | No | HTTP server port (default: `3978`) |
| `MSTEAMS_ALLOW_FROM` | No | Comma-separated list of allowed user names/IDs |

## Azure Bot Registration

1. Go to the [Azure Portal](https://portal.azure.com) and create a new **Azure Bot** resource.
2. Under **Configuration**, note the **Microsoft App ID**.
3. Go to **Manage Password** and create a new **Client Secret** — this is your App Password.
4. Under **Channels**, add **Microsoft Teams** as a channel.
5. In your Teams admin center, allow sideloading or publish the bot to your organization.

## Setup

1. Set the required environment variables.
2. Start OpenVole with the paw enabled.
3. The bot listens on `http://localhost:3978/api/messages` for incoming Bot Framework messages.
4. Configure your Azure Bot's **Messaging Endpoint** to point to this URL (use a tunnel like ngrok for local development).

## Tools

| Tool | Description |
|------|-------------|
| `msteams_send` | Send a message to a specific Teams conversation |
| `msteams_reply` | Reply to the current Teams conversation |
| `msteams_get_conversations` | List active Teams conversations |

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-ollama
Description: [DEPRECATED — use @openvole/paw-brain] Brain Paw powered by Ollama for local LLM inference
Latest version: 2.0.0
Deprecated: Use @openvole/paw-brain instead. It supports all providers (Anthropic, OpenAI, Gemini, xAI, Ollama) in a single paw.

# @openvole/paw-ollama

**Brain Paw powered by Ollama for local LLM inference.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-ollama)](https://www.npmjs.com/package/@openvole/paw-ollama)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-ollama
```

## Config

```json
{
  "name": "@openvole/paw-ollama",
  "allow": {
    "network": ["127.0.0.1"],
    "env": ["OLLAMA_MODEL", "OLLAMA_HOST"]
  }
}
```

## Environment Variables

| Variable | Description |
|----------|-------------|
| `OLLAMA_MODEL` | Model name to use (e.g. `llama3`) |
| `OLLAMA_HOST` | Ollama server address (default `http://127.0.0.1:11434`) |

## Brain

Implements the Think phase — receives the conversation context and registered tools, returns the next assistant message and any tool calls. Uses a locally running Ollama instance.

## BRAIN.md

The system prompt is loaded from `.openvole/paws/paw-ollama/BRAIN.md`. On first startup, the paw scaffolds a default prompt there. Edit this file to customize how the Brain reasons and responds.

The old `.openvole/BRAIN.md` path is no longer used.

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-openai
Description: [DEPRECATED — use @openvole/paw-brain] Brain Paw powered by OpenAI
Latest version: 2.0.0
Deprecated: Use @openvole/paw-brain instead. It supports all providers (Anthropic, OpenAI, Gemini, xAI, Ollama) in a single paw.

# @openvole/paw-openai

**Brain Paw powered by OpenAI.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-openai)](https://www.npmjs.com/package/@openvole/paw-openai)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-openai
```

## Config

```json
{
  "name": "@openvole/paw-openai",
  "allow": {
    "network": ["api.openai.com"],
    "env": ["OPENAI_API_KEY", "OPENAI_MODEL"]
  }
}
```

## Environment Variables

| Variable | Description |
|----------|-------------|
| `OPENAI_API_KEY` | OpenAI API key |
| `OPENAI_MODEL` | Model to use (e.g. `gpt-4o`) |

## Brain

Implements the Think phase — receives the conversation context and registered tools, returns the next assistant message and any tool calls. Connects to the OpenAI API.

## BRAIN.md

The system prompt is loaded from `.openvole/paws/paw-openai/BRAIN.md`. On first startup, the paw scaffolds a default prompt there. Edit this file to customize how the Brain reasons and responds.

The old `.openvole/BRAIN.md` path is no longer used.

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-pdf
Description: PDF Paw for OpenVole — read, merge, split, extract text from PDFs
Latest version: 2.0.0

# @openvole/paw-pdf

**Read, merge, split, and extract text from PDFs.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-pdf)](https://www.npmjs.com/package/@openvole/paw-pdf)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-pdf
```

## Config

```json
{
  "name": "@openvole/paw-pdf",
  "allow": {
    "filesystem": ["./"]
  }
}
```

## Tools

| Tool | Description |
|------|-------------|
| `pdf_read` | Extract text from a PDF file. Supports page range selection |
| `pdf_info` | Get metadata: page count, title, author, creation date, file size |
| `pdf_merge` | Merge multiple PDFs into a single file |
| `pdf_split` | Extract specific pages into a new PDF |

## Dependencies

Uses [pdf-lib](https://pdf-lib.js.org/) — pure JavaScript, no native dependencies.

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-resend
Description: Email sending Paw powered by Resend
Latest version: 2.0.0

# @openvole/paw-resend

**Email sending Paw powered by Resend.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-resend)](https://www.npmjs.com/package/@openvole/paw-resend)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-resend
```

## Config

```json
{
  "name": "@openvole/paw-resend",
  "allow": {
    "network": ["api.resend.com"],
    "env": ["RESEND_API_KEY", "RESEND_FROM"]
  }
}
```

## Environment Variables

| Variable | Required | Description |
|----------|----------|-------------|
| `RESEND_API_KEY` | Yes | Resend API key (from https://resend.com) |
| `RESEND_FROM` | No | Default sender email (default: `onboarding@resend.dev`) |

## Tools

| Tool | Description |
|------|-------------|
| `resend_send` | Send a plain text email |
| `resend_send_html` | Send an HTML email |
| `resend_batch` | Send multiple emails in one batch |

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-scraper
Description: Web scraper Paw for OpenVole — extract structured data from web pages
Latest version: 2.0.0

# @openvole/paw-scraper

**Extract structured data from web pages.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-scraper)](https://www.npmjs.com/package/@openvole/paw-scraper)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-scraper
```

## Config

```json
{
  "name": "@openvole/paw-scraper",
  "allow": {
    "network": ["*"]
  }
}
```

## Tools

| Tool | Description |
|------|-------------|
| `scrape_page` | Fetch a URL and extract structured content: title, headings, text, links, metadata |
| `scrape_links` | Extract all links from a page with optional text filter |
| `scrape_tables` | Extract HTML tables as structured arrays (headers + rows) |
| `scrape_selector` | Extract content matching a CSS selector (text or attributes) |

## vs paw-browser

`paw-scraper` uses [cheerio](https://cheerio.js.org/) for fast HTML parsing — no browser needed. Use it when you just need to extract data from static HTML. Use `paw-browser` when you need JavaScript execution, clicking, or form interaction.

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-sdk
Description: SDK for building OpenVole Paws — tool providers for the agent loop
Latest version: 3.0.0

# @openvole/paw-sdk

SDK for building [OpenVole](https://github.com/openvole/openvole) Paws — tool providers for the agent loop.

[![npm](https://img.shields.io/npm/v/@openvole/paw-sdk)](https://www.npmjs.com/package/@openvole/paw-sdk)

## Install

```bash
npm install @openvole/paw-sdk
```

## Quick Start

```typescript
import { definePaw, z } from '@openvole/paw-sdk'

export default definePaw({
  name: 'my-paw',
  version: '0.1.0',
  description: 'My custom paw',

  tools: [
    {
      name: 'my_tool',
      description: 'Does something useful',
      parameters: z.object({ input: z.string() }),
      execute: async ({ input }) => ({ result: input.toUpperCase() }),
    },
  ],

  async onLoad() {
    console.log('Paw loaded')
  },
})
```

## What's a Paw?

A Paw connects OpenVole to the outside world. It runs in an isolated subprocess and registers tools that the Brain can call.

**Types of Paws:**
- **Brain** — implements the Think phase (e.g., paw-brain)
- **Channel** — receives messages from users (e.g., paw-telegram, paw-slack)
- **Tool** — provides capabilities (e.g., paw-browser, paw-shell)
- **Infrastructure** — internal services (e.g., paw-memory, paw-session)

## Hooks

```typescript
hooks: {
  onBootstrap: async (context) => context,  // once per task
  onPerceive: async (context) => context,   // before Think
  onObserve: async (result) => {},          // after each tool call
  onCompact: async (context) => context,    // when context too large
}
```

## Transport

Paws communicate with the core via JSON-RPC 2.0 over IPC. The SDK handles all wiring — just export `definePaw()`.

## License

[MIT](https://github.com/openvole/openvole/blob/main/LICENSE)
npm package: @openvole/paw-session
Description: Session management Paw for OpenVole — per-session transcript and metadata
Latest version: 2.0.0

# @openvole/paw-session

**Session and conversation management.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-session)](https://www.npmjs.com/package/@openvole/paw-session)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-session
```

## Config

```json
{
  "name": "@openvole/paw-session",
  "allow": {
    "env": ["VOLE_SESSION_DIR", "VOLE_SESSION_TTL"]
  }
}
```

## Environment Variables

| Variable | Description |
|----------|-------------|
| `VOLE_SESSION_DIR` | Directory for storing session data |
| `VOLE_SESSION_TTL` | Session time-to-live before expiry |

## Tools

| Tool | Description |
|------|-------------|
| `session_history` | Read conversation history for a session |
| `session_clear` | Clear a session's transcript and metadata |
| `session_list` | List all active sessions with their last activity time |

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-shell
Description: Paw for executing shell commands with safety restrictions
Latest version: 2.0.0

# @openvole/paw-shell

**Shell command execution with safety restrictions.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-shell)](https://www.npmjs.com/package/@openvole/paw-shell)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-shell
```

## Config

```json
{
  "name": "@openvole/paw-shell",
  "allow": {
    "filesystem": ["/app/workspace"],
    "env": ["VOLE_SHELL_ALLOWED_DIRS"]
  }
}
```

## Environment Variables

| Variable | Description |
|----------|-------------|
| `VOLE_SHELL_ALLOWED_DIRS` | Comma-separated list of directories the shell can access |

## Tools

| Tool | Description |
|------|-------------|
| `shell_exec` | Run a shell command synchronously and return its output |
| `shell_exec_background` | Run a shell command in the background and return a process ID |
| `shell_status` | Check the status of a background process by its process ID |
| `shell_kill` | Kill a background process by its process ID |

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-slack
Description: Slack messaging channel Paw for OpenVole
Latest version: 2.0.0

# @openvole/paw-slack

**Slack bot channel for OpenVole.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-slack)](https://www.npmjs.com/package/@openvole/paw-slack)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-slack
```

## Config

```json
{
  "name": "@openvole/paw-slack",
  "allow": {
    "network": ["slack.com"],
    "listen": [3002],
    "env": ["SLACK_BOT_TOKEN", "SLACK_SIGNING_SECRET", "SLACK_APP_TOKEN", "SLACK_ALLOW_FROM"]
  }
}
```

## Environment Variables

| Variable | Description |
|----------|-------------|
| `SLACK_BOT_TOKEN` | Slack Bot User OAuth token |
| `SLACK_SIGNING_SECRET` | Slack app signing secret |
| `SLACK_APP_TOKEN` | Slack app-level token for Socket Mode |
| `SLACK_ALLOW_FROM` | Comma-separated list of allowed channel IDs |

## Tools

| Tool | Description |
|------|-------------|
| `slack_send` | Send a message to a Slack channel |
| `slack_reply` | Reply in a Slack thread |
| `slack_get_channel` | Get information about a Slack channel |

Connects to Slack as a bot, forwarding incoming messages to the agent and exposing tools for sending replies.

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-social
Description: Social media Paw for OpenVole — post to Twitter/X and LinkedIn
Latest version: 2.0.0

# @openvole/paw-social

**Post to Twitter/X and LinkedIn.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-social)](https://www.npmjs.com/package/@openvole/paw-social)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-social
```

## Config

```json
{
  "name": "@openvole/paw-social",
  "allow": {
    "network": ["api.twitter.com", "api.x.com", "api.linkedin.com"],
    "env": ["TWITTER_BEARER_TOKEN", "TWITTER_API_KEY", "TWITTER_API_SECRET",
            "TWITTER_ACCESS_TOKEN", "TWITTER_ACCESS_SECRET", "LINKEDIN_ACCESS_TOKEN"]
  }
}
```

## Environment Variables

### Twitter/X

| Variable | Description |
|----------|-------------|
| `TWITTER_BEARER_TOKEN` | For search (read-only) |
| `TWITTER_API_KEY` | OAuth 1.0a consumer key (for posting) |
| `TWITTER_API_SECRET` | OAuth 1.0a consumer secret |
| `TWITTER_ACCESS_TOKEN` | OAuth 1.0a access token |
| `TWITTER_ACCESS_SECRET` | OAuth 1.0a access secret |

### LinkedIn

| Variable | Description |
|----------|-------------|
| `LINKEDIN_ACCESS_TOKEN` | OAuth token with `w_member_social` scope |

## Tools

| Tool | Description |
|------|-------------|
| `twitter_post` | Post a tweet (max 280 chars). Supports reply threading |
| `twitter_search` | Search recent tweets with public metrics |
| `linkedin_post` | Post to LinkedIn feed |

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-stt
Description: Speech-to-text tool Paw for OpenVole — transcribe audio with OpenAI Whisper
Latest version: 2.0.0

# @openvole/paw-stt

**Speech-to-text tool for OpenVole using the OpenAI Whisper API.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-stt)](https://www.npmjs.com/package/@openvole/paw-stt)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-stt
```

## Config

```json
{
  "name": "@openvole/paw-stt",
  "allow": {
    "network": ["api.openai.com"],
    "env": ["OPENAI_API_KEY", "OPENAI_STT_MODEL"]
  }
}
```

## Environment Variables

| Variable | Required | Description |
|----------|----------|-------------|
| `OPENAI_API_KEY` | Yes | OpenAI API key for Whisper access |
| `OPENAI_STT_MODEL` | No | Whisper model to use (default: `whisper-1`) |

## Tool

### `stt_transcribe`

Transcribe an audio file to text using OpenAI Whisper.

**Parameters:**

- `file_path` (string, required) — Absolute path to the audio file.
- `language` (string, optional) — ISO-639-1 language code (e.g. `"en"`, `"fr"`). Whisper auto-detects if omitted.

**Supported formats:** mp3, wav, m4a, webm, mp4, mpeg, mpga, oga, ogg, flac.

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-telegram
Description: Telegram messaging channel Paw for OpenVole
Latest version: 2.1.0

# @openvole/paw-telegram

**Telegram bot channel for OpenVole.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-telegram)](https://www.npmjs.com/package/@openvole/paw-telegram)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-telegram
```

## Config

```json
{
  "name": "@openvole/paw-telegram",
  "allow": {
    "network": ["api.telegram.org"],
    "env": ["TELEGRAM_BOT_TOKEN", "TELEGRAM_ALLOW_FROM"]
  }
}
```

## Environment Variables

| Variable | Description |
|----------|-------------|
| `TELEGRAM_BOT_TOKEN` | Telegram Bot API token from @BotFather |
| `TELEGRAM_ALLOW_FROM` | Comma-separated list of allowed chat IDs |

## Tools

| Tool | Description |
|------|-------------|
| `telegram_send` | Send a message to a Telegram chat |
| `telegram_reply` | Reply to a specific message in a Telegram chat |
| `telegram_get_chat` | Get information about a Telegram chat |

Connects to Telegram as a bot, forwarding incoming messages to the agent and exposing tools for sending replies.

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-tts
Description: Text-to-speech tool Paw for OpenVole — ElevenLabs and OpenAI TTS providers
Latest version: 2.0.0

# @openvole/paw-tts

**Text-to-speech tool for OpenVole with multi-provider support (ElevenLabs and OpenAI).**

[![npm](https://img.shields.io/npm/v/@openvole/paw-tts)](https://www.npmjs.com/package/@openvole/paw-tts)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-tts
```

## Config

### ElevenLabs (default)

```json
{
  "name": "@openvole/paw-tts",
  "allow": {
    "network": ["api.elevenlabs.io"],
    "env": ["VOLE_TTS_PROVIDER", "ELEVENLABS_API_KEY", "ELEVENLABS_VOICE_ID"]
  }
}
```

### OpenAI

```json
{
  "name": "@openvole/paw-tts",
  "allow": {
    "network": ["api.openai.com"],
    "env": ["VOLE_TTS_PROVIDER", "OPENAI_API_KEY", "OPENAI_TTS_MODEL", "OPENAI_TTS_VOICE"]
  }
}
```

## Environment Variables

| Variable | Required | Description |
|----------|----------|-------------|
| `VOLE_TTS_PROVIDER` | No | TTS provider to use: `elevenlabs` (default) or `openai` |
| `ELEVENLABS_API_KEY` | Yes (ElevenLabs) | ElevenLabs API key |
| `ELEVENLABS_VOICE_ID` | No | Default ElevenLabs voice ID (default: `21m00Tcm4TlvDq8ikWAM`) |
| `OPENAI_API_KEY` | Yes (OpenAI) | OpenAI API key |
| `OPENAI_TTS_MODEL` | No | OpenAI TTS model: `tts-1` (default) or `tts-1-hd` |
| `OPENAI_TTS_VOICE` | No | Default OpenAI voice (default: `alloy`) |

## Tools

### `tts_speak`

Convert text to speech and save as an audio file.

- **text** (string, required) — The text to convert to speech
- **voice** (string, optional) — Voice ID (provider-specific)
- **output_format** (enum: `mp3` | `wav` | `pcm`, default: `mp3`) — Audio format

Audio files are saved to `.openvole/workspace/audio/`.

### `tts_list_voices`

List available voices for the active TTS provider.

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)
npm package: @openvole/paw-voice-call
Description: Voice call channel Paw for OpenVole — Twilio voice conversations
Latest version: 2.0.0

# @openvole/paw-voice-call

**Voice call channel for OpenVole — inbound and outbound calls via Twilio with real-time STT/TTS.**

[![npm](https://img.shields.io/npm/v/@openvole/paw-voice-call)](https://www.npmjs.com/package/@openvole/paw-voice-call)

Part of [OpenVole](https://github.com/openvole/openvole) — the microkernel AI agent framework.

## Install

```bash
npm install @openvole/paw-voice-call
```

## Config

Add the paw to your `vole.config.json`:

```json
{
  "name": "@openvole/paw-voice-call",
  "allow": {
    "network": ["api.twilio.com", "*.twilio.com"],
    "listen": [3979],
    "env": ["TWILIO_ACCOUNT_SID", "TWILIO_AUTH_TOKEN", "TWILIO_PHONE_NUMBER", "VOICE_CALL_WEBHOOK_URL", "VOICE_CALL_PORT"]
  }
}
```

## Environment Variables

| Variable | Required | Description |
|----------|----------|-------------|
| `TWILIO_ACCOUNT_SID` | Yes | Your Twilio Account SID |
| `TWILIO_AUTH_TOKEN` | Yes | Your Twilio Auth Token |
| `TWILIO_PHONE_NUMBER` | Yes | Your Twilio phone number in E.164 format (e.g. `+14155551234`) |
| `VOICE_CALL_WEBHOOK_URL` | Yes | Public URL where Twilio can reach the webhook server |
| `VOICE_CALL_PORT` | No | Local port for the webhook server (default: `3979`) |

## Twilio Account Setup

1. Create a [Twilio account](https://www.twilio.com/try-twilio)
2. Purchase a phone number with Voice capabilities
3. Note your Account SID and Auth Token from the Twilio Console
4. Configure your phone number's Voice webhook to point to your server (see Webhook Setup below)

## Call Flow

1. **Inbound call** arrives at Twilio, which hits `POST /voice/inbound`
2. Server responds with TwiML greeting + `<Gather>` to collect speech
3. Caller speaks — Twilio's built-in STT transcribes and sends to `POST /voice/gather`
4. Paw creates a task with the transcription, responds with TwiML redirect to `/voice/respond/<taskId>`
5. The respond endpoint holds the connection (long-poll, max 25s) waiting for the brain's response
6. When the task completes, TwiML with `<Say>` delivers the response + `<Gather>` continues the conversation
7. Loop back to step 3

Outbound calls follow the same flow after initial connection via the `initiate_call` tool.

## Webhook Setup

### Development (ngrok)

```bash
ngrok http 3979
```

Set `VOICE_CALL_WEBHOOK_URL` to your ngrok URL (e.g. `https://abc123.ngrok-free.app`).

In your Twilio Console, configure your phone number's Voice webhook:
- **A call comes in**: Webhook, `https://abc123.ngrok-free.app/voice/inbound`, HTTP POST

### Production

Point `VOICE_CALL_WEBHOOK_URL` to your production server's public URL and configure the Twilio webhook accordingly.

## License

[MIT](https://github.com/openvole/pawhub/blob/main/LICENSE)