agentfootprint 2.11.3 → 2.11.5

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 (104) hide show
  1. package/README.md +322 -144
  2. package/dist/adapters/llm/MockProvider.js +5 -0
  3. package/dist/adapters/llm/MockProvider.js.map +1 -1
  4. package/dist/adapters/observability/otel.js +4 -0
  5. package/dist/adapters/observability/otel.js.map +1 -1
  6. package/dist/adapters/observability/xray.js +4 -0
  7. package/dist/adapters/observability/xray.js.map +1 -1
  8. package/dist/cache/strategyRegistry.js +2 -1
  9. package/dist/cache/strategyRegistry.js.map +1 -1
  10. package/dist/core/Agent.js +44 -1
  11. package/dist/core/Agent.js.map +1 -1
  12. package/dist/core/agent/AgentBuilder.js +67 -1
  13. package/dist/core/agent/AgentBuilder.js.map +1 -1
  14. package/dist/core/agent/buildToolRegistry.js +5 -2
  15. package/dist/core/agent/buildToolRegistry.js.map +1 -1
  16. package/dist/core/agent/stages/callLLM.js +45 -17
  17. package/dist/core/agent/stages/callLLM.js.map +1 -1
  18. package/dist/core/agent/stages/reliabilityExecution.js +291 -0
  19. package/dist/core/agent/stages/reliabilityExecution.js.map +1 -0
  20. package/dist/esm/adapters/llm/MockProvider.js +5 -0
  21. package/dist/esm/adapters/llm/MockProvider.js.map +1 -1
  22. package/dist/esm/adapters/observability/otel.js +4 -0
  23. package/dist/esm/adapters/observability/otel.js.map +1 -1
  24. package/dist/esm/adapters/observability/xray.js +4 -0
  25. package/dist/esm/adapters/observability/xray.js.map +1 -1
  26. package/dist/esm/cache/strategyRegistry.js +2 -1
  27. package/dist/esm/cache/strategyRegistry.js.map +1 -1
  28. package/dist/esm/core/Agent.js +44 -1
  29. package/dist/esm/core/Agent.js.map +1 -1
  30. package/dist/esm/core/agent/AgentBuilder.js +67 -1
  31. package/dist/esm/core/agent/AgentBuilder.js.map +1 -1
  32. package/dist/esm/core/agent/buildToolRegistry.js +5 -2
  33. package/dist/esm/core/agent/buildToolRegistry.js.map +1 -1
  34. package/dist/esm/core/agent/stages/callLLM.js +45 -17
  35. package/dist/esm/core/agent/stages/callLLM.js.map +1 -1
  36. package/dist/esm/core/agent/stages/reliabilityExecution.js +287 -0
  37. package/dist/esm/core/agent/stages/reliabilityExecution.js.map +1 -0
  38. package/dist/esm/lib/rag/indexDocuments.js +4 -1
  39. package/dist/esm/lib/rag/indexDocuments.js.map +1 -1
  40. package/dist/esm/memory/causal/loadSnapshot.js +3 -0
  41. package/dist/esm/memory/causal/loadSnapshot.js.map +1 -1
  42. package/dist/esm/memory/embedding/loadRelevant.js +3 -0
  43. package/dist/esm/memory/embedding/loadRelevant.js.map +1 -1
  44. package/dist/esm/patterns/SelfConsistency.js +12 -3
  45. package/dist/esm/patterns/SelfConsistency.js.map +1 -1
  46. package/dist/esm/recorders/observability/FlowchartRecorder.js +11 -7
  47. package/dist/esm/recorders/observability/FlowchartRecorder.js.map +1 -1
  48. package/dist/esm/recorders/observability/commentary/commentaryTemplates.js +3 -1
  49. package/dist/esm/recorders/observability/commentary/commentaryTemplates.js.map +1 -1
  50. package/dist/esm/resilience/fallbackProvider.js +13 -3
  51. package/dist/esm/resilience/fallbackProvider.js.map +1 -1
  52. package/dist/esm/resilience/withCircuitBreaker.js +4 -0
  53. package/dist/esm/resilience/withCircuitBreaker.js.map +1 -1
  54. package/dist/esm/resilience/withRetry.js +2 -0
  55. package/dist/esm/resilience/withRetry.js.map +1 -1
  56. package/dist/esm/strategies/attach.js +3 -0
  57. package/dist/esm/strategies/attach.js.map +1 -1
  58. package/dist/esm/stream.js +2 -0
  59. package/dist/esm/stream.js.map +1 -1
  60. package/dist/lib/rag/indexDocuments.js +4 -1
  61. package/dist/lib/rag/indexDocuments.js.map +1 -1
  62. package/dist/memory/causal/loadSnapshot.js +3 -0
  63. package/dist/memory/causal/loadSnapshot.js.map +1 -1
  64. package/dist/memory/embedding/loadRelevant.js +3 -0
  65. package/dist/memory/embedding/loadRelevant.js.map +1 -1
  66. package/dist/patterns/SelfConsistency.js +12 -3
  67. package/dist/patterns/SelfConsistency.js.map +1 -1
  68. package/dist/recorders/observability/FlowchartRecorder.js +11 -7
  69. package/dist/recorders/observability/FlowchartRecorder.js.map +1 -1
  70. package/dist/recorders/observability/commentary/commentaryTemplates.js +3 -1
  71. package/dist/recorders/observability/commentary/commentaryTemplates.js.map +1 -1
  72. package/dist/resilience/fallbackProvider.js +13 -3
  73. package/dist/resilience/fallbackProvider.js.map +1 -1
  74. package/dist/resilience/withCircuitBreaker.js +4 -0
  75. package/dist/resilience/withCircuitBreaker.js.map +1 -1
  76. package/dist/resilience/withRetry.js +2 -0
  77. package/dist/resilience/withRetry.js.map +1 -1
  78. package/dist/strategies/attach.js +3 -0
  79. package/dist/strategies/attach.js.map +1 -1
  80. package/dist/stream.js +2 -0
  81. package/dist/stream.js.map +1 -1
  82. package/dist/types/adapters/llm/MockProvider.d.ts.map +1 -1
  83. package/dist/types/adapters/observability/otel.d.ts.map +1 -1
  84. package/dist/types/adapters/observability/xray.d.ts.map +1 -1
  85. package/dist/types/cache/strategyRegistry.d.ts.map +1 -1
  86. package/dist/types/core/Agent.d.ts +9 -1
  87. package/dist/types/core/Agent.d.ts.map +1 -1
  88. package/dist/types/core/agent/AgentBuilder.d.ts +61 -0
  89. package/dist/types/core/agent/AgentBuilder.d.ts.map +1 -1
  90. package/dist/types/core/agent/buildToolRegistry.d.ts.map +1 -1
  91. package/dist/types/core/agent/stages/callLLM.d.ts +8 -0
  92. package/dist/types/core/agent/stages/callLLM.d.ts.map +1 -1
  93. package/dist/types/core/agent/stages/reliabilityExecution.d.ts +66 -0
  94. package/dist/types/core/agent/stages/reliabilityExecution.d.ts.map +1 -0
  95. package/dist/types/memory/causal/loadSnapshot.d.ts.map +1 -1
  96. package/dist/types/memory/embedding/loadRelevant.d.ts.map +1 -1
  97. package/dist/types/patterns/SelfConsistency.d.ts.map +1 -1
  98. package/dist/types/recorders/observability/FlowchartRecorder.d.ts.map +1 -1
  99. package/dist/types/recorders/observability/commentary/commentaryTemplates.d.ts.map +1 -1
  100. package/dist/types/resilience/withCircuitBreaker.d.ts.map +1 -1
  101. package/dist/types/resilience/withRetry.d.ts.map +1 -1
  102. package/dist/types/strategies/attach.d.ts.map +1 -1
  103. package/dist/types/stream.d.ts.map +1 -1
  104. package/package.json +6 -1
