@ax-llm/ax 18.0.0 → 18.0.2

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/skills/ax-llm.md CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- name: ax-llm
2
+ name: ax
3
3
  description: This skill helps with using the @ax-llm/ax TypeScript library for building LLM applications. Use when the user asks about ax(), ai(), f(), s(), agent(), flow(), AxGen, AxAgent, AxFlow, signatures, streaming, or mentions @ax-llm/ax.
4
- version: "18.0.0"
4
+ version: "18.0.2"
5
5
  ---
6
6
 
7
7
  # Ax Library (@ax-llm/ax) Usage Guide
@@ -11,24 +11,20 @@ Ax is a TypeScript library for building LLM-powered applications with type-safe
11
11
  ## Quick Reference
12
12
 
13
13
  ```typescript
14
- import { ax, ai, s, f, agent, flow, AxGen, AxAgent, AxFlow } from '@ax-llm/ax';
14
+ import { ax, ai, f, agent, flow, AxGen, AxAgent, AxFlow } from '@ax-llm/ax';
15
15
 
16
16
  // Create AI provider
17
17
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_API_KEY });
18
18
 
19
- // Create typed generator
20
- const gen = ax('question:string -> answer:string');
19
+ // Create typed generator using f() fluent API
20
+ const gen = ax(
21
+ f()
22
+ .input('question', f.string('User question'))
23
+ .output('answer', f.string('AI response'))
24
+ .build()
25
+ );
21
26
  const result = await gen.forward(llm, { question: 'What is 2+2?' });
22
27
  // result.answer is typed as string
23
-
24
- // Create signature separately
25
- const sig = s('text:string -> summary:string');
26
-
27
- // Field builders for programmatic signatures
28
- const customSig = f()
29
- .input('text', f.string('Input text'))
30
- .output('summary', f.string('Summary output'))
31
- .build();
32
28
  ```
33
29
 
34
30
  ## 1. AI Provider Setup
@@ -89,7 +85,7 @@ const grok = ai({ name: 'grok', apiKey: 'your-key' });
89
85
  ### Full Provider Example
90
86
 
91
87
  ```typescript
92
- import { ai, ax } from '@ax-llm/ax';
88
+ import { ai, ax, f } from '@ax-llm/ax';
93
89
 
94
90
  // Create provider with options
95
91
  const llm = ai({
@@ -103,117 +99,34 @@ const llm = ai({
103
99
  });
104
100
 
105
101
  // Use with generator
106
- const gen = ax('topic:string -> essay:string "A short essay"');
102
+ const gen = ax(
103
+ f()
104
+ .input('topic', f.string())
105
+ .output('essay', f.string('A short essay'))
106
+ .build()
107
+ );
107
108
  const result = await gen.forward(llm, { topic: 'Climate change' });
108
109
  console.log(result.essay);
109
110
  ```
110
111
 
111
112
  ## 2. Signatures & Generators
112
113
 
113
- ### String Signature Syntax
114
-
115
- ```
116
- [description] inputField:type ["field desc"], ... -> outputField:type ["field desc"], ...
117
- ```
118
-
119
- **Types:** `string`, `number`, `boolean`, `json`, `class`, `date`, `datetime`, `image`, `audio`, `file`, `code`, `url`
114
+ Use the `f()` fluent builder to create type-safe signatures with validation, descriptions, and constraints.
120
115
 
121
- **Modifiers:**
122
- - `field?:type` - Optional field
123
- - `field:type[]` - Array type
124
- - `field:class "opt1, opt2, opt3"` - Enum/classification
125
-
126
- ### Signature Examples
116
+ ### Basic Signature
127
117
 
128
118
  ```typescript
129
- import { ax, s } from '@ax-llm/ax';
130
-
131
- // Basic signature
132
- const gen1 = ax('question:string -> answer:string');
133
-
134
- // With descriptions
135
- const gen2 = ax('question:string "User question" -> answer:string "AI response"');
119
+ import { ax, f } from '@ax-llm/ax';
136
120
 
137
- // Optional fields
138
- const gen3 = ax('query:string, context?:string -> response:string');
139
-
140
- // Arrays
141
- const gen4 = ax('text:string -> keywords:string[]');
142
-
143
- // Classification (enum)
144
- const gen5 = ax('review:string -> sentiment:class "positive, negative, neutral"');
145
-
146
- // Multiple outputs
147
- const gen6 = ax('article:string -> title:string, summary:string, tags:string[]');
148
-
149
- // Numbers and booleans
150
- const gen7 = ax('text:string -> wordCount:number, isQuestion:boolean');
151
-
152
- // JSON output
153
- const gen8 = ax('data:string -> parsed:json');
154
-
155
- // Dates
156
- const gen9 = ax('text:string -> extractedDate:date');
157
-
158
- // Code blocks
159
- const gen10 = ax('task:string -> code:code "python"');
160
-
161
- // Signature description
162
- const gen11 = ax('"Translate text to French" text:string -> translation:string');
163
-
164
- // Using s() for signature only
165
- const sig = s('input:string -> output:string');
166
- ```
167
-
168
- ### Complete Generator Example
169
-
170
- ```typescript
171
- import { ai, ax } from '@ax-llm/ax';
172
-
173
- const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_API_KEY! });
174
-
175
- // Create generator with options
176
- const summarizer = ax('article:string -> summary:string, keyPoints:string[]', {
177
- description: 'Summarize articles and extract key points',
178
- maxRetries: 3,
179
- maxSteps: 5
180
- });
181
-
182
- // Forward (non-streaming)
183
- const result = await summarizer.forward(llm, {
184
- article: 'Long article text here...'
185
- });
186
-
187
- console.log(result.summary); // string
188
- console.log(result.keyPoints); // string[]
189
-
190
- // With model override
191
- const result2 = await summarizer.forward(llm, { article: 'text' }, {
192
- model: 'gpt-4o-mini'
193
- });
194
- ```
195
-
196
- ## 3. Field Builders (f.xxx())
197
-
198
- Use field builders for programmatic signature creation with full type safety.
199
-
200
- ### Basic Field Types
201
-
202
- ```typescript
203
- import { f } from '@ax-llm/ax';
204
-
205
- // Start a signature builder
206
- const sig = f()
207
- .input('userQuery', f.string('The user question'))
208
- .input('context', f.string('Background context').optional())
209
- .output('response', f.string('AI response'))
210
- .output('confidence', f.number('Confidence score 0-1'))
211
- .output('isComplete', f.boolean('Whether response is complete'))
212
- .description('Answer questions with confidence scoring')
213
- .build();
121
+ const gen = ax(
122
+ f()
123
+ .input('question', f.string('User question'))
124
+ .output('answer', f.string('AI response'))
125
+ .build()
126
+ );
214
127
  ```
