@ax-llm/ax 23.0.1 → 23.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-flow.md CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: ax-flow
3
3
  description: This skill helps an LLM generate correct AxFlow workflow code using @ax-llm/ax. Use when the user asks about flow(), AxFlow, workflow orchestration, parallel execution, DAG workflows, conditional routing, map/reduce patterns, or multi-node AI pipelines.
4
- version: "23.0.1"
4
+ version: "23.0.2"
5
5
  ---
6
6
 
7
7
  # AxFlow Codegen Rules (@ax-llm/ax)
@@ -93,6 +93,21 @@ flow.node('extractor', 'documentText:string -> entities:string[]');
93
93
  flow.n('processor', 'input:string -> output:string');
94
94
  ```
95
95
 
96
+ ### Rich Node Contracts (String Grammar)
97
+
98
+ Node signatures accept the full extended string grammar — constraint bags, class decisions, optional fields, and nested objects (full modifier table in the ax-signature skill):
99
+
100
+ ```typescript
101
+ flow
102
+ .node('triage', 'ticketText:string -> ticketClass:class "bug, billing, question", severityScore:number(min 1, max 5)')
103
+ .node('draft', 'ticketText:string, ticketClass:string, severityScore:number -> replyText:string(max 400)')
104
+ .node('audit', 'replyText:string -> approved:boolean, flaggedSpans:object{ spanText:string, reasonNote:string }[]');
105
+ ```
106
+
107
+ - `class` is output-only: a downstream node consuming the decision declares it `:string`.
108
+ - Optional marks go on the name (`note?:string`), never after the type.
109
+ - `toString()` serializes these contracts losslessly into `%%ax` directives, so rich contracts survive the diagram round-trip.
110
+
96
111
  ## Extended Nodes (nx)
97
112
 
98
113
  Add fields to a base signature without rewriting it:
@@ -417,11 +432,204 @@ Common errors:
417
432
  - `"merge() without matching branch()"` -- every `.branch()` needs `.merge()`.
418
433
  - `"Label 'x' not found"` -- define `.label()` before `.feedback()` references it.
419
434
 
435
+ ## Native MCP/UCP
436
+
437
+ Use `ax-mcp` for MCP client construction, transport/authentication policy,
438
+ subscriptions, tasks, event routing, and replay. This section covers how Flow
439
+ inherits and coordinates the resulting live execution context.
440
+
441
+ Set `mcp`/`ucp` on the flow or a node. Sequential nodes reuse sessions; parallel nodes multiplex through each client's concurrency policy. Branch cancellation and flow aborts propagate to outstanding requests and newly created remote tasks. Structured protocol values stay structured in flow state.
442
+
443
+ ```typescript
444
+ const wf = flow({ mcp: [inventory], ucp: [merchant] })
445
+ .node('lookup', lookupProgram)
446
+ .node('checkout', checkoutProgram, { mcpInheritance: ['merchant'] });
447
+ ```
448
+
449
+ ## Mermaid Source (Author or Serialize Flows)
450
+
451
+ A whole flow can be written as (or exported to) a mermaid flowchart. Pass the
452
+ diagram string straight to `flow()` — a string argument compiles the AxFlow
453
+ mermaid dialect into a runnable flow (an options object still constructs an
454
+ empty builder). `String(wf)` / `wf.toString()` renders any flow back, so
455
+ `flow(String(wf))` round-trips.
456
+
457
+ ```typescript
458
+ import { flow } from '@ax-llm/ax';
459
+
460
+ const wf = flow<{ documentText: string }, { finalReport: string }>(`
461
+ flowchart TD
462
+ %%ax summarize: documentText:string -> summaryText:string(max 500)
463
+ %%ax check: summaryText:string -> verdict:class "pass, fail", note?:string
464
+ %%ax format: summaryText:string, note?:string -> finalReport:string
465
+
466
+ summarize[Summarize document] --> check{verdict}
467
+ check -->|pass| format
468
+ check -->|fail, max 3| summarize
469
+ `);
470
+
471
+ const { finalReport } = await wf.forward(llm, { documentText });
472
+ console.log(String(wf)); // render back to the same dialect
473
+ ```
474
+
475
+ Dialect:
476
+ - `%%ax nodeId: <signature>` comment directives carry node contracts (mermaid renderers ignore them); the full string-signature grammar applies (`?` optional on the name, constraint bags, `object{ ... }`).
477
+ - Data auto-wires by field name: each node input binds to the nearest upstream node that outputs that field; a field no node produces becomes a flow input.
478
+ - A diamond `nodeId{field}` names a `class` decision; its labeled out-edges (`-->|pass|`) become branches. A back-edge is a loop: `-->|label, max N|` is feedback, `-->|while cond, max N|` is a while loop.
479
+
480
+ Render options and bindings:
481
+ - `wf.toString({ direction: 'LR' })` when you need render options; bare `String(wf)` uses defaults (`flowchart TD`).
482
+ - `bindings` supplies closures the dialect can't inline: `{ nodes: { normalize: (s) => ({...}) }, conditions: { keepGoing: (s) => ... } }` for map steps and `while` conditions.
483
+
484
+ ### Flow Gallery
485
+
486
+ Every diagram below compiles with `flow(text)` as written (the while loop additionally needs its `conditions` binding).
487
+
488
+ Linear pipeline — three nodes auto-wired by field name:
489
+
490
+ ```text
491
+ flowchart TD
492
+ %%ax extract: contractText:string -> parties:string[], effectiveDate?:string(format date)
493
+ %%ax summarize: contractText:string, parties:string[] -> summaryText:string(max 300)
494
+ %%ax redline: summaryText:string -> riskNotes:string(item "one risk")[]
495
+
496
+ extract --> summarize --> redline
497
+ ```
498
+
499
+ Decision branch — a class diamond routes to per-branch responders, then re-joins:
500
+
501
+ ```text
502
+ flowchart TD
503
+ %%ax classify: requestText:string -> routeClass:class "support, sales"
504
+ %%ax supportReply: requestText:string -> replyText:string(max 300)
505
+ %%ax salesReply: requestText:string -> replyText:string(max 300)
506
+ %%ax send: replyText:string -> deliveredReply:string
507
+
508
+ classify{routeClass}
509
+ classify -->|support| supportReply
510
+ classify -->|sales| salesReply
511
+ supportReply --> send
512
+ salesReply --> send
513
+ ```
514
+
515
+ Retry loop — a reviewer sends drafts back with a capped revise edge:
516
+
517
+ ```text
518
+ flowchart TD
519
+ %%ax draft: briefText:string -> articleText:string(max 800)
520
+ %%ax review: articleText:string -> verdict:class "publish, revise", editorNote?:string
521
+ %%ax publish: articleText:string, editorNote?:string -> finalPost:string
522
+
523
+ draft --> review{verdict}
524
+ review -->|publish| publish
525
+ review -->|revise, max 2| draft
526
+ ```
527
+
528
+ Fan-out / fan-in — two perspectives run in parallel, then a judge joins them:
529
+
530
+ ```text
531
+ flowchart TD
532
+ %%ax outline: topicText:string -> questionText:string
533
+ %%ax proponent: questionText:string -> proArgument:string
534
+ %%ax skeptic: questionText:string -> conArgument:string
535
+ %%ax judge: proArgument:string, conArgument:string -> verdictSummary:string
536
+
537
+ outline --> proponent & skeptic
538
+ proponent & skeptic --> judge
539
+ ```
540
+
541
+ While loop — repeat until a host-owned condition says stop (`flow(text, { conditions: { keepPolishing } })`):
542
+
543
+ ```text
544
+ flowchart TD
545
+ %%ax polish: draftText:string -> polishedText:string
546
+ %%ax grade: polishedText:string -> qualityScore:number(min 0, max 1)
547
+
548
+ polish --> grade
549
+ grade -->|while keepPolishing, max 5| polish
550
+ ```
551
+
552
+ Three-way branch and re-join — triage routes to one of three handlers before delivery:
553
+
554
+ ```text
555
+ flowchart TD
556
+ %%ax triage: ticketText:string -> ticketClass:class "bug, billing, question"
557
+ %%ax bugHandler: ticketText:string -> replyText:string(max 300)
558
+ %%ax billingHandler: ticketText:string -> replyText:string(max 300)
559
+ %%ax questionHandler: ticketText:string -> replyText:string(max 300)
560
+ %%ax send: replyText:string -> deliveredReply:string
561
+
562
+ triage{ticketClass}
563
+ triage -->|bug| bugHandler
564
+ triage -->|billing| billingHandler
565
+ triage -->|question| questionHandler
566
+ bugHandler --> send
567
+ billingHandler --> send
568
+ questionHandler --> send
569
+ ```
570
+
571
+ Judge panel — three independent drafts fan out, then converge on one verdict:
572
+
573
+ ```text
574
+ flowchart TD
575
+ %%ax outline: topicText:string -> outlineText:string
576
+ %%ax draftA: outlineText:string -> draftAText:string
577
+ %%ax draftB: outlineText:string -> draftBText:string
578
+ %%ax draftC: outlineText:string -> draftCText:string
579
+ %%ax judge: draftAText:string, draftBText:string, draftCText:string -> verdictText:string
580
+
581
+ outline --> draftA & draftB & draftC
582
+ draftA & draftB & draftC --> judge
583
+ ```
584
+
585
+ Escalation ladder — a quality gate either sends the first answer or falls back to level two:
586
+
587
+ ```text
588
+ flowchart TD
589
+ %%ax l1Answer: ticketText:string -> answerText:string
590
+ %%ax qualityGate: answerText:string -> verdict:class "pass, escalate"
591
+ %%ax l2Answer: ticketText:string -> answerText:string
592
+ %%ax send: answerText:string -> deliveredAnswer:string
593
+
594
+ l1Answer --> qualityGate{verdict}
595
+ qualityGate -->|pass| send
596
+ qualityGate -->|escalate| l2Answer --> send
597
+ ```
598
+
599
+ Itinerary planner — rich contracts stay attached to a simple linear graph:
600
+
601
+ ```text
602
+ flowchart TD
603
+ %%ax parse: requestText:string -> destinationName:string, stayWindow:dateRange, travelerCount:number(min 1, max 12), budgetUsd?:number(min 0)
604
+ %%ax plan: destinationName:string, stayWindow:dateRange, travelerCount:number, budgetUsd?:number -> itineraryItems:object{ dayNumber:number(min 1), activityText:string }[]
605
+ %%ax price: itineraryItems:object{ dayNumber:number, activityText:string }[], travelerCount:number -> estimatedTotalUsd:number(min 0), bookingNotes?:string(max 300)
606
+
607
+ parse --> plan --> price
608
+ ```
609
+
610
+ Fan-out with capped revision — two sections join, then review can send the assembly back twice:
611
+
612
+ ```text
613
+ flowchart TD
614
+ %%ax outline: briefText:string -> outlineText:string
615
+ %%ax sectionA: outlineText:string -> sectionAText:string
616
+ %%ax sectionB: outlineText:string -> sectionBText:string
617
+ %%ax assemble: sectionAText:string, sectionBText:string -> articleText:string
618
+ %%ax review: articleText:string -> verdict:class "approve, revise", reviewNote?:string
619
+ %%ax publish: articleText:string, reviewNote?:string -> publishedArticle:string
620
+
621
+ outline --> sectionA & sectionB
622
+ sectionA & sectionB --> assemble --> review{verdict}
623
+ review -->|approve| publish
624
+ review -->|revise, max 2| assemble
625
+ ```
626
+
420
627
  ## Examples
421
628
 
422
629
  Fetch these for full working code:
423
630
 
424
631
  - [Flow](https://raw.githubusercontent.com/ax-llm/ax/refs/heads/main/src/examples/ax-flow.ts) — complete flow usage
632
+ - [Mermaid Flow](https://raw.githubusercontent.com/ax-llm/ax/refs/heads/main/src/examples/ax-flow-mermaid.ts) — author/serialize a flow as a mermaid diagram
425
633
  - [Auto-Parallel](https://raw.githubusercontent.com/ax-llm/ax/refs/heads/main/src/examples/ax-flow-auto-parallel.ts) — auto-parallelization
426
634
  - [Async Map](https://raw.githubusercontent.com/ax-llm/ax/refs/heads/main/src/examples/ax-flow-async-map.ts) — async map transforms
427
635
  - [Enhanced Demo](https://raw.githubusercontent.com/ax-llm/ax/refs/heads/main/src/examples/ax-flow-enhanced-demo.ts) — instance-based nodes
@@ -429,6 +637,38 @@ Fetch these for full working code:
429
637
  - [Fluent Builder](https://raw.githubusercontent.com/ax-llm/ax/refs/heads/main/src/examples/fluent-flow-example.ts) — fluent builder pattern
430
638
  - [Load Balancing](https://raw.githubusercontent.com/ax-llm/ax/refs/heads/main/src/examples/balancer.ts) — load balancing
431
639
 
640
+ ## Event-Triggered Flows
641
+
642
+ An AxFlow is an `AxProgrammable` event target. The runtime maps an event into
643
+ the Flow's typed initial state and propagates `eventContext`, cancellation, and
644
+ idempotency metadata to every node. Abandoned branches still use normal Flow
645
+ cancellation semantics.
646
+
647
+ Task-backed MCP tools called by a Flow node register a continuation on the
648
+ shared event context. `axMCPEventRoutes` observes progress and resumes the Flow
649
+ on input-required or terminal task notifications.
650
+
651
+ For resource-driven wake, discover the endpoint with `inspectCatalog()` and
652
+ give `AxMCPEventSource` an explicit `resourceSubscriptions` policy. Managed
653
+ subscriptions reconcile list changes and reconnect separately from the Flow;
654
+ subscription alone never starts or resumes a Flow.
655
+
656
+ UCP lifecycle webhooks use the same continuation boundary through
657
+ `AxUCPWebhookEventSource`. Correlate on `ucp.checkout` or `ucp.order` only after
658
+ the signed request has been verified and mapped to application identity.
659
+
660
+ Use `eventTarget('id').program(flow).wakeInput(...).resumeInput(...)` when wake
661
+ and resume events have different shapes. Segment-safe `eventPath` mappings are
662
+ validated against the Flow signature before any node executes; a declarative
663
+ `.waitFor(kind, path)` creates the owned continuation consumed by the resume
664
+ route.
665
+
666
+ Reusable `eventInput()` plans are the preferred callback-free boundary.
667
+ Callback `mapInput` is normalized against the Flow signature before any node
668
+ runs. In generated hosts, immediate publications dispatch inline; the host uses
669
+ `nextDueAt()` and `runDue()` for delayed retries, debounce, and continuation
670
+ expiry.
671
+
432
672
  ## Do Not Generate
433
673
 
434
674
  - Do not use `new AxFlow(...)` for new code.
package/skills/ax-gen.md CHANGED
@@ -1,13 +1,16 @@
1
1
  ---
2
2
  name: ax-gen
3
- description: This skill helps an LLM generate correct AxGen code using @ax-llm/ax. Use when the user asks about ax(), AxGen, generators, forward(), streamingForward(), validation, assertions, streaming assertions, field processors, step hooks, self-tuning, or structured outputs.
4
- version: "23.0.1"
3
+ description: This skill helps an LLM generate correct AxGen code using @ax-llm/ax. Use when the user asks about ax(), AxGen, generators, forward(), streamingForward(), validation, assertions, streaming assertions, field processors, step hooks, self-tuning, or structured outputs. For MCP clients, transports, prompts, resources, tasks, subscriptions, or authentication use ax-mcp alongside this skill.
4
+ version: "23.0.2"
5
5
  ---
6
6
 
7
7
  # AxGen Codegen Rules (@ax-llm/ax)
8
8
 
9
9
  Use this skill to generate `AxGen` code. Prefer short, modern, copyable patterns. Do not write tutorial prose unless the user explicitly asks for explanation.
10
10
 
11
+ Use the `ax-mcp` skill when AxGen attaches native MCP clients or consumes MCP
12
+ prompts, resources, tools, tasks, subscriptions, authentication, or events.
13
+
11
14
  ## Use These Defaults
12
15
 
13
16
  - Use `ax(...)` factory, not `new AxGen(...)`.
@@ -485,6 +488,51 @@ Fetch these for full working code:
485
488
  - [Extraction](https://raw.githubusercontent.com/ax-llm/ax/refs/heads/main/src/examples/extract.ts) — information extraction
486
489
  - [Multi-Sampling](https://raw.githubusercontent.com/ax-llm/ax/refs/heads/main/src/examples/sample-count.ts) — sample count usage
487
490
 
491
+ ## Native MCP/UCP
492
+
493
+ Use `ax-mcp` for client construction, transports, authentication, catalog and
494
+ task APIs, subscriptions, event routing, and recording/replay. This section
495
+ only covers the AxGen attachment boundary.
496
+
497
+ Pass live clients directly to constructor or forward options:
498
+
499
+ ```typescript
500
+ const gen = ax('question:string -> answer:string', { mcp: [docs, search] });
501
+ const result = await gen.forward(llm, { question }, {
502
+ mcpContext: [
503
+ { client: 'docs', resource: { uri: 'docs://guide' } },
504
+ ],
505
+ });
506
+ ```
507
+
508
+ The model receives native tool definitions. Structured, image, audio, resource-link, embedded-resource, metadata, task, and error results are preserved until the provider adapter maps supported content. Streaming keeps MCP progress/task events separate from Ax output. Never call `toFunction()` for native integration.
509
+
510
+ Use `client.inspectCatalog()` when an endpoint is the only configuration. It
511
+ discovers server-owned tool/prompt names, concrete resource URIs, and URI
512
+ templates. Event sources require an explicit none/all/URI/selector resource
513
+ subscription policy and never create a wake route implicitly.
514
+
515
+ Under an event target, a required task-backed MCP tool registers the owning
516
+ `namespace:taskId` continuation automatically. Use `AxMCPEventSource` plus
517
+ `axMCPEventRoutes` to observe progress and resume the target on
518
+ `input_required` or a terminal state.
519
+
520
+ ## Event Targets
521
+
522
+ Wrap an AxGen with
523
+ `eventTarget('id').program(gen).ai(ai).input(...).build()` to invoke it from an
524
+ explicit `wake` or `resume` route. Use segment-safe `eventPath` selectors;
525
+ projection and explicit fields are validated against the AxGen signature before
526
+ invocation. Use `.wakeInput()` and `.resumeInput()` for different action
527
+ contracts. Streaming targets persist each chunk before optional chunk sinks and
528
+ persist the final result before final sinks.
529
+
530
+ Use a reusable `eventInput().project(...).field(...)` plan when mapping should
531
+ be callback-free. Callback `mapInput` remains available, but its result is
532
+ cloned, stripped to declared AxGen inputs, and signature-validated before the
533
+ first model call; mapper exceptions become non-retryable
534
+ `event_input_invalid` deliveries.
535
+
488
536
  ## Do Not Generate
489
537
 
490
538
  - Do not use `new AxGen(...)` for new code unless explicitly required.
package/skills/ax-gepa.md CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: ax-gepa
3
3
  description: This skill helps an LLM generate correct AxGEPA optimization code using @ax-llm/ax. Use when the user asks about AxGEPA, GEPA, Pareto optimization, multi-objective prompt tuning, reflective prompt evolution, validationExamples, maxMetricCalls, or optimizing a generator, flow, or agent tree.
4
- version: "23.0.1"
4
+ version: "23.0.2"
5
5
  ---
6
6
 
7
7
  # GEPA Optimization Codegen Rules (@ax-llm/ax)
package/skills/ax-llm.md CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: ax-llm
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: "23.0.1"
4
+ version: "23.0.2"
5
5
  ---
6
6
 
7
7
  # Ax Library (@ax-llm/ax) Quick Reference
@@ -238,6 +238,9 @@ axGlobals.meter = openTelemetryMeter;
238
238
 
239
239
  ## MCP Integration
240
240
 
241
+ Use the `ax-mcp` skill for the complete native client, transport,
242
+ authentication, catalog, task, subscription, event, and replay workflow.
243
+
241
244
  ```typescript