package/README.md CHANGED
@@ -1,12 +1,17 @@
1
1
 
2
2
  <p align="center">
3
- <img width="220" alt="agentfootprint logo" src="https://github.com/user-attachments/assets/d548e2f4-cd49-4b9b-bdc2-2e6cbc2817ab" />
3
+ <picture>
4
+ <source media="(prefers-color-scheme: dark)" srcset="docs/assets/hero-dark.svg">
5
+ <source media="(prefers-color-scheme: light)" srcset="docs/assets/hero-light.svg">
6
+ <img alt="agentfootprint mascot composing context flavors (Skills, Steering, Guardrails, RAG, Tool APIs, Memory) into three structured LLM slots (system, messages, tools) — the central abstraction, visualized." src="docs/assets/hero-light.svg" width="100%"/>
7
+ </picture>
4
8
  </p>
5
9
 
6
- <h1 align="center">agentfootprint</h1>
10
+ <h1 align="center">Agentfootprint</h1>
7
11
 
8
12
  <p align="center">
9
- <strong>Context engineering, abstracted.</strong>
13
+ <strong>We abstract context engineering — and hand back the trace.</strong><br/>
14
+ <strong>Live</strong> to develop · <strong>offline</strong> to monitor · <strong>detailed</strong> to improve.
10
15
  </p>
11
16
 
12
17
  <p align="center">
@@ -19,82 +24,248 @@
19
24
 
20
25
  ---
21
26
 
22
- ## What is agentfootprint?
27
+ ## 1. What we abstract
23
28
 
24
- **A framework for building AI agents by treating context as a first-class runtime system.**
29
+ When you build an Agentic Application, you collect domain-specific data and instructions, then wire them up based on what your system receives.
25
30
 
26
- Most agent code becomes context plumbing: which instructions go in `system`, which messages get added after a tool returns, which tools should be exposed right now, which memory to load for this tenant, which parts of the prompt are stable enough to cache.
31
+ That data and those instructions wear many names **Skills · Steering · Guardrails · RAG · Tool APIs · Memory** with more on the way. But they all do the same thing: they **inject into one of three slots** in the LLM call (`system`, `messages`, `tools`).
27
32
 
28
- Without a framework, every agent hand-rolls this logic. Over time it becomes a fragile mix of prompt concatenation, tool routing, memory loading, cache markers, observability hooks, and retry logic.
33
+ So we abstracted the injection itself.
29
34
 
30
- **agentfootprint abstracts that bookkeeping.** You declare what context to inject, where it lands, and when it activates. The framework owns the agent loop, recomposes the LLM call every iteration, records typed events, applies caching, and persists replayable checkpoints.
35
+ <p align="center">
36
+ <picture>
37
+ <source media="(prefers-color-scheme: dark)" srcset="docs/assets/triggers-dark.svg">
38
+ <source media="(prefers-color-scheme: light)" srcset="docs/assets/triggers-light.svg">
39
+ <img alt="agentfootprint — Every LLM call has 3 fixed slots (system, messages, tools). Every flavor lands in one slot under one of 4 fixed triggers (always · rule · on-tool-return · llm-activated). Sparkle streams flow from each trigger lane down to a specific pill inside its destination slot — same slot can hold pills from different triggers (RAG via rule, Instruction via on-tool-return), and the same flavor (Skill) can land in different slots." src="docs/assets/triggers-light.svg" width="100%"/>
40
+ </picture>
41
+ </p>
42
+
43
+ The abstraction is three rules:
44
+
45
+ 1. **Three slots are fixed.** `system`, `messages`, `tools` — the LLM API surface.
46
+ 2. **N flavors are open.** You declare what you have. Tomorrow's flavor (few-shot, reflection, persona, A2A handoff…) plugs in the same way.
47
+ 3. **Rules decide *where* and *when*.** You provide the rules. We collect your data, fire the right one, land it in the right slot at the right iteration.
48
+
49
+ That's the whole model: `Injection = slot × trigger × cache`.
50
+
51
+ - **Slot** — which of the 3 LLM API regions the content lands in (`system` / `messages` / `tools`).
52
+ - **Trigger** — when the content fires (see below).
53
+ - **Cache** — how stable the content is across iterations. The framework places provider cache markers for you — stable content gets 80–90% cheaper prefixes.
54
+
55
+ ### Triggers — static or runtime
56
+
57
+ Every rule fires from one of two places:
58
+
59
+ - **Static** — set at build time, fires every iteration *(always-on)*
60
+ - **Runtime** — fires from something that happens during the run:
61
+ - a tool response *(after_tool)*
62
+ - an LLM activation *(read_skill)*
63
+ - a predicate over scope *(rule)*
31
64
 
