e2e 0.16.0 → 0.18.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.
Files changed (256) hide show
  1. package/README.md +10 -0
  2. package/dist/.build.json +1 -1
  3. package/dist/agent/act.js +7 -4
  4. package/dist/agent/action-dispatcher.js +4 -5
  5. package/dist/agent/actions.d.ts +32 -23
  6. package/dist/agent/actions.js +38 -24
  7. package/dist/agent/ai-sdk.js +5 -4
  8. package/dist/agent/error.js +3 -3
  9. package/dist/agent/invocation.js +3 -4
  10. package/dist/agent/model/sdk.js +2 -0
  11. package/dist/agent/model/tool-choice.d.ts +9 -0
  12. package/dist/agent/model/tool-choice.js +14 -0
  13. package/dist/agent/observation-feed.d.ts +5 -6
  14. package/dist/agent/observation-feed.js +8 -11
  15. package/dist/agent/observation.d.ts +40 -11
  16. package/dist/agent/observation.js +109 -59
  17. package/dist/agent/phases.d.ts +7 -1
  18. package/dist/agent/phases.js +12 -3
  19. package/dist/agent/point-tap.d.ts +8 -8
  20. package/dist/agent/point-tap.js +1 -1
  21. package/dist/agent/prompts.js +3 -0
  22. package/dist/agent/replay.d.ts +19 -8
  23. package/dist/agent/replay.js +29 -29
  24. package/dist/agent/scroll-target.d.ts +2 -3
  25. package/dist/agent/step-cache.d.ts +43 -15
  26. package/dist/agent/step-cache.js +156 -67
  27. package/dist/agent/tool-loop.js +94 -5
  28. package/dist/cache/anchors.d.ts +72 -23
  29. package/dist/cache/anchors.js +233 -60
  30. package/dist/cache/context.d.ts +25 -14
  31. package/dist/cache/context.js +50 -8
  32. package/dist/cache/decide.d.ts +2 -2
  33. package/dist/cache/decide.js +4 -6
  34. package/dist/cache/identity.d.ts +18 -4
  35. package/dist/cache/identity.js +9 -4
  36. package/dist/cache/recorder.d.ts +15 -1
  37. package/dist/cache/recorder.js +36 -23
  38. package/dist/cache/rekeyed.d.ts +46 -0
  39. package/dist/cache/rekeyed.js +89 -0
  40. package/dist/cache/relocate.d.ts +14 -14
  41. package/dist/cache/relocate.js +33 -25
  42. package/dist/cache/route.d.ts +32 -33
  43. package/dist/cache/route.js +94 -50
  44. package/dist/cache/store.d.ts +6 -0
  45. package/dist/cache/store.js +21 -1
  46. package/dist/cache/trace.d.ts +53 -14
  47. package/dist/cache/trace.js +76 -30
  48. package/dist/cli/bin.js +2 -2
  49. package/dist/cli/index.js +43 -32
  50. package/dist/cli/init/engines.d.ts +1 -3
  51. package/dist/cli/init/engines.js +2 -2
  52. package/dist/cli/init/gateways.d.ts +1 -1
  53. package/dist/cli/init/gateways.js +11 -1
  54. package/dist/cli/init/mcp-config.d.ts +2 -1
  55. package/dist/cli/init/mcp-config.js +8 -3
  56. package/dist/cli/init/sibling-versions.json +1 -1
  57. package/dist/cli/init/versions.d.ts +0 -8
  58. package/dist/cli/init/versions.js +1 -10
  59. package/dist/cli/mcp.d.ts +3 -2
  60. package/dist/cli/mcp.js +52 -16
  61. package/dist/cli/run-output.d.ts +17 -0
  62. package/dist/cli/run-output.js +45 -0
  63. package/dist/collect/collect.js +8 -4
  64. package/dist/collect/registry.js +27 -16
  65. package/dist/config/compiled-files.d.ts +36 -0
  66. package/dist/config/compiled-files.js +50 -0
  67. package/dist/config/diagnose.js +21 -19
  68. package/dist/config/esm-hooks.d.ts +39 -44
  69. package/dist/config/esm-hooks.js +238 -63
  70. package/dist/config/load.d.ts +1 -7
  71. package/dist/config/load.js +23 -66
  72. package/dist/config/register.d.ts +8 -0
  73. package/dist/config/register.js +9 -0
  74. package/dist/config/resolve.d.ts +1 -0
  75. package/dist/config/resolve.js +33 -1
  76. package/dist/config/specifiers.d.ts +19 -0
  77. package/dist/config/specifiers.js +33 -0
  78. package/dist/config/tsconfig.d.ts +56 -0
  79. package/dist/config/tsconfig.js +115 -0
  80. package/dist/config/typescript.d.ts +19 -0
  81. package/dist/config/typescript.js +253 -0
  82. package/dist/engine/contract.d.ts +1 -0
  83. package/dist/engine/index.d.ts +4 -2
  84. package/dist/engine/session.js +2 -2
  85. package/dist/expect/async.js +4 -2
  86. package/dist/expect/poll-scope.d.ts +52 -0
  87. package/dist/expect/poll-scope.js +113 -0
  88. package/dist/expect/poll.js +33 -6
  89. package/dist/expect/values.js +11 -4
  90. package/dist/internal/abandoned.d.ts +11 -0
  91. package/dist/internal/abandoned.js +23 -0
  92. package/dist/internal/brands.d.ts +2 -0
  93. package/dist/internal/brands.js +2 -0
  94. package/dist/internal/client-identity.d.ts +9 -0
  95. package/dist/internal/client-identity.js +14 -0
  96. package/dist/internal/errors.d.ts +10 -3
  97. package/dist/internal/errors.js +23 -8
  98. package/dist/internal/node-version.d.ts +16 -7
  99. package/dist/internal/node-version.js +50 -15
  100. package/dist/internal/package-manager.js +1 -1
  101. package/dist/internal/realm-slot.d.ts +5 -4
  102. package/dist/internal/redact.d.ts +9 -4
  103. package/dist/internal/redact.js +120 -23
  104. package/dist/internal/time.d.ts +26 -4
  105. package/dist/internal/time.js +58 -14
  106. package/dist/internal/urls.d.ts +9 -5
  107. package/dist/internal/urls.js +19 -10
  108. package/dist/locator/engine.d.ts +12 -2
  109. package/dist/locator/engine.js +55 -14
  110. package/dist/locator/screen.js +59 -9
  111. package/dist/mcp/catalog.d.ts +3 -2
  112. package/dist/mcp/catalog.js +6 -6
  113. package/dist/mcp/output.d.ts +59 -0
  114. package/dist/mcp/output.js +129 -0
  115. package/dist/mcp/server.d.ts +4 -0
  116. package/dist/mcp/server.js +9 -12
  117. package/dist/mcp/session.d.ts +8 -1
  118. package/dist/mcp/session.js +56 -15
  119. package/dist/mcp/tools.js +7 -5
  120. package/dist/oauth/chatgpt.js +3 -23
  121. package/dist/oauth/cli.js +1 -0
  122. package/dist/oauth/copilot.d.ts +5 -4
  123. package/dist/oauth/copilot.js +80 -7
  124. package/dist/oauth/grok.js +2 -1
  125. package/dist/oauth/models.js +2 -1
  126. package/dist/oauth/opencode-console.d.ts +10 -0
  127. package/dist/oauth/opencode-console.js +133 -0
  128. package/dist/oauth/providers/github-copilot.d.ts +12 -0
  129. package/dist/oauth/providers/github-copilot.js +77 -23
  130. package/dist/oauth/providers/opencode-console.d.ts +31 -0
  131. package/dist/oauth/providers/opencode-console.js +148 -0
  132. package/dist/oauth/providers.d.ts +2 -6
  133. package/dist/oauth/providers.js +3 -7
  134. package/dist/oauth/responses.d.ts +9 -0
  135. package/dist/oauth/responses.js +23 -0
  136. package/dist/report/build.d.ts +26 -0
  137. package/dist/report/build.js +16 -8
  138. package/dist/report/failure-text.d.ts +6 -1
  139. package/dist/report/failure-text.js +14 -4
  140. package/dist/report/format.d.ts +10 -5
  141. package/dist/report/format.js +12 -5
  142. package/dist/report/junit.js +11 -12
  143. package/dist/report/list.d.ts +12 -0
  144. package/dist/report/list.js +61 -24
  145. package/dist/report/markdown.d.ts +1 -1
  146. package/dist/report/markdown.js +37 -14
  147. package/dist/report/repeats.d.ts +6 -1
  148. package/dist/report/repeats.js +12 -3
  149. package/dist/run/artifacts.d.ts +22 -4
  150. package/dist/run/artifacts.js +71 -3
  151. package/dist/run/execute.d.ts +34 -5
  152. package/dist/run/execute.js +93 -44
  153. package/dist/run/extended-fixtures.js +6 -2
  154. package/dist/run/failure-evidence.js +10 -4
  155. package/dist/run/fixtures.js +6 -8
  156. package/dist/run/in-process.d.ts +2 -0
  157. package/dist/run/in-process.js +52 -10
  158. package/dist/run/last-run.d.ts +42 -8
  159. package/dist/run/last-run.js +121 -14
  160. package/dist/run/process-output.d.ts +73 -0
  161. package/dist/run/process-output.js +130 -0
  162. package/dist/run/provision.d.ts +2 -0
  163. package/dist/run/provision.js +1 -0
  164. package/dist/run/realm.d.ts +4 -1
  165. package/dist/run/realm.js +20 -6
  166. package/dist/run/records.d.ts +20 -4
  167. package/dist/run/records.js +26 -0
  168. package/dist/run/retry.d.ts +10 -1
  169. package/dist/run/retry.js +30 -12
  170. package/dist/run/runner.d.ts +9 -1
  171. package/dist/run/runner.js +101 -39
  172. package/dist/run/scheduler.js +255 -19
  173. package/dist/run/secrecy.d.ts +22 -19
  174. package/dist/run/secrecy.js +22 -18
  175. package/dist/run/serial.d.ts +75 -2
  176. package/dist/run/serial.js +243 -59
  177. package/dist/run/standalone.js +1 -1
  178. package/dist/run/steps.d.ts +0 -6
  179. package/dist/run/steps.js +3 -20
  180. package/dist/run/trace-redaction.d.ts +5 -6
  181. package/dist/run/trace-redaction.js +5 -6
  182. package/dist/run/worker/entry.js +40 -18
  183. package/dist/run/worker/handle.js +10 -5
  184. package/dist/run/worker/protocol.d.ts +85 -3
  185. package/dist/run/worker/session.d.ts +2 -0
  186. package/dist/run/worker/session.js +29 -0
  187. package/dist/telemetry/environment.d.ts +2 -1
  188. package/dist/telemetry/environment.js +12 -2
  189. package/dist/telemetry/events.js +1 -0
  190. package/dist/telemetry/project.d.ts +5 -6
  191. package/dist/telemetry/project.js +6 -11
  192. package/dist/telemetry/store.d.ts +5 -5
  193. package/dist/telemetry/store.js +5 -7
  194. package/dist/telemetry/telemetry.d.ts +2 -3
  195. package/dist/telemetry/telemetry.js +2 -4
  196. package/dist/types.d.ts +15 -6
  197. package/docs/agent-steps.mdx +1 -0
  198. package/docs/agents.mdx +7 -3
  199. package/docs/api-testing.mdx +2 -1
  200. package/docs/authentication.mdx +6 -3
  201. package/docs/browser.mdx +49 -12
  202. package/docs/bug-bash.mdx +2 -1
  203. package/docs/cache.mdx +66 -19
  204. package/docs/ci.mdx +14 -9
  205. package/docs/coding-agents.mdx +2 -1
  206. package/docs/core-concepts.mdx +208 -0
  207. package/docs/debugging.mdx +25 -12
  208. package/docs/decision-models.mdx +142 -0
  209. package/docs/example-projects.mdx +32 -0
  210. package/docs/executors.mdx +7 -2
  211. package/docs/explore.mdx +1 -0
  212. package/docs/github.mdx +14 -5
  213. package/docs/index.mdx +9 -5
  214. package/docs/integrations/eas.mdx +1 -0
  215. package/docs/integrations/index.mdx +1 -0
  216. package/docs/integrations/kernel.mdx +3 -2
  217. package/docs/migrate/cypress.mdx +26 -3
  218. package/docs/migrate/detox.mdx +24 -1
  219. package/docs/migrate/maestro.mdx +28 -4
  220. package/docs/migrate/playwright.mdx +44 -18
  221. package/docs/migrate/selenium.mdx +27 -3
  222. package/docs/mobile-ci.mdx +6 -5
  223. package/docs/mobile.mdx +96 -8
  224. package/docs/models.mdx +60 -9
  225. package/docs/quickstart.mdx +28 -16
  226. package/docs/reference/agent.mdx +13 -3
  227. package/docs/reference/app.mdx +2 -1
  228. package/docs/reference/cli.mdx +41 -18
  229. package/docs/reference/config.mdx +67 -13
  230. package/docs/reference/engine.mdx +25 -13
  231. package/docs/reference/environment.mdx +10 -2
  232. package/docs/reference/errors.mdx +13 -10
  233. package/docs/reference/expect.mdx +36 -13
  234. package/docs/reference/mcp.mdx +21 -8
  235. package/docs/reference/mobile.mdx +24 -13
  236. package/docs/reference/reporters.mdx +9 -2
  237. package/docs/reference/screen.mdx +49 -16
  238. package/docs/reference/test.mdx +32 -5
  239. package/docs/reference/web.mdx +133 -23
  240. package/docs/security.mdx +58 -42
  241. package/docs/subscriptions.mdx +92 -12
  242. package/docs/telemetry.mdx +9 -6
  243. package/docs/tools.mdx +1 -0
  244. package/docs/{starting-your-app.mdx → web.mdx} +157 -11
  245. package/docs/writing-an-engine.mdx +2 -1
  246. package/package.json +25 -8
  247. package/schema/report-v1.schema.json +14 -1
  248. package/skills/e2e/SKILL.md +5 -3
  249. package/skills/e2e/references/agent.md +33 -11
  250. package/skills/e2e/references/debugging.md +4 -4
  251. package/skills/e2e/references/mcp.md +8 -3
  252. package/skills/e2e/references/running.md +15 -9
  253. package/skills/e2e/references/setup.md +45 -16
  254. package/skills/e2e/references/writing-tests.md +35 -18
  255. package/docs/viewports.mdx +0 -146
  256. package/docs/writing-tests.mdx +0 -256
