Application-specific AI avatar runtime with configurable behavior, context-aware reasoning, and MCP tool orchestration
Project description
Application-specific AI avatar runtime with configurable behavior,
context-aware reasoning, and MCP-powered task execution.
Avatar Engine is designed for embedding a dedicated AI avatar into a specific application domain, not as a generic chatbot wrapper.
- Application-defined behavior — Your app controls avatar behavior through explicit configuration (model, prompts, permissions, tool policy, safety limits).
- Application-provided context — Your app supplies domain context and source data so the avatar can reason over real project information.
- MCP for complex operations — For tasks that are hard to encode as deterministic algorithms, the avatar can call MCP tools to inspect data, run analyses, and assist with larger changes.
- Provider abstraction as infrastructure — Gemini CLI, Claude Code, and Codex CLI support is an implementation layer that enables the avatar runtime, not the product goal itself.
Packages
Avatar Engine is a monorepo with a Python backend and npm frontend packages:
| Package | Description |
|---|---|
avatar-engine |
Python backend — AI engine, CLI, web server, provider bridges |
@avatar-engine/core |
TypeScript — framework-agnostic types, WebSocket protocol, client class |
@avatar-engine/react |
React — components, hooks, Tailwind preset, CSS styles |
Features
Backend (Python)
- Three Providers — Gemini CLI, Claude Code, Codex CLI — unified API
- Warm Sessions — ACP / stream-json persistent subprocess for instant responses
- Session Management — Resume, continue, and list sessions across all providers
- Event System — Callbacks for text, tools, thinking, diagnostics, state changes
- MCP Orchestration — Tool-based execution with configurable MCP servers
- Provider Capabilities — Runtime feature detection (thinking, cost tracking, MCP)
- Safety System — Three-mode safety (Safe / Ask / Unrestricted) with ACP permission routing
- Budget Control — Pre-request budget enforcement with cost tracking
- Zero Footprint — No config files written to your project directory
- CLI — Rich terminal interface with thinking spinner, tool panels, session management
- Web Server — FastAPI + WebSocket for real-time frontend integration
- Production Ready — Rate limiting, metrics, auto-restart, graceful shutdown
Frontend (TypeScript / React)
AvatarClient— Framework-agnostic WebSocket client with auto-reconnect- State Machine — Pure reducer for predictable state management
useAvatarChat— React hook for complete chat orchestration- 23 Components — Chat UI, provider selector, session panel, avatar bust, safety controls
- Tailwind Preset — Dark glassmorphism theme with customizable accent colors
- CSS Custom Properties — Runtime theming without rebuilds
- i18n — English and Czech translations (extensible)
Quick Start
Python Library
from avatar_engine import AvatarEngine
engine = AvatarEngine(provider="gemini")
engine.start_sync()
response = engine.chat_sync("Hello!")
print(response.content)
engine.stop_sync()
CLI
avatar chat "What is 2+2?"
avatar chat -p claude "Write a haiku"
avatar repl # Interactive REPL
avatar health --check-cli # Check installed providers
avatar session list # List sessions
React Frontend
npm install @avatar-engine/react
import { useAvatarChat, AvatarWidget } from '@avatar-engine/react'
import '@avatar-engine/react/styles.css'
function App() {
const chat = useAvatarChat('ws://localhost:8420/api/avatar/ws')
return <AvatarWidget {...chat} />
}
Non-React Frontend (Vue, Svelte, vanilla)
npm install @avatar-engine/core
import { AvatarClient } from '@avatar-engine/core'
const client = new AvatarClient('ws://localhost:8420/api/avatar/ws', {
onStateChange: (state) => console.log(state.engineState),
onMessage: (msg) => {
if (msg.type === 'text') process.stdout.write(msg.data.text)
},
})
client.connect()
client.sendChat('Hello!')
Web Demo
./install.sh --web # Install dependencies
./scripts/start-web.sh # Start backend + frontend dev servers
# Open http://localhost:5173
Installation
Python Backend
# Interactive installer (recommended)
./install.sh # Choose providers, optionally install web demo
./install.sh --all # Install everything
# Or manual with uv
uv sync --extra cli # Core + CLI
uv sync --extra cli --extra web # Core + CLI + Web server
Prerequisites
Install only the providers you need. All use account-based authentication (Pro/Max subscriptions, no API keys):
# Gemini CLI (Google account)
sudo npm install -g @google/gemini-cli
# Claude Code (Anthropic Pro / Max)
sudo npm install -g @anthropic-ai/claude-code
# Codex CLI (ChatGPT Plus / Pro)
sudo npm install -g @openai/codex
Architecture
avatar-engine/
├── avatar_engine/ # Python backend
│ ├── engine.py # AvatarEngine — main API
│ ├── bridges/ # Provider implementations
│ │ ├── gemini.py # Gemini CLI (ACP warm session)
│ │ ├── claude.py # Claude Code (stream-json)
│ │ └── codex.py # Codex CLI (ACP via codex-acp)
│ ├── events.py # Event system
│ ├── web/ # FastAPI + WebSocket server
│ └── cli/ # Rich CLI (click)
├── packages/
│ ├── core/ # @avatar-engine/core (npm)
│ │ └── src/
│ │ ├── types.ts # TypeScript types (mirrors Python events)
│ │ ├── protocol.ts # State machine (reducer + parser)
│ │ ├── client.ts # AvatarClient (WS client)
│ │ └── config/ # Provider & avatar configuration
│ └── react/ # @avatar-engine/react (npm)
│ └── src/
│ ├── hooks/ # useAvatarChat, useWidgetMode, ...
│ ├── components/ # 23 React components
│ ├── styles/ # Glassmorphism CSS
│ └── tailwind-preset.js
├── examples/
│ └── web-demo/ # Demo app (imports from @avatar-engine/react)
└── tests/ # 1200+ tests (Python + TypeScript)
Communication Flow
Browser (React) Python Backend (FastAPI)
┌─────────────────────┐ ┌──────────────────────────┐
│ useAvatarChat │◄──WS───► │ /api/avatar/ws │
│ (or AvatarClient) │ │ WebSocketBridge │
│ │ REST │ ├─ on(TextEvent) │
│ Components: │◄────────► │ ├─ on(ThinkingEvent) │
│ ├─ AvatarWidget │ │ ├─ on(ToolEvent) │
│ ├─ ChatPanel │ │ └─ on(CostEvent) │
│ ├─ MessageBubble │ │ │
│ └─ ... │ │ AvatarEngine │
└─────────────────────┘ │ └─ GeminiBridge │
│ └─ ClaudeBridge │
│ └─ CodexBridge │
└──────────────────────────┘
Embedding in Your Application
Python: FastAPI mount
from avatar_engine.web.server import create_api_app
# Mount avatar API into your existing FastAPI app
avatar_app = create_api_app(provider="gemini")
app.mount("/api/avatar", avatar_app)
Python: Standalone server
avatar-web --port 8420 --provider gemini
Frontend: Vite proxy
// vite.config.ts
export default defineConfig({
server: {
proxy: {
'/api/avatar': { target: 'http://localhost:8420', ws: true },
},
},
})
Configuration
YAML Config File
provider: "gemini"
gemini:
model: ""
approval_mode: "yolo"
acp_enabled: true
mcp_servers:
tools:
command: "python"
args: ["mcp_server.py"]
claude:
model: "claude-sonnet-4-5"
permission_mode: "acceptEdits"
cost_control:
max_turns: 10
max_budget_usd: 5.0
codex:
model: ""
auth_method: "chatgpt"
approval_mode: "auto"
engine:
auto_restart: true
max_restarts: 3
Programmatic Config
engine = AvatarEngine(
provider="claude",
model="claude-sonnet-4-5",
timeout=120,
system_prompt="You are a helpful assistant.",
mcp_servers={"tools": {"command": "python", "args": ["server.py"]}},
)
Event-Driven Integration
from avatar_engine import AvatarEngine
from avatar_engine.events import TextEvent, ToolEvent, ThinkingEvent
engine = AvatarEngine(provider="gemini")
@engine.on(TextEvent)
def on_text(event):
gui.update_speech_bubble(event.text)
@engine.on(ToolEvent)
def on_tool(event):
gui.show_tool_status(event.tool_name, event.status)
@engine.on(ThinkingEvent)
def on_thinking(event):
gui.animate_avatar(event.phase.value)
engine.start_sync()
response = engine.chat_sync("Analyze this project")
WebSocket Protocol
Connect to ws://localhost:8420/api/avatar/ws for real-time streaming.
Server → Client:
| Type | Description |
|---|---|
connected |
Session info on connect |
text |
Text chunk from AI |
thinking |
AI thinking phase + subject |
tool |
Tool execution status |
cost |
Usage/cost update |
error |
Error occurred |
engine_state |
Engine state change |
chat_response |
Complete response |
permission_request |
ACP permission request |
Client → Server:
| Type | Description |
|---|---|
chat |
{"type": "chat", "data": {"message": "..."}} |
stop |
Cancel current request |
switch |
Switch provider/model |
permission_response |
Respond to permission request |
REST API
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/avatar/health |
Health check |
| GET | /api/avatar/capabilities |
Provider capabilities |
| GET | /api/avatar/sessions |
List sessions |
| GET | /api/avatar/providers |
Available providers |
| POST | /api/avatar/chat |
Non-streaming chat |
| POST | /api/avatar/upload |
File upload |
API Reference
Python: AvatarEngine
class AvatarEngine:
# Lifecycle
async def start() -> None
async def stop() -> None
def start_sync() / def stop_sync()
# Chat
async def chat(message: str) -> BridgeResponse
async def chat_stream(message: str) -> AsyncIterator[str]
def chat_sync(message: str) -> BridgeResponse
# Sessions
async def list_sessions() -> list[SessionInfo]
async def resume_session(session_id: str) -> bool
session_capabilities: SessionCapabilitiesInfo
# Events
def on(event_type) -> Callable # Decorator
capabilities: ProviderCapabilities # Runtime feature flags
TypeScript: AvatarClient
class AvatarClient {
connect(): void
disconnect(): void
getState(): Readonly<AvatarState>
sendChat(text: string, attachments?: ChatAttachment[]): void
stop(): void
switchProvider(provider: string, model?: string, options?: Record<string, unknown>): void
resumeSession(sessionId: string): void
clearHistory(): void
}
React: useAvatarChat
const {
messages, // ChatMessage[]
sendMessage, // (text, attachments?) => void
isStreaming, // boolean
connected, // boolean
provider, // string
model, // string | null
thinking, // { active, phase, subject }
cost, // { totalCostUsd, totalInputTokens, totalOutputTokens }
switchProvider, // (provider, model?, options?) => void
permissionRequest, // PermissionRequest | null
error, // string | null
} = useAvatarChat(wsUrl, options?)
Testing
# Python tests (1036 tests)
uv run pytest tests/ -x -q --timeout=30
# TypeScript tests (204 tests)
npm test -w packages/core
npm test -w examples/web-demo
# Integration tests (with real providers)
uv run pytest tests/integration/ -m gemini -v
uv run pytest tests/integration/ -m claude -v
uv run pytest tests/integration/ -m codex -v
# Lint
uv run ruff check avatar_engine/
License
Apache License 2.0 — see LICENSE.
Legal Notice
This project is a wrapper that communicates with external AI CLI tools via their documented interfaces. It does not include or redistribute code from these tools.
User Responsibilities:
- Install external tools separately (
gemini,claude,codex-acp) - Accept terms of service for each provider
- Authenticate with your account (Google / Anthropic / OpenAI-ChatGPT)
External Tools:
- Gemini CLI — Apache 2.0
- Claude Code — Anthropic Terms
- Codex CLI — Apache 2.0
- codex-acp — ACP wrapper for Codex
- ACP SDK — Apache 2.0
Author
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file avatar_engine-1.2.0.tar.gz.
File metadata
- Download URL: avatar_engine-1.2.0.tar.gz
- Upload date:
- Size: 5.6 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
017cca3799f2939790032a0507d5a3e591de3405c29d8384113f5e7d47a0adca
|
|
| MD5 |
dc1c9a2943bce8d13a7a375f399d3ef6
|
|
| BLAKE2b-256 |
23d9ef722df51e69658860e659ab4a25d1e9ec2e2e9187e5ff1018479742ae43
|
Provenance
The following attestation bundles were made for avatar_engine-1.2.0.tar.gz:
Publisher:
publish.yml on raven2cz/avatar-engine
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
avatar_engine-1.2.0.tar.gz -
Subject digest:
017cca3799f2939790032a0507d5a3e591de3405c29d8384113f5e7d47a0adca - Sigstore transparency entry: 1009355521
- Sigstore integration time:
-
Permalink:
raven2cz/avatar-engine@2220f56b1636262c7c5c9d496d9487ddf75ad441 -
Branch / Tag:
refs/tags/v1.2.0 - Owner: https://github.com/raven2cz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2220f56b1636262c7c5c9d496d9487ddf75ad441 -
Trigger Event:
push
-
Statement type:
File details
Details for the file avatar_engine-1.2.0-py3-none-any.whl.
File metadata
- Download URL: avatar_engine-1.2.0-py3-none-any.whl
- Upload date:
- Size: 140.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3ae2196a96cc9ca4563629624e6a73e7d954dbbee749cb14f2b8f4b89420dfa0
|
|
| MD5 |
4a4b1ea7bac82c2a2e9a35d5c655981e
|
|
| BLAKE2b-256 |
6e2809e1cd9d0f37444e4e6afa76dccc153ca6e48a5ae3f2fbb1decf262bf536
|
Provenance
The following attestation bundles were made for avatar_engine-1.2.0-py3-none-any.whl:
Publisher:
publish.yml on raven2cz/avatar-engine
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
avatar_engine-1.2.0-py3-none-any.whl -
Subject digest:
3ae2196a96cc9ca4563629624e6a73e7d954dbbee749cb14f2b8f4b89420dfa0 - Sigstore transparency entry: 1009355528
- Sigstore integration time:
-
Permalink:
raven2cz/avatar-engine@2220f56b1636262c7c5c9d496d9487ddf75ad441 -
Branch / Tag:
refs/tags/v1.2.0 - Owner: https://github.com/raven2cz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2220f56b1636262c7c5c9d496d9487ddf75ad441 -
Trigger Event:
push
-
Statement type: