@botpress/adk-cli 1.19.0-beta.4 → 1.19.0-beta.6
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/{dist/index-a3ZL0_Jr-q145h35p.js → assets/ui-dist/assets/index-BC_iUF2d.js} +2 -2
- package/assets/ui-dist/assets/index-BxpvDT_K.css +1 -0
- package/{dist/index-BESZeTO5-2rpmcefa.js → assets/ui-dist/assets/index-C7gAokRv.js} +2 -2
- package/assets/ui-dist/assets/{index-B3b7PPgV.js → index-exyr_Djl.js} +424 -424
- package/assets/ui-dist/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
- package/assets/ui-dist/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
- package/assets/ui-dist/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- package/assets/ui-dist/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- package/assets/ui-dist/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
- package/assets/ui-dist/index.html +2 -2
- package/dist/{README-wjb7z7f0.md → README-824wa4jj.md} +1 -1
- package/dist/SKILL-75ym6tcj.md +257 -0
- package/dist/SKILL-chnwzmt1.md +548 -0
- package/dist/SKILL-d4bs53y3.md +244 -0
- package/dist/SKILL-h4b2f1n9.md +114 -0
- package/dist/SKILL-hbw5nt95.md +111 -0
- package/dist/actions-h7hxxvxr.md +823 -0
- package/dist/adk-build-emhwd0tg.md +39 -0
- package/dist/adk-debug-yrrdtpmb.md +23 -0
- package/dist/adk-dev-console-7z9rtjpy.md +17 -0
- package/dist/adk-document-ras6zzzh.md +68 -0
- package/dist/adk-eval-vx76dwq0.md +17 -0
- package/dist/adk-explain-fcsaw852.md +22 -0
- package/dist/adk-init-9kmxmbbe.md +30 -0
- package/dist/adk-ship-dybzn884.md +29 -0
- package/dist/adk-test-xq67savs.md +27 -0
- package/dist/adk-validate-1p4skv4m.md +31 -0
- package/dist/advanced-patterns-z86m9h1a.md +669 -0
- package/dist/agent-config-1aqvkrgf.md +450 -0
- package/dist/agent-steps-zj4c1n9t.md +115 -0
- package/dist/assets-q7jt8r2q.md +237 -0
- package/dist/autonomous-execution-fymc12e5.md +747 -0
- package/dist/cli-c31e06yr.md +1334 -0
- package/dist/cli.js +4241 -6449
- package/dist/commands.json +25 -4
- package/dist/common-failures-ht29w2db.md +231 -0
- package/dist/component-registry-bbpw0see.md +43 -0
- package/dist/context-api-760cvh0h.md +461 -0
- package/dist/conversation-analysis-8ka4nrm4.md +420 -0
- package/dist/conversation-lifecycle-4seqqjc1.md +311 -0
- package/dist/conversations-gwfvxaee.md +1111 -0
- package/dist/custom-components-y5wdgpey.md +167 -0
- package/dist/debug-workflow-vz84q80v.md +239 -0
- package/dist/desk-k54ktvsd.md +852 -0
- package/dist/doc-standards-ck6ax2jd.md +124 -0
- package/dist/eval-format-7n9brja4.md +354 -0
- package/dist/evals-y1zcr1mc.md +11 -0
- package/dist/explain-config-1yaq3zzd.md +424 -0
- package/dist/files-dzt0wxn3.md +918 -0
- package/dist/{index-3t354nbw.html → index-0qts7wfk.html} +2 -2
- package/{assets/ui-dist/assets/index-a3ZL0_Jr.js → dist/index-BC_iUF2d-3h9mqazs.js} +2 -2
- package/dist/index-BxpvDT_K-62864175.css +1 -0
- package/{assets/ui-dist/assets/index-BESZeTO5.js → dist/index-C7gAokRv-zr7dzkba.js} +2 -2
- package/dist/{index-B3b7PPgV-zetkb01w.js → index-exyr_Djl-ksys08wc.js} +424 -424
- package/dist/integration-actions-xang7tma.md +659 -0
- package/dist/integrations-k5ss07f4.md +266 -0
- package/dist/interfaces-6t0bpxs4.md +97 -0
- package/dist/jetbrains-mono-cyrillic-wght-normal-D73BlboJ-6vpq1jfh.woff2 +0 -0
- package/dist/jetbrains-mono-greek-wght-normal-Bw9x6K1M-jv5dqe09.woff2 +0 -0
- package/dist/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a-h2ysfc3f.woff2 +0 -0
- package/dist/jetbrains-mono-latin-wght-normal-B9CIFXIH-hj2e42wt.woff2 +0 -0
- package/dist/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq-wttk1pwp.woff2 +0 -0
- package/dist/knowledge-bases-20rg8p5c.md +456 -0
- package/dist/llm-debugging-76ng8rzm.md +209 -0
- package/dist/mcp-server-n1asyzhv.md +112 -0
- package/dist/messages-gkkg0b54.md +769 -0
- package/dist/model-configuration-f273kgd0.md +201 -0
- package/dist/multi-agent-dashboard-1mdfjdts.md +70 -0
- package/dist/pages-xn18xn73.md +273 -0
- package/dist/patterns-mistakes-5vb99dhf.md +469 -0
- package/dist/plugins-ttnx8f49.md +280 -0
- package/dist/tables-x45t36dd.md +1136 -0
- package/dist/tags-46td3qrg.md +516 -0
- package/dist/test-patterns-hj47w4nc.md +355 -0
- package/dist/testing-workflow-2vkp932f.md +225 -0
- package/dist/tools-wk7bq24z.md +581 -0
- package/dist/trace-summarization-hdyx1c2e.md +313 -0
- package/dist/traces-and-logs-f2kjfh19.md +203 -0
- package/dist/triggers-4j2cc86x.md +719 -0
- package/dist/ui-server-entry.js +1839 -791
- package/dist/workflow-steps-mrdrf1c5.md +851 -0
- package/dist/workflows-gadx3s69.md +1408 -0
- package/dist/zai-agent-reference-e6644aad.md +454 -0
- package/dist/zai-complete-guide-mnna5d6f.md +1408 -0
- package/package.json +4 -4
- package/assets/ui-dist/assets/index-DIFGtVmI.css +0 -1
- package/dist/index-DIFGtVmI-d4dhjg97.css +0 -1
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
# Per-Primitive Testing Patterns
|
|
2
|
+
|
|
3
|
+
How to write evals for each ADK primitive type. Each section shows the recommended pattern, what to assert, and common pitfalls.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Actions
|
|
8
|
+
|
|
9
|
+
Actions are strongly-typed functions callable from conversations, workflows, other actions, or exposed as AI-callable tools. Test them by triggering a conversation that invokes the action and asserting on the response.
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
import { Eval } from '@botpress/evals'
|
|
13
|
+
|
|
14
|
+
export default new Eval({
|
|
15
|
+
name: 'lookup-order-action',
|
|
16
|
+
tags: ['actions'],
|
|
17
|
+
|
|
18
|
+
conversation: [
|
|
19
|
+
{
|
|
20
|
+
user: 'What is the status of order ORD-123?',
|
|
21
|
+
assert: {
|
|
22
|
+
response: [
|
|
23
|
+
{ contains: 'ORD-123' },
|
|
24
|
+
{ llm_judge: 'Response includes order status information' },
|
|
25
|
+
],
|
|
26
|
+
tools: [
|
|
27
|
+
{ called: 'lookupOrder', params: { orderId: { equals: 'ORD-123' } } },
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
})
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**What to assert:**
|
|
36
|
+
- `tools.called` with expected params — verify the action was invoked correctly
|
|
37
|
+
- `response.contains` — verify the bot surfaced the action's result
|
|
38
|
+
- `state` — if the action writes to state, verify the write
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Tools
|
|
43
|
+
|
|
44
|
+
Tools are LLM-callable functions. Focus on asserting which tools were called, with what params, and in what order.
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
export default new Eval({
|
|
48
|
+
name: 'ticket-creation-tool',
|
|
49
|
+
tags: ['tools'],
|
|
50
|
+
|
|
51
|
+
conversation: [
|
|
52
|
+
{
|
|
53
|
+
user: 'I need help with a billing issue',
|
|
54
|
+
assert: {
|
|
55
|
+
tools: [{ not_called: 'createTicket' }], // not yet
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
user: 'Yes, please create a ticket for this',
|
|
60
|
+
assert: {
|
|
61
|
+
tools: [
|
|
62
|
+
{ called: 'createTicket', params: {
|
|
63
|
+
category: { equals: 'billing' },
|
|
64
|
+
priority: { in: ['normal', 'high'] },
|
|
65
|
+
}},
|
|
66
|
+
],
|
|
67
|
+
response: [{ contains: 'ticket' }],
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
})
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**What to assert:**
|
|
75
|
+
- `tools.called` with `params` — verify inputs are correctly extracted from the conversation
|
|
76
|
+
- `tools.not_called` — verify tools are NOT called prematurely or inappropriately
|
|
77
|
+
- `tools.call_order` — verify the correct sequence when multiple tools are involved
|
|
78
|
+
|
|
79
|
+
### Tool call order pattern
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
assert: {
|
|
83
|
+
tools: [
|
|
84
|
+
{ call_order: ['lookupUser', 'fetchAccountBalance', 'formatResponse'] },
|
|
85
|
+
],
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Workflows
|
|
92
|
+
|
|
93
|
+
Workflows are long-running resumable processes. Use `setup.workflow` to trigger one before the conversation and assert on its execution.
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
export default new Eval({
|
|
97
|
+
name: 'onboarding-workflow',
|
|
98
|
+
tags: ['workflows'],
|
|
99
|
+
|
|
100
|
+
setup: {
|
|
101
|
+
workflow: {
|
|
102
|
+
trigger: 'onboarding',
|
|
103
|
+
input: { userId: 'test-user-1', plan: 'pro' },
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
conversation: [
|
|
108
|
+
{
|
|
109
|
+
user: 'What happens next?',
|
|
110
|
+
assert: {
|
|
111
|
+
workflow: [
|
|
112
|
+
{ name: 'onboarding', entered: true },
|
|
113
|
+
],
|
|
114
|
+
response: [
|
|
115
|
+
{ llm_judge: 'Response explains the onboarding next steps' },
|
|
116
|
+
],
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
|
|
121
|
+
outcome: {
|
|
122
|
+
workflow: [
|
|
123
|
+
{ name: 'onboarding', completed: true },
|
|
124
|
+
],
|
|
125
|
+
state: [
|
|
126
|
+
{ path: 'user.onboardingComplete', equals: true },
|
|
127
|
+
],
|
|
128
|
+
},
|
|
129
|
+
})
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Testing time-based workflows (`step.sleep()`)
|
|
133
|
+
|
|
134
|
+
Server-side scheduling cannot be fast-forwarded. Workaround: make the sleep duration configurable in the workflow by reading from bot state.
|
|
135
|
+
|
|
136
|
+
**In your workflow:**
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
const state = await client.getState({ type: 'bot', id: botId, name: 'botState' })
|
|
140
|
+
const sleepMs = (state.state.payload?.value as any)?.sleepDurationMs ?? 10 * 60 * 1000
|
|
141
|
+
await step.sleep('wait', sleepMs)
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**In your eval:**
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
setup: {
|
|
148
|
+
state: {
|
|
149
|
+
bot: { sleepDurationMs: 3000 }, // 3 seconds instead of 10 minutes
|
|
150
|
+
},
|
|
151
|
+
workflow: {
|
|
152
|
+
trigger: 'reminderFlow',
|
|
153
|
+
input: { userId: 'test-user-1' },
|
|
154
|
+
},
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**What to assert:**
|
|
159
|
+
- `workflow.entered` — workflow was triggered
|
|
160
|
+
- `workflow.completed` — workflow ran to completion (use in `outcome`)
|
|
161
|
+
- `state` — final state after the workflow completes
|
|
162
|
+
- `tools` — any tools the workflow invoked
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Conversations
|
|
167
|
+
|
|
168
|
+
Conversations are channel-specific message handlers. Test multi-turn flows and context retention across turns.
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
export default new Eval({
|
|
172
|
+
name: 'multi-turn-context',
|
|
173
|
+
tags: ['conversations'],
|
|
174
|
+
|
|
175
|
+
conversation: [
|
|
176
|
+
{
|
|
177
|
+
user: 'My name is Alice',
|
|
178
|
+
assert: {
|
|
179
|
+
response: [{ llm_judge: 'Bot acknowledges the name' }],
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
user: 'What is my name?',
|
|
184
|
+
assert: {
|
|
185
|
+
response: [{ contains: 'Alice' }], // bot retained context
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
],
|
|
189
|
+
})
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Testing event-driven conversations
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
export default new Eval({
|
|
196
|
+
name: 'payment-failed-event',
|
|
197
|
+
tags: ['conversations', 'events'],
|
|
198
|
+
|
|
199
|
+
conversation: [
|
|
200
|
+
{
|
|
201
|
+
event: {
|
|
202
|
+
type: 'payment:failed',
|
|
203
|
+
payload: { amount: 99.99, currency: 'USD', customerId: 'cust-001' },
|
|
204
|
+
},
|
|
205
|
+
assert: {
|
|
206
|
+
response: [
|
|
207
|
+
{ llm_judge: 'Bot notifies about the failed payment and offers help' },
|
|
208
|
+
],
|
|
209
|
+
tools: [{ called: 'lookupCustomer' }],
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
],
|
|
213
|
+
})
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Testing that events produce no response
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
export default new Eval({
|
|
220
|
+
name: 'internal-event-silence',
|
|
221
|
+
tags: ['conversations', 'events'],
|
|
222
|
+
|
|
223
|
+
conversation: [
|
|
224
|
+
{
|
|
225
|
+
event: { type: 'internal:heartbeat' },
|
|
226
|
+
expectSilence: true, // bot should not respond to internal events
|
|
227
|
+
},
|
|
228
|
+
],
|
|
229
|
+
})
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## State
|
|
235
|
+
|
|
236
|
+
State is bot/user/conversation-scoped storage. Use `setup.state` to seed values and assert on state changes.
|
|
237
|
+
|
|
238
|
+
### Asserting state was set
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
export default new Eval({
|
|
242
|
+
name: 'state-write',
|
|
243
|
+
tags: ['state'],
|
|
244
|
+
|
|
245
|
+
conversation: [
|
|
246
|
+
{
|
|
247
|
+
user: 'I prefer to be contacted by email',
|
|
248
|
+
assert: {
|
|
249
|
+
state: [
|
|
250
|
+
{ path: 'user.contactPreference', equals: 'email' },
|
|
251
|
+
],
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
],
|
|
255
|
+
})
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Asserting state changed from seeded value
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
export default new Eval({
|
|
262
|
+
name: 'state-transition',
|
|
263
|
+
tags: ['state'],
|
|
264
|
+
|
|
265
|
+
setup: {
|
|
266
|
+
state: {
|
|
267
|
+
conversation: { phase: 'greeting' },
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
|
|
271
|
+
conversation: [
|
|
272
|
+
{
|
|
273
|
+
user: 'I need help with billing',
|
|
274
|
+
assert: {
|
|
275
|
+
state: [
|
|
276
|
+
{ path: 'conversation.phase', equals: 'support' },
|
|
277
|
+
{ path: 'conversation.phase', changed: true }, // changed from 'greeting'
|
|
278
|
+
],
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
],
|
|
282
|
+
})
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Asserting state did NOT change
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
outcome: {
|
|
289
|
+
state: [
|
|
290
|
+
{ path: 'bot.version', changed: false }, // seeded value, should be unchanged
|
|
291
|
+
],
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## Quick Reference: What to Assert Per Primitive
|
|
298
|
+
|
|
299
|
+
| Primitive | Primary assertions | Secondary assertions |
|
|
300
|
+
|-----------|-------------------|---------------------|
|
|
301
|
+
| Actions | `tools.called` + params | `response`, `state` |
|
|
302
|
+
| Tools | `tools.called/not_called/call_order` | `response` |
|
|
303
|
+
| Workflows | `workflow.entered/completed` | `state`, `outcome` |
|
|
304
|
+
| Conversations | `response` (multi-turn) | `tools`, `state` |
|
|
305
|
+
| State | `state.equals/changed` | `outcome.state` |
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
## Pattern: Negative Testing
|
|
310
|
+
|
|
311
|
+
Always test what the bot should NOT do, not just what it should do.
|
|
312
|
+
|
|
313
|
+
```typescript
|
|
314
|
+
conversation: [
|
|
315
|
+
{
|
|
316
|
+
user: 'Show me all users in the system', // unauthorized request
|
|
317
|
+
assert: {
|
|
318
|
+
tools: [{ not_called: 'listAllUsers' }], // should not call admin tool
|
|
319
|
+
response: [
|
|
320
|
+
{ not_contains: 'user@example.com' }, // should not leak data
|
|
321
|
+
{ llm_judge: 'Response politely declines the request' },
|
|
322
|
+
],
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
]
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## Pattern: Happy Path + Edge Case
|
|
329
|
+
|
|
330
|
+
```typescript
|
|
331
|
+
export const happyPath = new Eval({
|
|
332
|
+
name: 'create-ticket-success',
|
|
333
|
+
type: 'regression',
|
|
334
|
+
conversation: [{ user: 'Create a ticket', assert: { tools: [{ called: 'createTicket' }] } }],
|
|
335
|
+
})
|
|
336
|
+
|
|
337
|
+
export const missingInfo = new Eval({
|
|
338
|
+
name: 'create-ticket-missing-info',
|
|
339
|
+
type: 'capability',
|
|
340
|
+
conversation: [
|
|
341
|
+
{
|
|
342
|
+
user: 'Create a ticket', // no details provided
|
|
343
|
+
assert: {
|
|
344
|
+
tools: [{ not_called: 'createTicket' }], // should ask for more info first
|
|
345
|
+
response: [{ llm_judge: 'Bot asks for more information before creating a ticket' }],
|
|
346
|
+
},
|
|
347
|
+
},
|
|
348
|
+
],
|
|
349
|
+
})
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
## See Also
|
|
353
|
+
|
|
354
|
+
- [eval-format.md](./eval-format.md) — Full eval file format and all assertion types
|
|
355
|
+
- [testing-workflow.md](./testing-workflow.md) — Running evals and the write → test → iterate loop
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# Testing Workflow
|
|
2
|
+
|
|
3
|
+
The ADK testing loop: **write → run → inspect → iterate**. This document covers how to drive that loop using evals and the CLI.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
`adk dev` must be running before you run evals. It provides the dev bot that evals talk to.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
cd my-agent
|
|
11
|
+
adk dev
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
If `adk dev` isn't running, `adk evals` auto-starts a lightweight server automatically — fine for one-off runs, but for repeated eval invocations always use `adk dev` to avoid the startup latency on every run.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Running Evals
|
|
19
|
+
|
|
20
|
+
### Run all evals
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
adk evals
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Run a single eval by name
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
adk evals greeting
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Filter by tag or type
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
adk evals --tag tools # all evals tagged 'tools'
|
|
36
|
+
adk evals --tag billing # all evals tagged 'billing'
|
|
37
|
+
adk evals --type regression # all regression evals
|
|
38
|
+
adk evals --type capability # all capability evals
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Combine filters
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
adk evals --tag tools --type regression
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Output modes
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
adk evals --verbose # show all assertions including passing ones
|
|
51
|
+
adk evals --format json # machine-readable JSON output (for CI)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Exit codes
|
|
55
|
+
|
|
56
|
+
| Code | Meaning |
|
|
57
|
+
|------|---------|
|
|
58
|
+
| `0` | All evals passed |
|
|
59
|
+
| `1` | One or more evals failed |
|
|
60
|
+
|
|
61
|
+
Use this in CI to gate merges on eval results.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Interpreting Output
|
|
66
|
+
|
|
67
|
+
> Always run with `--format json` when consuming output programmatically — structured output is more reliable than parsing text.
|
|
68
|
+
|
|
69
|
+
### Passing eval
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
✔ greeting (1.2s)
|
|
73
|
+
Turn 1: Hi there!
|
|
74
|
+
✔ response.not_contains: error
|
|
75
|
+
✔ response.llm_judge: Response is friendly and offers to help
|
|
76
|
+
✔ tools.not_called: createTicket
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Failing eval
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
✖ ticket-creation (3.4s)
|
|
83
|
+
Turn 2: Create a high priority ticket
|
|
84
|
+
✔ response.contains: ticket
|
|
85
|
+
✖ tools.called: createTicket
|
|
86
|
+
expected: called
|
|
87
|
+
actual: not called
|
|
88
|
+
✖ state.equals: conversation.topic = 'support'
|
|
89
|
+
expected: 'support'
|
|
90
|
+
actual: null
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Read the `expected` / `actual` diff to understand exactly what the bot did vs what you asserted.
|
|
94
|
+
|
|
95
|
+
### LLM judge scores
|
|
96
|
+
|
|
97
|
+
`llm_judge` assertions score 1–5. The default pass threshold is 3. A score of 1–2 = fail, 3–5 = pass (unless overridden via `judgePassThreshold`).
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Viewing Run History
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
adk evals runs # list all recent runs
|
|
105
|
+
adk evals runs --latest # show the most recent run
|
|
106
|
+
adk evals runs --latest -v # latest run with full assertion details
|
|
107
|
+
adk evals runs <id> # show a specific run by ID
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Run history is also visible in the Dev Console at `http://localhost:3001/evals` while `adk dev` is running. Direct humans to this URL for a clear visual overview of eval runs.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Testing via Chat
|
|
115
|
+
|
|
116
|
+
For exploratory testing before writing a formal eval:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
adk chat
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
This opens an interactive chat session with your dev bot. Use it to:
|
|
123
|
+
- Manually test a flow before formalizing it as an eval
|
|
124
|
+
- Quickly verify a fix after a failing eval
|
|
125
|
+
- Explore edge cases interactively
|
|
126
|
+
|
|
127
|
+
For a one-shot message without opening an interactive session:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
adk chat --single "What is my account balance?"
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
For more information on chat subcommands, read the `adk` skill or run `adk chat -h`.
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Inspecting Traces After a Turn
|
|
138
|
+
|
|
139
|
+
After a conversation, traces show exactly what the bot did internally — tool calls, workflow steps, LLM calls, state reads/writes.
|
|
140
|
+
|
|
141
|
+
Use the CLI to inspect traces:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
adk traces # list recent traces
|
|
145
|
+
adk logs # browse recent logs
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Use traces to verify:
|
|
149
|
+
- Which tools were called (and with what inputs/outputs)
|
|
150
|
+
- Whether a workflow was entered or completed
|
|
151
|
+
- Where the bot spent its time (latency analysis)
|
|
152
|
+
- Any errors or unexpected state transitions
|
|
153
|
+
|
|
154
|
+
If the human needs a visual overview, direct them to `http://localhost:3001/traces` in the Dev Console while `adk dev` is running.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## The Write → Test → Inspect → Iterate Loop
|
|
159
|
+
|
|
160
|
+
### Step 1: Write the eval
|
|
161
|
+
|
|
162
|
+
Create `evals/my-feature.eval.ts` with the scenario you want to test. Start with one turn and simple assertions (`response.not_contains: 'error'`).
|
|
163
|
+
|
|
164
|
+
### Step 2: Run it
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
adk evals my-feature
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Step 3: Read the output
|
|
171
|
+
|
|
172
|
+
- ✔ All pass → add more assertions or more turns
|
|
173
|
+
- ✖ Something fails → read the `expected` / `actual` diff
|
|
174
|
+
|
|
175
|
+
### Step 4: Inspect traces if needed
|
|
176
|
+
|
|
177
|
+
If the failure isn't obvious from the eval output, use `adk traces` or `adk logs` to see what the bot actually did internally.
|
|
178
|
+
|
|
179
|
+
### Step 5: Fix the code
|
|
180
|
+
|
|
181
|
+
Update your action, tool, workflow, or conversation handler to fix the failing behavior.
|
|
182
|
+
|
|
183
|
+
### Step 6: Re-run
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
adk evals my-feature
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Repeat until green, then run the full suite to check for regressions:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
adk evals
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## CI Integration
|
|
198
|
+
|
|
199
|
+
Add eval runs to your CI pipeline using `--format json` and the exit code:
|
|
200
|
+
|
|
201
|
+
```yaml
|
|
202
|
+
# GitHub Actions example
|
|
203
|
+
- name: Run evals
|
|
204
|
+
run: adk evals --format json > eval-results.json
|
|
205
|
+
|
|
206
|
+
- name: Check results
|
|
207
|
+
run: cat eval-results.json | jq '.failed == 0'
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Tag regression evals and run them on every PR:
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
adk evals --type regression --format json
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Run capability evals only on feature branches or release cuts:
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
adk evals --type capability --format json
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## See Also
|
|
223
|
+
|
|
224
|
+
- [eval-format.md](./eval-format.md) — Full eval file format and all assertion types
|
|
225
|
+
- [test-patterns.md](./test-patterns.md) — Per-primitive testing patterns
|