@@ -1,256 +0,0 @@
1
- ---
2
- title: Writing tests
3
- description: Goals, checks, extraction, and the deterministic APIs.
4
- ---
5
-
6
- Use agent calls for goals and questions about the screen. Use `screen` and
7
- `expect` when you know the exact action or value to check. A test can freely mix both.
8
-
9
- ```ts title="tests/todos.e2e.ts"
10
- import { test, expect } from 'e2e';
11
-
12
- test('todos survive a filter round-trip', async ({ app, agent, screen }) => {
13
- await app.open('/todos');
14
-
15
- await agent.act('add todos "Buy milk" and "Walk the dog", complete the first');
16
- await agent.assert('only one todo remains open');
17
-
18
- await screen.getByRole('tab', 'Done').tap();
19
- await expect(screen.getByTestId('todo')).toHaveCount(1);
20
- });
21
- ```
22
-
23
- ## Goals: `agent.act`
24
-
25
- Give `act` one goal. The agent chooses and performs the actions, then returns
26
- when the goal passes or throws when it fails.
27
-
28
- ```ts
29
- await agent.act('complete checkout with the test card');
30
- await agent.act('invite {email} as an editor', { params: { email: 'ada@example.test' } });
31
- ```
32
-
33
- Pass values through `params` so the agent uses your test data. For passwords,
34
- use a `Secret`, this prevents the model from seeing your secrets. See [Signing in](/authentication).
35
-
36
- ```ts
37
- import { credentials } from 'e2e';
38
-
39
- const member = credentials.user('member');
40
- await agent.act('Sign in', {
41
- params: { username: member.username, password: member.password },
42
- });
43
- ```
44
-
45
- <Tip>
46
- **Write instructions as you would say them out loud**
47
-
48
- Name what is visible and prefer the exact wording on screen. One goal per
49
- call. The flow inside a goal is the model's job; the order of goals is yours.
50
- </Tip>
51
-
52
- For a value that changes on every run, wrap it in `unique()` so the
53
- [replay cache](/cache#what-must-match) can still replay the step:
54
-
55
- ```ts
56
- import { expect, unique } from 'e2e';
57
-
58
- const email = `ada+${Date.now()}@example.test`;
59
- await agent.act('sign up with email {email}', { params: { email: unique(email) } });
60
- await expect(screen.getByText(email)).toBeVisible();
61
- ```
62
-
63
- If a goal fails, check the report and make the instruction more specific.
64
- Use the labels on screen. Put vocabulary shared by several goals in the
65
- agent's `context`; see [Agents and personas](/agents).
66
-
67
- A step can pass, fail, or be blocked by something such as missing credentials.
68
- [How agent steps work](/agent-steps#how-a-step-ends) explains the verdicts and
69
- exit codes.
70
-
71
- ## Checks: `assert`, `waitFor`, `extract`
72
-
73
- `assert` checks a statement against the current screen. A false statement
74
- fails with `ASSERTION_FAILED`. If the screen does not provide enough evidence,
75
- it fails with `ASSERTION_INCONCLUSIVE`.
76
-
77
- The judging model sees the statement and the current screen. It does not see
78
- earlier steps or the acting agent's summaries.
79
-
80
- ```ts
81
- await agent.assert('the dashboard shows a trial badge');
82
- ```
83
-
84
- `assert` checks the screen now. Use `waitFor` when the condition may become true
85
- later. It polls the screen and only calls the model when the observation changes.
86
-
87
- ```ts
88
- await agent.waitFor('the export finishes and a download link appears', {
89
- interval: 500,
90
- timeout: 120_000,
91
- });
92
- ```
93
-
94
- `extract` reads structured data from the screen. Provide a
95
- [Standard Schema](https://standardschema.dev) validator, such as Zod, to define
96
- the result.
97
-
98
- ```ts
99
- import { z } from 'zod';
100
-
101
- const data = await agent.extract('every todo title and how many remain', {
102
- schema: z.object({ titles: z.array(z.string()), remaining: z.number().int() }),
103
- });
104
- expect(data.titles).toContain('Buy milk');
105
- ```
106
-
107
- <Tip>
108
- For model-generated descriptions, check the relevant meaning rather than the
109
- entire sentence. Use a locator assertion when the exact text matters.
110
- </Tip>
111
-
112
- ### Judging pixels
113
-
114
- By default, judgments read a redacted text snapshot of the screen. Add
115
- `vision: true` for visual checks, such as charts or layout. Use
116
- `vision: 'only'` to judge the screenshot alone.
117
-
118
- ```ts
119
- await agent.assert('the chart trends upward', { vision: true });
120
- await agent.assert('the search form is not covered by a banner', { vision: 'only' });
121
- ```
122
-
123
- `act` requests screenshots itself when it needs them, so it has no `vision`
124
- option. On supported engines, it can tap and type at points in the image:
125
-
126
- ```ts
127
- await agent.act('enter the code 3141 on the drawn keypad and press OK');
128
- ```
129
-
130
- Images add input tokens. Screenshots are withheld for the rest of an attempt
131
- after a secret is filled. The [agent reference](/reference/agent#vision)
132
- lists the modes and restrictions.
133
-
134
- ## Deterministic APIs: `screen` and `expect`
135
-
136
- Use locators to interact with known controls and check exact values.
137
- An `expect` after `act` checks the exact result. It is also what lets the
138
- [replay cache](/cache) record the step and keep it.
139
-
140
- ```ts
141
- // Semantic queries: role and name first, label second, test ID last.
142
- await screen.getByRole('button', 'Sign in').tap();
143
- await screen.getByLabel('Email').fill('ada@example.test');
144
- await screen.getByTestId('todo').first().tap();
145
-
146
- // Scope into a row, gesture like a user:
147
- const row = screen.getByRole('listitem').filter({ hasText: 'Design review' });
148
- await row.getByRole('button', 'Archive').tap();
149
- await screen.swipe({ direction: 'up', momentum: 'fast' });
150
-
151
- // Coordinates, for what the tree does not list:
152
- await screen.getByRole('image', 'Seat map').tap({ position: { x: 120, y: 48 } });
153
- await screen.swipe({ from: { x: 300, y: 400 }, to: { x: 40, y: 400 } });
154
-
155
- // Polling assertions:
156
- await expect(screen.getByRole('status')).toHaveText('2 remaining');
157
- await expect(screen.getByRole('heading', 'Dashboard')).toBeVisible();
158
- ```
159
-
160
- Actions and single-node reads or assertions fail when a query matches more
161
- than one node. Narrow it with `.filter()`, `.first()`, or `.nth()`.
162
- Locator assertions retry until they pass or time out. Direct reads such as
163
- `textContent()` do not retry a mismatched value.
164
-
165
- Use the `browser` fixture for browser features such as routes, cookies, dialogs,
166
- frames, and downloads; see [Working with the browser](/browser). The
167
- [screen reference](/reference/screen) lists every query and action.
168
-
169
- Share setup and cleanup through `test.extend`. A fixture can create a test
170
- workspace before the test and delete it afterward, including when the test
171
- fails. See [Your own fixtures](/reference/test#your-own-fixtures).
172
-
173
- ## Tests without a screen
174
-
175
- A test that takes only `app` calls no model and drives no screen. Use it to
176
- check your API with `fetch` in the same run as UI tests. See
177
- [Testing APIs](/api-testing).
178
-
179
- ## Structure
180
-
181
- ```ts
182
- import { beforeEach, describe, test } from 'e2e';
183
-
184
- describe('billing', { tags: ['billing'] }, () => {
185
- beforeEach(async ({ app }) => { await app.open('/billing'); });
186
-
187
- test('upgrades', { retries: 2, timeout: 60_000 }, async ({ agent }) => {
188
- await agent.act('upgrade to Pro');
189
- });
190
- });
191
-
192
- test.skip('not ready yet', async () => {});
193
- test.only('just this one while I work', async () => {}); // rejected in CI
194
-
195
- test('needs two organizations', async ({ app }) => {
196
- test.skip((await countOrganizations()) < 2, 'one organization: nothing to switch to');
197
- await app.open('/organizations');
198
- });
199
- ```
200
-
201
- `test.skip(condition, reason)` inside a body throws when the condition holds:
202
- the test stops at that line and is reported `skipped`, as in Playwright. Call
203
- it before the first step when it guards a precondition.
204
-
205
- `describe` and the hooks are also `test.describe`, `test.beforeEach`, and so
206
- on. A `beforeEach` imported from `e2e` sees the core fixtures; import
207
- `test`, `describe`, and the hooks from `@e2e-dev/web` (or `@e2e-dev/mobile`)
208
- to have `browser` (or `device`) typed from one import, and use
209
- `test.beforeEach` on a `test` you extended with your own fixtures.
210
-
211
- Common options include `timeout`, `retries`, and `tags`. Use `session` for
212
- state from a setup test, `agentContext` for extra instructions, and `agent`
213
- to choose a configured [agent](/agents). `trace` and `video` record one test
214
- without recording the suite; see [Watch it happen](/debugging#watch-it-happen).
215
- Group options apply to their tests. The [test reference](/reference/test)
216
- lists all options and defaults.
217
-
218
- Each test runs in its own attempt. Prepare the app data it needs through
219
- fixtures or hooks. When a flow must span several tests, mark the group
220
- `{ serial: true }`. Members share app state, run in order on one worker,
221
- and retry as a whole.
222
-
223
- ## Run one test
224
-
225
- <CodeGroup>
226
- ```bash npm
227
- npx e2e run tests/signup.e2e.ts:12 # the test declared at line 12
228
- npx e2e run --grep checkout # tests whose title matches
229
- npx e2e run --target web # one target, by name
230
- ```
231
-
232
- ```bash pnpm
233
- pnpm exec e2e run tests/signup.e2e.ts:12 # the test declared at line 12
234
- pnpm exec e2e run --grep checkout # tests whose title matches
235
- pnpm exec e2e run --target web # one target, by name
236
- ```
237
-
238
- ```bash bun
239
- bunx e2e run tests/signup.e2e.ts:12 # the test declared at line 12
240
- bunx e2e run --grep checkout # tests whose title matches
241
- bunx e2e run --target web # one target, by name
242
- ```
243
- </CodeGroup>
244
-
245
- The [CLI reference](/reference/cli#e2e-run) lists every flag.
246
-
247
- ## Next
248
-
249
- <CardGroup cols={2}>
250
- <Card title="Signing in" icon="key" href="/authentication">
251
- Sessions and secrets.
252
- </Card>
253
- <Card title="Agents and personas" icon="users" href="/agents">
254
- Several agents in one suite, and running a flow as each of them.
255
- </Card>
256
- </CardGroup>