242
245
  import { AxMCPClient, agent } from '@ax-llm/ax';
243
246
  import { AxMCPStdioTransport } from '@ax-llm/ax-tools';
@@ -248,47 +251,49 @@ const transport = new AxMCPStdioTransport({
248
251
  args: ['-y', '@modelcontextprotocol/server-memory'],
249
252
  });
250
253
 
251
- const mcpClient = new AxMCPClient(transport, { debug: false });
252
- await mcpClient.init();
254
+ const mcpClient = new AxMCPClient(transport, { namespace: 'memory' });
253
255
 
254
- // Use with agent under a namespace
256
+ // Native MCP context is initialized once and inherited by all agent stages.
255
257
  const myAgent = agent('userMessage:string -> response:string', {
256
- functions: [
257
- {
258
- namespace: 'memory',
259
- title: 'Memory MCP',
260
- description: 'Memory server tools',
261
- selectionCriteria: 'Use for persistent memory lookup and updates.',
262
- functions: [mcpClient],
263
- },
264
- ],
258
+ mcp: mcpClient,
265
259
  functionDiscovery: true,
266
260
  contextFields: [],
267
261
  });
262
+
263
+ const result = await myAgent.forward(llm, { userMessage: 'Remember this.' });
264
+ await mcpClient.close(); // caller-owned clients remain caller-owned
268
265
  ```
269
266
 
270
267
  ### HTTP Transport (Remote MCP)
271
268
 
272
269
  ```typescript