215
128
 
216
- ### All Field Types
129
+ ### Field Types
217
130
 
218
131
  ```typescript
219
132
  import { f } from '@ax-llm/ax';
@@ -270,51 +183,186 @@ f.string().internal() // Internal (not shown to LLM)
270
183
  f.string().cache() // Enable caching
271
184
  ```
272
185
 
273
- ### Complete Field Builder Example
186
+ ### Signature Examples
187
+
188
+ ```typescript
189
+ import { ax, f } from '@ax-llm/ax';
190
+
191
+ // Basic Q&A
192
+ const gen1 = ax(
193
+ f()
194
+ .input('question', f.string())
195
+ .output('answer', f.string())
196
+ .build()
197
+ );
198
+
199
+ // With descriptions
200
+ const gen2 = ax(
201
+ f()
202
+ .input('question', f.string('User question'))
203
+ .output('answer', f.string('AI response'))
204
+ .build()
205
+ );
206
+
207
+ // Optional fields
208
+ const gen3 = ax(
209
+ f()
210
+ .input('query', f.string())
211
+ .input('context', f.string('Background context').optional())
212
+ .output('response', f.string())
213
+ .build()
214
+ );
215
+
216
+ // Arrays
217
+ const gen4 = ax(
218
+ f()
219
+ .input('text', f.string())
220
+ .output('keywords', f.string().array())
221
+ .build()
222
+ );
223
+
224
+ // Classification (enum)
225
+ const gen5 = ax(
226
+ f()
227
+ .input('review', f.string())
228
+ .output('sentiment', f.class(['positive', 'negative', 'neutral']))
229
+ .build()
230
+ );
231
+
232
+ // Multiple outputs
233
+ const gen6 = ax(
234
+ f()
235
+ .input('article', f.string())
236
+ .output('title', f.string())
237
+ .output('summary', f.string())
238
+ .output('tags', f.string().array())
239
+ .build()
240
+ );
241
+
242
+ // Numbers and booleans
243
+ const gen7 = ax(
244
+ f()
245
+ .input('text', f.string())
246
+ .output('wordCount', f.number())
247
+ .output('isQuestion', f.boolean())
248
+ .build()
249
+ );
250
+
251
+ // JSON output
252
+ const gen8 = ax(
253
+ f()
254
+ .input('data', f.string())
255
+ .output('parsed', f.json())
256
+ .build()
257
+ );
258
+
259
+ // Dates
260
+ const gen9 = ax(
261
+ f()
262
+ .input('text', f.string())
263
+ .output('extractedDate', f.date())
264
+ .build()
265
+ );
266
+
267
+ // Code blocks
268
+ const gen10 = ax(
269
+ f()
270
+ .input('task', f.string())
271
+ .output('code', f.code('python'))
272
+ .build()
273
+ );
274
+
275
+ // Signature description
276
+ const gen11 = ax(
277
+ f()
278
+ .input('text', f.string())
279
+ .output('translation', f.string())
280
+ .description('Translate text to French')
281
+ .build()
282
+ );
283
+
284
+ // Nested objects
285
+ const gen12 = ax(
286
+ f()
287
+ .input('document', f.string('Document to analyze'))
288
+ .input('analysisType', f.class(['sentiment', 'entities', 'summary']))
289
+ .output('result', f.object({
290
+ score: f.number().min(0).max(1),
291
+ label: f.string(),
292
+ details: f.string().optional()
293
+ }))
294
+ .output('entities', f.object({
295
+ name: f.string(),
296
+ type: f.class(['person', 'org', 'location'])
297
+ }).array().optional())
298
+ .description('Analyze documents')
299
+ .build()
300
+ );
301
+ ```
302
+
303
+ ### Complete Generator Example
274
304
 
