Claude
Skills
Sign in
Back

phantom-ai-coworker

Included with Lifetime
$97 forever

AI co-worker agent with its own computer, persistent memory, self-evolution, MCP server, and Slack/email identity built on Claude Agent SDK

Backend & APIs

What this skill does


# Phantom AI Co-worker

> Skill by [ara.so](https://ara.so) — Daily 2026 Skills collection.

Phantom is an AI co-worker that runs on its own dedicated machine. Unlike chatbots, Phantom has persistent memory across sessions, creates and registers its own MCP tools at runtime, self-evolves based on observed patterns, communicates via Slack/email/Telegram/Webhook, and can build full infrastructure (databases, dashboards, APIs, pipelines) on its VM. Built on the Claude Agent SDK with TypeScript/Bun.

## Architecture Overview

```
┌─────────────────────────────────────────────────────┐
│                   Phantom Agent                     │
│  ┌──────────┐  ┌──────────┐  ┌───────────────────┐ │
│  │  Claude  │  │ Qdrant   │  │   MCP Server      │ │
│  │  Agent   │  │ (memory) │  │ (dynamic tools)   │ │
│  │   SDK    │  │          │  │                   │ │
│  └──────────┘  └──────────┘  └───────────────────┘ │
│  ┌──────────────────────────────────────────────┐   │
│  │         Channels                             │   │
│  │  Slack │ Email │ Telegram │ Webhook │ Discord │   │
│  └──────────────────────────────────────────────┘   │
│  ┌──────────────────────────────────────────────┐   │
│  │         Self-Evolution Engine                │   │
│  │  observe → reflect → propose → validate → evolve│
│  └──────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────┘
```

## Installation

### Docker (Recommended)

```bash
# Download compose file and env template
curl -fsSL https://raw.githubusercontent.com/ghostwright/phantom/main/docker-compose.user.yaml -o docker-compose.yaml
curl -fsSL https://raw.githubusercontent.com/ghostwright/phantom/main/.env.example -o .env

# Edit .env with your credentials (see Configuration section)
nano .env

# Start Phantom (includes Qdrant + Ollama)
docker compose up -d

# Check health
curl http://localhost:3100/health

# View logs
docker compose logs -f phantom
```

### From Source (Bun)

```bash
git clone https://github.com/ghostwright/phantom.git
cd phantom

# Install dependencies
bun install

# Copy env
cp .env.example .env
# Edit .env

# Start Qdrant (required for memory)
docker run -d -p 6333:6333 qdrant/qdrant

# Start Phantom
bun run start

# Development mode with hot reload
bun run dev
```

## Configuration (.env)

```bash
# === Required ===
ANTHROPIC_API_KEY=                  # Your Anthropic API key

# === Slack (required for Slack channel) ===
SLACK_BOT_TOKEN=xoxb-              # Bot OAuth token
SLACK_APP_TOKEN=xapp-              # App-level token (socket mode)
SLACK_SIGNING_SECRET=              # Signing secret
OWNER_SLACK_USER_ID=U0XXXXXXXXX    # Your Slack user ID

# === Memory (Qdrant) ===
QDRANT_URL=http://localhost:6333    # Qdrant vector DB URL
QDRANT_API_KEY=                    # Optional, for cloud Qdrant
OLLAMA_URL=http://localhost:11434   # Ollama for embeddings

# === Email (optional) ===
RESEND_API_KEY=                    # For email sending via Resend
PHANTOM_EMAIL=phantom@yourdomain   # Phantom's email address

# === Telegram (optional) ===
TELEGRAM_BOT_TOKEN=                # BotFather token

# === Infrastructure ===
PHANTOM_VM_DOMAIN=                 # Public domain for served assets
PHANTOM_PORT=3100                  # HTTP port (default 3100)

# === Self-Evolution ===
EVOLUTION_VALIDATION_MODEL=claude-3-5-sonnet-20241022  # Separate model for validation
EVOLUTION_ENABLED=true

# === Credentials Vault ===
CREDENTIAL_ENCRYPTION_KEY=         # AES-256-GCM key (auto-generated if empty)
```

## Key Commands

```bash
# Docker operations
docker compose up -d               # Start all services
docker compose down                # Stop all services
docker compose logs -f phantom     # Stream logs
docker compose pull                # Update to latest image

# Bun development
bun run start                      # Production start
bun run dev                        # Dev mode with watch
bun run test                       # Run test suite
bun run build                      # Build TypeScript

# Health checks
curl http://localhost:3100/health
curl http://localhost:3100/status

# MCP server endpoint
curl http://localhost:3100/mcp
```

## Core Concepts & Code Examples

### 1. Memory System (Qdrant + Embeddings)

Phantom stores memories as vector embeddings for semantic recall across sessions.

```typescript
// src/memory/memory-manager.ts pattern
import { QdrantClient } from '@qdrant/js-client-rest';

const client = new QdrantClient({ url: process.env.QDRANT_URL });

// Storing a memory
async function storeMemory(content: string, metadata: Record<string, unknown>) {
  const embedding = await generateEmbedding(content); // via Ollama
  await client.upsert('phantom_memory', {
    points: [{
      id: crypto.randomUUID(),
      vector: embedding,
      payload: {
        content,
        timestamp: Date.now(),
        ...metadata,
      },
    }],
  });
}

// Recalling relevant memories
async function recallMemories(query: string, limit = 5) {
  const queryEmbedding = await generateEmbedding(query);
  const results = await client.search('phantom_memory', {
    vector: queryEmbedding,
    limit,
    with_payload: true,
  });
  return results.map(r => r.payload?.content);
}
```

### 2. Dynamic MCP Tool Registration

Phantom creates MCP tools at runtime that persist across restarts.

```typescript
// Pattern: registering a dynamically created tool
interface PhantomTool {
  name: string;
  description: string;
  inputSchema: Record<string, unknown>;
  handler: string; // serialized or endpoint URL
}

// Phantom internally registers tools like this
async function registerDynamicTool(tool: PhantomTool) {
  // Store tool definition in persistent storage
  await storeMemory(JSON.stringify(tool), {
    type: 'mcp_tool',
    toolName: tool.name,
  });

  // Register with MCP server at runtime
  mcpServer.tool(tool.name, tool.description, tool.inputSchema, async (args) => {
    return await executeToolHandler(tool.handler, args);
  });
}

// MCP server setup (how Phantom exposes tools to Claude Code)
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';

const mcpServer = new McpServer({
  name: 'phantom',
  version: '0.18.1',
});

// Connect Claude Code to Phantom's MCP server:
// In claude_desktop_config.json or .cursor/mcp.json:
// {
//   "mcpServers": {
//     "phantom": {
//       "url": "http://your-phantom-vm:3100/mcp"
//     }
//   }
// }
```

### 3. Slack Channel Integration

```typescript
// How Phantom handles Slack messages
import { App } from '@slack/bolt';

const slack = new App({
  token: process.env.SLACK_BOT_TOKEN,
  appToken: process.env.SLACK_APP_TOKEN,
  socketMode: true,
  signingSecret: process.env.SLACK_SIGNING_SECRET,
});

// Phantom listens for direct messages and mentions
slack.event('message', async ({ event, say }) => {
  if (event.subtype) return; // Skip bot messages, edits

  const userMessage = (event as any).text;
  const userId = (event as any).user;

  // Recall relevant context from memory
  const memories = await recallMemories(userMessage);

  // Run Claude agent with memory context
  const response = await runPhantomAgent({
    message: userMessage,
    userId,
    memories,
    channel: (event as any).channel,
  });

  await say({ text: response, thread_ts: (event as any).ts });
});

// Phantom DMs you when ready
async function notifyOwnerReady() {
  await slack.client.chat.postMessage({
    channel: process.env.OWNER_SLACK_USER_ID!,
    text: "👻 Phantom is online and ready.",
  });
}
```

### 4. Claude Agent SDK Integration

```typescript
// Core agent loop using Anthropic Agent SDK
import Anthropic from '@anthropic-ai/sdk';

const anthropic = new Anthropic({
  apiKey: process.env.ANTHROPIC_API_KEY,
});

async function runPhantomAgent({
  message,
  userId,
  memories,
  channel,
}: PhantomAgentInput) {
  const systemPrompt = buildSystemPrompt(memories);

  // Agentic loop with tool use
  const response = await anthropic.messa

Related in Backend & APIs