@funkai/agents 0.1.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 (153) hide show
  1. package/.generated/req.txt +1 -0
  2. package/.turbo/turbo-build.log +21 -0
  3. package/.turbo/turbo-test$colon$coverage.log +109 -0
  4. package/.turbo/turbo-test.log +141 -0
  5. package/.turbo/turbo-typecheck.log +4 -0
  6. package/CHANGELOG.md +16 -0
  7. package/ISSUES.md +540 -0
  8. package/LICENSE +21 -0
  9. package/README.md +128 -0
  10. package/banner.svg +97 -0
  11. package/coverage/lcov-report/base.css +224 -0
  12. package/coverage/lcov-report/block-navigation.js +87 -0
  13. package/coverage/lcov-report/core/agents/base/agent.ts.html +1705 -0
  14. package/coverage/lcov-report/core/agents/base/index.html +146 -0
  15. package/coverage/lcov-report/core/agents/base/output.ts.html +256 -0
  16. package/coverage/lcov-report/core/agents/base/utils.ts.html +694 -0
  17. package/coverage/lcov-report/core/agents/flow/engine.ts.html +928 -0
  18. package/coverage/lcov-report/core/agents/flow/flow-agent.ts.html +1462 -0
  19. package/coverage/lcov-report/core/agents/flow/index.html +146 -0
  20. package/coverage/lcov-report/core/agents/flow/messages.ts.html +508 -0
  21. package/coverage/lcov-report/core/agents/flow/steps/factory.ts.html +1975 -0
  22. package/coverage/lcov-report/core/agents/flow/steps/index.html +116 -0
  23. package/coverage/lcov-report/core/index.html +131 -0
  24. package/coverage/lcov-report/core/logger.ts.html +541 -0
  25. package/coverage/lcov-report/core/models/providers/index.html +116 -0
  26. package/coverage/lcov-report/core/models/providers/openai.ts.html +337 -0
  27. package/coverage/lcov-report/core/provider/index.html +131 -0
  28. package/coverage/lcov-report/core/provider/provider.ts.html +346 -0
  29. package/coverage/lcov-report/core/provider/usage.ts.html +376 -0
  30. package/coverage/lcov-report/core/tool.ts.html +577 -0
  31. package/coverage/lcov-report/favicon.png +0 -0
  32. package/coverage/lcov-report/index.html +221 -0
  33. package/coverage/lcov-report/lib/hooks.ts.html +262 -0
  34. package/coverage/lcov-report/lib/index.html +161 -0
  35. package/coverage/lcov-report/lib/middleware.ts.html +274 -0
  36. package/coverage/lcov-report/lib/runnable.ts.html +151 -0
  37. package/coverage/lcov-report/lib/trace.ts.html +520 -0
  38. package/coverage/lcov-report/prettify.css +1 -0
  39. package/coverage/lcov-report/prettify.js +2 -0
  40. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  41. package/coverage/lcov-report/sorter.js +210 -0
  42. package/coverage/lcov-report/utils/attempt.ts.html +199 -0
  43. package/coverage/lcov-report/utils/error.ts.html +421 -0
  44. package/coverage/lcov-report/utils/index.html +176 -0
  45. package/coverage/lcov-report/utils/resolve.ts.html +208 -0
  46. package/coverage/lcov-report/utils/result.ts.html +538 -0
  47. package/coverage/lcov-report/utils/zod.ts.html +178 -0
  48. package/coverage/lcov.info +1566 -0
  49. package/dist/index.d.mts +2883 -0
  50. package/dist/index.d.mts.map +1 -0
  51. package/dist/index.mjs +2312 -0
  52. package/dist/index.mjs.map +1 -0
  53. package/docs/core/agent.md +231 -0
  54. package/docs/core/hooks.md +95 -0
  55. package/docs/core/overview.md +87 -0
  56. package/docs/core/step.md +279 -0
  57. package/docs/core/tools.md +98 -0
  58. package/docs/core/workflow.md +235 -0
  59. package/docs/guides/create-agent.md +224 -0
  60. package/docs/guides/create-tool.md +137 -0
  61. package/docs/guides/create-workflow.md +374 -0
  62. package/docs/overview.md +244 -0
  63. package/docs/provider/models.md +55 -0
  64. package/docs/provider/overview.md +106 -0
  65. package/docs/provider/usage.md +100 -0
  66. package/docs/research/experimental-context.md +167 -0
  67. package/docs/research/gap-analysis.md +86 -0
  68. package/docs/research/prepare-step-and-active-tools.md +138 -0
  69. package/docs/research/sub-agent-model.md +249 -0
  70. package/docs/troubleshooting.md +60 -0
  71. package/logo.svg +17 -0
  72. package/models.config.json +18 -0
  73. package/package.json +60 -0
  74. package/scripts/generate-models.ts +324 -0
  75. package/src/core/agents/base/agent.test.ts +1522 -0
  76. package/src/core/agents/base/agent.ts +547 -0
  77. package/src/core/agents/base/output.test.ts +93 -0
  78. package/src/core/agents/base/output.ts +57 -0
  79. package/src/core/agents/base/types.test-d.ts +69 -0
  80. package/src/core/agents/base/types.ts +503 -0
  81. package/src/core/agents/base/utils.test.ts +397 -0
  82. package/src/core/agents/base/utils.ts +197 -0
  83. package/src/core/agents/flow/engine.test.ts +452 -0
  84. package/src/core/agents/flow/engine.ts +281 -0
  85. package/src/core/agents/flow/flow-agent.test.ts +1027 -0
  86. package/src/core/agents/flow/flow-agent.ts +473 -0
  87. package/src/core/agents/flow/messages.test.ts +198 -0
  88. package/src/core/agents/flow/messages.ts +141 -0
  89. package/src/core/agents/flow/steps/agent.test.ts +280 -0
  90. package/src/core/agents/flow/steps/agent.ts +87 -0
  91. package/src/core/agents/flow/steps/all.test.ts +300 -0
  92. package/src/core/agents/flow/steps/all.ts +73 -0
  93. package/src/core/agents/flow/steps/builder.ts +124 -0
  94. package/src/core/agents/flow/steps/each.test.ts +257 -0
  95. package/src/core/agents/flow/steps/each.ts +61 -0
  96. package/src/core/agents/flow/steps/factory.test-d.ts +50 -0
  97. package/src/core/agents/flow/steps/factory.test.ts +1025 -0
  98. package/src/core/agents/flow/steps/factory.ts +645 -0
  99. package/src/core/agents/flow/steps/map.test.ts +273 -0
  100. package/src/core/agents/flow/steps/map.ts +75 -0
  101. package/src/core/agents/flow/steps/race.test.ts +290 -0
  102. package/src/core/agents/flow/steps/race.ts +59 -0
  103. package/src/core/agents/flow/steps/reduce.test.ts +310 -0
  104. package/src/core/agents/flow/steps/reduce.ts +73 -0
  105. package/src/core/agents/flow/steps/result.ts +27 -0
  106. package/src/core/agents/flow/steps/step.test.ts +402 -0
  107. package/src/core/agents/flow/steps/step.ts +51 -0
  108. package/src/core/agents/flow/steps/while.test.ts +283 -0
  109. package/src/core/agents/flow/steps/while.ts +75 -0
  110. package/src/core/agents/flow/types.ts +348 -0
  111. package/src/core/logger.test.ts +163 -0
  112. package/src/core/logger.ts +152 -0
  113. package/src/core/models/index.test.ts +137 -0
  114. package/src/core/models/index.ts +152 -0
  115. package/src/core/models/providers/openai.ts +84 -0
  116. package/src/core/provider/provider.test.ts +128 -0
  117. package/src/core/provider/provider.ts +99 -0
  118. package/src/core/provider/types.ts +98 -0
  119. package/src/core/provider/usage.test.ts +304 -0
  120. package/src/core/provider/usage.ts +97 -0
  121. package/src/core/tool.test.ts +65 -0
  122. package/src/core/tool.ts +164 -0
  123. package/src/core/types.ts +66 -0
  124. package/src/index.ts +95 -0
  125. package/src/lib/context.test.ts +86 -0
  126. package/src/lib/context.ts +49 -0
  127. package/src/lib/hooks.test.ts +102 -0
  128. package/src/lib/hooks.ts +59 -0
  129. package/src/lib/middleware.test.ts +122 -0
  130. package/src/lib/middleware.ts +63 -0
  131. package/src/lib/runnable.test.ts +41 -0
  132. package/src/lib/runnable.ts +22 -0
  133. package/src/lib/trace.test.ts +291 -0
  134. package/src/lib/trace.ts +145 -0
  135. package/src/models/index.ts +123 -0
  136. package/src/models/providers/index.ts +15 -0
  137. package/src/models/providers/openai.ts +84 -0
  138. package/src/testing/context.ts +32 -0
  139. package/src/testing/index.ts +2 -0
  140. package/src/testing/logger.ts +19 -0
  141. package/src/utils/attempt.test.ts +127 -0
  142. package/src/utils/attempt.ts +38 -0
  143. package/src/utils/error.test.ts +179 -0
  144. package/src/utils/error.ts +112 -0
  145. package/src/utils/resolve.test.ts +38 -0
  146. package/src/utils/resolve.ts +41 -0
  147. package/src/utils/result.test.ts +79 -0
  148. package/src/utils/result.ts +151 -0
  149. package/src/utils/zod.test.ts +69 -0
  150. package/src/utils/zod.ts +31 -0
  151. package/tsconfig.json +25 -0
  152. package/tsdown.config.ts +15 -0
  153. package/vitest.config.ts +46 -0