32
- > You write the intent. agentfootprint owns the context loop.
65
+ Four triggers, two flavors:
66
+
67
+ | # | Trigger | Fires when | One-line example | Default slot |
68
+ |---|---|---|---|---|
69
+ | 1 | `always` *(static)* | Every iteration | `.steering('You are a triage agent…')` | `system` |
70
+ | 2 | `rule` *(runtime — predicate)* | Your rule returns true | `.rag({ when: s => /price\|refund/.test(s.userQuery), source: docs })` | `messages` |
71
+ | 3 | `on-tool-return` *(runtime — lifecycle)* | After a specific tool returns | `.instruction({ after: 'search_db', text: 'Cite source IDs.' })` | `messages` |
72
+ | 4 | `llm-activated` *(runtime — agent-driven)* | LLM calls `read_skill('id')` | `.skill({ id: 'refund-policy', activatedBy: 'read_skill' })` | `messages` (body) |
73
+
74
+ > **Slot is a default, not a coupling — same flavor lives in any slot, strategy is config.**
75
+ > A `Skill` can live in:
76
+ > - `tools` slot → schema only, LLM discovers it via `read_skill` — trigger `always`
77
+ > - `messages` slot → body injected on activation — trigger `llm-activated`
78
+ > - `system` slot → body baked into the system prompt as permanent steering — trigger `always`
79
+
80
+ **3 slots × 4 triggers × N flavors = the entire context-engineering surface.** Locate any agent feature on this grid; that's enough to model it.
33
81
 
34
82
  ---
35
83
 
36
- ## The lineage
84
+ ## 2. Why we chose this abstraction
37
85
 
38
- Every load-bearing dev tool of the last decade made the same move:
86
+ The agent space has many credible primary abstractions:
39
87
 
40
- | Framework | You write | The framework abstracts |
41
- |---|---|---|
42
- | **PyTorch (autograd)** | Forward graph | Gradient computation, backward pass |
43
- | **Express / Fastify** | Routes + handlers | HTTP loop, middleware chain |
44
- | **Prisma** | Schema + query intent | SQL generation, migrations |
45
- | **React** | Components + state | DOM diffing, render path |
46
- | **agentfootprint** | Injections (slot × trigger × cache) | Slot composition, iteration loop, caching, observation, replay |
88
+ | Framework | What it abstracts |
89
+ |---|---|
90
+ | **LangChain** | Pipelines of composable components |
91
+ | **LangGraph** | State machines of nodes and edges |
92
+ | **CrewAI · AutoGen** | Crews of role-playing agents |
93
+ | **Mastra · Genkit · Pydantic AI** | Typed full-stack bundles |
94
+ | **DSPy** | Compiled prompts |
95
+ | **Inngest AgentKit** | Durable workflows |
96
+
97
+ We didn't have to choose between them.
98
+
99
+ agentfootprint is built on **footprintjs** — the flowchart pattern for backend code. footprintjs gives us every one of those abstractions out of the box:
100
+
101
+ - **Composition** — `Sequence` · `Parallel` · `Conditional` · `Loop`
102
+ - **State machines** — the ReAct loop *is* a flowchart
103
+ - **Multi-agent crews** — compose Agents through control flow, no special class needed
104
+ - **Durable workflows** — `pauseHere()` plus JSON-portable `resume()`
105
+ - **Typed observation** — 47+ events for free, because the framework owns the loop
47
106
 
