epsimo-agent

📁 thierryteisseire/epsimo-agent 📅 Jan 24, 2026
0
总安装量
5
周安装量
安装命令
npx skills add https://github.com/thierryteisseire/epsimo-agent --skill epsimo-agent

Agent 安装分布

opencode 5
antigravity 5
codex 5
github-copilot 4
claude-code 3

Skill 文档

Epsimo Agent Framework

[!NOTE] This is a Beta Release (v0.2.0). Features and APIs may evolve based on feedback.

The Epsimo Agent Framework allows you to build sophisticated AI-powered applications with agents, persistent threads, and a “Virtual Database” state layer. It provides a unified CLI, a Python SDK, and a React UI Kit.

Base URL: https://api.epsimoagents.com
Frontend URL: https://app.epsimoagents.com


🚀 Quick Start: Create an MVP in 3 Commands

The fastest way to build an Epsimo app is using the project generator:

# 1. Authenticate
epsimo auth login

# 2. Create a new Next.js project
epsimo create "My AI App"

# 3. Initialize and Deploy
cd my-ai-app
epsimo init
epsimo deploy

Your AI app is now live with persistent conversations, Virtual Database state, and a pre-built chat UI.


📦 Installation

CLI & Python SDK

# Install dependencies
pip install -r requirements.txt

# Make CLI executable (if using from source)
chmod +x epsimo/cli.py
export PATH="$PATH:$(pwd)/epsimo"

# Or via npm (for Claude Code skills)
npm install -g epsimo-agent

Dependencies:

  • requests>=2.28.0
  • pyyaml>=6.0
  • click>=8.0.0
  • python-dotenv>=0.19.0

🔐 Authentication

Login Flow

# Interactive login
epsimo auth login

# Login with environment variables
export EPSIMO_EMAIL=your@email.com
export EPSIMO_PASSWORD=your-password
epsimo auth login

Programmatic Authentication

from epsimo.auth import perform_login, get_token

# Login and get token
token = perform_login("your@email.com", "password")

# Get cached token (auto-refreshes if expired)
token = get_token()

Token Management

Tokens are stored in ~/code/epsimo-frontend/.epsimo_token and expire after 1 hour.

Token Storage Format:

{
  "access_token": "eyJhbG...",
  "token": "eyJhbG...",
  "jwt_token": "eyJhbG...",
  "expires_in": 3600
}

Best Practices:

  • ✅ Use environment variables (EPSIMO_API_KEY) for production
  • ✅ Never commit .epsimo_token to version control
  • ✅ Implement token refresh on 401 errors
  • ✅ Use project-specific tokens for multi-tenant apps

🛠️ Unified CLI (epsimo)

The epsimo CLI is the main tool for managing your agents and data.

Authentication Commands

Command Description
epsimo auth login Interactive login with email/password
epsimo whoami Display current user info and thread usage

Example:

$ epsimo whoami
👤 Fetching user info...
Logged in as: user@example.com
Threads Used: 45/100

Project Management

Command Description
epsimo projects List all projects
epsimo projects --json List projects in JSON format
epsimo create <name> Scaffold a full Next.js application with Epsimo
epsimo init Link a local directory to an Epsimo project
epsimo deploy Sync your epsimo.yaml configuration to the platform

Example:

$ epsimo projects
📁 Fetching projects...
ID                                      | Name
-----------------------------------------------------------------
proj_abc123                             | Customer Support Bot
proj_xyz789                             | Research Assistant

Virtual Database Commands

Threads can serve as a persistent structured storage layer.

Command Description
epsimo db query --project-id <P_ID> --thread-id <T_ID> View all structured thread state
epsimo db get --project-id <P_ID> --thread-id <T_ID> --key <K> Get specific key from thread state
epsimo db set --project-id <P_ID> --thread-id <T_ID> --key <K> --value <V> Seed state for testing

Example:

$ epsimo db query --project-id proj_abc --thread-id thread_123
{
  "user_preferences": {
    "theme": "dark",
    "language": "en"
  },
  "status": "active"
}

$ epsimo db set --project-id proj_abc --thread-id thread_123 \
  --key "status" --value '"completed"'

Credits & Billing

Command Description
epsimo credits balance Check current thread balance and subscription tier
epsimo credits buy --quantity <N> Generate a Stripe checkout URL for purchasing threads

Example:

$ epsimo credits balance
💳 Checking balance...

