@lakitu/sdk 0.1.2 → 0.1.4
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 +107 -275
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,360 +4,192 @@
|
|
|
4
4
|
|
|
5
5
|
# @lakitu/sdk
|
|
6
6
|
|
|
7
|
-
> Self-hosted AI agent
|
|
7
|
+
> Self-hosted AI agent runtime for [Convex](https://convex.dev) + [E2B](https://e2b.dev)
|
|
8
8
|
|
|
9
|
-
Lakitu
|
|
10
|
-
|
|
11
|
-
## Quick Start
|
|
9
|
+
Lakitu is a framework for AI agents that execute code instead of making tool calls. The agent writes TypeScript, imports capabilities from KSA modules, and runs in an isolated E2B sandbox with its own filesystem, terminal, and database.
|
|
12
10
|
|
|
13
11
|
```bash
|
|
14
|
-
# In your Convex project
|
|
15
12
|
npx @lakitu/sdk init
|
|
13
|
+
```
|
|
16
14
|
|
|
17
|
-
|
|
18
|
-
npx @lakitu/sdk build
|
|
15
|
+
---
|
|
19
16
|
|
|
20
|
-
|
|
21
|
-
npx @lakitu/sdk publish
|
|
22
|
-
```
|
|
17
|
+
## Why Lakitu?
|
|
23
18
|
|
|
24
|
-
|
|
19
|
+
**The core problem:** AI coding agents forget their plan halfway through complex tasks, corrupt the host environment, and hallucinate progress they haven't made.
|
|
25
20
|
|
|
26
|
-
|
|
27
|
-
npm install @lakitu/sdk
|
|
28
|
-
# or
|
|
29
|
-
bun add @lakitu/sdk
|
|
30
|
-
```
|
|
21
|
+
**Lakitu's solution:** Give the agent an isolated computer (E2B sandbox), structured capabilities (KSA files), persistent memory (Beads task graph), and verifiable state (Convex database).
|
|
31
22
|
|
|
32
|
-
|
|
23
|
+
| Component | What it solves |
|
|
24
|
+
|-----------|----------------|
|
|
25
|
+
| **E2B Sandbox** | Agent gets its own VM—can't break your machine. Boots in 150ms. |
|
|
26
|
+
| **KSA Files** | Agent capabilities defined in code, not buried in prompts. Testable, version-controlled. |
|
|
27
|
+
| **Beads** | Git-backed task graph. Agent always knows what's done, what's blocked, what's next. |
|
|
28
|
+
| **Convex** | Real-time database in the sandbox. Agent can verify actual state, not just claim progress. |
|
|
33
29
|
|
|
34
|
-
|
|
30
|
+
---
|
|
35
31
|
|
|
36
|
-
|
|
32
|
+
## Code Execution vs Tool Calls
|
|
37
33
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
npx @lakitu/sdk init --skip-install # Skip npm install
|
|
34
|
+
Most agent frameworks use JSON tool calls:
|
|
35
|
+
```json
|
|
36
|
+
{ "tool": "readFile", "args": { "path": "app.ts" } }
|
|
42
37
|
```
|
|
43
38
|
|
|
44
|
-
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
39
|
+
Lakitu agents write code:
|
|
40
|
+
```typescript
|
|
41
|
+
import { file, shell } from './ksa';
|
|
42
|
+
|
|
43
|
+
const code = await file.read('app.ts');
|
|
44
|
+
await file.write('app.ts', fixedCode);
|
|
45
|
+
const result = await shell.exec('bun test');
|
|
50
46
|
```
|
|
51
47
|
|
|
52
|
-
|
|
48
|
+
**Why this is better:**
|
|
49
|
+
- No tool schemas sent every request (saves 40-60% tokens)
|
|
50
|
+
- Natural composition—chain operations like normal code
|
|
51
|
+
- See exactly what ran, not just "tool was called"
|
|
52
|
+
- Works with any LLM that generates code
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Quick Start
|
|
57
|
+
|
|
58
|
+
### 1. Initialize
|
|
55
59
|
|
|
56
60
|
```bash
|
|
57
|
-
npx @lakitu/sdk
|
|
58
|
-
npx @lakitu/sdk build --base # Build base template only
|
|
59
|
-
npx @lakitu/sdk build --custom # Build custom template only
|
|
61
|
+
npx @lakitu/sdk init
|
|
60
62
|
```
|
|
61
63
|
|
|
62
|
-
|
|
64
|
+
Creates `convex/lakitu/config.ts` and an example KSA.
|
|
63
65
|
|
|
64
|
-
|
|
66
|
+
### 2. Build sandbox template
|
|
65
67
|
|
|
66
68
|
```bash
|
|
67
|
-
npx @lakitu/sdk
|
|
69
|
+
npx @lakitu/sdk build
|
|
68
70
|
```
|
|
69
71
|
|
|
70
|
-
|
|
72
|
+
Pre-deploys Convex functions into an E2B template. Sandboxes boot instantly with everything ready.
|
|
71
73
|
|
|
72
|
-
|
|
74
|
+
### 3. Configure
|
|
73
75
|
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
│ LLM Response │ │ LLM Response │
|
|
78
|
-
│ { │ │ ```typescript │
|
|
79
|
-
│ "tool": "x", │ vs │ import { x } │
|
|
80
|
-
│ "args": {} │ │ await x(...) │
|
|
81
|
-
│ } │ │ ``` │
|
|
82
|
-
└────────┬────────┘ └────────┬────────┘
|
|
83
|
-
│ │
|
|
84
|
-
Parse JSON Execute TypeScript
|
|
85
|
-
Route to tool (E2B sandbox)
|
|
86
|
-
│ │
|
|
87
|
-
┌────▼────┐ ┌───────▼───────┐
|
|
88
|
-
│ Executor │ │ KSA Modules │
|
|
89
|
-
└─────────┘ └───────────────┘
|
|
90
|
-
```
|
|
76
|
+
```typescript
|
|
77
|
+
// convex/lakitu/config.ts
|
|
78
|
+
import { Lakitu } from "@lakitu/sdk";
|
|
91
79
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
-
|
|
95
|
-
|
|
96
|
-
|
|
80
|
+
export default Lakitu.configure({
|
|
81
|
+
template: "lakitu",
|
|
82
|
+
model: "anthropic/claude-sonnet-4-20250514",
|
|
83
|
+
ksas: ["file", "shell", "browser", "beads"],
|
|
84
|
+
});
|
|
85
|
+
```
|
|
97
86
|
|
|
98
87
|
---
|
|
99
88
|
|
|
100
|
-
##
|
|
101
|
-
|
|
102
|
-
KSAs (Knowledge, Skills, and Abilities) are capability modules that agents use via code execution. The SDK provides a type-safe builder API for defining KSAs.
|
|
89
|
+
## Defining KSAs
|
|
103
90
|
|
|
104
|
-
|
|
91
|
+
KSAs (Knowledge, Skills, Abilities) are capability modules. Instead of prompt engineering, you define what the agent can do in TypeScript:
|
|
105
92
|
|
|
106
93
|
```typescript
|
|
107
94
|
import { defineKSA, fn, service, primitive } from "@lakitu/sdk";
|
|
108
95
|
|
|
109
|
-
export const
|
|
110
|
-
.description("
|
|
111
|
-
.category("skills")
|
|
112
|
-
|
|
113
|
-
.
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
.description("Search for something")
|
|
118
|
-
.param("query", { type: "string", required: true })
|
|
119
|
-
.param("limit", { type: "number", default: 10 })
|
|
120
|
-
.returns<SearchResult[]>()
|
|
121
|
-
.impl(service("services.Search.internal.query")
|
|
122
|
-
.mapArgs(({ query, limit }) => ({ q: query, max: limit }))
|
|
123
|
-
.mapResult(r => r.results)
|
|
124
|
-
)
|
|
96
|
+
export const dbKSA = defineKSA("database")
|
|
97
|
+
.description("Database operations")
|
|
98
|
+
.category("skills")
|
|
99
|
+
|
|
100
|
+
.fn("migrate", fn()
|
|
101
|
+
.description("Run database migration")
|
|
102
|
+
.param("version", { type: "string", required: true })
|
|
103
|
+
.impl(service("services.Database.internal.migrate"))
|
|
125
104
|
)
|
|
126
|
-
|
|
127
|
-
.fn("
|
|
128
|
-
.description("
|
|
129
|
-
.
|
|
130
|
-
.impl(primitive("file.read"))
|
|
105
|
+
|
|
106
|
+
.fn("backup", fn()
|
|
107
|
+
.description("Create database backup")
|
|
108
|
+
.impl(primitive("shell.exec"))
|
|
131
109
|
)
|
|
132
|
-
|
|
110
|
+
|
|
133
111
|
.build();
|
|
134
112
|
```
|
|
135
113
|
|
|
136
|
-
###
|
|
114
|
+
### Implementation types
|
|
137
115
|
|
|
116
|
+
**Service** — calls your Convex backend:
|
|
138
117
|
```typescript
|
|
139
|
-
|
|
140
|
-
// Builders
|
|
141
|
-
defineKSA, // Create a KSA definition
|
|
142
|
-
fn, // Create a function definition
|
|
143
|
-
service, // Service implementation (calls cloud Convex)
|
|
144
|
-
primitive, // Primitive implementation (local sandbox ops)
|
|
145
|
-
composite, // Composite implementation (chain operations)
|
|
146
|
-
|
|
147
|
-
// Registry utilities
|
|
148
|
-
createRegistry,
|
|
149
|
-
getFunction,
|
|
150
|
-
|
|
151
|
-
// Types
|
|
152
|
-
type KSADef,
|
|
153
|
-
type FunctionDef,
|
|
154
|
-
type ParamDef,
|
|
155
|
-
type Implementation,
|
|
156
|
-
} from "@lakitu/sdk";
|
|
118
|
+
.impl(service("services.MyApi.internal.doThing"))
|
|
157
119
|
```
|
|
158
120
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
#### Service Implementation
|
|
162
|
-
Calls a Convex function via the cloud gateway:
|
|
163
|
-
|
|
164
|
-
```typescript
|
|
165
|
-
.impl(service("services.MyService.internal.action")
|
|
166
|
-
.mapArgs(({ input }) => ({ data: input })) // Transform args
|
|
167
|
-
.mapResult(r => r.value) // Transform result
|
|
168
|
-
)
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
#### Primitive Implementation
|
|
172
|
-
Uses local sandbox capabilities (file, shell, browser):
|
|
173
|
-
|
|
121
|
+
**Primitive** — local sandbox operation:
|
|
174
122
|
```typescript
|
|
175
123
|
.impl(primitive("file.read"))
|
|
176
124
|
.impl(primitive("shell.exec"))
|
|
177
125
|
.impl(primitive("browser.screenshot"))
|
|
178
126
|
```
|
|
179
127
|
|
|
180
|
-
|
|
181
|
-
- `file.read`, `file.write`, `file.edit`, `file.glob`, `file.grep`, `file.ls`, `file.exists`, `file.stat`
|
|
182
|
-
- `shell.exec`
|
|
183
|
-
- `browser.open`, `browser.screenshot`, `browser.click`, `browser.type`, `browser.getHtml`, `browser.getText`, `browser.close`
|
|
184
|
-
|
|
185
|
-
#### Composite Implementation
|
|
186
|
-
Chain multiple operations:
|
|
187
|
-
|
|
188
|
-
```typescript
|
|
189
|
-
.impl(composite()
|
|
190
|
-
.call("file.read", { filePath: "./config.json" }, "config")
|
|
191
|
-
.call("myKsa.process", ctx => ({ data: ctx.vars.config }), "result")
|
|
192
|
-
.return(ctx => ctx.vars.result)
|
|
193
|
-
)
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
### Parameter Types
|
|
197
|
-
|
|
198
|
-
```typescript
|
|
199
|
-
.param("name", { type: "string", required: true })
|
|
200
|
-
.param("count", { type: "number", default: 10 })
|
|
201
|
-
.param("enabled", { type: "boolean", default: false })
|
|
202
|
-
.param("tags", { type: "array" })
|
|
203
|
-
.param("options", { type: "object" })
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
---
|
|
207
|
-
|
|
208
|
-
## Configuration
|
|
209
|
-
|
|
210
|
-
After running `init`, configure Lakitu in `convex/lakitu/config.ts`:
|
|
211
|
-
|
|
212
|
-
```typescript
|
|
213
|
-
import { Lakitu } from "@lakitu/sdk";
|
|
214
|
-
|
|
215
|
-
export default Lakitu.configure({
|
|
216
|
-
// E2B template name (build with: npx lakitu build)
|
|
217
|
-
template: "lakitu",
|
|
128
|
+
### Built-in primitives
|
|
218
129
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
// Built-in KSAs
|
|
225
|
-
"file",
|
|
226
|
-
"shell",
|
|
227
|
-
"browser",
|
|
228
|
-
"beads",
|
|
229
|
-
|
|
230
|
-
// Custom KSAs
|
|
231
|
-
"./myCustomKsa",
|
|
232
|
-
],
|
|
233
|
-
|
|
234
|
-
// Sandbox pool settings
|
|
235
|
-
pool: {
|
|
236
|
-
min: 0,
|
|
237
|
-
max: 5,
|
|
238
|
-
idleTimeout: 300_000,
|
|
239
|
-
},
|
|
240
|
-
});
|
|
241
|
-
```
|
|
130
|
+
| Category | Functions |
|
|
131
|
+
|----------|-----------|
|
|
132
|
+
| `file` | `read`, `write`, `edit`, `glob`, `grep`, `ls`, `exists`, `stat` |
|
|
133
|
+
| `shell` | `exec` |
|
|
134
|
+
| `browser` | `open`, `screenshot`, `click`, `type`, `getHtml`, `getText`, `close` |
|
|
242
135
|
|
|
243
136
|
---
|
|
244
137
|
|
|
245
138
|
## Built-in KSAs
|
|
246
139
|
|
|
247
|
-
|
|
|
248
|
-
|
|
249
|
-
|
|
|
250
|
-
|
|
|
251
|
-
|
|
|
252
|
-
|
|
|
253
|
-
|
|
|
254
|
-
|
|
|
255
|
-
|
|
|
256
|
-
| | `companies` | `enrich`, `search`, `techStack` |
|
|
257
|
-
| **Deliverables** | `pdf` | `generate` |
|
|
258
|
-
| | `email` | `send`, `sendBulk` |
|
|
140
|
+
| KSA | What it does |
|
|
141
|
+
|-----|--------------|
|
|
142
|
+
| `file` | Filesystem operations |
|
|
143
|
+
| `shell` | Terminal commands |
|
|
144
|
+
| `browser` | Web automation via Playwright |
|
|
145
|
+
| `beads` | Task tracking (`bd ready`, `bd close`, etc.) |
|
|
146
|
+
| `web` | Search and scrape |
|
|
147
|
+
| `pdf` | Generate PDFs from markdown |
|
|
148
|
+
| `email` | Send emails |
|
|
259
149
|
|
|
260
150
|
---
|
|
261
151
|
|
|
262
|
-
##
|
|
152
|
+
## CLI Commands
|
|
263
153
|
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
│ │ ┌──────┐ ┌──────┐ ┌───────┐ ┌─────────┐ ┌───────┐ ┌─────────┐ │ │
|
|
272
|
-
│ │ │ file │ │ web │ │ news │ │ social │ │ email │ │companies│ │ │
|
|
273
|
-
│ │ └──────┘ └──────┘ └───────┘ └─────────┘ └───────┘ └─────────┘ │ │
|
|
274
|
-
│ └─────────────────────────────────────────────────────────────────┘ │
|
|
275
|
-
│ │ │
|
|
276
|
-
│ Local ops │ Gateway calls │
|
|
277
|
-
│ ▼ │
|
|
278
|
-
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
|
279
|
-
│ │ CLOUD GATEWAY │ │
|
|
280
|
-
│ │ HTTP → Convex Services (OpenRouter, external APIs) │ │
|
|
281
|
-
│ └─────────────────────────────────────────────────────────────────┘ │
|
|
282
|
-
│ │
|
|
283
|
-
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
|
284
|
-
│ │ /home/user/workspace/ Working files │ │
|
|
285
|
-
│ │ /home/user/artifacts/ Persistent outputs (PDFs, screenshots) │ │
|
|
286
|
-
│ └─────────────────────────────────────────────────────────────────┘ │
|
|
287
|
-
└─────────────────────────────────────────────────────────────────────────┘
|
|
154
|
+
```bash
|
|
155
|
+
npx @lakitu/sdk init # Setup in Convex project
|
|
156
|
+
npx @lakitu/sdk init --dir ./convex # Custom directory
|
|
157
|
+
npx @lakitu/sdk build # Build E2B template
|
|
158
|
+
npx @lakitu/sdk build --base # Base template only
|
|
159
|
+
npx @lakitu/sdk build --custom # Custom template only
|
|
160
|
+
npx @lakitu/sdk publish # Template management
|
|
288
161
|
```
|
|
289
162
|
|
|
290
163
|
---
|
|
291
164
|
|
|
292
|
-
##
|
|
293
|
-
|
|
294
|
-
Create `convex/lakitu/weather.ts`:
|
|
165
|
+
## How the pieces fit together
|
|
295
166
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
.group("data")
|
|
303
|
-
|
|
304
|
-
.fn("current", fn()
|
|
305
|
-
.description("Get current weather for a location")
|
|
306
|
-
.param("location", { type: "string", required: true, description: "City name or coordinates" })
|
|
307
|
-
.impl(service("services.Weather.internal.getCurrent"))
|
|
308
|
-
)
|
|
309
|
-
|
|
310
|
-
.fn("forecast", fn()
|
|
311
|
-
.description("Get weather forecast")
|
|
312
|
-
.param("location", { type: "string", required: true })
|
|
313
|
-
.param("days", { type: "number", default: 7 })
|
|
314
|
-
.impl(service("services.Weather.internal.getForecast"))
|
|
315
|
-
)
|
|
316
|
-
|
|
317
|
-
.build();
|
|
318
|
-
|
|
319
|
-
export default weatherKSA;
|
|
320
|
-
```
|
|
167
|
+
1. **Agent receives task** → loads relevant KSAs
|
|
168
|
+
2. **Queries Beads** → `bd ready` returns unblocked work
|
|
169
|
+
3. **Executes in sandbox** → writes code using KSA functions
|
|
170
|
+
4. **Verifies via Convex** → checks actual state matches expected
|
|
171
|
+
5. **Updates Beads** → marks tasks done, creates follow-ups
|
|
172
|
+
6. **Session ends** → `bd sync` persists everything to git
|
|
321
173
|
|
|
322
|
-
The agent can
|
|
323
|
-
|
|
324
|
-
```typescript
|
|
325
|
-
import { current, forecast } from './ksa/weather';
|
|
326
|
-
|
|
327
|
-
const weather = await current("San Francisco");
|
|
328
|
-
console.log(`Current: ${weather.temp}°F, ${weather.condition}`);
|
|
329
|
-
|
|
330
|
-
const nextWeek = await forecast("San Francisco", 7);
|
|
331
|
-
for (const day of nextWeek) {
|
|
332
|
-
console.log(`${day.date}: ${day.high}°F / ${day.low}°F`);
|
|
333
|
-
}
|
|
334
|
-
```
|
|
174
|
+
The agent can pick up exactly where it left off, even across sessions or handoffs to other agents.
|
|
335
175
|
|
|
336
176
|
---
|
|
337
177
|
|
|
338
178
|
## Environment Variables
|
|
339
179
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
---
|
|
344
|
-
|
|
345
|
-
## Requirements
|
|
346
|
-
|
|
347
|
-
- [Convex](https://convex.dev) project
|
|
348
|
-
- [E2B](https://e2b.dev) account (for sandbox hosting)
|
|
349
|
-
- Node.js 18+ or Bun
|
|
180
|
+
| Variable | Description |
|
|
181
|
+
|----------|-------------|
|
|
182
|
+
| `E2B_API_KEY` | Your E2B API key (or `e2b auth login`) |
|
|
350
183
|
|
|
351
184
|
---
|
|
352
185
|
|
|
353
186
|
## Links
|
|
354
187
|
|
|
355
|
-
- [npm
|
|
188
|
+
- [npm](https://www.npmjs.com/package/@lakitu/sdk)
|
|
356
189
|
- [GitHub](https://github.com/shinyobjectz/lakitu)
|
|
357
|
-
- [E2B
|
|
358
|
-
- [Convex
|
|
359
|
-
|
|
360
|
-
---
|
|
190
|
+
- [E2B](https://e2b.dev/docs)
|
|
191
|
+
- [Convex](https://docs.convex.dev)
|
|
192
|
+
- [Beads](https://github.com/steveyegge/beads)
|
|
361
193
|
|
|
362
194
|
## License
|
|
363
195
|
|