48
- The closest structural parallel is **autograd**: you describe the graph, the framework traverses it, and *because the framework owns the traversal it can record everything for free*. Same idea here — typed events, replayable checkpoints, and provider-agnostic prompt caching are consequences of owning the loop, not extra features.
107
+ So we used the budget those abstractions would have cost us to invest deeply in something they all leave to the developer: **the injection loop.**
108
+
109
+ > **We abstract context engineering.**
110
+ > Live to develop · offline to monitor · detailed to improve — handed back as the trace.
111
+
112
+ ### The reason — agents have a new class of bug
113
+
114
+ For fifty years, software bugs have been **logic errors**. A wrong condition, a missed edge case, an off-by-one. You step through the code until you find the bad branch.
115
+
116
+ LLM-powered apps add a second class of bug: **contextual errors.** The code is correct. The model is correct. The answer is wrong because **the LLM's decision rests on context that was ambiguous, confusing, or misleading at the moment of inference.**
117
+
118
+ Tracking *which content the model actually saw, and why,* is the entire debugging job. Without it, the failure mode is invisible:
119
+
120
+ - The wrong instruction landed in the `system` slot — the model followed the wrong rule.
121
+ - A predicate fired one iteration too early — context arrived with stale assumptions.
122
+ - A skill body was missing when the LLM called `read_skill` — the model invented its own.
123
+ - The cache prefix invalidated — a stable instruction got silently rewritten with a stale version.
124
+ - A tool returned — but the on-tool-return injection that explains how to interpret the result never fired.
125
+
126
+ **The model doesn't tell you which of these went wrong. It just gives you the wrong answer.**
127
+
128
+ You can't step through that with a debugger. By the time you read the response, the context that produced it is gone unless something recorded it.
129
+
130
+ That's the gap agentfootprint fills. A framework that owns the control flow can debug logic errors. A framework that owns the *injection* can debug contextual errors — because every injection is a typed event with a where, when, why, and how-it-cached.
131
+
132
+ ### What that buys you
133
+
134
+ Because we own the injection, every LLM call backtracks to four typed answers:
135
+
136
+ - **What** was injected
137
+ - **Who** triggered it (which rule)
138
+ - **When** it fired
139
+ - **How** it landed — slot, position, cache
140
+
141
+ Same trace, three workflows:
142
+
143
+ - **Live — debug as you build.** See exactly which injection produced which token, which predicate fired this iteration, which prefix actually got cached.
144
+ - **Offline — monitor what shipped.** Replay any past run from its trace. Alert on drift. Attribute cost per injection.
145
+ - **Detailed — improve via export.** Every successful trajectory is labeled training data for SFT, DPO, or RL — no separate data-collection phase.
146
+
147
+ And a fourth, novel: **the agent can read its own trace.** Six months after the agent rejected loan #42, *"why did you reject it?"* answers from the recorded evidence (`creditScore=580`, `threshold=600`), not a rerun. Causal memory turns the trace into the agent's working memory.
49
148
 
50
149
  ---
51
150
 
52
- ## The core idea
151
+ ## Where this sits
53
152
 
54
- Every LLM call has three slots:
153
+ You'll find pieces of agentfootprint in two adjacent categories of framework.
55
154
 
56
- ```text
57
- system messages tools
58
- ```
155
+ - **Model-driven agent runners** let the LLM drive the loop. We ship one — Dynamic ReAct.
156
+ - **Low-level orchestration frameworks** let you wire nodes and edges. We ship the same compositions one level up: `Sequence` · `Parallel` · `Conditional` · `Loop`.
59
157
 
60
- Every agent feature steering, instructions, skills, facts, memory, RAG, tool schemas is content flowing into one of those slots. agentfootprint models all of them as one primitive:
158
+ What neither category ships: the **Injection primitive** (Beat 1) and the **causal trace** (Beat 4). Both are free side effects of owning the runtime loop.
61
159
 
62
- ```text
63
- Injection = slot × trigger × cache
160
+ > agentfootprint = a model-driven agent runner + compositional orchestration + context engineering as a first-class layer, trace baked in.
161
+
162
+ ---
163
+
164
+ ## 3. How do I design my agent or system of agents?
165
+
166
+ Two scales — same alphabet. Four control flows are the entire vocabulary.
167
+
168
+ <table>
169
+ <tr>
170
+ <td width="50%" align="center">
171
+ <picture>
172
+ <source media="(prefers-color-scheme: dark)" srcset="docs/assets/sequence-dark.svg">
173
+ <source media="(prefers-color-scheme: light)" srcset="docs/assets/sequence-light.svg">
174
+ <img alt="Sequence — linear chain A → B → C." src="docs/assets/sequence-light.svg" width="100%"/>
175
+ </picture>
176
+ </td>
177
+ <td width="50%">
178
+
179
+ ```typescript
180
+ import { Sequence } from 'agentfootprint';
181
+
182
+ const flow = Sequence.create()
183
+ .step('a', stageA)
184
+ .step('b', stageB)
185
+ .step('c', stageC)
186
+ .build();
64
187
  ```
65
188
 
66
- An Injection answers three questions:
189
+ </td>
190
+ </tr>
191
+ <tr>
192
+ <td width="50%" align="center">
193
+ <picture>
194
+ <source media="(prefers-color-scheme: dark)" srcset="docs/assets/parallel-dark.svg">
195
+ <source media="(prefers-color-scheme: light)" srcset="docs/assets/parallel-light.svg">
196
+ <img alt="Parallel — fan-out then fan-in across N agents." src="docs/assets/parallel-light.svg" width="100%"/>
197
+ </picture>
198
+ </td>
199
+ <td width="50%">
200
+
201
+ ```typescript
202
+ import { Parallel } from 'agentfootprint';
203
+
204
+ const fan = Parallel.create()
205
+ .branch('web', searchWeb)
206
+ .branch('docs', searchDocs)
207
+ .mergeWithFn(synthesizer)
208
+ .build();
209
+ ```
67
210
 
68
- 1. **Where does this content land?** `system`, `messages`, or `tools`
69
- 2. **When does it activate?** `always` · `rule` · `on-tool-return` · `llm-activated`
70
- 3. **How is it cached?** `always` · `never` · `while-active` · predicate
211
+ </td>
212
+ </tr>
213
+ <tr>
214
+ <td width="50%" align="center">
215
+ <picture>
216
+ <source media="(prefers-color-scheme: dark)" srcset="docs/assets/conditional-dark.svg">
217
+ <source media="(prefers-color-scheme: light)" srcset="docs/assets/conditional-light.svg">
218
+ <img alt="Conditional — diamond gate routes to one of N branches based on a predicate." src="docs/assets/conditional-light.svg" width="100%"/>
219
+ </picture>
220
+ </td>
221
+ <td width="50%">
71
222
 
72
- That is the whole abstraction. Every named pattern in the agent literature — Reflexion, Tree-of-Thoughts, Skills, RAG, Constitutional AI — reduces to *which slot* + *which trigger*. You learn one model; the field's growth lands as new factories on the same primitive.
223
+ ```typescript
224
+ import { Conditional } from 'agentfootprint';
73
225
 