@@ -0,0 +1,69 @@
1
+ import { Output } from "ai";
2
+ import { describe, expectTypeOf, it } from "vitest";
3
+ import { z } from "zod";
4
+
5
+ import type { OutputParam, OutputSpec } from "@/core/agents/base/output.js";
6
+ import { resolveOutput } from "@/core/agents/base/output.js";
7
+ import type { AgentConfig, AgentOverrides } from "@/core/agents/base/types.js";
8
+
9
+ describe("OutputParam accepts all Output factories", () => {
10
+ it("accepts Output.text()", () => {
11
+ expectTypeOf(Output.text()).toExtend<OutputParam>();
12
+ });
13
+
14
+ it("accepts Output.object()", () => {
15
+ expectTypeOf(Output.object({ schema: z.object({ name: z.string() }) })).toExtend<OutputParam>();
16
+ });
17
+
18
+ it("accepts Output.array()", () => {
19
+ expectTypeOf(Output.array({ element: z.object({ name: z.string() }) })).toExtend<OutputParam>();
20
+ });
21
+
22
+ it("accepts Output.choice()", () => {
23
+ expectTypeOf(
24
+ Output.choice({ options: ["positive", "negative", "neutral"] as const }),
25
+ ).toExtend<OutputParam>();
26
+ });
27
+
28
+ it("accepts Output.json()", () => {
29
+ expectTypeOf(Output.json()).toExtend<OutputParam>();
30
+ });
31
+ });
32
+
33
+ describe("OutputParam accepts raw Zod schemas", () => {
34
+ it("accepts z.object()", () => {
35
+ expectTypeOf(z.object({ name: z.string() })).toExtend<OutputParam>();
36
+ });
37
+
38
+ it("accepts z.array()", () => {
39
+ expectTypeOf(z.array(z.object({ name: z.string() }))).toExtend<OutputParam>();
40
+ });
41
+
42
+ it("accepts z.string()", () => {
43
+ expectTypeOf(z.string()).toExtend<OutputParam>();
44
+ });
45
+ });
46
+
47
+ describe("OutputParam is assignable to config fields", () => {
48
+ it("is assignable to AgentConfig.output", () => {
49
+ expectTypeOf<OutputParam>().toExtend<AgentConfig<string, string, {}, {}>["output"]>();
50
+ });
51
+
52
+ it("is assignable to AgentOverrides.output", () => {
53
+ expectTypeOf<OutputParam>().toExtend<AgentOverrides["output"]>();
54
+ });
55
+ });
56
+
57
+ describe("resolveOutput return type", () => {
58
+ it("returns OutputSpec", () => {
59
+ expectTypeOf(resolveOutput).returns.toExtend<OutputSpec>();
60
+ });
61
+
62
+ it("accepts OutputSpec input", () => {
63
+ expectTypeOf(resolveOutput).toBeCallableWith(Output.text());
64
+ });
65
+
66
+ it("accepts ZodType input", () => {
67
+ expectTypeOf(resolveOutput).toBeCallableWith(z.object({ x: z.number() }));
68
+ });
69
+ });
@@ -0,0 +1,503 @@
1
+ import type { AsyncIterableStream, ModelMessage, TextStreamPart, ToolSet } from "ai";
2
+ import type { ZodType } from "zod";
3
+
4
+ import type { OutputParam } from "@/core/agents/base/output.js";
5
+ import type { Logger } from "@/core/logger.js";
6
+ import type { TokenUsage } from "@/core/provider/types.js";
7
+ import type { Tool } from "@/core/tool.js";
8
+ import type { Model } from "@/core/types.js";
9
+ import type { Result } from "@/utils/result.js";
10
+
11
+ /**
12
+ * Concrete stream event type re-exported from the Vercel AI SDK.
13
+ *
14
+ * This is `TextStreamPart<ToolSet>` — the discriminated union of all
15
+ * possible stream events (`text-delta`, `tool-call`, `tool-result`,
16
+ * `finish`, `error`, etc.). Use `part.type` to discriminate.
17
+ */
18
+ export type StreamPart = TextStreamPart<ToolSet>;
19
+
20
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
21
+ export type SubAgents = Record<string, Agent<any, any, any, any>>;
22
+
23
+ /**
24
+ * Chat message type.
25
+ *
26
+ * Re-exported from the Vercel AI SDK (`ModelMessage`). Used for
27
+ * multi-turn conversations, message arrays, and tool-call history.
28
+ */
29
+ export type Message = ModelMessage;
30
+
31
+ /**
32
+ * Result of a completed agent generation.
33
+ *
34
+ * Mirrors the AI SDK's `GenerateTextResult`. The `output` field is
35
+ * typed based on the agent's configured Output variant.
36
+ *
37
+ * @typeParam TOutput - The output type.
38
+ * - `string` for `Output.text()` (the default).
39
+ * - `T` for `Output.object({ schema })`.
40
+ * - `T[]` for `Output.array({ element })`.
41
+ * - `T` for `Output.choice({ options })`.
42
+ */
43
+ export interface GenerateResult<TOutput = string> {
44
+ /**
45
+ * The generation output.
46
+ *
47
+ * Type depends on the configured `Output` variant:
48
+ * - `string` when using `Output.text()` (default).
49
+ * - `T` when using `Output.object<T>({ schema })`.
50
+ * - `T[]` when using `Output.array<T>({ element })`.
51
+ * - One of the option strings when using `Output.choice()`.
52
+ */
53
+ output: TOutput;
54
+
55
+ /**
56
+ * Full message history including tool calls.
57
+ *
58
+ * Contains the complete conversation from the generation,
59
+ * including system messages, user prompts, assistant responses,
60
+ * and tool call/result pairs.
61
+ */
62
+ messages: Message[];
63
+
64
+ /**
65
+ * Aggregated token usage across all tool-loop steps.
66
+ *
67
+ * Includes input, output, cache, and reasoning token counts.
68
+ * All fields are resolved numbers (0 when the provider does not
69
+ * report a given field).
70
+ */
71
+ usage: TokenUsage;
72
+
73
+ /**
74
+ * The reason the model stopped generating.
75
+ *
76
+ * Common values: `"stop"`, `"length"`, `"content-filter"`,
77
+ * `"tool-calls"`, `"error"`, `"other"`.
78
+ */
79
+ finishReason: string;
80
+ }
81
+
82
+ /**
83
+ * Result of a streaming agent generation.
84
+ *
85
+ * The `fullStream` emits typed `StreamPart` events as they arrive —
86
+ * text deltas, tool calls, tool results, step boundaries, finish,
87
+ * and errors. Implements both `AsyncIterable` and `ReadableStream`
88
+ * so consumers can use `for await...of` or `.getReader()`.
89
+ *
90
+ * `output` and `messages` are promises that resolve once the stream
91
+ * has been fully consumed.
92
+ *
93
+ * @typeParam TOutput - The output type (available after stream completes).
94
+ */
95
+ export interface StreamResult<TOutput = string> {
96
+ /**
97
+ * The generation output.
98
+ *
99
+ * Resolves after the stream completes. Same typing rules as
100
+ * `GenerateResult.output`.
101
+ */
102
+ output: Promise<TOutput>;
103
+
104
+ /**
105
+ * Full message history.
106
+ *
107
+ * Resolves after the stream completes. Contains the complete
108
+ * conversation including tool calls.
109
+ */
110
+ messages: Promise<Message[]>;
111
+
112
+ /**
113
+ * Aggregated token usage across all tool-loop steps.
114
+ *
115
+ * Resolves after the stream completes. Includes input, output,
116
+ * cache, and reasoning token counts.
117
+ */
118
+ usage: Promise<TokenUsage>;
119
+
120
+ /**
121
+ * The reason the model stopped generating.
122
+ *
123
+ * Resolves after the stream completes. Common values: `"stop"`,
124
+ * `"length"`, `"content-filter"`, `"tool-calls"`, `"error"`, `"other"`.
125
+ */
126
+ finishReason: Promise<string>;
127
+
128
+ /**
129
+ * The full stream of typed events.
130
+ *
131
+ * Emits `StreamPart` events (a discriminated union from the AI SDK)
132
+ * including `text-delta`, `tool-call`, `tool-result`, `finish`,
133
+ * `error`, and more. Use `part.type` to discriminate.
134
+ *
135
+ * Supports both `for await (const part of fullStream)` and
136
+ * `fullStream.getReader()`.
137
+ */
138
+ fullStream: AsyncIterableStream<StreamPart>;
139
+ }
140
+
141
+ /**
142
+ * Per-call overrides for agent generation.
143
+ *
144
+ * Passed as the optional second parameter to `.generate()` or `.stream()`.
145
+ * Override fields replace the base config for that call only. Per-call
146
+ * hooks **merge** with base hooks — base fires first, then call-level.
147
+ *
148
+ * @typeParam TTools - The agent's tool record type.
149
+ * @typeParam TSubAgents - The agent's subagent record type.
150
+ */
151
+ export interface AgentOverrides<
152
+ TTools extends Record<string, Tool> = Record<string, Tool>,
153
+ TSubAgents extends SubAgents = Record<string, never>,
154
+ > {
155
+ /**
156
+ * Override the logger for this call.
157
+ *
158
+ * When an agent runs inside a workflow step (`$.agent()`), the
159
+ * framework passes the step's scoped logger so agent logs include
160
+ * workflow and step context bindings.
161
+ */
162
+ logger?: Logger;
163
+
164
+ /**
165
+ * Abort signal for cancellation.
166
+ *
167
+ * When fired, the agent should stop generation and clean up.
168
+ */
169
+ signal?: AbortSignal;
170
+
171
+ /**
172
+ * Override the model for this call.
173
+ *
174
+ * Accepts a string model ID or an AI SDK `LanguageModel` instance.
175
+ */
176
+ model?: Model;
177
+
178
+ /**
179
+ * Override the system prompt for this call.
180
+ *
181
+ * Can be a static string or a function that receives the input
182
+ * and returns the system prompt.
183
+ */
184
+ system?: string | ((params: { input: unknown }) => string);
185
+
186
+ /**
187
+ * Override or extend tools for this call.
188
+ *
189
+ * Merged with the agent's base tools. Use `Partial<TTools>` to
190
+ * replace specific tools, or add new ones via the index signature.
191
+ */
192
+ tools?: Partial<TTools> & Record<string, Tool>;
193
+
194
+ /**
195
+ * Override or extend subagents for this call.
196
+ *
197
+ * Merged with the agent's base subagents.
198
+ */
199
+ agents?: Partial<TSubAgents> & Record<string, Agent>;
200
+
201
+ /**
202
+ * Override max tool-loop steps for this call.
203
+ *
204
+ * Controls how many tool-loop iterations the agent will run
205
+ * before stopping.
206
+ */
207
+ maxSteps?: number;
208
+
209
+ /**
210
+ * Override or set the output type for this call.
211
+ *
212
+ * Accepts an AI SDK `Output` strategy or a raw Zod schema:
213
+ * - `Output.text()`, `Output.object()`, `Output.array()`, `Output.choice()`
214
+ * - `z.object({ ... })` → auto-wrapped as `Output.object({ schema })`
215
+ * - `z.array(z.object({ ... }))` → auto-wrapped as `Output.array({ element })`
216
+ */
217
+ output?: OutputParam;
218
+
219
+ /**
220
+ * Per-call hook — fires after base `onStart`.
221
+ *
222
+ * @param event - Event containing the input.
223
+ * @param event.input - The input passed to `.generate()` or `.stream()`.
224
+ */
225
+ onStart?: (event: { input: unknown }) => void | Promise<void>;
226
+
227
+ /**
228
+ * Per-call hook — fires after base `onFinish`.
229
+ *
230
+ * @param event - Event containing the input, result, and duration.
231
+ * @param event.input - The input passed to `.generate()` or `.stream()`.
232
+ * @param event.result - The generation result.
233
+ * @param event.duration - Wall-clock time in milliseconds.
234
+ */
235
+ onFinish?: (event: {
236
+ input: unknown;
237
+ result: GenerateResult;
238
+ duration: number;
239
+ }) => void | Promise<void>;
240
+
241
+ /**
242
+ * Per-call hook — fires after base `onError`.
243
+ *
244
+ * @param event - Event containing the input and error.
245
+ * @param event.input - The input passed to `.generate()` or `.stream()`.
246
+ * @param event.error - The error that occurred.
247
+ */
248
+ onError?: (event: { input: unknown; error: Error }) => void | Promise<void>;
249
+
250
+ /**
251
+ * Per-call hook — fires after base `onStepFinish`.
252
+ *
253
+ * @param event - Event containing the step ID.
254
+ * @param event.stepId - The ID of the tool-loop step that completed.
255
+ */
256
+ onStepFinish?: (event: {
257
+ stepId: string;
258
+ toolCalls: readonly { toolName: string; argsTextLength: number }[];
259
+ toolResults: readonly { toolName: string; resultTextLength: number }[];
260
+ usage: { inputTokens: number; outputTokens: number; totalTokens: number };
261
+ }) => void | Promise<void>;
262
+ }
263
+
264
+ /**
265
+ * Configuration for creating an agent.
266
+ *
267
+ * Supports two modes:
268
+ *
269
+ * | Config | `.generate()` first param | How prompt is built |
270
+ * |---|---|---|
271
+ * | `input` + `prompt` provided | Typed `TInput` | `prompt({ input })` renders it |
272
+ * | Both omitted | `string \| Message[]` | Passed directly to the model |
273
+ *
274
+ * @typeParam TInput - Agent input type (default: `string | Message[]`).
275
+ * @typeParam TOutput - Agent output type (default: `string`).
276
+ * @typeParam TTools - Record of tools available to this agent.
277
+ * @typeParam TSubAgents - Record of subagents available to this agent.
278
+ */
279
+ export interface AgentConfig<
280
+ TInput,
281
+ TOutput,
282
+ TTools extends Record<string, Tool>,
283
+ TSubAgents extends SubAgents,
284
+ > {
285
+ /**
286
+ * Unique agent name.
287
+ *
288
+ * Used in logging, trace entries, and hook events.
289
+ */
290
+ name: string;
291
+
292
+ /**
293
+ * Model to use for generation.
294
+ *
295
+ * Accepts a string model ID (resolved via OpenRouter) or an
296
+ * AI SDK `LanguageModel` instance — including middleware-wrapped models.
297
+ *
298
+ * @see {@link Model}
299
+ */
300
+ model: Model;
301
+
302
+ /**
303
+ * Zod schema for the agent's typed input.
304
+ *
305
+ * When provided alongside `prompt`, `.generate()` accepts `TInput`
306
+ * as its first param and validates it against this schema.
307
+ *
308
+ * When omitted, `.generate()` accepts a raw `string` or `Message[]`
309
+ * instead (simple mode).
310
+ */
311
+ input?: ZodType<TInput>;
312
+
313
+ /**
314
+ * Map typed input to the prompt sent to the model.
315
+ *
316
+ * Required when `input` is provided. Ignored when `input` is
317
+ * omitted (the raw string/messages are used directly in simple mode).
318
+ *
319
+ * @param params - Object containing the validated input.
320
+ * @param params.input - The validated input value.
321
+ * @returns The prompt string or message array to send to the model.
322
+ */
323
+ prompt?: (params: { input: TInput }) => string | Message[];
324
+
325
+ /**
326
+ * System prompt.
327
+ *
328
+ * Can be a static string or a function that receives the validated
329
+ * input and returns the system prompt dynamically.
330
+ */
331
+ system?: string | ((params: { input: TInput }) => string);
332
+
333
+ /**
334
+ * Tools available to this agent for function calling.
335
+ *
336
+ * Each tool is exposed to the model in the tool-loop. The model
337
+ * can call these tools to gather information or perform actions.
338
+ */
339
+ tools?: TTools;
340
+
341
+ /**
342
+ * Subagents — automatically wrapped as tools the agent can delegate to.
343
+ *
344
+ * Each subagent becomes a callable tool that the parent agent can
345
+ * invoke. Abort signals propagate automatically from parent to child.
346
+ */
347
+ agents?: TSubAgents;
348
+
349
+ /**
350
+ * Maximum tool-loop iterations.
351
+ *
352
+ * Controls how many times the agent will call tools before stopping.
353
+ * Set higher for complex multi-step tasks, lower for simple queries.
354
+ *
355
+ * @default 20
356
+ */
357
+ maxSteps?: number;
358
+
359
+ /**
360
+ * Output type strategy.
361
+ *
362
+ * Controls the shape of the generation output. Accepts an AI SDK
363
+ * `Output` strategy or a raw Zod schema:
364
+ * - `Output.text()` — plain string (default).
365
+ * - `Output.object({ schema })` — validated structured object.
366
+ * - `Output.array({ element })` — validated array of elements.
367
+ * - `Output.choice({ options })` — enum/classification.
368
+ * - `z.object({ ... })` — auto-wrapped as `Output.object({ schema })`.
369
+ * - `z.array(z.object({ ... }))` — auto-wrapped as `Output.array({ element })`.
370
+ *
371
+ * @default Output.text()
372
+ */
373
+ output?: OutputParam;
374
+
375
+ /**
376
+ * Pino-compatible logger.
377
+ *
378
+ * When omitted, the SDK creates a default pino instance at `info`
379
+ * level. The framework automatically creates scoped child loggers
380
+ * with contextual bindings (`agentId`).
381
+ */
382
+ logger?: Logger;
383
+
384
+ /**
385
+ * Hook: fires when the agent starts execution.
386
+ *
387
+ * @param event - Event containing the input.
388
+ * @param event.input - The validated input value.
389
+ */
390
+ onStart?: (event: { input: TInput }) => void | Promise<void>;
391
+
392
+ /**
393
+ * Hook: fires when the agent finishes successfully.
394
+ *
395
+ * @param event - Event containing the input, result, and duration.
396
+ * @param event.input - The validated input value.
397
+ * @param event.result - The generation result.
398
+ * @param event.duration - Wall-clock time in milliseconds.
399
+ */
400
+ onFinish?: (event: {
401
+ input: TInput;
402
+ result: GenerateResult<TOutput>;
403
+ duration: number;
404
+ }) => void | Promise<void>;
405
+
406
+ /**
407
+ * Hook: fires when the agent encounters an error.
408
+ *
409
+ * @param event - Event containing the input and error.
410
+ * @param event.input - The validated input value.
411
+ * @param event.error - The error that occurred.
412
+ */
413
+ onError?: (event: { input: TInput; error: Error }) => void | Promise<void>;
414
+
415
+ /**
416
+ * Hook: fires after each tool-loop step completes.
417
+ *
418
+ * @param event - Event containing the step ID.
419
+ * @param event.stepId - The ID of the completed tool-loop step.
420
+ */
421
+ onStepFinish?: (event: {
422
+ stepId: string;
423
+ toolCalls: readonly { toolName: string; argsTextLength: number }[];
424
+ toolResults: readonly { toolName: string; resultTextLength: number }[];
425
+ usage: { inputTokens: number; outputTokens: number; totalTokens: number };
426
+ }) => void | Promise<void>;
427
+ }
428
+
429
+ /**
430
+ * A created agent — exposes `.generate()`, `.stream()`, and `.fn()`.
431
+ *
432
+ * Under the hood, agents run a tool loop (like `generateText` with tools)
433
+ * until a stop condition is met. Everything is wrapped in `Result`
434
+ * so callers never need try/catch.
435
+ *
436
+ * @typeParam TInput - Agent input type.
437
+ * @typeParam TOutput - Agent output type.
438
+ * @typeParam TTools - Record of tools.
439
+ * @typeParam TSubAgents - Record of subagents.
440
+ */
441
+ export interface Agent<
442
+ TInput = string | Message[],
443
+ TOutput = string,
444
+ TTools extends Record<string, Tool> = Record<string, Tool>,
445
+ TSubAgents extends SubAgents = Record<string, never>,
446
+ > {
447
+ /**
448
+ * Run the agent to completion.
449
+ *
450
+ * Executes the tool loop until the model produces a final response
451
+ * or `maxSteps` is reached. Returns a `Result` wrapping the
452
+ * generation result.
453
+ *
454
+ * @param input - Typed input (when `input` schema is configured)
455
+ * or `string | Message[]` in simple mode.
456
+ * @param config - Optional per-call overrides for model, tools,
457
+ * output, hooks, etc.
458
+ * @returns A `Result` wrapping the `GenerateResult`. On success,
459
+ * `result.ok` is `true` and generation fields are flat on the object.
460
+ */
461
+ generate(
462
+ input: TInput,
463
+ config?: AgentOverrides<TTools, TSubAgents>,
464
+ ): Promise<Result<GenerateResult<TOutput>>>;
465
+
466
+ /**
467
+ * Run the agent with streaming output.
468
+ *
469
+ * Returns immediately with `fullStream` — an `AsyncIterableStream`
470
+ * of typed `StreamPart` events. `output` and `messages` are
471
+ * promises that resolve after the stream completes.
472
+ *
473
+ * @param input - Typed input (when `input` schema is configured)
474
+ * or `string | Message[]` in simple mode.
475
+ * @param config - Optional per-call overrides.
476
+ * @returns A `Result` wrapping the `StreamResult`. On success,
477
+ * consume `result.fullStream` for typed events; await
478
+ * `result.output` / `result.messages` after the stream ends.
479
+ */
480
+ stream(
481
+ input: TInput,
482
+ config?: AgentOverrides<TTools, TSubAgents>,
483
+ ): Promise<Result<StreamResult<TOutput>>>;
484
+
485
+ /**
486
+ * Returns a plain function that calls `.generate()`.
487
+ *
488
+ * Use for clean single-function exports where you want to hide
489
+ * the agent object and just expose a callable.
490
+ *
491
+ * @returns A function with the same signature as `.generate()`.
492
+ *
493
+ * @example
494
+ * ```typescript
495
+ * export const analyzeFile = fileAnalyzer.fn()
496
+ * // Usage: const result = await analyzeFile({ filePath: '...' })
497
+ * ```
498
+ */
499
+ fn(): (
500
+ input: TInput,
501
+ config?: AgentOverrides<TTools, TSubAgents>,
502
+ ) => Promise<Result<GenerateResult<TOutput>>>;
503
+ }