@agentuity/claude-code 2.0.10 → 3.0.0-alpha.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/.claude-plugin/plugin.json +16 -6
- package/AGENTS.md +48 -60
- package/README.md +51 -126
- package/dist/install.d.ts +2 -2
- package/dist/install.d.ts.map +1 -1
- package/dist/install.js +4 -4
- package/dist/install.js.map +1 -1
- package/hooks/hooks.json +2 -56
- package/hooks/session-start.sh +43 -0
- package/package.json +12 -8
- package/skills/agentuity-backend/SKILL.md +181 -378
- package/skills/agentuity-cloud/SKILL.md +34 -75
- package/skills/agentuity-frontend/SKILL.md +79 -218
- package/skills/agentuity-ops/SKILL.md +72 -180
- package/skills/agentuity-project/SKILL.md +507 -0
- package/src/install.ts +4 -6
- package/agents/architect.md +0 -322
- package/agents/builder.md +0 -414
- package/agents/lead.md +0 -738
- package/agents/memory.md +0 -1015
- package/agents/product.md +0 -520
- package/agents/reviewer.md +0 -374
- package/agents/scout.md +0 -320
- package/commands/agentuity-cadence-cancel.md +0 -20
- package/commands/agentuity-cadence.md +0 -76
- package/commands/agentuity-coder.md +0 -15
- package/commands/agentuity-memory-share.md +0 -31
- package/commands/agentuity-sandbox.md +0 -33
- package/hooks/scripts/block-sensitive-commands.sh +0 -43
- package/hooks/scripts/cadence-stop.sh +0 -180
- package/hooks/scripts/pre-compact.sh +0 -24
- package/hooks/scripts/session-end.sh +0 -203
- package/hooks/scripts/session-start.sh +0 -68
- package/hooks/scripts/setup-cadence.sh +0 -133
- package/hooks/scripts/stop-memory-save.sh +0 -69
- package/skills/agentuity-command-runner/SKILL.md +0 -128
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: agentuity-backend
|
|
3
|
-
description: When
|
|
4
|
-
version:
|
|
3
|
+
description: When building AI agents, backend APIs, or server-side logic with Agentuity. Covers @agentuity/runtime for agent handlers and HTTP routing, @agentuity/schema for validation, @agentuity/drizzle and @agentuity/postgres for database access, and @agentuity/evals for testing agent quality.
|
|
4
|
+
version: 2.0.0
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Agentuity Backend Reference
|
|
8
8
|
|
|
9
|
-
Deep reference material for the Agentuity SDK backend packages used to build agents, APIs, and server-side applications.
|
|
10
|
-
|
|
11
9
|
## Package Overview
|
|
12
10
|
|
|
13
11
|
| Package | Purpose |
|
|
@@ -31,450 +29,255 @@ Deep reference material for the Agentuity SDK backend packages used to build age
|
|
|
31
29
|
| `zod` | `@agentuity/schema` | Lightweight, built-in, StandardSchemaV1 |
|
|
32
30
|
| `console.log` | `ctx.logger` | Structured, observable, OpenTelemetry |
|
|
33
31
|
| Generic SQL clients | Bun's native `sql` | Bun-native, auto-credentials |
|
|
32
|
+
| `createRouter()` wrapper | `new Hono<Env>()` directly | Chained methods enable hc<AppRouter>() type safety |
|
|
34
33
|
|
|
35
34
|
**Note:** Both Zod and @agentuity/schema implement StandardSchemaV1, so agent schemas accept either.
|
|
36
35
|
|
|
37
|
-
##
|
|
38
|
-
|
|
39
|
-
When uncertain, look up:
|
|
40
|
-
|
|
41
|
-
- **SDK Source**: https://github.com/agentuity/sdk/tree/main/packages
|
|
42
|
-
- **Docs**: https://agentuity.dev
|
|
43
|
-
- **Runtime**: https://github.com/agentuity/sdk/tree/main/packages/runtime/src
|
|
44
|
-
- **Examples**: https://github.com/agentuity/sdk/tree/main/apps/testing/integration-suite
|
|
45
|
-
|
|
46
|
-
---
|
|
47
|
-
|
|
48
|
-
## @agentuity/runtime
|
|
36
|
+
## AI Gateway (Default — No API Keys Needed)
|
|
49
37
|
|
|
50
|
-
|
|
38
|
+
LLM requests automatically route through Agentuity's **AI Gateway** when running via `agentuity dev` or deployed. **Do not ask users for LLM provider API keys.** The gateway supports models from any provider (OpenAI, Anthropic, Groq, etc.) — use the provider SDK that matches the model:
|
|
51
39
|
|
|
52
40
|
```typescript
|
|
53
|
-
|
|
54
|
-
import
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
input: s.object({ message: s.string() }),
|
|
60
|
-
output: s.object({ reply: s.string() }),
|
|
61
|
-
},
|
|
62
|
-
// Optional: setup runs once on app startup
|
|
63
|
-
setup: async (app) => {
|
|
64
|
-
const cache = new Map();
|
|
65
|
-
return { cache }; // Available via ctx.config
|
|
66
|
-
},
|
|
67
|
-
// Optional: cleanup on shutdown
|
|
68
|
-
shutdown: async (app, config) => {
|
|
69
|
-
config.cache.clear();
|
|
70
|
-
},
|
|
71
|
-
handler: async (ctx, input) => {
|
|
72
|
-
// ctx has all services
|
|
73
|
-
return { reply: `Got: ${input.message}` };
|
|
74
|
-
},
|
|
41
|
+
// For OpenAI models (gpt-5-mini, gpt-5, etc.) — use the OpenAI SDK
|
|
42
|
+
import OpenAI from 'openai';
|
|
43
|
+
const openai = new OpenAI();
|
|
44
|
+
const res = await openai.chat.completions.create({
|
|
45
|
+
model: 'gpt-5-mini',
|
|
46
|
+
messages: [{ role: 'user', content: input.message }],
|
|
75
47
|
});
|
|
76
48
|
```
|
|
77
49
|
|
|
78
|
-
**CRITICAL:** Do NOT add type annotations to handler parameters - let TypeScript infer them from schema.
|
|
79
|
-
|
|
80
|
-
### AgentContext (ctx)
|
|
81
|
-
|
|
82
|
-
| Property | Purpose |
|
|
83
|
-
| ----------------- | ------------------------------------------------------ |
|
|
84
|
-
| `ctx.logger` | Structured logging (trace/debug/info/warn/error/fatal) |
|
|
85
|
-
| `ctx.tracer` | OpenTelemetry tracing |
|
|
86
|
-
| `ctx.kv` | Key-value storage |
|
|
87
|
-
| `ctx.vector` | Semantic search |
|
|
88
|
-
| `ctx.stream` | Stream storage |
|
|
89
|
-
| `ctx.sandbox` | Code execution |
|
|
90
|
-
| `ctx.auth` | User authentication (if configured) |
|
|
91
|
-
| `ctx.thread` | Conversation context (up to 1 hour) |
|
|
92
|
-
| `ctx.session` | Request-scoped context |
|
|
93
|
-
| `ctx.state` | Request-scoped Map (sync) |
|
|
94
|
-
| `ctx.config` | Agent config from setup() |
|
|
95
|
-
| `ctx.app` | App state from createApp setup() |
|
|
96
|
-
| `ctx.current` | Agent metadata (name, agentId, version) |
|
|
97
|
-
| `ctx.sessionId` | Unique request ID |
|
|
98
|
-
| `ctx.waitUntil()` | Background tasks after response |
|
|
99
|
-
|
|
100
|
-
### State Management
|
|
101
|
-
|
|
102
50
|
```typescript
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
// Request state - cleared after handler (sync)
|
|
113
|
-
ctx.state.set('startTime', Date.now());
|
|
114
|
-
|
|
115
|
-
// KV - persists across threads/projects
|
|
116
|
-
await ctx.kv.set('namespace', 'key', value);
|
|
117
|
-
};
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
### Calling Other Agents
|
|
121
|
-
|
|
122
|
-
```typescript
|
|
123
|
-
// Import at top of file
|
|
124
|
-
import otherAgent from '@agent/other-agent';
|
|
125
|
-
|
|
126
|
-
handler: async (ctx, input) => {
|
|
127
|
-
// Type-safe call
|
|
128
|
-
const result = await otherAgent.run({ query: input.text });
|
|
129
|
-
return { data: result };
|
|
130
|
-
};
|
|
51
|
+
// For Anthropic models (claude-sonnet-4-6, etc.) — use the Anthropic SDK
|
|
52
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
53
|
+
const anthropic = new Anthropic();
|
|
54
|
+
const res = await anthropic.messages.create({
|
|
55
|
+
model: 'claude-sonnet-4-6',
|
|
56
|
+
max_tokens: 1024,
|
|
57
|
+
messages: [{ role: 'user', content: input.message }],
|
|
58
|
+
});
|
|
131
59
|
```
|
|
132
60
|
|
|
133
|
-
### Streaming Responses
|
|
134
|
-
|
|
135
61
|
```typescript
|
|
136
|
-
|
|
137
|
-
import {
|
|
62
|
+
// Or use the Vercel AI SDK for a provider-agnostic approach
|
|
63
|
+
import { generateText } from 'ai';
|
|
138
64
|
import { openai } from '@ai-sdk/openai';
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
input: s.object({ message: s.string() }),
|
|
143
|
-
stream: true, // Enable streaming
|
|
144
|
-
},
|
|
145
|
-
handler: async (ctx, input) => {
|
|
146
|
-
const { textStream } = streamText({
|
|
147
|
-
model: openai('gpt-4o'),
|
|
148
|
-
prompt: input.message,
|
|
149
|
-
});
|
|
150
|
-
return textStream;
|
|
151
|
-
},
|
|
65
|
+
const { text } = await generateText({
|
|
66
|
+
model: openai('gpt-5-mini'),
|
|
67
|
+
prompt: input.message,
|
|
152
68
|
});
|
|
153
69
|
```
|
|
154
70
|
|
|
155
|
-
|
|
71
|
+
No API keys needed — the gateway sets provider base URLs automatically. **Match the SDK to the model provider** — don't pass Anthropic model names to the OpenAI client or vice versa.
|
|
156
72
|
|
|
157
|
-
|
|
158
|
-
handler: async (ctx, input) => {
|
|
159
|
-
// Schedule non-blocking work after response
|
|
160
|
-
ctx.waitUntil(async () => {
|
|
161
|
-
await ctx.vector.upsert('docs', {
|
|
162
|
-
key: input.docId,
|
|
163
|
-
document: input.content,
|
|
164
|
-
});
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
return { status: 'Queued for indexing' };
|
|
168
|
-
};
|
|
169
|
-
```
|
|
73
|
+
**Important:** The AI Gateway only works when running via `agentuity dev` or when deployed to Agentuity. It does NOT work with raw `bun run app.ts`.
|
|
170
74
|
|
|
171
|
-
|
|
75
|
+
- Docs: https://agentuity.dev/agents/ai-gateway.md
|
|
76
|
+
- Docs: https://agentuity.dev/agents/ai-sdk-integration.md
|
|
172
77
|
|
|
173
|
-
|
|
174
|
-
import { createRouter } from '@agentuity/runtime';
|
|
175
|
-
import myAgent from '@agent/my-agent';
|
|
78
|
+
## Key Concepts
|
|
176
79
|
|
|
177
|
-
|
|
80
|
+
- Agents are created with `createAgent('name', { description, schema, handler })` from `@agentuity/runtime`
|
|
81
|
+
- Agents must be barrel-exported from `src/agent/index.ts` and passed to `createApp({ agents })`
|
|
82
|
+
- Handler receives `ctx` (AgentContext) and typed `input`
|
|
83
|
+
- `ctx` provides: logger, tracer, kv, vector, stream, sandbox, auth, thread, session, state, config
|
|
84
|
+
- Schemas use `@agentuity/schema` (or Zod — both implement StandardSchemaV1)
|
|
85
|
+
- Call other agents via `@agent/<name>` import alias
|
|
86
|
+
- DON'T add type annotations to handler params — let TS infer from schema
|
|
178
87
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
88
|
+
## Agents Need API Routes
|
|
89
|
+
|
|
90
|
+
**Agents are NOT HTTP endpoints.** To expose an agent over HTTP, create a route in `src/api/` that calls it. Use Hono directly with chained methods for type safety:
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
// src/api/index.ts — compose all routes into a single Hono instance
|
|
94
|
+
import { Hono } from 'hono';
|
|
95
|
+
import type { Env } from '@agentuity/runtime';
|
|
96
|
+
import chat from '@agent/chat';
|
|
97
|
+
|
|
98
|
+
const router = new Hono<Env>()
|
|
99
|
+
.post('/chat', chat.validator(), async (c) => {
|
|
100
|
+
const data = c.req.valid('json');
|
|
101
|
+
const result = await chat.run(data);
|
|
102
|
+
return c.json(result);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
export default router;
|
|
184
106
|
```
|
|
185
107
|
|
|
186
|
-
|
|
108
|
+
For streaming responses, use the `stream()` middleware:
|
|
187
109
|
|
|
188
|
-
|
|
110
|
+
```typescript
|
|
111
|
+
import { Hono } from 'hono';
|
|
112
|
+
import type { Env } from '@agentuity/runtime';
|
|
113
|
+
import { stream } from '@agentuity/runtime';
|
|
114
|
+
import chat from '@agent/chat';
|
|
115
|
+
|
|
116
|
+
const router = new Hono<Env>()
|
|
117
|
+
.post('/chat', stream(async (c) => {
|
|
118
|
+
const body = await c.req.json();
|
|
119
|
+
return chat.run(body);
|
|
120
|
+
}));
|
|
121
|
+
|
|
122
|
+
export default router;
|
|
123
|
+
```
|
|
189
124
|
|
|
190
|
-
|
|
125
|
+
For routes that don't call agents, use the standalone `validator()` for schema validation:
|
|
191
126
|
|
|
192
127
|
```typescript
|
|
128
|
+
import { Hono } from 'hono';
|
|
129
|
+
import type { Env } from '@agentuity/runtime';
|
|
130
|
+
import { validator } from '@agentuity/runtime';
|
|
193
131
|
import { s } from '@agentuity/schema';
|
|
194
132
|
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
email: s.string(),
|
|
198
|
-
age: s.number().optional(),
|
|
199
|
-
role: s.enum(['admin', 'user', 'guest']),
|
|
200
|
-
metadata: s
|
|
201
|
-
.object({
|
|
202
|
-
createdAt: s.string(),
|
|
203
|
-
})
|
|
204
|
-
.optional(),
|
|
205
|
-
tags: s.array(s.string()),
|
|
133
|
+
const OutputSchema = s.object({
|
|
134
|
+
history: s.array(s.object({ text: s.string(), timestamp: s.string() })),
|
|
206
135
|
});
|
|
207
136
|
|
|
208
|
-
|
|
209
|
-
|
|
137
|
+
const router = new Hono<Env>()
|
|
138
|
+
.get('/history', validator({ output: OutputSchema }), async (c) => {
|
|
139
|
+
const history = (await c.var.thread.state.get('history')) ?? [];
|
|
140
|
+
return c.json({ history });
|
|
141
|
+
});
|
|
210
142
|
|
|
211
|
-
|
|
212
|
-
s.coerce.string(); // Coerces to string
|
|
213
|
-
s.coerce.number(); // Coerces to number
|
|
214
|
-
s.coerce.boolean(); // Coerces to boolean
|
|
215
|
-
s.coerce.date(); // Coerces to Date
|
|
143
|
+
export default router;
|
|
216
144
|
```
|
|
217
145
|
|
|
218
|
-
|
|
146
|
+
- Docs: https://agentuity.dev/routes/http.md
|
|
219
147
|
|
|
220
|
-
|
|
221
|
-
- User prefers Zod
|
|
222
|
-
- Existing Zod schemas in codebase
|
|
148
|
+
## Agent Context vs Route Context
|
|
223
149
|
|
|
224
|
-
|
|
150
|
+
**Different APIs for agents and routes — don't mix them up:**
|
|
225
151
|
|
|
226
|
-
|
|
152
|
+
| Service | In agents (`handler`) | In routes (`router`) |
|
|
153
|
+
| --- | --- | --- |
|
|
154
|
+
| Logger | `ctx.logger` | `c.var.logger` |
|
|
155
|
+
| KV Storage | `ctx.kv` | `c.var.kv` |
|
|
156
|
+
| Vector | `ctx.vector` | `c.var.vector` |
|
|
157
|
+
| Stream | `ctx.stream` | `c.var.stream` |
|
|
158
|
+
| Sandbox | `ctx.sandbox` | `c.var.sandbox` |
|
|
159
|
+
| Thread | `ctx.thread` | `c.var.thread` |
|
|
160
|
+
| Session | `ctx.session` | `c.var.session` |
|
|
227
161
|
|
|
228
|
-
|
|
162
|
+
- Docs: https://agentuity.dev/agents/creating-agents.md
|
|
229
163
|
|
|
230
|
-
|
|
164
|
+
## KV Storage API
|
|
231
165
|
|
|
232
|
-
|
|
233
|
-
import { createPostgresDrizzle, pgTable, text, serial, eq } from '@agentuity/drizzle';
|
|
234
|
-
|
|
235
|
-
// Define schema
|
|
236
|
-
const users = pgTable('users', {
|
|
237
|
-
id: serial('id').primaryKey(),
|
|
238
|
-
name: text('name').notNull(),
|
|
239
|
-
email: text('email').notNull().unique(),
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
// Create database instance (uses DATABASE_URL by default)
|
|
243
|
-
const { db, client, close } = createPostgresDrizzle({
|
|
244
|
-
schema: { users },
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
// Or with explicit configuration
|
|
248
|
-
const { db, close } = createPostgresDrizzle({
|
|
249
|
-
connectionString: 'postgres://user:pass@localhost:5432/mydb',
|
|
250
|
-
schema: { users },
|
|
251
|
-
logger: true,
|
|
252
|
-
reconnect: {
|
|
253
|
-
maxAttempts: 5,
|
|
254
|
-
initialDelayMs: 100,
|
|
255
|
-
},
|
|
256
|
-
onReconnected: () => console.log('Reconnected!'),
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
// Execute type-safe queries
|
|
260
|
-
const allUsers = await db.select().from(users);
|
|
261
|
-
const user = await db.select().from(users).where(eq(users.id, 1));
|
|
262
|
-
|
|
263
|
-
// Clean up
|
|
264
|
-
await close();
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
### Integration with @agentuity/auth
|
|
166
|
+
**`ctx.kv` requires a namespace and key — NOT just a key.** Returns a `DataResult<T>` discriminated union, not `T | null`:
|
|
268
167
|
|
|
269
168
|
```typescript
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
169
|
+
// GET — check .exists before accessing .data
|
|
170
|
+
const result = await ctx.kv.get<MyType>('my-namespace', 'my-key');
|
|
171
|
+
const data: MyType[] = result.exists ? result.data : [];
|
|
273
172
|
|
|
274
|
-
|
|
173
|
+
// SET — namespace, key, value, optional params
|
|
174
|
+
await ctx.kv.set('my-namespace', 'my-key', { count: 42 }, { ttl: 3600 });
|
|
275
175
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
});
|
|
176
|
+
// DELETE
|
|
177
|
+
await ctx.kv.delete('my-namespace', 'my-key');
|
|
279
178
|
```
|
|
280
179
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
The package re-exports commonly used items:
|
|
284
|
-
|
|
285
|
-
- From drizzle-orm: `sql`, `eq`, `and`, `or`, `not`, `desc`, `asc`, `gt`, `gte`, `lt`, `lte`, etc.
|
|
286
|
-
- From drizzle-orm/pg-core: `pgTable`, `pgSchema`, `pgEnum`, column types
|
|
287
|
-
- From @agentuity/postgres: `postgres`, `PostgresClient`, etc.
|
|
180
|
+
Namespaces are auto-created on first write with a 7-day default TTL. Override per-key via `{ ttl: seconds }` (min 60s, max 365 days). In routes, use `c.var.kv` instead of `ctx.kv` — same API.
|
|
288
181
|
|
|
289
|
-
|
|
182
|
+
- Docs: https://agentuity.dev/services/storage/key-value.md
|
|
290
183
|
|
|
291
|
-
##
|
|
184
|
+
## Agent Evaluations
|
|
292
185
|
|
|
293
|
-
|
|
186
|
+
Use `@agentuity/evals` for preset evaluations and `agent.createEval()` for custom ones:
|
|
294
187
|
|
|
295
188
|
```typescript
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
189
|
+
// Preset eval (e.g., adversarial testing)
|
|
190
|
+
import { adversarial } from '@agentuity/evals';
|
|
191
|
+
import agent from './index';
|
|
192
|
+
|
|
193
|
+
export const adversarialEval = agent.createEval(
|
|
194
|
+
adversarial({
|
|
195
|
+
middleware: {
|
|
196
|
+
transformInput: (input) => ({ request: input.text }),
|
|
197
|
+
transformOutput: (output) => ({ response: output.result }),
|
|
198
|
+
},
|
|
199
|
+
})
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
// Custom eval
|
|
203
|
+
export const qualityEval = agent.createEval('quality-check', {
|
|
204
|
+
description: 'Verifies output quality meets threshold',
|
|
205
|
+
handler: async (ctx, input, output) => {
|
|
206
|
+
return {
|
|
207
|
+
passed: output.result.length > 0,
|
|
208
|
+
reason: output.result.length > 0 ? 'Output is non-empty' : 'Empty output',
|
|
209
|
+
};
|
|
210
|
+
},
|
|
310
211
|
});
|
|
311
|
-
|
|
312
|
-
// Query using tagged template literals
|
|
313
|
-
const users = await sql`SELECT * FROM users WHERE active = ${true}`;
|
|
314
|
-
|
|
315
|
-
// Transactions
|
|
316
|
-
const tx = await sql.begin();
|
|
317
|
-
try {
|
|
318
|
-
await tx`INSERT INTO users (name) VALUES (${name})`;
|
|
319
|
-
await tx.commit();
|
|
320
|
-
} catch (error) {
|
|
321
|
-
await tx.rollback();
|
|
322
|
-
throw error;
|
|
323
|
-
}
|
|
324
212
|
```
|
|
325
213
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
- **Lazy connections**: Connection established on first query (set `preconnect: true` for immediate)
|
|
329
|
-
- **Auto-reconnection**: Exponential backoff with jitter
|
|
330
|
-
- **Graceful shutdown**: Detects SIGTERM/SIGINT, prevents reconnection during shutdown
|
|
331
|
-
- **Global registry**: All clients tracked for coordinated shutdown
|
|
214
|
+
Place eval files alongside the agent: `src/agent/<name>/eval.ts`.
|
|
332
215
|
|
|
333
|
-
|
|
216
|
+
- Docs: https://agentuity.dev/agents/evaluations.md
|
|
334
217
|
|
|
335
|
-
|
|
218
|
+
## v2 Migration
|
|
336
219
|
|
|
337
|
-
|
|
338
|
-
import { sql } from 'bun';
|
|
339
|
-
const rows = await sql`SELECT * FROM users`;
|
|
340
|
-
```
|
|
220
|
+
If upgrading from v1, run `npx @agentuity/migrate` to auto-convert `createRouter()` to chained Hono style and generate barrel files. See the [Migration Guide](https://agentuity.dev/reference/migration-guide.md).
|
|
341
221
|
|
|
342
|
-
|
|
222
|
+
## Documentation Links
|
|
343
223
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
224
|
+
| Topic | Link |
|
|
225
|
+
| --- | --- |
|
|
226
|
+
| Creating Agents | https://agentuity.dev/agents/creating-agents.md |
|
|
227
|
+
| State Management | https://agentuity.dev/agents/state-management.md |
|
|
228
|
+
| Streaming Responses | https://agentuity.dev/agents/streaming-responses.md |
|
|
229
|
+
| Schema Libraries | https://agentuity.dev/agents/schema-libraries.md |
|
|
230
|
+
| Calling Other Agents | https://agentuity.dev/agents/calling-other-agents.md |
|
|
231
|
+
| Events & Lifecycle | https://agentuity.dev/agents/events-lifecycle.md |
|
|
232
|
+
| Evaluations | https://agentuity.dev/agents/evaluations.md |
|
|
233
|
+
| AI SDK Integration | https://agentuity.dev/agents/ai-sdk-integration.md |
|
|
234
|
+
| AI Gateway | https://agentuity.dev/agents/ai-gateway.md |
|
|
235
|
+
| Drizzle ORM | https://agentuity.dev/services/database/drizzle.md |
|
|
236
|
+
| Postgres Client | https://agentuity.dev/services/database/postgres.md |
|
|
237
|
+
| SDK Reference | https://agentuity.dev/reference/sdk-reference.md |
|
|
238
|
+
| Migration Guide | https://agentuity.dev/reference/migration-guide.md |
|
|
349
239
|
|
|
350
|
-
##
|
|
240
|
+
## Common Mistakes
|
|
351
241
|
|
|
352
|
-
|
|
242
|
+
| Mistake | Better Approach | Why |
|
|
243
|
+
| ---------------------------------------------------- | ----------------------------------------------- | ------------------------------ |
|
|
244
|
+
| `handler: async (ctx: AgentContext, input: MyInput)` | `handler: async (ctx, input)` | Let TS infer types from schema |
|
|
245
|
+
| `const schema = { name: s.string() }` | `const schema = s.object({ name: s.string() })` | Must use s.object() wrapper |
|
|
246
|
+
| `console.log('debug')` in production | `ctx.logger.debug('debug')` | Structured, observable |
|
|
247
|
+
| Ignoring connection resilience | Use @agentuity/drizzle or @agentuity/postgres | Auto-reconnect on failures |
|
|
248
|
+
| Asking for OpenAI/Anthropic API keys | Use the AI Gateway (works with SDK key) | LLM requests route through Agentuity automatically |
|
|
249
|
+
| Using `c.var.logger` in agent handlers | Use `ctx.logger` in agents | Agent context and route context have different APIs |
|
|
250
|
+
| Using `ctx.logger` in route handlers | Use `c.var.logger` in routes | Agent context and route context have different APIs |
|
|
251
|
+
| Exposing agents without routes | Create API routes in `src/api/` | Agents are not HTTP endpoints |
|
|
252
|
+
| Skipping agent evaluations | Add eval.ts alongside agent index.ts | Evals catch regressions and validate quality |
|
|
253
|
+
| Using mutating router style (.get() separately) | Use chained Hono methods (.get().post()) | Chained style required for hc<AppRouter>() types |
|
|
254
|
+
| Missing agent barrel file | Create src/agent/index.ts re-exporting agents | v2 requires explicit agent registration |
|
|
255
|
+
| `ctx.kv.get('key')` (missing namespace) | `ctx.kv.get<T>('namespace', 'key')` — check `.exists` | KV requires namespace + key, returns DataResult not T |
|
|
256
|
+
| Passing Claude model to `new OpenAI()` | Use `new Anthropic()` for Claude models | Match the SDK to the model provider — gateway routes automatically |
|
|
257
|
+
| Running `new OpenAI()` outside `agentuity dev` | Always run via `agentuity dev` or deploy first | AI Gateway only sets provider base URLs in the Agentuity runtime |
|
|
258
|
+
|
|
259
|
+
## Example
|
|
353
260
|
|
|
354
261
|
```typescript
|
|
355
|
-
import {
|
|
262
|
+
import { createAgent } from '@agentuity/runtime';
|
|
356
263
|
import { s } from '@agentuity/schema';
|
|
357
264
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
// Create preset eval
|
|
364
|
-
export const toneEval = createPresetEval<
|
|
365
|
-
typeof inputSchema, // TInput
|
|
366
|
-
typeof outputSchema, // TOutput
|
|
367
|
-
ToneEvalOptions // TOptions
|
|
368
|
-
>({
|
|
369
|
-
name: 'tone-check',
|
|
370
|
-
description: 'Evaluates if response matches expected tone',
|
|
371
|
-
options: {
|
|
372
|
-
model: openai('gpt-4o'), // LanguageModel instance from AI SDK
|
|
373
|
-
expectedTone: 'friendly',
|
|
265
|
+
export default createAgent('my-agent', {
|
|
266
|
+
schema: {
|
|
267
|
+
input: s.object({ message: s.string() }),
|
|
268
|
+
output: s.object({ reply: s.string() }),
|
|
374
269
|
},
|
|
375
|
-
handler: async (ctx, input
|
|
376
|
-
//
|
|
377
|
-
return {
|
|
378
|
-
passed: true,
|
|
379
|
-
score: 0.85, // optional (0.0-1.0)
|
|
380
|
-
reason: 'Response matches friendly tone',
|
|
381
|
-
};
|
|
270
|
+
handler: async (ctx, input) => {
|
|
271
|
+
// ctx provides: logger, kv, vector, stream, sandbox, auth, thread, session, state
|
|
272
|
+
return { reply: `Got: ${input.message}` };
|
|
382
273
|
},
|
|
383
274
|
});
|
|
384
|
-
|
|
385
|
-
// Usage on agent
|
|
386
|
-
agent.createEval(toneEval()); // Use defaults
|
|
387
|
-
agent.createEval(toneEval({ expectedTone: 'formal' })); // Override options
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
**Key points:**
|
|
391
|
-
|
|
392
|
-
- Use `s.object({...})` for typed input/output, or `undefined` for generic evals
|
|
393
|
-
- Options are flattened (not nested under `options`)
|
|
394
|
-
- Return `{ passed, score?, reason? }` - throw on error
|
|
395
|
-
- Use middleware to transform agent input/output to eval's expected types
|
|
396
|
-
|
|
397
|
-
---
|
|
398
|
-
|
|
399
|
-
## @agentuity/core
|
|
400
|
-
|
|
401
|
-
Foundational types and utilities used by all Agentuity packages.
|
|
402
|
-
|
|
403
|
-
### StructuredError
|
|
404
|
-
|
|
405
|
-
```typescript
|
|
406
|
-
import { StructuredError } from '@agentuity/core';
|
|
407
|
-
|
|
408
|
-
const MyError = StructuredError('MyError', 'Something went wrong')<{
|
|
409
|
-
code: string;
|
|
410
|
-
details: string;
|
|
411
|
-
}>();
|
|
412
|
-
|
|
413
|
-
throw new MyError({ code: 'ERR_001', details: 'More info' });
|
|
414
|
-
```
|
|
415
|
-
|
|
416
|
-
### Core Types
|
|
417
|
-
|
|
418
|
-
- **StructuredError**: Create typed errors with structured data
|
|
419
|
-
- **StandardSchemaV1**: Interface for schema validation (implemented by @agentuity/schema and Zod)
|
|
420
|
-
- **Json types**: Type utilities for JSON-serializable data
|
|
421
|
-
- **Service interfaces**: KeyValueStorage, VectorStorage, StreamStorage
|
|
422
|
-
|
|
423
|
-
---
|
|
424
|
-
|
|
425
|
-
## @agentuity/server
|
|
426
|
-
|
|
427
|
-
Server utilities that work in both Node.js and Bun.
|
|
428
|
-
|
|
429
|
-
```typescript
|
|
430
|
-
import { validateDatabaseName, validateBucketName } from '@agentuity/server';
|
|
431
|
-
|
|
432
|
-
// Validate before provisioning
|
|
433
|
-
const dbResult = validateDatabaseName(userInput);
|
|
434
|
-
if (!dbResult.valid) {
|
|
435
|
-
throw new Error(dbResult.error);
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
const bucketResult = validateBucketName(userInput);
|
|
439
|
-
if (!bucketResult.valid) {
|
|
440
|
-
throw new Error(bucketResult.error);
|
|
441
|
-
}
|
|
442
275
|
```
|
|
443
276
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
## Common Patterns
|
|
277
|
+
## When In Doubt, Check the Docs
|
|
447
278
|
|
|
448
|
-
|
|
279
|
+
If you're unsure about any API signature, context method, or pattern, **check the documentation first** rather than guessing:
|
|
449
280
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
├── package.json
|
|
454
|
-
├── src/
|
|
455
|
-
│ ├── agent/<name>/ # Each agent in its own folder
|
|
456
|
-
│ │ ├── agent.ts # Agent definition
|
|
457
|
-
│ │ └── index.ts # Exports
|
|
458
|
-
│ ├── api/ # API routes (Hono)
|
|
459
|
-
│ └── web/ # React frontend
|
|
460
|
-
└── .env # AGENTUITY_SDK_KEY, DATABASE_URL, etc.
|
|
461
|
-
```
|
|
462
|
-
|
|
463
|
-
### Bun-First Runtime
|
|
464
|
-
|
|
465
|
-
Always prefer Bun built-in APIs:
|
|
466
|
-
|
|
467
|
-
- `Bun.file(f).exists()` not `fs.existsSync(f)`
|
|
468
|
-
- `import { sql } from 'bun'` for simple queries
|
|
469
|
-
- `import { s3 } from 'bun'` for object storage
|
|
470
|
-
|
|
471
|
-
---
|
|
472
|
-
|
|
473
|
-
## Common Mistakes
|
|
474
|
-
|
|
475
|
-
| Mistake | Better Approach | Why |
|
|
476
|
-
| ---------------------------------------------------- | ----------------------------------------------- | ------------------------------ |
|
|
477
|
-
| `handler: async (ctx: AgentContext, input: MyInput)` | `handler: async (ctx, input)` | Let TS infer types from schema |
|
|
478
|
-
| `const schema = { name: s.string() }` | `const schema = s.object({ name: s.string() })` | Must use s.object() wrapper |
|
|
479
|
-
| `console.log('debug')` in production | `ctx.logger.debug('debug')` | Structured, observable |
|
|
480
|
-
| Ignoring connection resilience | Use @agentuity/drizzle or @agentuity/postgres | Auto-reconnect on failures |
|
|
281
|
+
- Full docs: https://agentuity.dev
|
|
282
|
+
- LLM-friendly index: https://agentuity.dev/llms.txt
|
|
283
|
+
- AI Gateway: https://agentuity.dev/agents/ai-gateway.md
|