epsimo-agent 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +409 -0
- package/SKILL.md +769 -42
- package/package.json +41 -19
- package/references/api_reference.md +802 -34
- package/requirements.txt +4 -2
- package/verify_skill.py +126 -0
- /package/{references → docs}/virtual_db_guide.md +0 -0
- /package/{scripts/test_sdk.py → test_sdk.py} +0 -0
package/SKILL.md
CHANGED
|
@@ -1,85 +1,812 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: epsimo-agent
|
|
3
|
-
description: Comprehensive
|
|
3
|
+
description: Comprehensive Epsimo AI platform SDK and CLI for managing agents, projects, threads, Virtual Database, and frontend design. Build AI apps with persistent state, streaming conversations, and React UI kit. Use for: multi-agent orchestration, conversation persistence, structured state management, chatbot UIs, AI application scaffolding.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Epsimo Agent Framework
|
|
6
|
+
# Epsimo Agent Framework
|
|
7
7
|
|
|
8
8
|
> [!NOTE]
|
|
9
|
-
> This is a **Beta**
|
|
9
|
+
> This is a **Beta Release** (v0.2.0). Features and APIs may evolve based on feedback.
|
|
10
10
|
|
|
11
11
|
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**.
|
|
12
12
|
|
|
13
|
-
**Base URL:** `https://api.epsimoagents.com`
|
|
13
|
+
**Base URL:** `https://api.epsimoagents.com`
|
|
14
14
|
**Frontend URL:** `https://app.epsimoagents.com`
|
|
15
15
|
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 🚀 Quick Start: Create an MVP in 3 Commands
|
|
19
|
+
|
|
20
|
+
The fastest way to build an Epsimo app is using the project generator:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# 1. Authenticate
|
|
24
|
+
epsimo auth login
|
|
25
|
+
|
|
26
|
+
# 2. Create a new Next.js project
|
|
27
|
+
epsimo create "My AI App"
|
|
28
|
+
|
|
29
|
+
# 3. Initialize and Deploy
|
|
30
|
+
cd my-ai-app
|
|
31
|
+
epsimo init
|
|
32
|
+
epsimo deploy
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Your AI app is now live with persistent conversations, Virtual Database state, and a pre-built chat UI.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 📦 Installation
|
|
40
|
+
|
|
41
|
+
### CLI & Python SDK
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Install dependencies
|
|
45
|
+
pip install -r requirements.txt
|
|
46
|
+
|
|
47
|
+
# Make CLI executable (if using from source)
|
|
48
|
+
chmod +x epsimo/cli.py
|
|
49
|
+
export PATH="$PATH:$(pwd)/epsimo"
|
|
50
|
+
|
|
51
|
+
# Or via npm (for Claude Code skills)
|
|
52
|
+
npm install -g epsimo-agent
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Dependencies:**
|
|
56
|
+
- `requests>=2.28.0`
|
|
57
|
+
- `pyyaml>=6.0`
|
|
58
|
+
- `click>=8.0.0`
|
|
59
|
+
- `python-dotenv>=0.19.0`
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## 🔐 Authentication
|
|
64
|
+
|
|
65
|
+
### Login Flow
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# Interactive login
|
|
69
|
+
epsimo auth login
|
|
70
|
+
|
|
71
|
+
# Login with environment variables
|
|
72
|
+
export EPSIMO_EMAIL=your@email.com
|
|
73
|
+
export EPSIMO_PASSWORD=your-password
|
|
74
|
+
epsimo auth login
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Programmatic Authentication
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
from epsimo.auth import perform_login, get_token
|
|
81
|
+
|
|
82
|
+
# Login and get token
|
|
83
|
+
token = perform_login("your@email.com", "password")
|
|
84
|
+
|
|
85
|
+
# Get cached token (auto-refreshes if expired)
|
|
86
|
+
token = get_token()
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Token Management
|
|
90
|
+
|
|
91
|
+
Tokens are stored in `~/code/epsimo-frontend/.epsimo_token` and expire after **1 hour**.
|
|
92
|
+
|
|
93
|
+
**Token Storage Format:**
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"access_token": "eyJhbG...",
|
|
97
|
+
"token": "eyJhbG...",
|
|
98
|
+
"jwt_token": "eyJhbG...",
|
|
99
|
+
"expires_in": 3600
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Best Practices:**
|
|
104
|
+
- ✅ Use environment variables (`EPSIMO_API_KEY`) for production
|
|
105
|
+
- ✅ Never commit `.epsimo_token` to version control
|
|
106
|
+
- ✅ Implement token refresh on 401 errors
|
|
107
|
+
- ✅ Use project-specific tokens for multi-tenant apps
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
16
111
|
## 🛠️ Unified CLI (`epsimo`)
|
|
17
112
|
|
|
18
113
|
The `epsimo` CLI is the main tool for managing your agents and data.
|
|
19
114
|
|
|
20
|
-
### Authentication
|
|
115
|
+
### Authentication Commands
|
|
116
|
+
|
|
117
|
+
| Command | Description |
|
|
118
|
+
|---------|-------------|
|
|
119
|
+
| `epsimo auth login` | Interactive login with email/password |
|
|
120
|
+
| `epsimo whoami` | Display current user info and thread usage |
|
|
121
|
+
|
|
122
|
+
**Example:**
|
|
21
123
|
```bash
|
|
22
|
-
|
|
23
|
-
|
|
124
|
+
$ epsimo whoami
|
|
125
|
+
👤 Fetching user info...
|
|
126
|
+
Logged in as: user@example.com
|
|
127
|
+
Threads Used: 45/100
|
|
24
128
|
```
|
|
25
129
|
|
|
26
|
-
### Project
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
130
|
+
### Project Management
|
|
131
|
+
|
|
132
|
+
| Command | Description |
|
|
133
|
+
|---------|-------------|
|
|
134
|
+
| `epsimo projects` | List all projects |
|
|
135
|
+
| `epsimo projects --json` | List projects in JSON format |
|
|
136
|
+
| `epsimo create <name>` | Scaffold a full Next.js application with Epsimo |
|
|
137
|
+
| `epsimo init` | Link a local directory to an Epsimo project |
|
|
138
|
+
| `epsimo deploy` | Sync your `epsimo.yaml` configuration to the platform |
|
|
139
|
+
|
|
140
|
+
**Example:**
|
|
141
|
+
```bash
|
|
142
|
+
$ epsimo projects
|
|
143
|
+
📁 Fetching projects...
|
|
144
|
+
ID | Name
|
|
145
|
+
-----------------------------------------------------------------
|
|
146
|
+
proj_abc123 | Customer Support Bot
|
|
147
|
+
proj_xyz789 | Research Assistant
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Virtual Database Commands
|
|
30
151
|
|
|
31
|
-
### Virtual Database
|
|
32
152
|
Threads can serve as a persistent structured storage layer.
|
|
33
|
-
- `python3 -m epsimo.cli db query --project-id <P_ID> --thread-id <T_ID>`: View structured thread state.
|
|
34
|
-
- `python3 -m epsimo.cli db set --project-id <P_ID> --thread-id <T_ID> --key <K> --value <V>`: Seed state.
|
|
35
153
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
154
|
+
| Command | Description |
|
|
155
|
+
|---------|-------------|
|
|
156
|
+
| `epsimo db query --project-id <P_ID> --thread-id <T_ID>` | View all structured thread state |
|
|
157
|
+
| `epsimo db get --project-id <P_ID> --thread-id <T_ID> --key <K>` | Get specific key from thread state |
|
|
158
|
+
| `epsimo db set --project-id <P_ID> --thread-id <T_ID> --key <K> --value <V>` | Seed state for testing |
|
|
159
|
+
|
|
160
|
+
**Example:**
|
|
161
|
+
```bash
|
|
162
|
+
$ epsimo db query --project-id proj_abc --thread-id thread_123
|
|
163
|
+
{
|
|
164
|
+
"user_preferences": {
|
|
165
|
+
"theme": "dark",
|
|
166
|
+
"language": "en"
|
|
167
|
+
},
|
|
168
|
+
"status": "active"
|
|
169
|
+
}
|
|
39
170
|
|
|
40
|
-
|
|
171
|
+
$ epsimo db set --project-id proj_abc --thread-id thread_123 \
|
|
172
|
+
--key "status" --value '"completed"'
|
|
173
|
+
```
|
|
41
174
|
|
|
42
|
-
|
|
175
|
+
### Credits & Billing
|
|
176
|
+
|
|
177
|
+
| Command | Description |
|
|
178
|
+
|---------|-------------|
|
|
179
|
+
| `epsimo credits balance` | Check current thread balance and subscription tier |
|
|
180
|
+
| `epsimo credits buy --quantity <N>` | Generate a Stripe checkout URL for purchasing threads |
|
|
181
|
+
|
|
182
|
+
**Example:**
|
|
183
|
+
```bash
|
|
184
|
+
$ epsimo credits balance
|
|
185
|
+
💳 Checking balance...
|
|
186
|
+
|
|
187
|
+
=== Thread Balance ===
|
|
188
|
+
Threads Used: 45
|
|
189
|
+
Total Allowance: 100
|
|
190
|
+
Threads Remaining: 55
|
|
191
|
+
======================
|
|
192
|
+
|
|
193
|
+
$ epsimo credits buy --quantity 1000
|
|
194
|
+
🛒 Preparing purchase of 1000 threads...
|
|
195
|
+
ℹ️ Estimated cost: 80.0 EUR
|
|
196
|
+
|
|
197
|
+
✅ Checkout session created successfully!
|
|
198
|
+
Please visit this URL to complete your purchase:
|
|
199
|
+
|
|
200
|
+
https://checkout.stripe.com/session_...
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**Pricing:**
|
|
204
|
+
- < 500 threads: €0.10/thread
|
|
205
|
+
- 500-999 threads: €0.09/thread
|
|
206
|
+
- 1000+ threads: €0.08/thread
|
|
207
|
+
|
|
208
|
+
### Resource Listing
|
|
209
|
+
|
|
210
|
+
| Command | Description |
|
|
211
|
+
|---------|-------------|
|
|
212
|
+
| `epsimo assistants --project-id <P_ID>` | List all assistants in a project |
|
|
213
|
+
| `epsimo assistants --project-id <P_ID> --json` | List assistants in JSON format |
|
|
214
|
+
| `epsimo threads --project-id <P_ID>` | List all threads in a project |
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## 📚 Python SDK
|
|
219
|
+
|
|
220
|
+
### Installation & Setup
|
|
43
221
|
|
|
44
222
|
```python
|
|
45
223
|
from epsimo import EpsimoClient
|
|
46
224
|
|
|
47
|
-
|
|
225
|
+
# Initialize with API key (JWT token)
|
|
226
|
+
client = EpsimoClient(api_key="your-token-here")
|
|
227
|
+
|
|
228
|
+
# Or use environment variable
|
|
229
|
+
# export EPSIMO_API_KEY=your-token-here
|
|
230
|
+
client = EpsimoClient()
|
|
231
|
+
|
|
232
|
+
# Or use custom base URL
|
|
233
|
+
client = EpsimoClient(
|
|
234
|
+
api_key="token",
|
|
235
|
+
base_url="https://api.epsimoagents.com"
|
|
236
|
+
)
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Resource Clients
|
|
240
|
+
|
|
241
|
+
The SDK provides dedicated resource clients for each entity type:
|
|
242
|
+
|
|
243
|
+
| Resource | Access via | Purpose |
|
|
244
|
+
|----------|-----------|---------|
|
|
245
|
+
| **Projects** | `client.projects` | Top-level containers |
|
|
246
|
+
| **Assistants** | `client.assistants` | AI agents with instructions |
|
|
247
|
+
| **Threads** | `client.threads` | Persistent conversations |
|
|
248
|
+
| **Files** | `client.files` | Document uploads |
|
|
249
|
+
| **Credits** | `client.credits` | Billing & usage |
|
|
250
|
+
| **Database** | `client.db` | Virtual DB access |
|
|
251
|
+
|
|
252
|
+
### Projects
|
|
253
|
+
|
|
254
|
+
```python
|
|
255
|
+
# List all projects
|
|
256
|
+
projects = client.projects.list()
|
|
257
|
+
for p in projects:
|
|
258
|
+
print(f"{p['project_id']}: {p['name']}")
|
|
48
259
|
|
|
49
|
-
#
|
|
50
|
-
|
|
260
|
+
# Create a new project
|
|
261
|
+
project = client.projects.create(
|
|
262
|
+
name="My AI Project",
|
|
263
|
+
description="Customer support automation"
|
|
264
|
+
)
|
|
265
|
+
print(f"Created project: {project['project_id']}")
|
|
51
266
|
|
|
52
|
-
#
|
|
53
|
-
|
|
54
|
-
|
|
267
|
+
# Get project details (includes project-specific token)
|
|
268
|
+
details = client.projects.get(project_id="proj_abc123")
|
|
269
|
+
project_token = details['access_token']
|
|
270
|
+
|
|
271
|
+
# Delete a project
|
|
272
|
+
client.projects.delete(project_id="proj_abc123")
|
|
55
273
|
```
|
|
56
274
|
|
|
275
|
+
### Assistants
|
|
276
|
+
|
|
277
|
+
```python
|
|
278
|
+
# List assistants in a project
|
|
279
|
+
assistants = client.assistants.list(project_id="proj_abc123")
|
|
280
|
+
|
|
281
|
+
# Create an assistant
|
|
282
|
+
assistant = client.assistants.create(
|
|
283
|
+
project_id="proj_abc123",
|
|
284
|
+
config={
|
|
285
|
+
"name": "Support Agent",
|
|
286
|
+
"instructions": "You are a helpful customer support agent.",
|
|
287
|
+
"model": "gpt-4o",
|
|
288
|
+
"configurable": {
|
|
289
|
+
"type": "agent",
|
|
290
|
+
"agent_type": "agent"
|
|
291
|
+
},
|
|
292
|
+
"tools": [
|
|
293
|
+
{
|
|
294
|
+
"type": "search_tavily",
|
|
295
|
+
"max_results": 5
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
"type": "function",
|
|
299
|
+
"name": "update_database",
|
|
300
|
+
"description": "Save structured data to thread state",
|
|
301
|
+
"parameters": {
|
|
302
|
+
"type": "object",
|
|
303
|
+
"properties": {
|
|
304
|
+
"key": {"type": "string"},
|
|
305
|
+
"value": {"type": "object"}
|
|
306
|
+
},
|
|
307
|
+
"required": ["key", "value"]
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
]
|
|
311
|
+
}
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
# Get assistant details
|
|
315
|
+
assistant = client.assistants.get(
|
|
316
|
+
project_id="proj_abc123",
|
|
317
|
+
assistant_id="asst_xyz789"
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
# Delete an assistant
|
|
321
|
+
client.assistants.delete(
|
|
322
|
+
project_id="proj_abc123",
|
|
323
|
+
assistant_id="asst_xyz789"
|
|
324
|
+
)
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Threads
|
|
328
|
+
|
|
329
|
+
```python
|
|
330
|
+
# List threads in a project
|
|
331
|
+
threads = client.threads.list(project_id="proj_abc123")
|
|
332
|
+
|
|
333
|
+
# Create a new thread
|
|
334
|
+
thread = client.threads.create(
|
|
335
|
+
project_id="proj_abc123",
|
|
336
|
+
assistant_id="asst_xyz789",
|
|
337
|
+
name="Customer #1234",
|
|
338
|
+
metadata={
|
|
339
|
+
"configurable": {},
|
|
340
|
+
"type": "thread"
|
|
341
|
+
}
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
# Get thread details and messages
|
|
345
|
+
thread_data = client.threads.get(
|
|
346
|
+
project_id="proj_abc123",
|
|
347
|
+
thread_id="thread_123"
|
|
348
|
+
)
|
|
349
|
+
print(f"Messages: {len(thread_data['messages'])}")
|
|
350
|
+
|
|
351
|
+
# Delete a thread
|
|
352
|
+
client.threads.delete(
|
|
353
|
+
project_id="proj_abc123",
|
|
354
|
+
thread_id="thread_123"
|
|
355
|
+
)
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### Streaming Conversations
|
|
359
|
+
|
|
360
|
+
```python
|
|
361
|
+
# Stream assistant responses
|
|
362
|
+
for chunk in client.threads.run_stream(
|
|
363
|
+
project_id="proj_abc123",
|
|
364
|
+
thread_id="thread_123",
|
|
365
|
+
assistant_id="asst_xyz789",
|
|
366
|
+
message="Hello, how can you help me?"
|
|
367
|
+
):
|
|
368
|
+
print(chunk, end="", flush=True)
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### Files
|
|
372
|
+
|
|
373
|
+
```python
|
|
374
|
+
# List files in a project
|
|
375
|
+
files = client.files.list(project_id="proj_abc123")
|
|
376
|
+
|
|
377
|
+
# Upload a file
|
|
378
|
+
file = client.files.upload(
|
|
379
|
+
project_id="proj_abc123",
|
|
380
|
+
file_path="/path/to/document.pdf",
|
|
381
|
+
purpose="retrieval" # or "assistants"
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
# Delete a file
|
|
385
|
+
client.files.delete(
|
|
386
|
+
project_id="proj_abc123",
|
|
387
|
+
file_id="file_abc123"
|
|
388
|
+
)
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
### Credits
|
|
392
|
+
|
|
393
|
+
```python
|
|
394
|
+
# Get current balance
|
|
395
|
+
balance = client.credits.get_balance()
|
|
396
|
+
print(f"Threads used: {balance['thread_counter']}/{balance['thread_max']}")
|
|
397
|
+
|
|
398
|
+
# Create checkout session
|
|
399
|
+
checkout = client.credits.create_checkout_session(
|
|
400
|
+
quantity=1000,
|
|
401
|
+
amount=80.00
|
|
402
|
+
)
|
|
403
|
+
print(f"Checkout URL: {checkout['url']}")
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
### Virtual Database
|
|
407
|
+
|
|
408
|
+
```python
|
|
409
|
+
# Get all structured data from a thread
|
|
410
|
+
db_state = client.db.get_all(
|
|
411
|
+
project_id="proj_abc123",
|
|
412
|
+
thread_id="thread_123"
|
|
413
|
+
)
|
|
414
|
+
print(f"User preferences: {db_state.get('user_preferences')}")
|
|
415
|
+
|
|
416
|
+
# Get specific key
|
|
417
|
+
user_prefs = client.db.get(
|
|
418
|
+
project_id="proj_abc123",
|
|
419
|
+
thread_id="thread_123",
|
|
420
|
+
key="user_preferences"
|
|
421
|
+
)
|
|
422
|
+
print(f"Theme: {user_prefs.get('theme')}")
|
|
423
|
+
|
|
424
|
+
# Set value (for seeding/testing)
|
|
425
|
+
client.db.set(
|
|
426
|
+
project_id="proj_abc123",
|
|
427
|
+
thread_id="thread_123",
|
|
428
|
+
key="status",
|
|
429
|
+
value="active"
|
|
430
|
+
)
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
---
|
|
434
|
+
|
|
57
435
|
## 🎨 React UI Kit
|
|
58
436
|
|
|
59
|
-
The UI Kit provides high-level components for immediate integration.
|
|
437
|
+
The UI Kit provides high-level components for immediate integration.
|
|
438
|
+
|
|
439
|
+
### ThreadChat Component
|
|
440
|
+
|
|
441
|
+
A modern, dark-themed chat interface with streaming and tool support.
|
|
442
|
+
|
|
443
|
+
```tsx
|
|
444
|
+
import { ThreadChat } from "@/components/epsimo";
|
|
445
|
+
|
|
446
|
+
export default function App() {
|
|
447
|
+
return (
|
|
448
|
+
<ThreadChat
|
|
449
|
+
assistantId="asst_xyz789"
|
|
450
|
+
projectId="proj_abc123"
|
|
451
|
+
placeholder="Ask me anything..."
|
|
452
|
+
theme="dark"
|
|
453
|
+
/>
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
**Features:**
|
|
459
|
+
- ✅ Real-time streaming responses
|
|
460
|
+
- ✅ Tool call visualization
|
|
461
|
+
- ✅ Message history
|
|
462
|
+
- ✅ Dark/light theme support
|
|
463
|
+
- ✅ Mobile responsive
|
|
464
|
+
|
|
465
|
+
### useChat Hook (Headless)
|
|
466
|
+
|
|
467
|
+
For custom UI implementations:
|
|
468
|
+
|
|
469
|
+
```tsx
|
|
470
|
+
import { useChat } from "@/hooks/epsimo";
|
|
471
|
+
|
|
472
|
+
export default function CustomChat() {
|
|
473
|
+
const {
|
|
474
|
+
messages,
|
|
475
|
+
sendMessage,
|
|
476
|
+
isLoading,
|
|
477
|
+
error
|
|
478
|
+
} = useChat({
|
|
479
|
+
projectId: "proj_abc123",
|
|
480
|
+
threadId: "thread_123",
|
|
481
|
+
assistantId: "asst_xyz789"
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
return (
|
|
485
|
+
<div>
|
|
486
|
+
{messages.map(msg => (
|
|
487
|
+
<div key={msg.id} className={msg.role}>
|
|
488
|
+
{msg.content}
|
|
489
|
+
</div>
|
|
490
|
+
))}
|
|
491
|
+
|
|
492
|
+
<button
|
|
493
|
+
onClick={() => sendMessage("Hello")}
|
|
494
|
+
disabled={isLoading}
|
|
495
|
+
>
|
|
496
|
+
{isLoading ? "Sending..." : "Send"}
|
|
497
|
+
</button>
|
|
498
|
+
|
|
499
|
+
{error && <div className="error">{error}</div>}
|
|
500
|
+
</div>
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
---
|
|
506
|
+
|
|
507
|
+
## 📦 Tool Library
|
|
508
|
+
|
|
509
|
+
Found in `epsimo/tools/library.yaml`, this collection provides reusable JSON schemas for common tasks.
|
|
510
|
+
|
|
511
|
+
### Available Tools
|
|
512
|
+
|
|
513
|
+
| Tool | Type | Description | Configuration |
|
|
514
|
+
|------|------|-------------|---------------|
|
|
515
|
+
| **database_sync** | function | Allow agents to write structured JSON to thread state | `key`, `value` parameters |
|
|
516
|
+
| **web_search_tavily** | search_tavily | Advanced search with source attribution | `max_results: 5` |
|
|
517
|
+
| **web_search_ddg** | ddg_search | Fast DuckDuckGo search for simple queries | None |
|
|
518
|
+
| **retrieval_optimized** | retrieval | High-accuracy document search in uploaded files | `top_k: 5`, `score_threshold: 0.7` |
|
|
519
|
+
| **task_management** | function | Track and update user tasks | `action`, `details` parameters |
|
|
520
|
+
|
|
521
|
+
### Using Tools in epsimo.yaml
|
|
522
|
+
|
|
523
|
+
```yaml
|
|
524
|
+
assistants:
|
|
525
|
+
- name: "Research Assistant"
|
|
526
|
+
model: "gpt-4o"
|
|
527
|
+
instructions: "You help with research tasks and save findings to the database."
|
|
528
|
+
tools:
|
|
529
|
+
- type: search_tavily
|
|
530
|
+
max_results: 5
|
|
531
|
+
- type: function
|
|
532
|
+
name: update_database
|
|
533
|
+
description: "Persist research findings to thread state"
|
|
534
|
+
parameters:
|
|
535
|
+
type: object
|
|
536
|
+
properties:
|
|
537
|
+
key:
|
|
538
|
+
type: string
|
|
539
|
+
description: "The data category (e.g. 'research_notes')"
|
|
540
|
+
value:
|
|
541
|
+
type: object
|
|
542
|
+
description: "The JSON data to store"
|
|
543
|
+
required: ["key", "value"]
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
---
|
|
547
|
+
|
|
548
|
+
## 💾 Virtual Database Pattern
|
|
549
|
+
|
|
550
|
+
Threads serve as persistent, structured storage — eliminating the need for a separate database.
|
|
551
|
+
|
|
552
|
+
### How It Works
|
|
553
|
+
|
|
554
|
+
1. **Agent writes to DB** using the `update_database` tool
|
|
555
|
+
2. **Data persists** in thread state (indexed by thread)
|
|
556
|
+
3. **Query from SDK, CLI, or frontend**
|
|
557
|
+
|
|
558
|
+
### Benefits
|
|
559
|
+
|
|
560
|
+
- ✅ **Zero Configuration** — No database server required
|
|
561
|
+
- ✅ **Contextual Storage** — Data is naturally partitioned by conversation
|
|
562
|
+
- ✅ **Agent Awareness** — The assistant always "knows" what's in its DB
|
|
563
|
+
- ✅ **Queryable** — Access from both agent code and application code
|
|
564
|
+
|
|
565
|
+
### Example Workflow
|
|
566
|
+
|
|
567
|
+
**Step 1:** Assistant saves user preferences
|
|
568
|
+
|
|
569
|
+
```json
|
|
570
|
+
// Agent calls update_database tool
|
|
571
|
+
{
|
|
572
|
+
"name": "update_database",
|
|
573
|
+
"arguments": {
|
|
574
|
+
"key": "user_preferences",
|
|
575
|
+
"value": {
|
|
576
|
+
"theme": "dark",
|
|
577
|
+
"language": "en",
|
|
578
|
+
"notifications": true
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
**Step 2:** Query from your application
|
|
585
|
+
|
|
586
|
+
```python
|
|
587
|
+
# Python SDK
|
|
588
|
+
prefs = client.db.get(project_id, thread_id, "user_preferences")
|
|
589
|
+
if prefs.get('theme') == 'dark':
|
|
590
|
+
apply_dark_theme()
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
**Step 3:** CLI inspection
|
|
594
|
+
|
|
595
|
+
```bash
|
|
596
|
+
$ epsimo db query --project-id proj_123 --thread-id thread_456
|
|
597
|
+
{
|
|
598
|
+
"user_preferences": {
|
|
599
|
+
"theme": "dark",
|
|
600
|
+
"language": "en",
|
|
601
|
+
"notifications": true
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
See [docs/virtual_db_guide.md](docs/virtual_db_guide.md) for comprehensive guide.
|
|
607
|
+
|
|
608
|
+
---
|
|
609
|
+
|
|
610
|
+
## 🔧 Error Handling & Best Practices
|
|
611
|
+
|
|
612
|
+
### HTTP Status Codes
|
|
613
|
+
|
|
614
|
+
| Code | Meaning | Action |
|
|
615
|
+
|------|---------|--------|
|
|
616
|
+
| 200 | Success | Continue processing |
|
|
617
|
+
| 201 | Created | Capture returned ID |
|
|
618
|
+
| 401 | Unauthorized | Refresh token or re-authenticate |
|
|
619
|
+
| 403 | Forbidden | Check user/project permissions |
|
|
620
|
+
| 404 | Not Found | Verify resource ID |
|
|
621
|
+
| 429 | Rate Limited | Implement exponential backoff |
|
|
622
|
+
| 500 | Server Error | Retry with exponential backoff |
|
|
623
|
+
|
|
624
|
+
### Retry Logic with Exponential Backoff
|
|
625
|
+
|
|
626
|
+
```python
|
|
627
|
+
import time
|
|
628
|
+
import requests
|
|
629
|
+
from requests.exceptions import HTTPError
|
|
630
|
+
|
|
631
|
+
def make_request_with_retry(url, headers, method="GET", json_data=None, max_retries=5):
|
|
632
|
+
"""Make API request with automatic retry on rate limits and server errors."""
|
|
633
|
+
for attempt in range(max_retries):
|
|
634
|
+
try:
|
|
635
|
+
response = requests.request(method, url, headers=headers, json=json_data)
|
|
636
|
+
response.raise_for_status()
|
|
637
|
+
return response.json() if response.content else None
|
|
638
|
+
|
|
639
|
+
except HTTPError as e:
|
|
640
|
+
if e.response.status_code == 429:
|
|
641
|
+
# Rate limited - exponential backoff
|
|
642
|
+
wait_time = min(60 * (2 ** attempt), 300) # Max 5 minutes
|
|
643
|
+
print(f"⏳ Rate limited. Waiting {wait_time}s...")
|
|
644
|
+
time.sleep(wait_time)
|
|
645
|
+
elif e.response.status_code >= 500:
|
|
646
|
+
# Server error - retry with backoff
|
|
647
|
+
wait_time = min(10 * (2 ** attempt), 60) # Max 1 minute
|
|
648
|
+
print(f"⚠️ Server error. Waiting {wait_time}s...")
|
|
649
|
+
time.sleep(wait_time)
|
|
650
|
+
elif e.response.status_code == 401:
|
|
651
|
+
# Token expired - try to refresh
|
|
652
|
+
print("🔑 Token expired. Re-authenticating...")
|
|
653
|
+
raise
|
|
654
|
+
else:
|
|
655
|
+
# Other errors - don't retry
|
|
656
|
+
raise
|
|
657
|
+
|
|
658
|
+
raise Exception(f"Max retries ({max_retries}) exceeded")
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
### Rate Limits
|
|
662
|
+
|
|
663
|
+
| Tier | Limit |
|
|
664
|
+
|------|-------|
|
|
665
|
+
| Free | 60 requests/minute |
|
|
666
|
+
| Standard | 300 requests/minute |
|
|
667
|
+
| Premium | 1,000 requests/minute |
|
|
60
668
|
|
|
61
|
-
|
|
62
|
-
- **`useChat`**: A headless hook for managing conversation state.
|
|
669
|
+
### Security Best Practices
|
|
63
670
|
|
|
64
|
-
|
|
65
|
-
|
|
671
|
+
1. **API Key Management**
|
|
672
|
+
- Never commit `.epsimo_token` to version control
|
|
673
|
+
- Use environment variables (`EPSIMO_API_KEY`)
|
|
674
|
+
- Rotate tokens regularly
|
|
675
|
+
- Use different tokens for dev/staging/production
|
|
676
|
+
|
|
677
|
+
2. **Data Privacy**
|
|
678
|
+
- Always use project-scoped tokens for multi-tenant apps
|
|
679
|
+
- Implement proper access controls at application layer
|
|
680
|
+
- Audit stored thread data regularly
|
|
681
|
+
- Tag sensitive information appropriately
|
|
682
|
+
|
|
683
|
+
3. **Network Security**
|
|
684
|
+
- Always use HTTPS endpoints
|
|
685
|
+
- Validate SSL certificates in production
|
|
686
|
+
- Consider using API gateways for additional security layers
|
|
687
|
+
- Monitor API usage for unusual patterns
|
|
688
|
+
|
|
689
|
+
---
|
|
690
|
+
|
|
691
|
+
## 🧪 Verification & Testing
|
|
66
692
|
|
|
67
|
-
## 🧪 Verification
|
|
68
693
|
Ensure your environment is correctly configured:
|
|
694
|
+
|
|
695
|
+
```bash
|
|
696
|
+
# Verify skill configuration
|
|
697
|
+
python3 verify_skill.py
|
|
698
|
+
|
|
699
|
+
# Run comprehensive E2E test suite
|
|
700
|
+
python3 scripts/test_all_skills.py
|
|
701
|
+
|
|
702
|
+
# Test streaming functionality
|
|
703
|
+
python3 scripts/test_streaming.py
|
|
704
|
+
|
|
705
|
+
# Test Virtual DB operations
|
|
706
|
+
python3 scripts/test_vdb.py
|
|
707
|
+
```
|
|
708
|
+
|
|
709
|
+
**Verification Steps:**
|
|
710
|
+
1. ✅ Authentication successful
|
|
711
|
+
2. ✅ Project creation
|
|
712
|
+
3. ✅ Assistant creation
|
|
713
|
+
4. ✅ Thread creation
|
|
714
|
+
5. ✅ Resource listing
|
|
715
|
+
6. ✅ Cleanup (automatic deletion)
|
|
716
|
+
|
|
717
|
+
---
|
|
718
|
+
|
|
719
|
+
## 🔍 Troubleshooting
|
|
720
|
+
|
|
721
|
+
### Authentication Issues
|
|
722
|
+
|
|
723
|
+
**Problem:** `❌ Not logged in. Use 'epsimo auth'.`
|
|
724
|
+
|
|
725
|
+
**Solution:**
|
|
69
726
|
```bash
|
|
70
|
-
|
|
727
|
+
epsimo auth login
|
|
728
|
+
# Or set environment variables
|
|
729
|
+
export EPSIMO_EMAIL=your@email.com
|
|
730
|
+
export EPSIMO_PASSWORD=your-password
|
|
71
731
|
```
|
|
72
732
|
|
|
73
|
-
|
|
733
|
+
### Token Expiration
|
|
734
|
+
|
|
735
|
+
**Problem:** `401 Unauthorized - Token has expired`
|
|
736
|
+
|
|
737
|
+
**Solution:**
|
|
738
|
+
```python
|
|
739
|
+
from epsimo.auth import perform_login
|
|
74
740
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
741
|
+
# Re-authenticate
|
|
742
|
+
token = perform_login(email, password)
|
|
743
|
+
```
|
|
744
|
+
|
|
745
|
+
### Rate Limiting
|
|
746
|
+
|
|
747
|
+
**Problem:** `429 Too Many Requests`
|
|
748
|
+
|
|
749
|
+
**Solution:**
|
|
750
|
+
- Implement exponential backoff (see examples above)
|
|
751
|
+
- Upgrade to higher tier
|
|
752
|
+
- Implement client-side request throttling
|
|
753
|
+
|
|
754
|
+
### Project-Scoped Operations Failing
|
|
755
|
+
|
|
756
|
+
**Problem:** `403 Forbidden` when accessing assistants/threads
|
|
757
|
+
|
|
758
|
+
**Solution:**
|
|
759
|
+
```python
|
|
760
|
+
# Get project-specific token
|
|
761
|
+
project = client.projects.get(project_id)
|
|
762
|
+
project_token = project['access_token']
|
|
763
|
+
|
|
764
|
+
# Use project token for scoped operations
|
|
765
|
+
project_client = EpsimoClient(api_key=project_token)
|
|
766
|
+
assistants = project_client.assistants.list(project_id)
|
|
767
|
+
```
|
|
768
|
+
|
|
769
|
+
---
|
|
770
|
+
|
|
771
|
+
## 📖 Reference Documentation
|
|
772
|
+
|
|
773
|
+
- **Full API Reference**: [references/api_reference.md](references/api_reference.md)
|
|
774
|
+
- **Virtual DB Guide**: [docs/virtual_db_guide.md](docs/virtual_db_guide.md)
|
|
775
|
+
- **README**: [README.md](README.md)
|
|
776
|
+
- **Tool Library**: [epsimo/tools/library.yaml](epsimo/tools/library.yaml)
|
|
777
|
+
|
|
778
|
+
---
|
|
779
|
+
|
|
780
|
+
## 🔗 Links
|
|
781
|
+
|
|
782
|
+
- **GitHub Repository**: https://github.com/thierryteisseire/epsimo-agent
|
|
783
|
+
- **Web Application**: https://app.epsimoagents.com
|
|
784
|
+
- **API Base URL**: https://api.epsimoagents.com
|
|
785
|
+
|
|
786
|
+
---
|
|
787
|
+
|
|
788
|
+
## 📋 System Architecture
|
|
789
|
+
|
|
790
|
+
```
|
|
791
|
+
Epsimo Platform
|
|
792
|
+
├── Authentication Layer (JWT tokens)
|
|
793
|
+
├── Projects (top-level containers)
|
|
794
|
+
│ ├── Assistants (AI agents with instructions)
|
|
795
|
+
│ ├── Threads (persistent conversations)
|
|
796
|
+
│ │ └── Virtual Database (structured state)
|
|
797
|
+
│ └── Files (uploaded documents)
|
|
798
|
+
└── Billing (thread-based credits)
|
|
799
|
+
|
|
800
|
+
Client Tools
|
|
801
|
+
├── CLI (epsimo command)
|
|
802
|
+
├── Python SDK (EpsimoClient)
|
|
803
|
+
└── React UI Kit (ThreadChat, useChat)
|
|
804
|
+
```
|
|
805
|
+
|
|
806
|
+
---
|
|
79
807
|
|
|
80
|
-
|
|
81
|
-
|
|
808
|
+
**Version:** 0.2.0
|
|
809
|
+
**License:** MIT
|
|
810
|
+
**Author:** Thierry Teisseire
|
|
82
811
|
|
|
83
|
-
|
|
84
|
-
- `api_reference.md`: Detailed API documentation and schemas.
|
|
85
|
-
- `virtual_db_guide.md`: Comprehensive guide for managing persistent state.
|
|
812
|
+
For questions or issues, visit [GitHub Issues](https://github.com/thierryteisseire/epsimo-agent/issues).
|