=== Thread Balance ===
Threads Used:      45
Total Allowance:   100
Threads Remaining: 55
======================

$ epsimo credits buy --quantity 1000
🛒 Preparing purchase of 1000 threads...
ℹ️  Estimated cost: 80.0 EUR

✅ Checkout session created successfully!
Please visit this URL to complete your purchase:

https://checkout.stripe.com/session_...

Pricing:

  • < 500 threads: €0.10/thread
  • 500-999 threads: €0.09/thread
  • 1000+ threads: €0.08/thread

Resource Listing

Command Description
epsimo assistants --project-id <P_ID> List all assistants in a project
epsimo assistants --project-id <P_ID> --json List assistants in JSON format
epsimo threads --project-id <P_ID> List all threads in a project

📚 Python SDK

Installation & Setup

from epsimo import EpsimoClient

# Initialize with API key (JWT token)
client = EpsimoClient(api_key="your-token-here")

# Or use environment variable
# export EPSIMO_API_KEY=your-token-here
client = EpsimoClient()

# Or use custom base URL
client = EpsimoClient(
    api_key="token",
    base_url="https://api.epsimoagents.com"
)

Resource Clients

The SDK provides dedicated resource clients for each entity type:

Resource Access via Purpose
Projects client.projects Top-level containers
Assistants client.assistants AI agents with instructions
Threads client.threads Persistent conversations
Files client.files Document uploads
Credits client.credits Billing & usage
Database client.db Virtual DB access

Projects

# List all projects
projects = client.projects.list()
for p in projects:
    print(f"{p['project_id']}: {p['name']}")

# Create a new project
project = client.projects.create(
    name="My AI Project",
    description="Customer support automation"
)
print(f"Created project: {project['project_id']}")

# Get project details (includes project-specific token)
details = client.projects.get(project_id="proj_abc123")
project_token = details['access_token']

# Delete a project
client.projects.delete(project_id="proj_abc123")

Assistants

# List assistants in a project
assistants = client.assistants.list(project_id="proj_abc123")

# Create an assistant
assistant = client.assistants.create(
    project_id="proj_abc123",
    config={
        "name": "Support Agent",
        "instructions": "You are a helpful customer support agent.",
        "model": "gpt-4o",
        "configurable": {
            "type": "agent",
            "agent_type": "agent"
        },
        "tools": [
            {
                "type": "search_tavily",
                "max_results": 5
            },
            {
                "type": "function",
                "name": "update_database",
                "description": "Save structured data to thread state",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "key": {"type": "string"},
                        "value": {"type": "object"}
                    },
                    "required": ["key", "value"]
                }
            }
        ]
    }
)

# Get assistant details
assistant = client.assistants.get(
    project_id="proj_abc123",
    assistant_id="asst_xyz789"
)

# Delete an assistant
client.assistants.delete(
    project_id="proj_abc123",
    assistant_id="asst_xyz789"
)

Threads

# List threads in a project
threads = client.threads.list(project_id="proj_abc123")

# Create a new thread
thread = client.threads.create(
    project_id="proj_abc123",
    assistant_id="asst_xyz789",
    name="Customer #1234",
    metadata={
        "configurable": {},
        "type": "thread"
    }
)

# Get thread details and messages
thread_data = client.threads.get(
    project_id="proj_abc123",
    thread_id="thread_123"
)
print(f"Messages: {len(thread_data['messages'])}")

# Delete a thread
client.threads.delete(
    project_id="proj_abc123",
    thread_id="thread_123"
)

Streaming Conversations

# Stream assistant responses
for chunk in client.threads.run_stream(
    project_id="proj_abc123",
    thread_id="thread_123",
    assistant_id="asst_xyz789",
    message="Hello, how can you help me?"
):
    print(chunk, end="", flush=True)

Files

# List files in a project
files = client.files.list(project_id="proj_abc123")

# Upload a file
file = client.files.upload(
    project_id="proj_abc123",
    file_path="/path/to/document.pdf",
    purpose="retrieval"  # or "assistants"
)

# Delete a file
client.files.delete(
    project_id="proj_abc123",
    file_id="file_abc123"
)

Credits

# Get current balance
balance = client.credits.get_balance()
print(f"Threads used: {balance['thread_counter']}/{balance['thread_max']}")