74
- ```text
75
- LLM call
76
- ┌────────────────────────────────────┐
77
- │ system messages tools
78
- │ ▲ ▲ ▲ │
79
- └──────┼────────────┼────────────┼───┘
80
- │ │ │
81
- Injection Injection Injection
82
-
83
-
84
- always · rule · on-tool-return · llm-activated
226
+ const router = Conditional.create()
227
+ .when('billing', s => s.intent === 'billing', billingAgent)
228
+ .when('tech', s => s.intent === 'tech', techAgent)
229
+ .otherwise('default', defaultAgent)
230
+ .build();
85
231
  ```
86
232
 
87
- ---
233
+ </td>
234
+ </tr>
235
+ <tr>
236
+ <td width="50%" align="center">
237
+ <picture>
238
+ <source media="(prefers-color-scheme: dark)" srcset="docs/assets/loop-dark.svg">
239
+ <source media="(prefers-color-scheme: light)" srcset="docs/assets/loop-light.svg">
240
+ <img alt="Loop — body cycles back from end to start until a condition is met." src="docs/assets/loop-light.svg" width="100%"/>
241
+ </picture>
242
+ </td>
243
+ <td width="50%">
88
244
 
89
- ## Why this isn't just an ergonomics win — Dynamic ReAct
245
+ ```typescript
246
+ import { Loop } from 'agentfootprint';
90
247
 
91
- Because the framework owns the loop, **all three slots recompose every iteration based on what just happened.**
248
+ const reflexion = Loop.create()
249
+ .repeat(thinkAgent)
250
+ .until(s => s.satisfied)
251
+ .build();
252
+ ```
92
253
 
93
- - **LangChain** assembles prompts once per turn.
94
- - **LangGraph** composes state per node, not per loop iteration.
95
- - **agentfootprint** recomposes per iteration.
254
+ </td>
255
+ </tr>
256
+ </table>
257
+
258
+ ### Inside one agent — Dynamic vs Classic ReAct
259
+
260
+ <p align="center">
261
+ <picture>
262
+ <source media="(prefers-color-scheme: dark)" srcset="docs/assets/dynamic-vs-classic-dark.svg">
263
+ <source media="(prefers-color-scheme: light)" srcset="docs/assets/dynamic-vs-classic-light.svg">
264
+ <img alt="Classic ReAct vs Dynamic ReAct loop topology — same 5 stages (SystemPrompt, Messages, Tools, CallLLM, Route → ExecuteTools/Finalize), but the loop edge differs: Classic returns to CallLLM only (slots frozen at 12 tools every iteration), Dynamic returns to SystemPrompt (slots recompose, tools shrink from 1 to 5 as skills activate)." src="docs/assets/dynamic-vs-classic-light.svg" width="100%"/>
265
+ </picture>
266
+ </p>
96
267
 
97
- Per-iteration recomposition is what makes context engineering compositional instead of static. It's also the structural prerequisite for the cache layer cache markers can't track active injections in lockstep without it.
268
+ **Same five stages on both sides. Only one thing differs — where the loop returns.** Classic ReAct loops back to `CallLLM` and slots stay frozen. Dynamic ReAct (agentfootprint) loops back to `SystemPrompt`, so injections that fired on the previous tool result recompose the next prompt. Per-iteration recomposition is also the structural prerequisite for the cache layer.
98
269
 
99
270
  ```text
100
271
  Classic ReAct Dynamic ReAct
@@ -104,9 +275,85 @@ iter 2: 12 tools shown iter 2: 5 tools (skill activated)
104
275
  iter 3: 12 tools shown iter 3: 5 tools
105
276
  ```
106
277
 