275
305
  ```typescript
276
306
  import { ai, ax, f } from '@ax-llm/ax';
277
307
 
278
- // Build a complex signature
279
- const analysisSig = f()
280
- .input('document', f.string('Document to analyze'))
281
- .input('analysisType', f.class(['sentiment', 'entities', 'summary']))
282
- .output('result', f.object({
283
- score: f.number().min(0).max(1),
284
- label: f.string(),
285
- details: f.string().optional()
286
- }))
287
- .output('entities', f.object({
288
- name: f.string(),
289
- type: f.class(['person', 'org', 'location'])
290
- }).array().optional())
291
- .description('Analyze documents')
292
- .build();
308
+ const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_API_KEY! });
293
309
 
294
- // Create generator from signature
295
- const analyzer = ax(analysisSig);
310
+ // Create generator with options
311
+ const summarizer = ax(
312
+ f()
313
+ .input('article', f.string('Article to summarize'))
314
+ .output('summary', f.string('Concise summary'))
315
+ .output('keyPoints', f.string('Key point').array())
316
+ .build(),
317
+ {
318
+ description: 'Summarize articles and extract key points',
319
+ maxRetries: 3,
320
+ maxSteps: 5
321
+ }
322
+ );
296
323
 
297
- const llm = ai({ name: 'anthropic', apiKey: process.env.ANTHROPIC_API_KEY! });
324
+ // Forward (non-streaming)
325
+ const result = await summarizer.forward(llm, {
326
+ article: 'Long article text here...'
327
+ });
328
+
329
+ console.log(result.summary); // string
330
+ console.log(result.keyPoints); // string[]
298
331
 
299
- const result = await analyzer.forward(llm, {
300
- document: 'Apple Inc. announced new products in Cupertino.',
301
- analysisType: 'entities'
332
+ // With model override
333
+ const result2 = await summarizer.forward(llm, { article: 'text' }, {
334
+ model: 'gpt-4o-mini'
302
335
  });
336
+ ```
337
+
338
+ ### String Shorthand
339
+
340
+ For simple cases, you can also use string syntax:
341
+
342
+ ```typescript
343
+ import { ax } from '@ax-llm/ax';
303
344
 
304
- // Fully typed result
305
- console.log(result.result.score);
306
- console.log(result.entities?.[0]?.name);
345
+ // String shorthand: 'inputField:type -> outputField:type'
346
+ const gen = ax('question:string -> answer:string');
347
+
348
+ // Types: string, number, boolean, json, class, date, datetime, image, audio, file, code, url
349
+ // Modifiers: field?:type (optional), field:type[] (array), field:class "opt1, opt2" (enum)
307
350
  ```
308
351
 
309
- ## 4. Streaming
352
+ ## 3. Streaming
310
353
 
311
354
  ### Basic Streaming
312
355
 
313
356
  ```typescript
314
- import { ai, ax } from '@ax-llm/ax';
357
+ import { ai, ax, f } from '@ax-llm/ax';
315
358
 
316
359
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_API_KEY! });
317
- const gen = ax('topic:string -> content:string');
360
+ const gen = ax(
361
+ f()
362
+ .input('topic', f.string())
363
+ .output('content', f.string())
364
+ .build()
365
+ );
318
366
 
319
367
  // Stream responses
320
368
  for await (const chunk of gen.streamingForward(llm, { topic: 'AI' })) {
@@ -328,11 +376,17 @@ for await (const chunk of gen.streamingForward(llm, { topic: 'AI' })) {
328
376
  ### Complete Streaming Example
329
377
 
330
378
  ```typescript
331
- import { ai, ax } from '@ax-llm/ax';
379
+ import { ai, ax, f } from '@ax-llm/ax';
332
380
 
333
381
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_API_KEY! });
334
382
 
335
- const writer = ax('prompt:string -> story:string, title:string');
383
+ const writer = ax(
384
+ f()
385
+ .input('prompt', f.string())
386
+ .output('story', f.string())
387
+ .output('title', f.string())
388
+ .build()
389
+ );
336
390
 
337
391
  async function streamStory() {
338
392
  let fullStory = '';
@@ -365,11 +419,16 @@ await streamStory();
365
419
  ### Streaming with Field Processors
366
420
 
367
421
  ```typescript
368
- import { ai, ax } from '@ax-llm/ax';
422
+ import { ai, ax, f } from '@ax-llm/ax';
369
423
 
370
424
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_API_KEY! });
371
425
 
372
- const gen = ax('query:string -> response:string');
426
+ const gen = ax(
427
+ f()
428
+ .input('query', f.string())
429
+ .output('response', f.string())
430
+ .build()
431
+ );
373
432
 
374
433
  // Add streaming field processor
375
434
  gen.addStreamingFieldProcessor('response', (chunk, context) => {
@@ -381,7 +440,7 @@ gen.addStreamingFieldProcessor('response', (chunk, context) => {
381
440
  await gen.forward(llm, { query: 'Hello' }, { stream: true });
382
441
  ```
383
442
 
384
- ## 5. Agents with Tools
443
+ ## 4. Agents with Tools
385
444
 
386
445
  Agents can use functions (tools) to perform actions.
387
446
 
@@ -412,17 +471,23 @@ const getCurrentWeather = {
412
471
  ### Creating Agents
413
472
 
414
473
  ```typescript
415
- import { ai, agent } from '@ax-llm/ax';
474
+ import { ai, agent, f } from '@ax-llm/ax';
416
475
 
417
476
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_API_KEY! });
418
477
 
419
478
  // Create agent with functions
420
- const weatherAgent = agent('query:string -> response:string', {
421
- name: 'weatherAssistant',
422
- description: 'An assistant that helps with weather queries',
423
- definition: 'You are a helpful weather assistant. Use the getCurrentWeather function to get weather data and provide friendly responses.',
424
- functions: [getCurrentWeather]
425
- });
479
+ const weatherAgent = agent(
480
+ f()
481
+ .input('query', f.string())
482
+ .output('response', f.string())
483
+ .build(),
484
+ {
485
+ name: 'weatherAssistant',
486
+ description: 'An assistant that helps with weather queries',
487
+ definition: 'You are a helpful weather assistant. Use the getCurrentWeather function to get weather data and provide friendly responses.',
488
+ functions: [getCurrentWeather]
489
+ }
490
+ );
426
491
 
427
492
  const result = await weatherAgent.forward(llm, {
428
493
  query: 'What is the weather in Tokyo?'
@@ -434,7 +499,7 @@ console.log(result.response);
434
499
  ### Complete Agent Example
435
500
 
436
501
  ```typescript
437
- import { ai, agent } from '@ax-llm/ax';
502
+ import { ai, agent, f } from '@ax-llm/ax';
438
503
 
439
504
  // Define tools
440
505
  const searchDatabase = {
@@ -480,7 +545,11 @@ const getProductDetails = {
480
545
 
481
546
  // Create agent
482
547
  const shopAssistant = agent(
483
- 'userQuery:string -> response:string, recommendations:string[]',
548
+ f()
549
+ .input('userQuery', f.string())
550
+ .output('response', f.string())
551
+ .output('recommendations', f.string().array())
552
+ .build(),
484
553
  {
485
554
  name: 'shoppingAssistant',
486
555
  description: 'An AI assistant that helps users find and learn about products',
@@ -507,20 +576,32 @@ console.log('Recommendations:', result.recommendations);
507
576
  ### Nested Agents
508
577
 
509
578
  ```typescript
510
- import { ai, agent } from '@ax-llm/ax';
579
+ import { ai, agent, f } from '@ax-llm/ax';
511
580
 
512
581
  // Child agent
513
- const researcher = agent('topic:string -> findings:string', {
514
- name: 'researchAgent',
515
- description: 'Researches topics and provides detailed findings'
516
- });
582
+ const researcher = agent(
583
+ f()
584
+ .input('topic', f.string())
585
+ .output('findings', f.string())
586
+ .build(),
587
+ {
588
+ name: 'researchAgent',
589
+ description: 'Researches topics and provides detailed findings'
590
+ }
591
+ );
517
592
 
518
593
  // Parent agent that can use child agent
519
- const writer = agent('topic:string -> article:string', {
520
- name: 'writerAgent',
521
- description: 'Writes articles using research from the research agent',
522
- agents: [researcher]
523
- });
594
+ const writer = agent(
595
+ f()
596
+ .input('topic', f.string())
597
+ .output('article', f.string())
598
+ .build(),
599
+ {
600
+ name: 'writerAgent',
601
+ description: 'Writes articles using research from the research agent',
602
+ agents: [researcher]
603
+ }
604
+ );
524
605
 
525
606
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_API_KEY! });
526
607
 
@@ -529,20 +610,30 @@ const result = await writer.forward(llm, {
529
610
  });
530
611
  ```
531
612
 
532
- ## 6. Workflows (AxFlow)
613
+ ## 5. Workflows (AxFlow)
533
614
 
534
615
  AxFlow enables building complex, multi-step AI workflows with type safety.
535
616
 
536
617
  ### Basic Flow
537
618
 
538
619
  ```typescript
539
- import { ai, flow } from '@ax-llm/ax';
620
+ import { ai, flow, f } from '@ax-llm/ax';
540
621
 
541
622
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_API_KEY! });
542
623
 
624
+ const summarizerSig = f()
625
+ .input('text', f.string())
626
+ .output('summary', f.string())
627
+ .build();
628
+
629
+ const translatorSig = f()
630
+ .input('text', f.string())
631
+ .output('translation', f.string())
632
+ .build();
633
+
543
634
  const pipeline = flow<{ text: string }, { result: string }>()
544
- .node('summarizer', 'text:string -> summary:string')
545
- .node('translator', 'text:string -> translation:string')
635
+ .node('summarizer', summarizerSig)
636
+ .node('translator', translatorSig)
546
637
  .execute('summarizer', (state) => ({ text: state.text }))
547
638
  .execute('translator', (state) => ({ text: state.summarizerResult.summary }))
548
639
  .map((state) => ({ result: state.translatorResult.translation }));
@@ -554,13 +645,23 @@ console.log(result.result);
554
645
  ### Flow with Branching
555
646
 
556
647
  ```typescript
557
- import { ai, flow } from '@ax-llm/ax';
648
+ import { ai, flow, f } from '@ax-llm/ax';
558
649
 
559
650
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_API_KEY! });
560
651
 
652
+ const technicalSig = f()
653
+ .input('query', f.string())
654
+ .output('answer', f.string())
655
+ .build();
656
+
657
+ const creativeSig = f()
658
+ .input('query', f.string())
659
+ .output('answer', f.string())
660
+ .build();
661
+
561
662
  const workflow = flow<{ query: string; type: string }, { output: string }>()
562
- .node('technical', 'query:string -> answer:string')
563
- .node('creative', 'query:string -> answer:string')
663
+ .node('technical', technicalSig)
664
+ .node('creative', creativeSig)
564
665
  .branch(
565
666
  (state) => state.type === 'technical',
566
667
  (branch) => branch.execute('technical', (s) => ({ query: s.query })),
@@ -579,14 +680,30 @@ const result = await workflow.forward(llm, {
579
680
  ### Flow with Parallel Execution
580
681
 
581
682
  ```typescript
582
- import { ai, flow } from '@ax-llm/ax';
683
+ import { ai, flow, f } from '@ax-llm/ax';
583
684
 
584
685
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_API_KEY! });
585
686
 
687
+ const prosSig = f()
688
+ .input('topic', f.string())
689
+ .output('arguments', f.string())
690
+ .build();
691
+
692
+ const consSig = f()
693
+ .input('topic', f.string())
694
+ .output('arguments', f.string())
695
+ .build();
696
+
697
+ const summarySig = f()
698
+ .input('prosArgs', f.string())
699
+ .input('consArgs', f.string())
700
+ .output('summary', f.string())
701
+ .build();
702
+
586
703
  const parallelFlow = flow<{ topic: string }, { combined: string }>()
587
- .node('pros', 'topic:string -> arguments:string')
588
- .node('cons', 'topic:string -> arguments:string')
589
- .node('summary', 'prosArgs:string, consArgs:string -> summary:string')
704
+ .node('pros', prosSig)
705
+ .node('cons', consSig)
706
+ .node('summary', summarySig)
590
707
  .parallel([
591
708
  { branch: (b) => b.execute('pros', (s) => ({ topic: s.topic })) },
592
709
  { branch: (b) => b.execute('cons', (s) => ({ topic: s.topic })) }
@@ -666,15 +783,19 @@ console.log('Article:', result.article);
666
783
  console.log('Word count:', result.wordCount);
667
784
  ```
668
785
 
669
- ## 7. Common Patterns
786
+ ## 6. Common Patterns
670
787
 
671
788
  ### Classification
672
789
 
673
790
  ```typescript
674
- import { ai, ax } from '@ax-llm/ax';
791
+ import { ai, ax, f } from '@ax-llm/ax';
675
792
 
676
793
  const classifier = ax(
677
- 'text:string -> category:class "spam, ham, uncertain", confidence:number'
794
+ f()
795
+ .input('text', f.string())
796
+ .output('category', f.class(['spam', 'ham', 'uncertain']))
797
+ .output('confidence', f.number().min(0).max(1))
798
+ .build()
678
799
  );
679
800
 
680
801
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_API_KEY! });
@@ -692,17 +813,7 @@ console.log(result.confidence); // 0.95
692
813
  ```typescript
693
814
  import { ai, ax, f } from '@ax-llm/ax';
694
815
 
695
- // Using string syntax
696
- const extractor = ax(`
697
- text:string ->
698
- people:string[],
699
- organizations:string[],
700
- locations:string[],
701
- dates:date[]
702
- `);
703
-
704
- // Or with field builders for structured output
705
- const structuredExtractor = ax(
816
+ const extractor = ax(
706
817
  f()
707
818
  .input('text', f.string())
708
819
  .output('entities', f.object({
@@ -719,9 +830,9 @@ const result = await extractor.forward(llm, {
719
830
  text: 'Tim Cook announced that Apple will open a new store in Paris on January 15th.'
720
831
  });
721
832
 
722
- console.log(result.people); // ['Tim Cook']
723
- console.log(result.organizations); // ['Apple']
724
- console.log(result.locations); // ['Paris']
833
+ console.log(result.entities.people); // ['Tim Cook']
834
+ console.log(result.entities.organizations); // ['Apple']
835
+ console.log(result.entities.locations); // ['Paris']
725
836
  ```
726
837
 
727
838
  ### Multi-modal (Images)
@@ -757,14 +868,34 @@ const result2 = await imageAnalyzer.forward(llm, {
757
868
  ### Chaining Generators
758
869
 
759
870
  ```typescript
760
- import { ai, ax } from '@ax-llm/ax';
871
+ import { ai, ax, f } from '@ax-llm/ax';
761
872
 
762
873
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_API_KEY! });
763
874
 
764
875
  // Define generators
765
- const researcher = ax('topic:string -> research:string, keyFacts:string[]');
766
- const writer = ax('research:string, keyFacts:string[] -> article:string');
767
- const editor = ax('article:string -> editedArticle:string, suggestions:string[]');
876
+ const researcher = ax(
877
+ f()
878
+ .input('topic', f.string())
879
+ .output('research', f.string())
880
+ .output('keyFacts', f.string().array())
881
+ .build()
882
+ );
883
+
884
+ const writer = ax(
885
+ f()
886
+ .input('research', f.string())
887
+ .input('keyFacts', f.string().array())
888
+ .output('article', f.string())
889
+ .build()
890
+ );
891
+
892
+ const editor = ax(
893
+ f()
894
+ .input('article', f.string())
895
+ .output('editedArticle', f.string())
896
+ .output('suggestions', f.string().array())
897
+ .build()
898
+ );
768
899
 
769
900
  // Chain them
770
901
  async function createArticle(topic: string) {
@@ -789,9 +920,14 @@ console.log(result.editedArticle);
789
920
  ### Error Handling
790
921
 
791
922
  ```typescript
792
- import { ai, ax, AxGenerateError, AxAIServiceError } from '@ax-llm/ax';
923
+ import { ai, ax, f, AxGenerateError, AxAIServiceError } from '@ax-llm/ax';
793
924
 
794
- const gen = ax('input:string -> output:string');
925
+ const gen = ax(
926
+ f()
927
+ .input('input', f.string())
928
+ .output('output', f.string())
929
+ .build()
930
+ );
795
931
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_API_KEY! });
796
932
 
797
933
  try {
@@ -812,9 +948,14 @@ try {
812
948
  ### Examples and Few-Shot Learning
813
949
 
814
950
  ```typescript
815
- import { ai, ax } from '@ax-llm/ax';
951
+ import { ai, ax, f } from '@ax-llm/ax';
816
952
 
817
- const classifier = ax('text:string -> sentiment:class "positive, negative, neutral"');
953
+ const classifier = ax(
954
+ f()
955
+ .input('text', f.string())
956
+ .output('sentiment', f.class(['positive', 'negative', 'neutral']))
957
+ .build()
958
+ );
818
959
 
819
960
  // Set examples for few-shot learning
820
961
  classifier.setExamples([
@@ -833,9 +974,14 @@ const result = await classifier.forward(llm, {
833
974
  ### Assertions and Validation
834
975
 
835
976
  ```typescript
836
- import { ai, ax } from '@ax-llm/ax';
977
+ import { ai, ax, f } from '@ax-llm/ax';
837
978
 
838
- const gen = ax('number:number -> doubled:number');
979
+ const gen = ax(
980
+ f()
981
+ .input('number', f.number())
982
+ .output('doubled', f.number())
983
+ .build()
984
+ );
839
985
 
840
986
  // Add assertion
841
987
  gen.addAssert(
@@ -852,9 +998,14 @@ const result = await gen.forward(llm, { number: 5 }, { maxRetries: 3 });
852
998
  ### Memory and Context
853
999
 
854
1000
  ```typescript
855
- import { ai, ax, AxMemory } from '@ax-llm/ax';
1001
+ import { ai, ax, f, AxMemory } from '@ax-llm/ax';
856
1002
 
857
- const chatbot = ax('userMessage:string -> response:string');
1003
+ const chatbot = ax(
1004
+ f()
1005
+ .input('userMessage', f.string())
1006
+ .output('response', f.string())
1007
+ .build()
1008
+ );
858
1009
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_API_KEY! });
859
1010
 
860
1011
  // Create shared memory
@@ -866,15 +1017,20 @@ const response = await chatbot.forward(llm, { userMessage: 'What is my name?' },
866
1017
  // response.response will reference "Alice"
867
1018
  ```
868
1019
 
869
- ## 8. Advanced Configuration
1020
+ ## 7. Advanced Configuration
870
1021
 
871
1022
  ### Model Configuration
872
1023
 
873
1024
  ```typescript
874
- import { ai, ax } from '@ax-llm/ax';
1025
+ import { ai, ax, f } from '@ax-llm/ax';
875
1026
 
876
1027
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_API_KEY! });
877
- const gen = ax('input:string -> output:string');
1028
+ const gen = ax(
1029
+ f()
1030
+ .input('input', f.string())
1031
+ .output('output', f.string())
1032
+ .build()
1033
+ );
878
1034
 
879
1035
  const result = await gen.forward(llm, { input: 'test' }, {
880
1036
  model: 'gpt-4o',
@@ -889,10 +1045,15 @@ const result = await gen.forward(llm, { input: 'test' }, {
889
1045
  ### Debugging
890
1046
 
891
1047
  ```typescript
892
- import { ai, ax, axCreateDefaultColorLogger } from '@ax-llm/ax';
1048
+ import { ai, ax, f, axCreateDefaultColorLogger } from '@ax-llm/ax';
893
1049
 
894
1050
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_API_KEY! });
895
- const gen = ax('input:string -> output:string');
1051
+ const gen = ax(
1052
+ f()
1053
+ .input('input', f.string())
1054
+ .output('output', f.string())
1055
+ .build()
1056
+ );
896
1057
 
897
1058
  // Enable debug logging
898
1059
  const result = await gen.forward(llm, { input: 'test' }, {
@@ -904,9 +1065,15 @@ const result = await gen.forward(llm, { input: 'test' }, {
904
1065
  ### Context Caching
905
1066
 
906
1067
  ```typescript
907
- import { ai, ax } from '@ax-llm/ax';
1068
+ import { ai, ax, f } from '@ax-llm/ax';
908
1069
 
909
- const gen = ax('document:string, question:string -> answer:string');
1070
+ const gen = ax(
1071
+ f()
1072
+ .input('document', f.string())
1073
+ .input('question', f.string())
1074
+ .output('answer', f.string())
1075
+ .build()
1076
+ );
910
1077
  const llm = ai({ name: 'anthropic', apiKey: process.env.ANTHROPIC_API_KEY! });
911
1078
 
912
1079
  // Enable context caching for long documents
@@ -920,7 +1087,7 @@ const result = await gen.forward(llm, {
920
1087
  });
921
1088
  ```
922
1089
 
923
- ## 9. Forward & AI Options
1090
+ ## 8. Forward & AI Options
924
1091
 
925
1092
  ### Quick Reference Table
926
1093
 
@@ -940,10 +1107,15 @@ const result = await gen.forward(llm, {
940
1107
  ### Execution Control Options
941
1108
 
942
1109
  ```typescript
943
- import { ai, ax } from '@ax-llm/ax';
1110
+ import { ai, ax, f } from '@ax-llm/ax';
944
1111
 
945
1112
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_API_KEY! });
946
- const gen = ax('input:string -> output:string');
1113
+ const gen = ax(
1114
+ f()
1115
+ .input('input', f.string())
1116
+ .output('output', f.string())
1117
+ .build()
1118
+ );
947
1119
 
948
1120
  const result = await gen.forward(llm, { input: 'test' }, {
949
1121
  // Retry failed generations (validation failures, API errors)
@@ -960,10 +1132,15 @@ const result = await gen.forward(llm, { input: 'test' }, {
960
1132
  ### Model Configuration
961
1133
 
962
1134
  ```typescript
963
- import { ai, ax } from '@ax-llm/ax';
1135
+ import { ai, ax, f } from '@ax-llm/ax';
964
1136
 
965
1137
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_API_KEY! });
966
- const gen = ax('input:string -> output:string');
1138
+ const gen = ax(
1139
+ f()
1140
+ .input('input', f.string())
1141
+ .output('output', f.string())
1142
+ .build()
1143
+ );
967
1144
 
968
1145
  const result = await gen.forward(llm, { input: 'test' }, {
969
1146
  // Override the model for this request
@@ -1006,10 +1183,16 @@ const result = await gen.forward(llm, { input: 'test' }, {
1006
1183
  Context caching saves costs when repeatedly querying with the same large context (documents, system prompts, examples).
1007
1184
 
1008
1185
  ```typescript
1009
- import { ai, ax } from '@ax-llm/ax';
1186
+ import { ai, ax, f } from '@ax-llm/ax';
1010
1187
 
1011
1188
  const llm = ai({ name: 'anthropic', apiKey: process.env.ANTHROPIC_API_KEY! });
1012
- const gen = ax('document:string, question:string -> answer:string');
1189
+ const gen = ax(
1190
+ f()
1191
+ .input('document', f.string())
1192
+ .input('question', f.string())
1193
+ .output('answer', f.string())
1194
+ .build()
1195
+ );
1013
1196
 
1014
1197
  const longDocument = '... very long document ...';
1015
1198
 
@@ -1047,10 +1230,15 @@ for (const question of questions) {
1047
1230
  For reasoning models that support extended thinking:
1048
1231
 
1049
1232
  ```typescript
1050
- import { ai, ax } from '@ax-llm/ax';
1233
+ import { ai, ax, f } from '@ax-llm/ax';
1051
1234
 
1052
1235
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_API_KEY! });
1053
- const gen = ax('problem:string -> solution:string');
1236
+ const gen = ax(
1237
+ f()
1238
+ .input('problem', f.string())
1239
+ .output('solution', f.string())
1240
+ .build()
1241
+ );
1054
1242
 
1055
1243
  const result = await gen.forward(llm, { problem: 'Complex math problem' }, {
1056
1244
  model: 'o1',
@@ -1071,10 +1259,16 @@ const result = await gen.forward(llm, { problem: 'Complex math problem' }, {
1071
1259
  Generate multiple samples and pick the best one:
1072
1260
 
1073
1261
  ```typescript
1074
- import { ai, ax } from '@ax-llm/ax';
1262
+ import { ai, ax, f } from '@ax-llm/ax';
1075
1263
 
1076
1264
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_API_KEY! });
1077
- const gen = ax('input:string -> output:string, confidence:number');
1265
+ const gen = ax(
1266
+ f()
1267
+ .input('input', f.string())
1268
+ .output('output', f.string())
1269
+ .output('confidence', f.number())
1270
+ .build()
1271
+ );
1078
1272
 
1079
1273
  const result = await gen.forward(llm, { input: 'test' }, {
1080
1274
  // Generate multiple samples
@@ -1095,13 +1289,21 @@ const result = await gen.forward(llm, { input: 'test' }, {
1095
1289
  Control how agents use tools/functions:
1096
1290
 
1097
1291
  ```typescript
1098
- import { ai, agent } from '@ax-llm/ax';
1292
+ import { ai, agent, f } from '@ax-llm/ax';
1099
1293
 
1100
1294
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_API_KEY! });
1101
1295
 
1102
- const myAgent = agent('query:string -> answer:string', {
1103
- functions: [searchTool, calculatorTool]
1104
- });
1296
+ const myAgent = agent(
1297
+ f()
1298
+ .input('query', f.string())
1299
+ .output('answer', f.string())
1300
+ .build(),
1301
+ {
1302
+ name: 'toolAgent',
1303
+ description: 'An agent that uses tools to answer queries',
1304
+ functions: [searchTool, calculatorTool]
1305
+ }
1306
+ );
1105
1307
 
1106
1308
  const result = await myAgent.forward(llm, { query: 'test' }, {
1107
1309
  // Function calling mode:
@@ -1130,10 +1332,15 @@ const result = await myAgent.forward(llm, { query: 'test' }, {
1130
1332
  ### Debugging & Observability
1131
1333
 
1132
1334
  ```typescript
1133
- import { ai, ax, axCreateDefaultColorLogger } from '@ax-llm/ax';
1335
+ import { ai, ax, f, axCreateDefaultColorLogger } from '@ax-llm/ax';
1134
1336
 
1135
1337
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_API_KEY! });
1136
- const gen = ax('input:string -> output:string');
1338
+ const gen = ax(
1339
+ f()
1340
+ .input('input', f.string())
1341
+ .output('output', f.string())
1342
+ .build()
1343
+ );
1137
1344
 
1138
1345
  const result = await gen.forward(llm, { input: 'test' }, {
1139
1346
  // Enable debug logging
@@ -1168,7 +1375,7 @@ const result = await gen.forward(llm, { input: 'test' }, {
1168
1375
  ### Retry & Error Handling
1169
1376
 
1170
1377
  ```typescript
1171
- import { ai, ax } from '@ax-llm/ax';
1378
+ import { ai, ax, f } from '@ax-llm/ax';
1172
1379
 
1173
1380
  const llm = ai({
1174
1381
  name: 'openai',
@@ -1207,10 +1414,15 @@ const llm = ai({
1207
1414
  ### Request Control
1208
1415
 
1209
1416
  ```typescript
1210
- import { ai, ax } from '@ax-llm/ax';
1417
+ import { ai, ax, f } from '@ax-llm/ax';
1211
1418
 
1212
1419
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_API_KEY! });
1213
- const gen = ax('input:string -> output:string');
1420
+ const gen = ax(
1421
+ f()
1422
+ .input('input', f.string())
1423
+ .output('output', f.string())
1424
+ .build()
1425
+ );
1214
1426
 
1215
1427
  // Create abort controller
1216
1428
  const controller = new AbortController();
@@ -1242,10 +1454,15 @@ try {
1242
1454
  ### Memory Configuration
1243
1455
 
1244
1456
  ```typescript
1245
- import { ai, ax, AxMemory } from '@ax-llm/ax';
1457
+ import { ai, ax, f, AxMemory } from '@ax-llm/ax';
1246
1458
 
1247
1459
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_API_KEY! });
1248
- const gen = ax('message:string -> response:string');
1460
+ const gen = ax(
1461
+ f()
1462
+ .input('message', f.string())
1463
+ .output('response', f.string())
1464
+ .build()
1465
+ );
1249
1466
 
1250
1467
  const memory = new AxMemory();
1251
1468
 
@@ -1261,10 +1478,15 @@ const result = await gen.forward(llm, { message: 'Hello' }, {
1261
1478
  ### Validation Options
1262
1479
 
1263
1480
  ```typescript
1264
- import { ai, ax } from '@ax-llm/ax';
1481
+ import { ai, ax, f } from '@ax-llm/ax';
1265
1482
 
1266
1483
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_API_KEY! });
1267
- const gen = ax('input:string -> output:string');
1484
+ const gen = ax(
1485
+ f()
1486
+ .input('input', f.string())
1487
+ .output('output', f.string())
1488
+ .build()
1489
+ );
1268
1490
 
1269
1491
  const result = await gen.forward(llm, { input: 'test' }, {
1270
1492
  // Strict mode: fail on any validation error
@@ -1288,7 +1510,7 @@ const result = await gen.forward(llm, { input: 'test' }, {
1288
1510
  });
1289
1511
  ```
1290
1512
 
1291
- ## 10. MCP Integration
1513
+ ## 9. MCP Integration
1292
1514
 
1293
1515
  MCP (Model Context Protocol) enables AxAgent to use external tools from MCP-compliant servers. This allows your agents to interact with databases, file systems, APIs, and other services through a standardized protocol.
1294
1516
 
@@ -1312,7 +1534,10 @@ await mcpClient.init();
1312
1534
  const agent = new AxAgent({
1313
1535
  name: 'MyAssistant',
1314
1536
  description: 'An assistant with MCP capabilities',
1315
- signature: 'userMessage -> response',
1537
+ signature: f()
1538
+ .input('userMessage', f.string())
1539
+ .output('response', f.string())
1540
+ .build(),
1316
1541
  functions: [mcpClient], // Pass client directly
1317
1542
  });
1318
1543
 
@@ -1364,7 +1589,7 @@ const transport = new AxMCPStreambleHTTPTransport(
1364
1589
  Pass the MCP client directly to the agent's `functions` array:
1365
1590
 
1366
1591
  ```typescript
1367
- import { AxAgent, AxAI, AxMCPClient } from '@ax-llm/ax';
1592
+ import { AxAgent, AxAI, AxMCPClient, f } from '@ax-llm/ax';
1368
1593
  import { AxMCPStdioTransport } from '@ax-llm/ax-tools';
1369
1594
 
1370
1595
  const transport = new AxMCPStdioTransport({
@@ -1381,7 +1606,11 @@ const memoryAgent = new AxAgent<
1381
1606
  >({
1382
1607
  name: 'MemoryAssistant',
1383
1608
  description: 'An assistant that remembers past conversations. Use the database functions to manage, search, and add memories.',
1384
- signature: 'userMessage, userId -> assistantResponse',
1609
+ signature: f()
1610
+ .input('userMessage', f.string())
1611
+ .input('userId', f.string())
1612
+ .output('assistantResponse', f.string())
1613
+ .build(),
1385
1614
  functions: [mcpClient],
1386
1615
  });
1387
1616
 
@@ -1470,7 +1699,10 @@ const functions = mcpClient.toFunction();
1470
1699
  // Use with agent
1471
1700
  const agent = new AxAgent({
1472
1701
  name: 'MyAgent',
1473
- signature: 'query -> answer',
1702
+ signature: f()
1703
+ .input('query', f.string())
1704
+ .output('answer', f.string())
1705
+ .build(),
1474
1706
  functions: functions, // Or spread: [...functions, otherFunction]
1475
1707
  });
1476
1708
  ```
@@ -1478,7 +1710,7 @@ const agent = new AxAgent({
1478
1710
  ### Complete Example: Remote HTTP MCP Server
1479
1711
 
1480
1712
  ```typescript
1481
- import { AxAgent, AxAI, AxMCPClient } from '@ax-llm/ax';
1713
+ import { AxAgent, AxAI, AxMCPClient, f } from '@ax-llm/ax';
1482
1714
  import { AxMCPStreambleHTTPTransport } from '@ax-llm/ax/mcp/transports/httpStreamTransport.js';
1483
1715
  import { createBackendClient } from '@pipedream/sdk/server';
1484
1716
 
@@ -1522,7 +1754,10 @@ const notionAgent = new AxAgent<
1522
1754
  >({
1523
1755
  name: 'NotionAssistant',
1524
1756
  description: 'An assistant that can interact with Notion documents. Use the provided functions to read, search, and analyze Notion content.',
1525
- signature: 'userRequest -> assistantResponse',
1757
+ signature: f()
1758
+ .input('userRequest', f.string())
1759
+ .output('assistantResponse', f.string())
1760
+ .build(),
1526
1761
  functions: [mcpClient],
1527
1762
  });
1528
1763