# Create checkout session
checkout = client.credits.create_checkout_session(
    quantity=1000,
    amount=80.00
)
print(f"Checkout URL: {checkout['url']}")

Virtual Database

# Get all structured data from a thread
db_state = client.db.get_all(
    project_id="proj_abc123",
    thread_id="thread_123"
)
print(f"User preferences: {db_state.get('user_preferences')}")

# Get specific key
user_prefs = client.db.get(
    project_id="proj_abc123",
    thread_id="thread_123",
    key="user_preferences"
)
print(f"Theme: {user_prefs.get('theme')}")

# Set value (for seeding/testing)
client.db.set(
    project_id="proj_abc123",
    thread_id="thread_123",
    key="status",
    value="active"
)

🎨 React UI Kit

The UI Kit provides high-level components for immediate integration.

ThreadChat Component

A modern, dark-themed chat interface with streaming and tool support.

import { ThreadChat } from "@/components/epsimo";

export default function App() {
  return (
    <ThreadChat 
      assistantId="asst_xyz789"
      projectId="proj_abc123"
      placeholder="Ask me anything..."
      theme="dark"
    />
  );
}

Features:

  • ✅ Real-time streaming responses
  • ✅ Tool call visualization
  • ✅ Message history
  • ✅ Dark/light theme support
  • ✅ Mobile responsive

useChat Hook (Headless)

For custom UI implementations:

import { useChat } from "@/hooks/epsimo";

export default function CustomChat() {
  const { 
    messages, 
    sendMessage, 
    isLoading,
    error
  } = useChat({
    projectId: "proj_abc123",
    threadId: "thread_123",
    assistantId: "asst_xyz789"
  });

  return (
    <div>
      {messages.map(msg => (
        <div key={msg.id} className={msg.role}>
          {msg.content}
        </div>
      ))}
      
      <button 
        onClick={() => sendMessage("Hello")} 
        disabled={isLoading}
      >
        {isLoading ? "Sending..." : "Send"}
      </button>
      
      {error && <div className="error">{error}</div>}
    </div>
  );
}

📦 Tool Library

Found in epsimo/tools/library.yaml, this collection provides reusable JSON schemas for common tasks.

Available Tools

Tool Type Description Configuration
database_sync function Allow agents to write structured JSON to thread state key, value parameters
web_search_tavily search_tavily Advanced search with source attribution max_results: 5
web_search_ddg ddg_search Fast DuckDuckGo search for simple queries None
retrieval_optimized retrieval High-accuracy document search in uploaded files top_k: 5, score_threshold: 0.7
task_management function Track and update user tasks action, details parameters

Using Tools in epsimo.yaml

assistants:
  - name: "Research Assistant"
    model: "gpt-4o"
    instructions: "You help with research tasks and save findings to the database."
    tools:
      - type: search_tavily
        max_results: 5
      - type: function
        name: update_database
        description: "Persist research findings to thread state"
        parameters:
          type: object
          properties:
            key: 
              type: string
              description: "The data category (e.g. 'research_notes')"
            value: 
              type: object
              description: "The JSON data to store"
          required: ["key", "value"]

💾 Virtual Database Pattern

Threads serve as persistent, structured storage — eliminating the need for a separate database.

How It Works

  1. Agent writes to DB using the update_database tool
  2. Data persists in thread state (indexed by thread)
  3. Query from SDK, CLI, or frontend

Benefits

  • ✅ Zero Configuration — No database server required
  • ✅ Contextual Storage — Data is naturally partitioned by conversation
  • ✅ Agent Awareness — The assistant always “knows” what’s in its DB
  • ✅ Queryable — Access from both agent code and application code

Example Workflow

Step 1: Assistant saves user preferences

// Agent calls update_database tool
{
  "name": "update_database",
  "arguments": {
    "key": "user_preferences",
    "value": {
      "theme": "dark",
      "language": "en",
      "notifications": true
    }
  }
}

Step 2: Query from your application

# Python SDK
prefs = client.db.get(project_id, thread_id, "user_preferences")
if prefs.get('theme') == 'dark':
    apply_dark_theme()

Step 3: CLI inspection

$ epsimo db query --project-id proj_123 --thread-id thread_456
{
  "user_preferences": {
    "theme": "dark",
    "language": "en",
    "notifications": true
  }
}

See docs/virtual_db_guide.md for comprehensive guide.


🔧 Error Handling & Best Practices

HTTP Status Codes

Code Meaning Action
200 Success Continue processing
201 Created Capture returned ID
401 Unauthorized Refresh token or re-authenticate
403 Forbidden Check user/project permissions
404 Not Found Verify resource ID
429 Rate Limited Implement exponential backoff
500 Server Error Retry with exponential backoff

Retry Logic with Exponential Backoff

import time
import requests
from requests.exceptions import HTTPError

def make_request_with_retry(url, headers, method="GET", json_data=None, max_retries=5):
    """Make API request with automatic retry on rate limits and server errors."""
    for attempt in range(max_retries):
        try:
            response = requests.request(method, url, headers=headers, json=json_data)
            response.raise_for_status()
            return response.json() if response.content else None

        except HTTPError as e:
            if e.response.status_code == 429:
                # Rate limited - exponential backoff
                wait_time = min(60 * (2 ** attempt), 300)  # Max 5 minutes
                print(f"⏳ Rate limited. Waiting {wait_time}s...")
                time.sleep(wait_time)
            elif e.response.status_code >= 500:
                # Server error - retry with backoff
                wait_time = min(10 * (2 ** attempt), 60)  # Max 1 minute
                print(f"⚠️ Server error. Waiting {wait_time}s...")
                time.sleep(wait_time)
            elif e.response.status_code == 401:
                # Token expired - try to refresh
                print("🔑 Token expired. Re-authenticating...")
                raise
            else:
                # Other errors - don't retry
                raise

    raise Exception(f"Max retries ({max_retries}) exceeded")

Rate Limits

Tier Limit
Free 60 requests/minute
Standard 300 requests/minute
Premium 1,000 requests/minute

Security Best Practices

  1. API Key Management

    • Never commit .epsimo_token to version control
    • Use environment variables (EPSIMO_API_KEY)
    • Rotate tokens regularly
    • Use different tokens for dev/staging/production
  2. Data Privacy

    • Always use project-scoped tokens for multi-tenant apps
    • Implement proper access controls at application layer
    • Audit stored thread data regularly
    • Tag sensitive information appropriately
  3. Network Security

    • Always use HTTPS endpoints
    • Validate SSL certificates in production
    • Consider using API gateways for additional security layers
    • Monitor API usage for unusual patterns

🧪 Verification & Testing

Ensure your environment is correctly configured:

# Verify skill configuration
python3 verify_skill.py

# Run comprehensive E2E test suite
python3 scripts/test_all_skills.py

# Test streaming functionality
python3 scripts/test_streaming.py

# Test Virtual DB operations
python3 scripts/test_vdb.py

Verification Steps:

  1. ✅ Authentication successful
  2. ✅ Project creation
  3. ✅ Assistant creation
  4. ✅ Thread creation
  5. ✅ Resource listing
  6. ✅ Cleanup (automatic deletion)

🔍 Troubleshooting

Authentication Issues

Problem: ❌ Not logged in. Use 'epsimo auth'.

Solution:

epsimo auth login
# Or set environment variables
export EPSIMO_EMAIL=your@email.com
export EPSIMO_PASSWORD=your-password

Token Expiration

Problem: 401 Unauthorized - Token has expired

Solution:

from epsimo.auth import perform_login

# Re-authenticate
token = perform_login(email, password)

Rate Limiting

Problem: 429 Too Many Requests

Solution:

  • Implement exponential backoff (see examples above)
  • Upgrade to higher tier
  • Implement client-side request throttling

Project-Scoped Operations Failing

Problem: 403 Forbidden when accessing assistants/threads

Solution:

# Get project-specific token
project = client.projects.get(project_id)
project_token = project['access_token']

# Use project token for scoped operations
project_client = EpsimoClient(api_key=project_token)
assistants = project_client.assistants.list(project_id)

📖 Reference Documentation


🔗 Links


📋 System Architecture

Epsimo Platform
├── Authentication Layer (JWT tokens)
├── Projects (top-level containers)
│   ├── Assistants (AI agents with instructions)
│   ├── Threads (persistent conversations)
│   │   └── Virtual Database (structured state)
│   └── Files (uploaded documents)
└── Billing (thread-based credits)

Client Tools
├── CLI (epsimo command)
├── Python SDK (EpsimoClient)
└── React UI Kit (ThreadChat, useChat)

Version: 0.2.0
License: MIT
Author: Thierry Teisseire

For questions or issues, visit GitHub Issues.