107
- Use Dynamic ReAct when your tools have dependencies (one tool's output implies which tool to call next). Use Classic ReAct when all tools are independent and ordering doesn't matter.
278
+ > 📖 [Dynamic ReAct guide](https://footprintjs.github.io/agentfootprint/guides/dynamic-react/) · [Key concepts](https://footprintjs.github.io/agentfootprint/getting-started/key-concepts/)
279
+
280
+ ### Multi-agent — compose with the alphabet
281
+
282
+ <p align="center">
283
+ <picture>
284
+ <source media="(prefers-color-scheme: dark)" srcset="docs/assets/compose-dark.svg">
285
+ <source media="(prefers-color-scheme: light)" srcset="docs/assets/compose-light.svg">
286
+ <img alt="A custom research agent built from the same 4 control flows: input flows into a Conditional gate (plan more research?), which fans out to a Parallel block (search_web, search_docs, search_kb), then chains into a Sequence (synthesize → critique), and a Loop arrow returns from the end back to the Conditional gate so the agent iterates until satisfied. Formula: Loop( Conditional(plan?) → Parallel(search_web, search_docs, search_kb) → Sequence(synth → critique) )." src="docs/assets/compose-light.svg" width="100%"/>
287
+ </picture>
288
+ </p>
289
+
290
+ Pick the flows that match your problem. Chain them. **That's your Agentic Application.**
291
+
292
+ ```typescript
293
+ const research = Loop.create()
294
+ .repeat(Sequence.create().step('plan', plan).step('search', searchAll).build())
295
+ .until(s => s.satisfied).build();
296
+ ```
297
+
298
+ Same `.create().method().build()` shape as the four rows above — just composed.
299
+
300
+ ### Named patterns — also compositions of the same 4
301
+
302
+ <p align="center">
303
+ <picture>
304
+ <source media="(prefers-color-scheme: dark)" srcset="docs/assets/patterns-dark.svg">
305
+ <source media="(prefers-color-scheme: light)" srcset="docs/assets/patterns-light.svg">
306
+ <img alt="6 named multi-agent patterns reduce to compositions of the same 4 control flows: Swarm = Loop(Parallel(Agent×N) → merge); Tree-of-Thoughts = Loop(Parallel(Agent×N) → Conditional(score)); Reflexion = Loop(Agent → Conditional(critique) → Agent); Debate = Parallel(Agent_pro, Agent_con) → Agent_judge; Router = Conditional → Agent_A | Agent_B | Agent_C; Hierarchical = Agent_planner → Sequence(Agent_worker×N) → synth." src="docs/assets/patterns-light.svg" width="100%"/>
307
+ </picture>
308
+ </p>
309
+
310
+ The patterns the field knows reduce to the same alphabet:
311
+
312
+ | Pattern | Composition |
313
+ |---|---|
314
+ | **Swarm** | `Loop( Parallel( Agent×N ) → merge )` |
315
+ | **Tree-of-Thoughts** | `Loop( Parallel( Agent×N ) → Conditional(score) )` |
316
+ | **Reflexion** | `Loop( Agent → Conditional(critique) → Agent )` |
317
+ | **Debate** | `Parallel( Agent_pro, Agent_con ) → Agent_judge` |
318
+ | **Router** | `Conditional → Agent_A \| Agent_B \| Agent_C` |
319
+ | **Hierarchical** | `Agent_planner → Sequence( Agent_worker×N ) → synth` |
320
+
321
+ Same trick as Beat 1: instead of N libraries for N patterns, we found the M building blocks all N patterns are made of.
322
+
323
+ > 📖 Compare: [hand-rolled vs declarative](https://footprintjs.github.io/agentfootprint/getting-started/why/) · [migration from LangChain / CrewAI / LangGraph](https://footprintjs.github.io/agentfootprint/getting-started/vs/)
324
+
325
+ ---
326
+
327
+ ## 4. How do I see what my agent did?
328
+
329
+ Because we own the loop (Beat 2), every decision and execution is captured during traversal — not bolted on. The default capture is the **causal trace**: every stage, read, write, and decision evidence, as a JSON-portable, scrubbable, queryable, exportable artifact. Beyond the default, wire custom recorders for cost, latency, or quality scoring — any observation hook fires on the same stream.
330
+
331
+ <p align="center">
332
+ <picture>
333
+ <source media="(prefers-color-scheme: dark)" srcset="docs/assets/causal-memory-dark.svg">
334
+ <source media="(prefers-color-scheme: light)" srcset="docs/assets/causal-memory-light.svg">
335
+ <img alt="agentfootprint causal memory — Each agent run produces a JSON-portable causal trace: a scrubbable timeline of every stage with reads, writes, and captured decision evidence. The trace card shows a time-travel slider (Step 5 of 17, Live), an execution timeline with stage-duration bars, and the captured decision evidence pill (riskTier eq high → reject). Two built-in lenses view it: Lens (agent-centric) and Explainable Trace (structural). Three programmatic consumers fan out from it: audit replay (GDPR Article 22 adverse-action notice answered from chain, no LLM call, $15/1M to $0.25/1M tokens), cheap-model triage (Sonnet trace fed to Haiku for follow-ups), and training data export (every chain is a labeled trajectory ready for SFT/DPO/process-RL). One recording, two lenses, three consumers, zero extra instrumentation. Powered by footprintjs causalChain()." src="docs/assets/causal-memory-light.svg" width="100%"/>
336
+ </picture>
337
+ </p>
338
+
339
+ The same trace serves three downstream consumers — no extra instrumentation:
340
+
341
+ 1. **Audit / compliance.** Six months later, *"why was loan #42 rejected?"* answers from the chain (`creditScore=580 < 620 ∧ dti=0.6 > 0.43 → riskTier=high → REJECTED`). No LLM call. GDPR Art. 22, ECOA, and EU AI Act adverse-action notices write themselves from the captured decision evidence.
342
+
343
+ 2. **Cheap-model triage.** A Sonnet trace becomes good *input* for Haiku to answer follow-ups. ~200 tokens at any model ($0.25/1M) vs ~2,500 tokens at a reasoning model ($15/1M). Memoization for agent thinking — no agent rerun.
344
+
345
+ 3. **Training data export.** Every successful chain is a labeled trajectory — `causalMemory.exportForTraining({ format: 'sft' \| 'dpo' \| 'process-rl' })`. The chain provides per-step rewards out of the box, so process-RL is ready without a separate data-collection phase.
346
+
347
+ Two built-in lenses view the same trace:
348
+
349
+ | Lens | View | When to use |
350
+ |---|---|---|
351
+ | **Lens** | Agent-centric — User/Agent[3 slots]/Tool flowchart with iteration scrubber and round commentary | Live debugging, "what did Neo see at step 5?" |
352
+ | **Explainable Trace** | Structural — subflow tree, full flowchart, memory inspector, per-stage execution timeline | Architecture review, root-cause analysis |
353
+
354
+ > 📖 Powered by [footprintjs `causalChain()`](https://footprintjs.github.io/footPrint/blog/backward-causal-chain/) — backward thin-slicing on the commit log. [Causal memory deep dive](https://footprintjs.github.io/agentfootprint/causal-deep-dive/) · [Explainability & compliance](https://footprintjs.github.io/footPrint/blog/explainability-compliance/)
108
355
 
109
- > 📖 Deep dive: [Dynamic ReAct guide](https://footprintjs.github.io/agentfootprint/guides/dynamic-react/) · [Cache layer](https://footprintjs.github.io/agentfootprint/guides/caching/)
356
+ **One recording. Two lenses. Three consumers. Zero extra instrumentation.**
110
357
 
111
358
  ---
112
359
 
@@ -146,69 +393,6 @@ Swap `mock(...)` for `anthropic(...)` / `openai(...)` / `bedrock(...)` / `ollama
146
393
 
147
394
  ---
148
395
 
149
- ## A real agent in 8 lines
150
-
151
- ```typescript
152
- const agent = Agent.create({ provider, model: 'claude-sonnet-4-5-20250929' })
153
- .system('You are a support assistant.')
154
- .steering(toneRule) // always-on
155
- .instruction(urgentRule) // rule-gated
156
- .skill(billingSkill) // LLM-activated
157
- .memory(conversationMemory) // cross-run, multi-tenant
158
- .tool(weather)
159
- .build();
160
-
161
- await agent.run({ message: userInput, identity: { conversationId } });
162
- ```
163
-
164
- The hand-rolled equivalent is ~80 lines of slot management, trigger evaluation, memory loading, and cache marker placement — and growing with every feature. The declarative version stays at 8.
165
-
166
- > 📖 Compare: [hand-rolled vs declarative](https://footprintjs.github.io/agentfootprint/getting-started/why/) · [migration from LangChain / CrewAI / LangGraph](https://footprintjs.github.io/agentfootprint/getting-started/vs/)
167
-
168
- ---
169
-
170
- ## The differentiator: the trace is a cache of the agent's thinking
171
-
172
- Other agent frameworks remember *what was said*. agentfootprint's causal memory records the **decision evidence** — every value the flowchart captured during the run, persisted as a JSON-portable snapshot.
173
-
174
- That changes the cost structure of everything that happens after the agent runs:
175
-
176
- 1. **Audit / explain** — six months later, "why was loan #42 rejected?" answers from the original evidence (creditScore=580, threshold=600), not reconstruction.
177
- 2. **Cheap-model triage** — a trace from Sonnet is good *input* for Haiku to answer follow-up questions about that run. Memoization for agent reasoning.
178
- 3. **Training data** — every successful production run is a labeled trajectory for SFT/DPO/process-RL, no separate data-collection phase.
179
-
180
- One recording, three downstream consumers, no extra instrumentation.
181
-
182
- > 📖 Deep dive: [Causal memory guide](https://footprintjs.github.io/agentfootprint/guides/causal-memory/)
183
-
184
- ---
185
-
186
- ## What you can build
187
-
188
- ```typescript
189
- // Customer support — skills + memory + audit + cache
190
- const agent = Agent.create({ provider, model })
191
- .system('You are a friendly support assistant.')
192
- .skill(billingSkill)
193
- .steering(toneGuidelines)
194
- .memory(conversationMemory)
195
- .build();
196
-
197
- // Research pipeline — multi-agent fan-out + merge
198
- const research = Parallel.create()
199
- .branch(optimist).branch(skeptic).branch(historian)
200
- .merge(synthesizer)
201
- .build();
202
-
203
- // Streaming chat — token-by-token to a browser via SSE
204
- agent.on('agentfootprint.stream.token', (e) => res.write(toSSE(e)));
205
- await agent.run({ message: req.query.message });
206
- ```
207
-
208
- > 📖 Full examples: [examples gallery](https://github.com/footprintjs/agentfootprint/tree/main/examples) · every example is also a CI test.
209
-
210
- ---
211
-
212
396
  ## Mocks first, production second
213
397
 
214
398
  Build the entire app against in-memory mocks with **zero API cost**, then swap real infrastructure one boundary at a time.
@@ -226,19 +410,27 @@ The flowchart, recorders, and tests don't change between dev and prod.
226
410
 
227
411
  ## What ships today
228
412
 
229
- - **2 primitives** — `LLMCall`, `Agent` (the ReAct loop)
230
- - **4 compositions** — `Sequence`, `Parallel`, `Conditional`, `Loop`
231
- - **7 LLM providers**Anthropic · OpenAI · Bedrock · Ollama · Browser-Anthropic · Browser-OpenAI · Mock
232
- - **One Injection primitive** — `defineSkill` / `defineSteering` / `defineInstruction` / `defineFact`
233
- - **One Memory factory** — 4 types × 7 strategies including **Causal**
234
- - **Provider-agnostic prompt caching** — declarative per-injection, per-iteration marker recomputation
235
- - **RAG · MCP · Memory store adapters** InMemory · Redis · AgentCore
236
- - **48+ typed observability events** across context · stream · agent · cost · skill · permission · eval · memory · cache · embedding · error
237
- - **Pause / resume** — JSON-serializable checkpoints; resume hours later on a different server
238
- - **Resilience** — `withRetry`, `withFallback`, `resilientProvider`
239
- - **AI-coding-tool support**Claude Code · Cursor · Windsurf · Cline · Kiro · Copilot
413
+ **Core**
414
+ - 2 primitives — `LLMCall`, `Agent` (the ReAct loop)
415
+ - 4 control flows`Sequence`, `Parallel`, `Conditional`, `Loop`
416
+ - One Injection primitive — `defineSkill` / `defineSteering` / `defineInstruction` / `defineFact`
417
+
418
+ **Adapters**
419
+ - 7 LLM providers — Anthropic · OpenAI · Bedrock · Ollama · Browser-Anthropic · Browser-OpenAI · Mock
420
+ - RAG · MCP · Memory store adapters InMemory · Redis · AgentCore (Postgres / DynamoDB / Pinecone via lazy peer-deps)
421
+
422
+ **Operability**
423
+ - One Memory factory 4 types × 7 strategies including **Causal**
424
+ - Provider-agnostic prompt caching — declarative per-injection, per-iteration marker recomputation
425
+ - Pause / resume — JSON-serializable checkpoints; resume hours later on a different server
426
+ - Resilience — `withRetry`, `withFallback`, `resilientProvider`
427
+ - 48+ typed observability events — context · stream · agent · cost · skill · permission · eval · memory · cache · embedding · error
428
+
429
+ **Tooling**
430
+ - **Lens** · **Explainable Trace** — two visual replays of the causal trace
431
+ - AI-coding-tool support — Claude Code · Cursor · Windsurf · Cline · Kiro · Copilot
240
432
 
241
- > 📖 [Full feature list & API reference](https://footprintjs.github.io/agentfootprint/reference/) · [CHANGELOG](./CHANGELOG.md)
433
+ > 📖 [Agent API reference](https://footprintjs.github.io/agentfootprint/api/agent/) · [CHANGELOG](./CHANGELOG.md)
242
434
 
243
435
  ---
244
436
 
@@ -256,20 +448,6 @@ Roadmap items are *not* current API claims. If a feature isn't in `npm install a
256
448
 
257
449
  ---
258
450
 
259
- ## Design philosophy
260
-
261
- Two principles shape the runtime:
262
-
263
- **Connected data (Palantir, 2003).** Enterprise insight is bottlenecked by data fragmentation, not analyst skill. Agents face the same problem at runtime — disconnected tool state, lost decision evidence, scattered execution context. agentfootprint connects state, decisions, execution, and memory into one runtime footprint so the next iteration compounds the connection instead of paying for it again.
264
-
265
- **Modular boundaries (Liskov, 1974).** Every framework boundary — `LLMProvider`, `ToolProvider`, `CacheStrategy`, `Recorder`, `MemoryStore` — is an LSP-substitutable interface. Swap implementations without changing agent code.
266
-
267
- Connected data alone is fast but unmaintainable. Modular boundaries alone are clean but dumb. Together: a runtime that's both fast and reasonable.
268
-
269
- > 📖 Long-form: [the Palantir lineage](https://footprintjs.github.io/agentfootprint/inspiration/connected-data/) · [the Liskov lineage](https://footprintjs.github.io/agentfootprint/inspiration/modularity/)
270
-
271
- ---
272
-
273
451
  ## Where to next
274
452
 
275
453
  | If you are... | Go here |
@@ -277,8 +455,8 @@ Connected data alone is fast but unmaintainable. Modular boundaries alone are cl
277
455
  | New to agents | [5-minute quick start](https://footprintjs.github.io/agentfootprint/getting-started/quick-start/) |
278
456
  | Coming from LangChain / CrewAI / LangGraph | [Migration guide](https://footprintjs.github.io/agentfootprint/getting-started/vs/) |
279
457
  | Architecting an enterprise rollout | [Production guide](https://footprintjs.github.io/agentfootprint/guides/deployment/) |
280
- | Doing due diligence | [Architecture overview](https://footprintjs.github.io/agentfootprint/architecture/) |
281
- | Researcher / extending | [Extension guide](https://footprintjs.github.io/agentfootprint/contributing/extension-guide/) |
458
+ | Doing due diligence | [Architecture overview](https://footprintjs.github.io/agentfootprint/architecture/dependency-graph/) |
459
+ | Researcher / academic background | [Citations & prior art](https://footprintjs.github.io/agentfootprint/research/citations/) |
282
460
  | Curious about design | [Inspiration docs](https://footprintjs.github.io/agentfootprint/inspiration/) |
283
461
 
284
462
  Or jump into the [examples gallery](https://github.com/footprintjs/agentfootprint/tree/main/examples) — every example is also an end-to-end CI test.
@@ -287,7 +465,7 @@ Or jump into the [examples gallery](https://github.com/footprintjs/agentfootprin
287
465
 
288
466
  ## Built on
289
467
 
290
- [footprintjs](https://github.com/footprintjs/footPrint) — the flowchart pattern for backend code. The decision-evidence capture, narrative recording, and time-travel checkpointing this library uses are footprintjs primitives. The same way autograd's forward-pass traversal is what makes gradient inspection automatic, footprintjs's flowchart traversal is what makes agentfootprint's typed-event stream and replayable traces automatic.
468
+ [footprintjs](https://github.com/footprintjs/footPrint) — the flowchart pattern for backend code. agentfootprint's decision-evidence capture, narrative recording, and time-travel checkpointing are footprintjs primitives at the runtime layer.
291
469
 
292
470
  You don't need to learn footprintjs to use agentfootprint — but if you want to build your own primitives at this depth, [start there](https://footprintjs.github.io/footPrint/).
293
471
 
@@ -139,6 +139,8 @@ class MockProvider {
139
139
  `\`replies\` or bound the agent with \`maxIterations\`. ` +
140
140
  `Call \`provider.resetReplies()\` to rewind across test scenarios.`);
141
141
  }
142
+ // Cursor was just bounds-checked above (`>= replies.length` throws).
143
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
142
144
  const next = this.replies[this.repliesCursor];
143
145
  this.repliesCursor++;
144
146
  return next;
@@ -191,6 +193,9 @@ function sleep(ms, signal) {
191
193
  }, ms);
192
194
  const onAbort = () => {
193
195
  clearTimeout(id);
196
+ // onAbort is registered only when signal is defined (line below);
197
+ // accessing signal.reason here is structurally guaranteed.
198
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
194
199
  reject(signal.reason ?? new Error('Aborted'));
195
200
  };
196
201
  signal?.addEventListener('abort', onAbort, { once: true });
@@ -1 +1 @@
1
- {"version":3,"file":"MockProvider.js","sourceRoot":"","sources":["../../../src/adapters/llm/MockProvider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MockProvider.js","sourceRoot":"","sources":["../../../src/adapters/llm/MockProvider.ts"],"names":[],"mappings":"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"}
@@ -132,11 +132,15 @@ function otelObservability(opts) {
132
132
  function popSpan(turnState, expectedName) {
133
133
  let idx = turnState.stack.length - 1;
134
134
  if (expectedName) {
135
+ // idx >= 0 guard above guarantees stack[idx] exists.
136
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
135
137
  while (idx >= 0 && turnState.stack[idx].name !== expectedName)
136
138
  idx--;
137
139
  }
138
140
  if (idx < 0)
139
141
  return undefined;
142
+ // splice(idx, 1) returns a 1-element array; idx < 0 guarded above.
143
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
140
144
  return turnState.stack.splice(idx, 1)[0].span;
141
145
  }
142
146
  function endSpan(span, opts) {