273
- import { AxMCPStreambleHTTPTransport } from '@ax-llm/ax/mcp/transports/httpStreamTransport.js';
270
+ import { AxMCPStreamableHTTPTransport } from '@ax-llm/ax';
274
271
 
275
- const transport = new AxMCPStreambleHTTPTransport('https://remote.mcp.pipedream.net', {
272
+ const transport = new AxMCPStreamableHTTPTransport('https://remote.example/mcp', {
276
273
  headers: { 'x-pd-project-id': projectId },
277
274
  authorization: `Bearer ${accessToken}`,
278
275
  });
279
276
  ```
280
277
 
281
- ### MCP Capabilities
278
+ ### Native MCP and UCP behavior
282
279
 
283
- | Capability | Prefix | Description |
284
- |---|---|---|
285
- | Tools | *(none)* | Function calls |
286
- | Prompts | `prompt_` | Prompt templates |
287
- | Resources | `resource_` | File/data access |
280
+ - Pass `mcp` and `ucp` to AxGen, streaming AxGen, chat, AxAgent, AxFlow, optimization, or evaluation options.
281
+ - Use `mcpContext` to inject attributed prompts/resources before the first model call.
282
+ - Use `mcpInheritance: 'all' | 'none' | string[]` to restrict child programs.
283
+ - Tool calls retain raw MCP content, metadata, errors, tasks, and protocol provenance in memory.
284
+ - AxAgent exposes native modules as `mcp.<namespace>` and `ucp.<namespace>`.
285
+ - `inspectCatalog()` discovers tool/prompt names, concrete resources, and URI
286
+ templates from only an endpoint. Resource event sources default to no
287
+ subscriptions and require an explicit all/URI/selector policy.
288
+ - `toFunction()` remains a compatibility adapter only; native Ax execution never uses it.
289
+ - Live optimization is rejected by default. Use recording/replay or explicitly opt into live MCP evaluation.
288
290
 
289
291
  ```typescript
290
- const caps = mcpClient.getCapabilities();
291
- const functions = mcpClient.toFunction();
292
+ const catalog = await mcpClient.inspectCatalog();
293
+ const tools = catalog.tools;
294
+ const prompts = await mcpClient.listPrompts();
295
+ const resource = await mcpClient.readResource('docs://guide');
296
+ const tasks = await mcpClient.listTasks();
292
297
  ```
293
298
 
294
299
  ### Function Overrides
@@ -329,6 +334,13 @@ class AxFlow<IN, OUT> {
329
334
  }
330
335
  ```
331
336
 
337
+ ## Event-Driven Programs
338
+
339
+ Use `eventRuntime()` when notifications, webhooks, timers, or remote tasks
340
+ should wake or resume an Ax program. Sources publish into an inbox; explicit
341
+ routes choose `observe`, `invalidate`, `wake`, or `resume`. Event payloads are
342
+ never inserted as user messages automatically. See `ax-event-runtime.md`.
343
+
332
344
  ## Examples
333
345
 
334
346
  Fetch these for full working code: