diff --git a/apps/web/package.json b/apps/web/package.json index a2ae259..a7a1bcd 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -3,7 +3,7 @@ "version": "0.0.0", "private": true, "scripts": { - "dev": "next dev", + "dev": "npx @react-grab/claude-code@latest && next dev", "build": "next build", "start": "next start", "lint": "eslint .", diff --git a/apps/web/src/app/tool/[...slug]/page.tsx b/apps/web/src/app/tool/[...slug]/page.tsx index 0feb619..d60d92b 100644 --- a/apps/web/src/app/tool/[...slug]/page.tsx +++ b/apps/web/src/app/tool/[...slug]/page.tsx @@ -119,9 +119,11 @@ export default function ToolDetailPage({
-
- - Loading tool... +
+ + + Loading tool... +
diff --git a/apps/web/src/app/tool/broken/page.tsx b/apps/web/src/app/tool/broken/page.tsx index 1112e28..cf8cb37 100644 --- a/apps/web/src/app/tool/broken/page.tsx +++ b/apps/web/src/app/tool/broken/page.tsx @@ -88,9 +88,11 @@ export default function BrokenToolsPage(): React.ReactElement { {/* Loading state */} {loading && ( -
- - Loading broken tools... +
+ + + Loading broken tools... +
)} diff --git a/apps/web/src/app/tool/tool-search/page.tsx b/apps/web/src/app/tool/tool-search/page.tsx index 6277df8..9b696d2 100644 --- a/apps/web/src/app/tool/tool-search/page.tsx +++ b/apps/web/src/app/tool/tool-search/page.tsx @@ -184,9 +184,11 @@ export default function ToolSearchPage(): React.ReactElement { {/* Loading state */} {loading && ( -
- - Loading tools... +
+ + + Loading tools... +
)} diff --git a/apps/web/src/components/ToolPlayground.tsx b/apps/web/src/components/ToolPlayground.tsx index 378a8d5..c8a81b1 100644 --- a/apps/web/src/components/ToolPlayground.tsx +++ b/apps/web/src/components/ToolPlayground.tsx @@ -323,9 +323,11 @@ export function ToolPlayground({ tool }: ToolPlaygroundProps): React.ReactElemen })()}
) : isExecuting ? ( -
- -

Executing...

+
+ +

+ Executing... +

) : (
diff --git a/docs/CASCADING_COMPLEXITY_AND_FRAGILITY.md b/docs/CASCADING_COMPLEXITY_AND_FRAGILITY.md new file mode 100644 index 0000000..349a3d4 --- /dev/null +++ b/docs/CASCADING_COMPLEXITY_AND_FRAGILITY.md @@ -0,0 +1,1112 @@ +# Cascading Complexity and Logical Fragility + +How adding more steps, conditions, and branches can transform reliable systems into brittle ones—and strategies to maintain robustness. + +--- + +## The Conjunction Fallacy in Tool Plans + +The conjunction fallacy (Linda problem) demonstrates that humans intuitively believe: + +``` +P(A ∧ B) > P(A) + +"Linda is a bank teller AND active in the feminist movement" +seems more likely than +"Linda is a bank teller" +``` + +This is mathematically impossible. Adding conditions can only maintain or reduce probability: + +``` +P(A ∧ B) ≤ P(A) +``` + +**Applied to tool plans:** + +``` +Plan A: 3 steps +───────────────────────────────────────────────────── +Step 1 (P=0.95) → Step 2 (P=0.92) → Step 3 (P=0.90) + +P(success) = 0.95 × 0.92 × 0.90 = 0.787 (78.7%) + + +Plan B: 8 steps +───────────────────────────────────────────────────── +Step 1 (P=0.95) → Step 2 (P=0.92) → Step 3 (P=0.90) → Step 4 (P=0.93) + → Step 5 (P=0.91) → Step 6 (P=0.94) → Step 7 (P=0.89) → Step 8 (P=0.92) + +P(success) = 0.95 × 0.92 × 0.90 × 0.93 × 0.91 × 0.94 × 0.89 × 0.92 = 0.478 (47.8%) + + +Plan C: 20 steps (each P=0.95) +───────────────────────────────────────────────────── +P(success) = 0.95^20 = 0.358 (35.8%) +``` + +**More steps = more conjunction = lower probability of complete success** + +--- + +## The Fragility Spectrum + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ ROBUST ◄─────────────────────────────────────────────────────► FRAGILE │ +│ │ +│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ +│ │ 1 step │ │ 3 steps │ │ 8 steps │ │15 steps │ │25 steps │ │ +│ │ P=0.95 │ │ P=0.78 │ │ P=0.48 │ │ P=0.28 │ │ P=0.13 │ │ +│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ +│ │ +│ Simple Standard Complex Enterprise Ambitious │ +│ task workflow pipeline process fantasy │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Types of Fragility in Cascading Systems + +### 1. Sequential Fragility + +Each step depends on the previous. One failure breaks the chain. + +``` +┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ +│ A │───►│ B │───►│ C │───►│ D │───►│ E │ +└─────┘ └─────┘ └──┬──┘ └─────┘ └─────┘ + │ + ✗ FAIL + │ + ▼ + Everything after C is blocked +``` + +### 2. Conditional Fragility + +Branching logic compounds failure modes. + +``` + ┌─────┐ + │ A │ + └──┬──┘ + │ + ┌────────┼────────┐ + │ │ │ + ▼ ▼ ▼ + ┌─────┐ ┌─────┐ ┌─────┐ + │if X │ │if Y │ │if Z │ + └──┬──┘ └──┬──┘ └──┬──┘ + │ │ │ + ▼ ▼ ▼ + ┌─────┐ ┌─────┐ ┌─────┐ + │ B │ │ C │ │ D │ + └─────┘ └─────┘ └─────┘ + + Each branch is its own failure domain. + Condition evaluation itself can fail. + Wrong branch selection = cascading wrongness. +``` + +### 3. Accumulation Fragility + +Errors compound. Small inaccuracies become large ones. + +``` +Step 1: Extract data → 2% error rate +Step 2: Transform data → 3% error rate +Step 3: Analyze data → 2% error rate +Step 4: Generate report → 1% error rate + +But errors compound: +┌─────────────────────────────────────────────────────────────────┐ +│ │ +│ Input: 1000 records │ +│ │ +│ After Step 1: 980 correct, 20 errors introduced │ +│ After Step 2: 951 correct, 29 errors (some errors on errors) │ +│ After Step 3: 932 correct, 19 new errors + propagated errors │ +│ After Step 4: 923 correct, 9 new errors + all previous │ +│ │ +│ Final accuracy: ~77% (not 92% as naive multiplication suggests)│ +│ │ +│ Some errors AMPLIFY through the pipeline. │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### 4. Context Fragility + +Information loss at each handoff. + +``` +┌────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ Original user intent: "Find cheap flights to Tokyo in cherry blossom │ +│ season, preferably window seat, vegetarian meal" │ +│ │ +│ Step 1 output: { destination: "Tokyo", dates: "March-April" } │ +│ ↓ │ +│ Lost: "cheap", "window seat", "vegetarian" │ +│ │ +│ Step 2 output: { flights: [...] } │ +│ ↓ │ +│ Lost: "cherry blossom season" nuance │ +│ │ +│ Step 3 output: { booking: "confirmed" } │ +│ ↓ │ +│ User gets: expensive flight, middle seat, regular meal │ +│ │ +│ Each step loses context. By the end, original intent is unrecognizable. │ +│ │ +└────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Occam's Razor Applied to Tool Plans + +> "When multiple explanations exist, the one requiring the fewest assumptions +> is the most likely to be true." + +**Applied to tool orchestration:** + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ Task: "Convert this CSV to a formatted Excel report" │ +│ │ +│ PLAN A (Occam's Razor): │ +│ ─────────────────────── │ +│ ┌─────────────────────────┐ │ +│ │ csv-to-xlsx-converter │ ← 1 tool, 1 assumption │ +│ │ (handles formatting) │ │ +│ └─────────────────────────┘ │ +│ │ +│ Assumptions: 1 │ +│ P(success) ≈ 0.95 │ +│ │ +│ │ +│ PLAN B (Over-engineered): │ +│ ───────────────────────── │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ csv-parser │──►│ data-cleaner │──►│ formatter │──►│ xlsx-writer │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │ +│ │ +│ Assumptions: 4 │ +│ P(success) ≈ 0.95^4 = 0.81 │ +│ │ +│ │ +│ PLAN C (Kitchen sink): │ +│ ────────────────────── │ +│ csv-parser → validator → type-inferrer → null-handler → normalizer │ +│ → enricher → formatter → styler → chart-generator → xlsx-writer │ +│ │ +│ Assumptions: 10 │ +│ P(success) ≈ 0.95^10 = 0.60 │ +│ │ +│ ═══════════════════════════════════════════════════════════════════════ │ +│ Occam says: Use Plan A unless you have specific evidence you need more. │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## The Determinism vs. Flexibility Tradeoff + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ DETERMINISTIC FLEXIBLE │ +│ ───────────── ──────── │ +│ │ +│ ┌─────────────────────────┐ ┌─────────────────────────────────────┐ │ +│ │ │ │ │ │ +│ │ A → B → C → D │ │ A ──┬──► B ──┬──► D │ │ +│ │ │ │ │ │ │ │ +│ │ Same path every time │ │ └──► C ──┘ │ │ +│ │ Predictable │ │ │ │ +│ │ Testable │ │ Path varies by context │ │ +│ │ Auditable │ │ Adaptive │ │ +│ │ │ │ Handles edge cases │ │ +│ │ But: Brittle to edge │ │ │ │ +│ │ cases │ │ But: Unpredictable │ │ +│ │ │ │ Hard to debug │ │ +│ └─────────────────────────┘ └─────────────────────────────────────┘ │ +│ │ +│ │ +│ THE LEARNED PATHWAY APPROACH: │ +│ ───────────────────────────── │ +│ │ +│ Start flexible, converge toward deterministic based on usage: │ +│ │ +│ Week 1 Week 4 Week 12 │ +│ ─────── ─────── ──────── │ +│ │ +│ A ─┬─► B A ─┬─► B A ────► B │ +│ │ │ (85%) (99%) │ +│ ├─► C │ │ │ +│ │ └─► C │ │ +│ └─► D (15%) ▼ │ +│ C │ +│ (99%) │ +│ Many paths Dominant path Near-deterministic │ +│ explored emerges with escape hatch │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Strategies for Managing Fragility + +### 1. Minimize Conjunction (Fewer Steps) + +``` +Before: 8 steps +┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ +│ 1 │►│ 2 │►│ 3 │►│ 4 │►│ 5 │►│ 6 │►│ 7 │►│ 8 │ +└───┘ └───┘ └───┘ └───┘ └───┘ └───┘ └───┘ └───┘ + +After: Combine into 3 "super-tools" +┌─────────┐ ┌─────────┐ ┌─────────┐ +│ 1,2,3 │►│ 4,5,6 │►│ 7,8 │ +└─────────┘ └─────────┘ └─────────┘ + +Same capability, fewer failure points. +``` + +### 2. Parallel Over Sequential + +``` +Sequential (fragile): Parallel (robust): + +A → B → C → D A ──┬──► B ──┐ + │ │ +If B fails, C and D blocked. ├──► C ──┼──► E + │ │ + └──► D ──┘ + + If B fails, C and D still run. + E gets partial results. +``` + +### 3. Checkpoints and Recovery + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ │ +│ │ A │────►│ B │────►│ C │────►│ D │────►│ E │ │ +│ └───┘ └─┬─┘ └───┘ └─┬─┘ └───┘ │ +│ │ │ │ +│ ▼ ▼ │ +│ [CHECKPOINT] [CHECKPOINT] │ +│ Save state Save state │ +│ │ +│ If D fails: │ +│ • Don't restart from A │ +│ • Resume from checkpoint after B │ +│ • Retry only C → D → E │ +│ │ +│ Reduces effective conjunction from 5 steps to 3 steps max. │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### 4. Fallback Chains + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ Instead of: │ +│ ┌─────────────┐ │ +│ │ Tool A │──── FAIL ────► Pipeline stops │ +│ └─────────────┘ │ +│ │ +│ Use: │ +│ ┌─────────────┐ │ +│ │ Tool A │──── FAIL ────┐ │ +│ └─────────────┘ │ │ +│ ▼ │ +│ ┌─────────────┐ │ +│ │ Tool A' │──── FAIL ────┐ │ +│ │ (fallback) │ │ │ +│ └─────────────┘ ▼ │ +│ ┌─────────────┐ │ +│ │ Tool A'' │ │ +│ │ (last resort)│ │ +│ └─────────────┘ │ +│ │ +│ P(at least one works) = 1 - P(all fail) │ +│ = 1 - (0.05)³ │ +│ = 0.999875 │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### 5. Graceful Degradation + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ Full plan (ideal): │ +│ A → B → C → D → E → F → G │ +│ Output: Comprehensive report with charts, analysis, and recommendations │ +│ │ +│ Degraded plan (if D fails): │ +│ A → B → C → [skip D] → E' → F' → G' │ +│ Output: Report with analysis and recommendations (no charts) │ +│ │ +│ Minimal plan (if B and D fail): │ +│ A → [skip B] → C' → [skip D] → E'' → G'' │ +│ Output: Basic summary with key findings │ +│ │ +│ ═══════════════════════════════════════════════════════════════════════ │ +│ Something is better than nothing. │ +│ Define acceptable degradation levels upfront. │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### 6. Learned Pathway Weighting (K-Factor) + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ Track which paths users actually take: │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ Path A → B → C → D: Used 847 times (84.7%) ◄── K = 0.847 │ │ +│ │ Path A → B → X → D: Used 102 times (10.2%) │ │ +│ │ Path A → Y → C → D: Used 38 times ( 3.8%) │ │ +│ │ Path A → B → C → Z: Used 13 times ( 1.3%) │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ When generating new plans, weight toward learned paths: │ +│ │ +│ P(suggest path) = base_probability × (1 + K × learning_weight) │ +│ │ +│ As K → 1.0 for a path, it becomes effectively deterministic. │ +│ But the escape hatch remains for the 0.1% edge cases. │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ K = 0.50: Suggest learned path, but explore alternatives │ │ +│ │ K = 0.85: Strongly prefer learned path │ │ +│ │ K = 0.99: Almost deterministic, rare deviation │ │ +│ │ K = 1.00: Locked in (manual override to change) │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## The Fragility Budget + +Every plan has a "fragility budget"—the maximum acceptable failure probability. + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ FRAGILITY BUDGET ALLOCATION │ +│ │ +│ Acceptable failure rate: 10% (P(success) ≥ 90%) │ +│ │ +│ Budget equation: │ +│ P(success) = P₁ × P₂ × P₃ × ... × Pₙ ≥ 0.90 │ +│ │ +│ If each step has P = 0.98: │ +│ 0.98ⁿ ≥ 0.90 │ +│ n ≤ 5.2 │ +│ │ +│ Maximum steps: 5 │ +│ │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ │ +│ If each step has P = 0.95: │ +│ 0.95ⁿ ≥ 0.90 │ +│ n ≤ 2.0 │ +│ │ +│ Maximum steps: 2 (!) │ +│ │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ │ +│ To allow more steps, you must: │ +│ • Increase individual step reliability │ +│ • Add fallbacks (changes the math) │ +│ • Accept higher failure rate │ +│ • Use parallel branches │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## When More Steps ARE Justified + +Not all conjunction is bad. More steps are justified when: + +### 1. Each step genuinely adds value + +``` +Good: A (fetch) → B (parse) → C (analyze) → D (format) + Each step transforms data in a necessary way. + +Bad: A (fetch) → B (validate fetch) → C (log fetch) → D (cache fetch) → E (parse) + Steps B, C, D are defensive overhead that could be internal to A. +``` + +### 2. Steps have independent failure recovery + +``` +A → [checkpoint] → B → [checkpoint] → C → [checkpoint] → D + +Each checkpoint isolates failure. +Effective conjunction = max(steps between checkpoints), not total steps. +``` + +### 3. The domain genuinely requires it + +``` +Medical diagnosis: + symptoms → differential → tests → results → diagnosis → treatment + +You can't skip steps. The conjunction is inherent to the domain. +Accept the fragility, but add maximum safeguards. +``` + +### 4. Parallel execution changes the math + +``` + ┌── B ──┐ + │ │ + A ───┼── C ──┼─── E + │ │ + └── D ──┘ + +P(success) = P(A) × P(at least one of B,C,D) × P(E) + = P(A) × (1 - P(B fails) × P(C fails) × P(D fails)) × P(E) + = 0.95 × (1 - 0.05³) × 0.95 + = 0.95 × 0.999875 × 0.95 + = 0.902 + +Much better than sequential B → C → D! +``` + +--- + +## Pathway Learning Algorithms + +Beyond simple "most used" frequency counting, here are algorithms for learning and suggesting pathways: + +### 1. Multi-Armed Bandit (Explore vs Exploit) + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ EPSILON-GREEDY STRATEGY │ +│ ─────────────────────── │ +│ │ +│ ε = exploration rate (e.g., 0.1 = 10% exploration) │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ Roll random(0,1) │ │ +│ │ │ │ │ +│ │ ├───► < ε ───► EXPLORE: Pick random path │ │ +│ │ │ (discover potentially better routes) │ │ +│ │ │ │ │ +│ │ └───► ≥ ε ───► EXPLOIT: Pick best known path │ │ +│ │ (use what's worked before) │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ Over time, ε decays: │ +│ │ +│ Week 1: ε = 0.30 ███████████░░░░░░░░░░░░░░░░░░░ 30% exploration │ +│ Week 4: ε = 0.15 █████░░░░░░░░░░░░░░░░░░░░░░░░░ 15% exploration │ +│ Week 12: ε = 0.05 ██░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 5% exploration │ +│ Week 52: ε = 0.01 ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1% exploration │ +│ │ +│ System converges to best paths while always leaving door open. │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### 2. Upper Confidence Bound (UCB) + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ UCB ALGORITHM: Optimism in the face of uncertainty │ +│ ────────────── │ +│ │ +│ Score(path) = average_success + C × √(ln(total_runs) / path_runs) │ +│ ─────────────── ───────────────────────────────── │ +│ exploitation exploration bonus │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ Path A: 100 runs, 92% success │ │ +│ │ Score = 0.92 + 0.5 × √(ln(500)/100) = 0.92 + 0.12 = 1.04 │ │ +│ │ │ │ +│ │ Path B: 5 runs, 80% success │ │ +│ │ Score = 0.80 + 0.5 × √(ln(500)/5) = 0.80 + 0.78 = 1.58 │ │ +│ │ ▲ │ │ +│ │ │ │ │ +│ │ Path B wins! It has high uncertainty, deserves exploration. │ │ +│ │ │ │ +│ │ After 50 more runs of Path B (now 70% success): │ │ +│ │ Score = 0.70 + 0.5 × √(ln(550)/55) = 0.70 + 0.24 = 0.94 │ │ +│ │ │ │ +│ │ Now Path A wins. Exploration revealed B is actually worse. │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ Automatically balances exploration of uncertain paths vs exploitation. │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### 3. Thompson Sampling (Bayesian) + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ THOMPSON SAMPLING: Sample from belief distributions │ +│ ───────────────── │ +│ │ +│ Each path has a Beta distribution: Beta(successes + 1, failures + 1) │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ Path A: 90 successes, 10 failures │ │ +│ │ Beta(91, 11) │ │ +│ │ │ │ +│ │ Probability density: │ │ +│ │ ▄▄▄▄ │ │ +│ │ ▄██████▄ │ │ +│ │ ▄██████████▄ │ │ +│ │ ──────▄██████████████▄────── │ │ +│ │ 0.7 0.8 0.9 1.0 │ │ +│ │ ▲ │ │ +│ │ tight peak (confident) │ │ +│ │ │ │ +│ │ Path B: 4 successes, 1 failure │ │ +│ │ Beta(5, 2) │ │ +│ │ │ │ +│ │ Probability density: │ │ +│ │ ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ │ │ +│ │ ▄████████████████████▄ │ │ +│ │ ▄████████████████████████▄ │ │ +│ │ ────────────────────────── │ │ +│ │ 0.2 0.4 0.6 0.8 1.0 │ │ +│ │ ▲ │ │ +│ │ wide spread (uncertain) │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ Selection: Sample one value from each distribution, pick highest. │ +│ │ +│ Path A sample: 0.88 │ +│ Path B sample: 0.73 ← Sometimes samples high due to uncertainty! │ +│ │ +│ Naturally explores uncertain options proportional to their potential. │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### 4. Contextual Bandits (User/Query Aware) + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ CONTEXTUAL BANDITS: Path selection depends on context │ +│ ────────────────── │ +│ │ +│ Context features: │ +│ • User type (developer, marketer, analyst) │ +│ • Query complexity (simple, medium, complex) │ +│ • Time of day (morning, afternoon, evening) │ +│ • Previous success rate with this user │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ Model learns: P(success | path, context) │ │ +│ │ │ │ +│ │ ┌─────────────────────────────────────────────────────────────┐ │ │ +│ │ │ Context: {user: "developer", complexity: "high"} │ │ │ +│ │ │ │ │ │ +│ │ │ Path A (thorough): P(success) = 0.89 ◄── BEST FOR THIS │ │ │ +│ │ │ Path B (quick): P(success) = 0.62 CONTEXT │ │ │ +│ │ │ Path C (balanced): P(success) = 0.78 │ │ │ +│ │ └─────────────────────────────────────────────────────────────┘ │ │ +│ │ │ │ +│ │ ┌─────────────────────────────────────────────────────────────┐ │ │ +│ │ │ Context: {user: "marketer", complexity: "low"} │ │ │ +│ │ │ │ │ │ +│ │ │ Path A (thorough): P(success) = 0.71 │ │ │ +│ │ │ Path B (quick): P(success) = 0.94 ◄── BEST FOR THIS │ │ │ +│ │ │ Path C (balanced): P(success) = 0.85 CONTEXT │ │ │ +│ │ └─────────────────────────────────────────────────────────────┘ │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ Different users/contexts get different "best" paths automatically. │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### 5. Collaborative Filtering (Similar Users) + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ COLLABORATIVE FILTERING: "Users like you also used..." │ +│ ─────────────────────── │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ User-Path Success Matrix: │ │ +│ │ │ │ +│ │ Path A Path B Path C Path D Path E │ │ +│ │ User 1: ✓ ✗ ✓ ✓ ? │ │ +│ │ User 2: ✓ ✓ ✗ ✓ ✓ │ │ +│ │ User 3: ✗ ✓ ✓ ✗ ✓ │ │ +│ │ User 4: ✓ ✗ ✓ ✓ ? ◄── Current │ │ +│ │ │ │ +│ │ User 4 is most similar to User 1 (matching pattern). │ │ +│ │ User 1 succeeded with Path E? → Recommend Path E to User 4. │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ Matrix factorization finds latent features: │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ User 4 latent vector: [0.8, 0.2, 0.9, 0.1] │ │ +│ │ Path E latent vector: [0.7, 0.3, 0.8, 0.2] │ │ +│ │ │ │ +│ │ Predicted score = dot_product = 0.56 + 0.06 + 0.72 + 0.02 = 1.36 │ │ +│ │ │ │ +│ │ High score → Recommend! │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### 6. Q-Learning (Reinforcement Learning) + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ Q-LEARNING: Learn value of state-action pairs │ +│ ────────── │ +│ │ +│ Q(state, action) = expected future reward │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ State = (current_step, accumulated_context, user_feedback) │ │ +│ │ Action = which tool to call next │ │ +│ │ Reward = +1 (task success), -0.1 (per step), -1 (failure) │ │ +│ │ │ │ +│ │ ┌────────────────────────────────────────────────────────┐ │ │ +│ │ │ │ │ │ +│ │ │ State: "just fetched webpage" │ │ │ +│ │ │ │ │ │ +│ │ │ Q-values: │ │ │ +│ │ │ → parse-html: Q = 0.82 ◄── Highest, select │ │ │ +│ │ │ → extract-text: Q = 0.71 │ │ │ +│ │ │ → screenshot: Q = 0.45 │ │ │ +│ │ │ → validate: Q = 0.23 │ │ │ +│ │ │ │ │ │ +│ │ └────────────────────────────────────────────────────────┘ │ │ +│ │ │ │ +│ │ Update rule (after each execution): │ │ +│ │ │ │ +│ │ Q(s,a) ← Q(s,a) + α × [reward + γ×max(Q(s',a')) - Q(s,a)] │ │ +│ │ ▲ ▲ │ │ +│ │ learning rate discount future rewards │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ Learns optimal policy through trial and error over time. │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### 7. Monte Carlo Tree Search (MCTS) + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ MCTS: Simulate many possible futures, pick best path │ +│ ──── │ +│ │ +│ Four phases: SELECT → EXPAND → SIMULATE → BACKPROPAGATE │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ ┌─────┐ │ │ +│ │ │START│ visits: 1000 │ │ +│ │ └──┬──┘ │ │ +│ │ ┌───────┼───────┐ │ │ +│ │ ▼ ▼ ▼ │ │ +│ │ ┌───┐ ┌───┐ ┌───┐ │ │ +│ │ │ A │ │ B │ │ C │ SELECT: Follow UCB down tree │ │ +│ │ │420│ │380│ │200│ (balance visits & wins) │ │ +│ │ └─┬─┘ └─┬─┘ └───┘ │ │ +│ │ │ │ │ │ +│ │ ▼ ▼ │ │ +│ │ ┌───┐ ┌───┐ ┌───┐ │ │ +│ │ │A1 │ │B1 │ │B2 │ EXPAND: Add new node │ │ +│ │ │350│ │200│ │180│ │ │ +│ │ └───┘ └─┬─┘ └───┘ │ │ +│ │ │ │ │ +│ │ ▼ │ │ +│ │ ┌───┐ │ │ +│ │ │???│ SIMULATE: Random rollout to terminal │ │ +│ │ │NEW│ → Success! │ │ +│ │ └───┘ │ │ +│ │ │ │ +│ │ BACKPROPAGATE: Update all ancestors with result │ │ +│ │ B1: 200 → 201 wins │ │ +│ │ B: 380 → 381 wins │ │ +│ │ START: 1000 → 1001 visits │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ After N simulations, pick path with most visits (most confident). │ +│ Great for planning multiple steps ahead. │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### 8. Genetic Algorithms (Evolve Pathways) + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ GENETIC ALGORITHM: Evolve better pathways over generations │ +│ ───────────────── │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ Generation 1: Random pathways │ │ +│ │ ───────────────────────────────── │ │ +│ │ Path 1: [A, B, C, D, E] fitness: 0.65 │ │ +│ │ Path 2: [A, C, B, E, D] fitness: 0.72 │ │ +│ │ Path 3: [B, A, D, C, E] fitness: 0.58 │ │ +│ │ Path 4: [A, B, D, C, E] fitness: 0.81 ◄── Best │ │ +│ │ │ │ +│ │ ───────────────────────────────────────────────────────────────── │ │ +│ │ │ │ +│ │ SELECTION: Keep top 50% │ │ +│ │ Path 4: [A, B, D, C, E] ✓ │ │ +│ │ Path 2: [A, C, B, E, D] ✓ │ │ +│ │ │ │ +│ │ CROSSOVER: Combine successful paths │ │ +│ │ Parent 1: [A, B, | D, C, E] │ │ +│ │ Parent 2: [A, C, | B, E, D] │ │ +│ │ ↓ │ │ +│ │ Child: [A, B, | B, E, D] (take prefix from P1, suffix from P2)│ │ +│ │ │ │ +│ │ MUTATION: Random tweaks (5% chance per gene) │ │ +│ │ [A, B, B, E, D] → [A, B, F, E, D] (B mutated to F) │ │ +│ │ │ │ +│ │ ───────────────────────────────────────────────────────────────── │ │ +│ │ │ │ +│ │ Generation 10: │ │ +│ │ Best path: [A, B, D, E] fitness: 0.94 │ │ +│ │ (Evolved to drop unnecessary step C!) │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ Discovers optimal pathways through evolution, not explicit programming. │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### 9. Inverse Reinforcement Learning (Learn from Experts) + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ INVERSE RL: Infer reward function from expert demonstrations │ +│ ────────── │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ Observe expert (power user) behavior: │ │ +│ │ │ │ +│ │ Expert Session 1: A → B → D → E (skipped C) │ │ +│ │ Expert Session 2: A → B → D → E (skipped C) │ │ +│ │ Expert Session 3: A → B → C → D → E (included C for edge case) │ │ +│ │ Expert Session 4: A → B → D → E (skipped C) │ │ +│ │ │ │ +│ │ Inferred reward function: │ │ +│ │ • High reward for: A → B, B → D, D → E │ │ +│ │ • Low/negative reward for: B → C (usually skipped) │ │ +│ │ • Context-dependent: C only when specific conditions met │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ Now apply learned reward to new users: │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ New user at step B: │ │ +│ │ │ │ +│ │ Options: │ │ +│ │ B → C: reward = -0.2 (experts usually skip) │ │ +│ │ B → D: reward = +0.8 (experts prefer) ◄── SUGGEST │ │ +│ │ B → E: reward = +0.1 (sometimes works) │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ System learns "what experts value" rather than explicit rules. │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### 10. Bayesian Optimization (Efficient Exploration) + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ BAYESIAN OPTIMIZATION: Smart exploration with Gaussian Processes │ +│ ──────────────────── │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ Model uncertainty about unexplored paths: │ │ +│ │ │ │ +│ │ Success │ │ +│ │ Rate │ │ +│ │ │ │ │ +│ │ 1.0┤ ╭───╮ │ │ +│ │ │ ╭─┤ ├─╮ ← Uncertainty band │ │ +│ │ 0.8┤ ● ╭─┤ │ ├╮ │ │ +│ │ │ ╱ ╲ ╭─┤ │ │ │ ╲ │ │ +│ │ 0.6┤ ╱ ╲ ╱ │ │ │ │ ╲ ● = observed data │ │ +│ │ │ ╱ ╲╱ ╰─┤ │ ├───╲ │ │ +│ │ 0.4┤ ● ● ╰───┴───╯ ╲ │ │ +│ │ │ ╱ ╲● │ │ +│ │ 0.2┤ ╱ │ │ +│ │ │ ● │ │ +│ │ 0.0┼──────────────────────────────────────────────── │ │ +│ │ Path Path Path Path Path Path Path Path │ │ +│ │ A B C D E F G H │ │ +│ │ │ │ +│ │ Acquisition function picks next path to try: │ │ +│ │ • Expected Improvement (EI) │ │ +│ │ • Upper Confidence Bound (UCB) │ │ +│ │ • Probability of Improvement (PI) │ │ +│ │ │ │ +│ │ → Try Path E: High uncertainty + decent predicted mean │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ Minimizes trials needed to find optimal path. │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### 11. Hierarchical Clustering (Path Families) + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ HIERARCHICAL CLUSTERING: Group similar paths into families │ +│ ─────────────────────── │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ ┌───────────┴───────────┐ │ │ +│ │ │ │ │ │ +│ │ ┌───────┴───────┐ ┌───────┴───────┐ │ │ +│ │ │ │ │ │ │ │ +│ │ ┌─────┴─────┐ ┌─────┴─────┐ │ ┌─────┴─────┐ │ │ +│ │ │ │ │ │ │ │ │ │ │ +│ │ [A→B→D→E] [A→B→D→F] [A→B→C→E] [A→C→D→E] [B→A→D→E] [B→C→D→E] │ │ +│ │ │ │ +│ │ ════════════════════════════════════════════════════════════════ │ │ +│ │ "Direct paths" "C-inclusive" "B-first variants" │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ Benefits: │ +│ • When "Direct paths" cluster works, prefer it as a family │ +│ • If it fails, try "C-inclusive" family │ +│ • Don't randomly jump between distant clusters │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ Selection strategy: │ │ +│ │ │ │ +│ │ 1. Pick best cluster (based on cluster-level success rate) │ │ +│ │ 2. Pick best path within cluster (based on path-level success) │ │ +│ │ 3. If cluster fails repeatedly, move to sibling cluster │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### 12. Recency-Weighted Success (Time Decay) + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ RECENCY WEIGHTING: Recent outcomes matter more than old ones │ +│ ──────────────── │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ Path A history: │ │ +│ │ │ │ +│ │ Time Outcome Raw Weight Decayed Weight (λ=0.95) │ │ +│ │ ───── ─────── ────────── ────────────────────── │ │ +│ │ t-30 Success 1.0 0.95^30 = 0.21 │ │ +│ │ t-20 Success 1.0 0.95^20 = 0.36 │ │ +│ │ t-10 Failure 1.0 0.95^10 = 0.60 │ │ +│ │ t-5 Success 1.0 0.95^5 = 0.77 │ │ +│ │ t-2 Success 1.0 0.95^2 = 0.90 │ │ +│ │ t-1 Failure 1.0 0.95^1 = 0.95 │ │ +│ │ t-0 Success 1.0 0.95^0 = 1.00 │ │ +│ │ │ │ +│ │ Naive success rate: 5/7 = 71% │ │ +│ │ Recency-weighted: (0.21+0.36+0.77+0.90+1.00) / total = 68% │ │ +│ │ (recent failure pulls it down) │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ Why it matters: │ +│ • Tools get updated (newer versions may be better/worse) │ +│ • User preferences drift │ +│ • External APIs change behavior │ +│ • Old successes may not predict current performance │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### Algorithm Comparison Matrix + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ ALGORITHM SELECTION GUIDE │ +│ │ +│ ┌──────────────────┬───────────┬───────────┬───────────┬─────────────┐ │ +│ │ Algorithm │ Best For │ Data Req │ Compute │ Convergence │ │ +│ ├──────────────────┼───────────┼───────────┼───────────┼─────────────┤ │ +│ │ ε-Greedy │ Simple │ Low │ O(1) │ Slow │ │ +│ │ UCB │ Balanced │ Low │ O(1) │ Medium │ │ +│ │ Thompson │ Uncertain │ Low │ O(1) │ Fast │ │ +│ │ Contextual │ Personlzd │ Medium │ O(n) │ Medium │ │ +│ │ Collaborative │ Multi-usr │ High │ O(n²) │ Medium │ │ +│ │ Q-Learning │ Sequences │ High │ O(s×a) │ Slow │ │ +│ │ MCTS │ Planning │ Low │ O(sims) │ Fast │ │ +│ │ Genetic │ Discovery │ Medium │ O(pop×gen)│ Variable │ │ +│ │ Inverse RL │ Experts │ Medium │ O(demos) │ Fast │ │ +│ │ Bayesian Opt │ Expensive │ Low │ O(n³) │ Very Fast │ │ +│ │ Clustering │ Families │ Medium │ O(n²) │ N/A │ │ +│ │ Recency │ Drift │ Low │ O(1) │ Adaptive │ │ +│ └──────────────────┴───────────┴───────────┴───────────┴─────────────┘ │ +│ │ +│ Hybrid approaches often work best: │ +│ • UCB + Recency for drifting environments │ +│ • Contextual + Collaborative for personalization │ +│ • MCTS + Q-Learning for complex sequential decisions │ +│ • Clustering + Thompson for structured exploration │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Summary: The Fragility Principles + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ 1. CONJUNCTION REDUCES PROBABILITY │ +│ Every additional step multiplies failure risk. │ +│ P(A ∧ B) ≤ P(A) │ +│ │ +│ 2. OCCAM'S RAZOR APPLIES │ +│ Prefer fewer assumptions. Fewer steps = fewer assumptions. │ +│ Don't add steps "just in case." │ +│ │ +│ 3. DETERMINISM EMERGES FROM LEARNING │ +│ Don't design deterministic upfront. │ +│ Let frequently-used paths become deterministic through K-factor. │ +│ │ +│ 4. BUDGET YOUR FRAGILITY │ +│ Know your acceptable failure rate. │ +│ Calculate maximum steps accordingly. │ +│ │ +│ 5. PARALLEL > SEQUENTIAL │ +│ When possible, run steps in parallel. │ +│ Changes multiplication to "at least one succeeds" math. │ +│ │ +│ 6. CHECKPOINTS BOUND FAILURE │ +│ Divide long chains into recoverable segments. │ +│ Effective fragility = longest segment, not total length. │ +│ │ +│ 7. FALLBACKS COMPOUND SUCCESS │ +│ P(at least one works) = 1 - P(all fail) │ +│ Three 95% tools as fallbacks = 99.99% effective reliability. │ +│ │ +│ 8. GRACEFUL DEGRADATION > TOTAL FAILURE │ +│ Define "good enough" outputs at each degradation level. │ +│ Something is better than nothing. │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Visualizing the Tradeoff + +``` + CAPABILITY + ▲ + │ + │ ╭────────────────────╮ + │ ╱ ╲ + │ ╱ OPTIMAL ZONE ╲ + │ ╱ (enough steps for ╲ + │ ╱ capability, not so ╲ + │ ╱ many that it breaks) ╲ + │ ╱ ╲ + │ ╱ ╲ + │ ╱ ╲ + │ ╱ ┌─────────────────────────────────┐ + │ ╱ │ │ + │╱ │ FRAGILITY CLIFF │ + │ │ (too many steps, │ + │ │ system breaks more │ + │ │ than it works) │ + │ │ │ + │ └─────────────────────────────────┘ + │ + └──────────────────────────────────────────► STEPS + 1 3 5 8 12 20 50 + + Robust ◄───────────────────► Fragile +``` + +The goal: **Stay in the optimal zone**—enough capability to solve the problem, not so many steps that the system becomes unreliable. diff --git a/docs/DYNAMIC_TOOL_ORCHESTRATION.md b/docs/DYNAMIC_TOOL_ORCHESTRATION.md new file mode 100644 index 0000000..4f0129c --- /dev/null +++ b/docs/DYNAMIC_TOOL_ORCHESTRATION.md @@ -0,0 +1,1950 @@ +# Dynamic Multi-Tool Orchestration + +A comprehensive exploration of generating and executing complex multi-step tool plans from natural language queries using the TPMJS registry. + +--- + +## Table of Contents + +1. [Vision](#vision) +2. [Core Concepts](#core-concepts) +3. [Plan Generation Architecture](#plan-generation-architecture) +4. [The Y×X Framework](#the-yx-framework) +5. [Plan Schema Design](#plan-schema-design) +6. [Execution Strategies](#execution-strategies) +7. [Complex Task Examples](#complex-task-examples) +8. [Tool Discovery & Selection](#tool-discovery--selection) +9. [Context & State Management](#context--state-management) +10. [Error Handling & Recovery](#error-handling--recovery) +11. [Optimization Techniques](#optimization-techniques) +12. [Security Considerations](#security-considerations) +13. [Implementation Roadmap](#implementation-roadmap) + +--- + +## Vision + +Traditional AI tool use requires developers to predefine which tools an agent can access at build time. TPMJS flips this paradigm: **tools are discovered and loaded dynamically from a live registry at runtime**. + +This unlocks a new capability: **for any sufficiently complex user query, we can generate Y alternative execution plans, each containing X sequential tool invocations, all loaded dynamically from the registry**. + +### The Power of Dynamic Orchestration + +``` +User Query: "Analyze my competitor's landing page and create a better version" + +Plan A (5 steps): + 1. web-scraper → Extract competitor's page HTML + 2. html-to-markdown → Convert to readable format + 3. sentiment-analyzer → Analyze copy tone + 4. color-extractor → Extract design palette + 5. landing-page-generator → Generate improved version + +Plan B (7 steps): + 1. screenshot-tool → Capture visual snapshot + 2. image-to-text → OCR any text content + 3. seo-analyzer → Check SEO structure + 4. competitor-analyzer → Compare against benchmarks + 5. copywriting-assistant → Generate new copy + 6. tailwind-generator → Create component code + 7. preview-renderer → Generate preview image + +Plan C (3 steps): + 1. full-page-analyzer → Comprehensive page analysis + 2. ai-designer → Generate complete redesign + 3. code-exporter → Export to framework of choice +``` + +The user chooses their preferred approach, or the system auto-selects based on available tools, cost, and reliability. + +--- + +## Core Concepts + +### 1. Tool as a Unit of Work + +A **tool** in TPMJS is an atomic unit of computation that: +- Has well-defined inputs (parameters with types) +- Produces a specific output (return type) +- Is self-documenting (description, use cases, examples) +- Runs in isolation (sandboxed execution) + +```typescript +// Tool metadata structure +interface Tool { + exportName: string; + description: string; + parameters: Parameter[]; + returns: ReturnType; + aiAgent?: { + useCase: string; + limitations?: string; + examples?: string[]; + }; +} +``` + +### 2. Plan as a Directed Acyclic Graph (DAG) + +A **plan** is not just a linear sequence—it's a DAG where: +- Nodes are tool invocations +- Edges represent data dependencies +- Parallel branches can execute concurrently +- Convergence points combine results + +``` + ┌─────────────┐ + │ INPUT │ + └──────┬──────┘ + │ + ┌──────▼──────┐ + │ Tool A │ + └──────┬──────┘ + │ + ┌────────┴────────┐ + │ │ +┌─────▼─────┐ ┌─────▼─────┐ +│ Tool B │ │ Tool C │ ← Parallel execution +└─────┬─────┘ └─────┬─────┘ + │ │ + └────────┬────────┘ + │ + ┌──────▼──────┐ + │ Tool D │ ← Combines B + C outputs + └──────┬──────┘ + │ + ┌──────▼──────┐ + │ OUTPUT │ + └─────────────┘ +``` + +### 3. Context Window + +The **context window** is the accumulated state passed through the plan: +- Original user query +- Intermediate results from each tool +- Extracted entities and references +- Error history and recovery attempts + +### 4. Plan Variants (Y) + +For any query, we generate **Y alternative plans** that differ in: +- Tool selection (different tools for same subtask) +- Granularity (few powerful tools vs many focused tools) +- Approach (different methodologies) +- Risk profile (proven tools vs experimental tools) +- Cost (token/compute efficient vs thorough) + +### 5. Step Count (X) + +Each plan has **X sequential steps** where: +- Minimum X: 1 (single tool solves the task) +- Typical X: 3-10 (most workflows) +- Maximum X: 20+ (complex multi-stage pipelines) +- No hard upper limit, but diminishing returns apply + +--- + +## Plan Generation Architecture + +### Phase 1: Query Analysis + +```typescript +interface QueryAnalysis { + // What the user wants to accomplish + intent: string; + + // Extracted entities (URLs, file paths, names, etc.) + entities: Entity[]; + + // Required capabilities to fulfill the request + requiredCapabilities: Capability[]; + + // Constraints mentioned by user + constraints: { + format?: string; // "as JSON", "in markdown" + style?: string; // "professional", "casual" + timeLimit?: number; // "quickly", "in under a minute" + quality?: string; // "high quality", "draft" + }; + + // Ambiguities that need resolution + ambiguities: string[]; + + // Complexity score (1-10) + complexity: number; +} +``` + +### Phase 2: Capability Matching + +Map required capabilities to available tools: + +```typescript +interface CapabilityMatch { + capability: string; + matchingTools: Tool[]; + confidence: number; + alternatives: Tool[]; +} + +// Example capability matching +const matches = [ + { + capability: "extract-webpage-content", + matchingTools: [ + { name: "web-scraper", confidence: 0.95 }, + { name: "puppeteer-extractor", confidence: 0.90 }, + { name: "readability-parser", confidence: 0.85 } + ] + }, + { + capability: "convert-html-to-text", + matchingTools: [ + { name: "html-to-markdown", confidence: 0.92 }, + { name: "turndown", confidence: 0.88 }, + { name: "html-strip", confidence: 0.70 } + ] + } +]; +``` + +### Phase 3: Plan Synthesis + +Generate Y distinct plans by varying: + +```typescript +interface PlanSynthesisStrategy { + // Tool selection strategy + toolSelection: + | "highest-confidence" // Use best-matching tools + | "most-reliable" // Use tools with best health scores + | "lowest-cost" // Minimize token usage + | "fastest" // Optimize for speed + | "most-granular" // Break into smallest steps + | "most-consolidated"; // Use fewest powerful tools + + // Parallelization strategy + parallelization: + | "maximize" // Run as much in parallel as possible + | "sequential" // Run everything in order + | "balanced"; // Smart parallelization + + // Error handling strategy + errorHandling: + | "fail-fast" // Stop on first error + | "best-effort" // Continue despite errors + | "with-fallbacks"; // Use alternative tools on failure +} +``` + +--- + +## The Y×X Framework + +### Defining Y: Number of Alternative Plans + +**Factors that increase Y:** +- High ambiguity in user query +- Multiple valid approaches +- Trade-offs between speed/quality/cost +- User hasn't specified preferences + +**Typical Y values:** +- Simple queries: Y = 1-2 +- Moderate queries: Y = 2-4 +- Complex queries: Y = 3-5 +- Highly ambiguous: Y = 5-8 + +### Defining X: Steps per Plan + +**Factors that increase X:** +- Task complexity +- Data transformation requirements +- Multiple output formats needed +- Validation/verification steps +- User's quality requirements + +**Typical X values:** +- Quick tasks: X = 1-3 +- Standard workflows: X = 4-8 +- Complex pipelines: X = 8-15 +- Enterprise workflows: X = 15-25 + +### The Y×X Matrix + +``` + │ X = 3 │ X = 7 │ X = 12 │ X = 20 +────────────┼───────────┼───────────┼───────────┼─────────── +Y = 1 │ Simple │ Standard │ Complex │ Pipeline + │ Task │ Workflow │ Process │ System +────────────┼───────────┼───────────┼───────────┼─────────── +Y = 3 │ Multi- │ Standard │ Complex │ Enterprise + │ Option │ Options │ Options │ Options +────────────┼───────────┼───────────┼───────────┼─────────── +Y = 5 │ High │ High │ Very │ Maximum + │ Choice │ Flex │ Complex │ Flexibility +``` + +--- + +## Plan Schema Design + +### ExecutionPlan Schema + +```typescript +interface ExecutionPlan { + id: string; + version: "1.0"; + + // Metadata + metadata: { + generatedAt: string; + query: string; + complexity: number; + estimatedDuration: number; // milliseconds + estimatedCost: number; // USD + confidence: number; // 0-1 + }; + + // Plan classification + classification: { + approach: string; // "thorough" | "quick" | "balanced" + riskLevel: "low" | "medium" | "high"; + parallelizable: boolean; + }; + + // The actual steps + steps: ExecutionStep[]; + + // Expected final output + expectedOutput: { + type: string; + schema?: JSONSchema; + description: string; + }; +} +``` + +### ExecutionStep Schema + +```typescript +interface ExecutionStep { + id: string; + order: number; + + // Tool reference + tool: { + packageName: string; + exportName: string; + version?: string; + }; + + // Why this step exists + purpose: string; + + // Input configuration + input: { + // Static values + static?: Record; + + // References to previous step outputs + fromStep?: { + stepId: string; + path: string; // JSONPath to extract value + }; + + // References to original query entities + fromQuery?: { + entityType: string; + index?: number; + }; + + // Dynamic values computed at runtime + computed?: { + expression: string; + dependencies: string[]; + }; + }; + + // Output expectations + output: { + type: string; + storeAs: string; // Variable name in context + validate?: ValidationRule[]; + }; + + // Execution configuration + execution: { + timeout: number; + retries: number; + canSkipOnError: boolean; + fallbackTools?: string[]; + }; + + // Dependencies + dependsOn: string[]; // Step IDs that must complete first + + // Enables parallel execution with other steps + parallelGroup?: string; +} +``` + +### Example: Full Plan JSON + +```json +{ + "id": "plan_abc123", + "version": "1.0", + "metadata": { + "generatedAt": "2024-01-15T10:30:00Z", + "query": "Scrape the product listings from example.com/products, extract prices, and create a price comparison spreadsheet", + "complexity": 6, + "estimatedDuration": 45000, + "estimatedCost": 0.12, + "confidence": 0.87 + }, + "classification": { + "approach": "thorough", + "riskLevel": "low", + "parallelizable": true + }, + "steps": [ + { + "id": "step_1", + "order": 1, + "tool": { + "packageName": "tpmjs-web-scraper", + "exportName": "scrapeUrl" + }, + "purpose": "Fetch the product listings page HTML", + "input": { + "static": { + "waitForSelector": ".product-card", + "timeout": 10000 + }, + "fromQuery": { + "entityType": "url", + "index": 0 + } + }, + "output": { + "type": "string", + "storeAs": "rawHtml", + "validate": [ + { "rule": "minLength", "value": 1000 } + ] + }, + "execution": { + "timeout": 15000, + "retries": 2, + "canSkipOnError": false, + "fallbackTools": ["puppeteer-scraper", "playwright-fetch"] + }, + "dependsOn": [] + }, + { + "id": "step_2", + "order": 2, + "tool": { + "packageName": "tpmjs-html-parser", + "exportName": "extractElements" + }, + "purpose": "Extract product cards from the HTML", + "input": { + "fromStep": { + "stepId": "step_1", + "path": "$.rawHtml" + }, + "static": { + "selector": ".product-card", + "attributes": ["data-name", "data-price", "data-sku"] + } + }, + "output": { + "type": "array", + "storeAs": "productElements" + }, + "execution": { + "timeout": 5000, + "retries": 1, + "canSkipOnError": false + }, + "dependsOn": ["step_1"] + }, + { + "id": "step_3a", + "order": 3, + "tool": { + "packageName": "tpmjs-price-extractor", + "exportName": "extractPrices" + }, + "purpose": "Parse and normalize price values", + "input": { + "fromStep": { + "stepId": "step_2", + "path": "$.productElements[*].data-price" + }, + "static": { + "currency": "USD", + "handleRanges": true + } + }, + "output": { + "type": "array", + "storeAs": "normalizedPrices" + }, + "execution": { + "timeout": 3000, + "retries": 1, + "canSkipOnError": false + }, + "dependsOn": ["step_2"], + "parallelGroup": "data_processing" + }, + { + "id": "step_3b", + "order": 3, + "tool": { + "packageName": "tpmjs-text-cleaner", + "exportName": "cleanProductNames" + }, + "purpose": "Clean and normalize product names", + "input": { + "fromStep": { + "stepId": "step_2", + "path": "$.productElements[*].data-name" + } + }, + "output": { + "type": "array", + "storeAs": "cleanedNames" + }, + "execution": { + "timeout": 2000, + "retries": 1, + "canSkipOnError": true + }, + "dependsOn": ["step_2"], + "parallelGroup": "data_processing" + }, + { + "id": "step_4", + "order": 4, + "tool": { + "packageName": "tpmjs-data-merger", + "exportName": "mergeArrays" + }, + "purpose": "Combine prices and names into product objects", + "input": { + "fromStep": [ + { "stepId": "step_3a", "path": "$.normalizedPrices" }, + { "stepId": "step_3b", "path": "$.cleanedNames" } + ], + "static": { + "keys": ["price", "name"] + } + }, + "output": { + "type": "array", + "storeAs": "products" + }, + "execution": { + "timeout": 2000, + "retries": 1, + "canSkipOnError": false + }, + "dependsOn": ["step_3a", "step_3b"] + }, + { + "id": "step_5", + "order": 5, + "tool": { + "packageName": "tpmjs-spreadsheet-generator", + "exportName": "createXlsx" + }, + "purpose": "Generate Excel spreadsheet with price comparison", + "input": { + "fromStep": { + "stepId": "step_4", + "path": "$.products" + }, + "static": { + "sheetName": "Price Comparison", + "columns": [ + { "header": "Product Name", "key": "name", "width": 40 }, + { "header": "Price (USD)", "key": "price", "width": 15, "format": "currency" } + ], + "includeStats": true, + "sortBy": "price" + } + }, + "output": { + "type": "buffer", + "storeAs": "spreadsheet" + }, + "execution": { + "timeout": 5000, + "retries": 1, + "canSkipOnError": false + }, + "dependsOn": ["step_4"] + } + ], + "expectedOutput": { + "type": "file", + "schema": { + "format": "xlsx", + "mimeType": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + }, + "description": "Excel spreadsheet containing product names and prices, sorted by price with summary statistics" + } +} +``` + +--- + +## Execution Strategies + +### 1. Sequential Execution + +Execute steps one at a time in order: + +```typescript +async function executeSequential(plan: ExecutionPlan): Promise { + const context = new ExecutionContext(); + + for (const step of plan.steps) { + const result = await executeStep(step, context); + context.store(step.output.storeAs, result); + } + + return context.getFinalOutput(); +} +``` + +**Pros:** Simple, predictable, easy to debug +**Cons:** Slow, doesn't utilize parallelization opportunities + +### 2. Parallel Execution with Dependencies + +Execute steps as soon as their dependencies are satisfied: + +```typescript +async function executeParallel(plan: ExecutionPlan): Promise { + const context = new ExecutionContext(); + const completed = new Set(); + const inProgress = new Map>(); + + async function canExecute(step: ExecutionStep): boolean { + return step.dependsOn.every(dep => completed.has(dep)); + } + + async function executeWhenReady(step: ExecutionStep): Promise { + // Wait for dependencies + await Promise.all( + step.dependsOn.map(dep => inProgress.get(dep)) + ); + + const result = await executeStep(step, context); + context.store(step.output.storeAs, result); + completed.add(step.id); + } + + // Start all steps, they'll wait for their dependencies + const promises = plan.steps.map(step => { + const promise = executeWhenReady(step); + inProgress.set(step.id, promise); + return promise; + }); + + await Promise.all(promises); + return context.getFinalOutput(); +} +``` + +**Pros:** Fast, maximizes throughput +**Cons:** Complex state management, harder to debug + +### 3. Streaming Execution + +Stream results as they become available: + +```typescript +async function* executeStreaming( + plan: ExecutionPlan +): AsyncGenerator { + const context = new ExecutionContext(); + + for (const step of plan.steps) { + yield { type: 'step_start', stepId: step.id }; + + try { + const result = await executeStep(step, context); + context.store(step.output.storeAs, result); + + yield { + type: 'step_complete', + stepId: step.id, + result: summarize(result) + }; + } catch (error) { + yield { + type: 'step_error', + stepId: step.id, + error: error.message + }; + + if (!step.execution.canSkipOnError) { + throw error; + } + } + } + + yield { + type: 'plan_complete', + output: context.getFinalOutput() + }; +} +``` + +**Pros:** Real-time feedback, good UX +**Cons:** Complexity in client handling + +### 4. Checkpoint Execution + +Save state after each step for resumability: + +```typescript +async function executeWithCheckpoints( + plan: ExecutionPlan, + checkpoint?: Checkpoint +): Promise { + const context = checkpoint?.context ?? new ExecutionContext(); + const startIndex = checkpoint?.lastCompletedStep ?? 0; + + for (let i = startIndex; i < plan.steps.length; i++) { + const step = plan.steps[i]; + + try { + const result = await executeStep(step, context); + context.store(step.output.storeAs, result); + + // Save checkpoint + await saveCheckpoint({ + planId: plan.id, + lastCompletedStep: i + 1, + context: context.serialize() + }); + } catch (error) { + // Checkpoint saved, can resume from here + throw new ResumableError(error, i, context); + } + } + + return context.getFinalOutput(); +} +``` + +**Pros:** Resilient, can resume after failures +**Cons:** Storage overhead, checkpoint management + +--- + +## Complex Task Examples + +### Example 1: Content Marketing Pipeline (12 steps) + +**User Query:** "Research trending topics in AI, write a blog post, create social media content, and generate promotional images" + +```yaml +Plan: Content Marketing Pipeline +Steps: 12 +Estimated Duration: 3-5 minutes +Estimated Cost: $0.45 + +Step 1: trending-topics-analyzer + Purpose: Find trending AI topics from multiple sources + Input: { domain: "artificial-intelligence", sources: ["reddit", "hackernews", "twitter"] } + Output: trendingTopics[] + +Step 2: topic-scorer + Purpose: Score topics by relevance and engagement potential + Input: { topics: $trendingTopics, criteria: ["novelty", "engagement", "relevance"] } + Output: scoredTopics[] + +Step 3: topic-selector + Purpose: Select best topic for blog post + Input: { topics: $scoredTopics, count: 1 } + Output: selectedTopic + +Step 4: research-aggregator + Purpose: Gather research materials on selected topic + Input: { topic: $selectedTopic, depth: "comprehensive" } + Output: researchMaterials + +Step 5: outline-generator + Purpose: Create blog post outline + Input: { topic: $selectedTopic, research: $researchMaterials, style: "informative" } + Output: blogOutline + +Step 6: blog-writer + Purpose: Write full blog post from outline + Input: { outline: $blogOutline, wordCount: 1500, tone: "professional" } + Output: blogPost + +Step 7: seo-optimizer + Purpose: Optimize blog post for search engines + Input: { content: $blogPost, targetKeywords: $selectedTopic.keywords } + Output: optimizedBlogPost + +Step 8: twitter-thread-generator (parallel group: social) + Purpose: Create Twitter thread from blog post + Input: { content: $optimizedBlogPost, maxTweets: 10 } + Output: twitterThread + +Step 9: linkedin-post-generator (parallel group: social) + Purpose: Create LinkedIn post from blog post + Input: { content: $optimizedBlogPost, format: "professional" } + Output: linkedinPost + +Step 10: image-prompt-generator + Purpose: Generate prompts for promotional images + Input: { content: $optimizedBlogPost, count: 3, style: "modern-tech" } + Output: imagePrompts[] + +Step 11: image-generator + Purpose: Generate promotional images + Input: { prompts: $imagePrompts, size: "1200x630", style: "blog-header" } + Output: images[] + +Step 12: content-package-assembler + Purpose: Assemble final content package + Input: { + blog: $optimizedBlogPost, + twitter: $twitterThread, + linkedin: $linkedinPost, + images: $images + } + Output: contentPackage +``` + +### Example 2: Code Repository Analysis (15 steps) + +**User Query:** "Analyze my GitHub repository, identify security vulnerabilities, generate documentation, and create a README" + +```yaml +Plan: Repository Analysis Pipeline +Steps: 15 +Estimated Duration: 5-8 minutes +Estimated Cost: $0.75 + +Step 1: github-repo-fetcher + Purpose: Clone and fetch repository metadata + Input: { repoUrl: $userProvidedUrl } + Output: repoData + +Step 2: language-detector + Purpose: Detect programming languages used + Input: { files: $repoData.files } + Output: languages[] + +Step 3: dependency-extractor + Purpose: Extract all dependencies + Input: { repoData: $repoData, languages: $languages } + Output: dependencies[] + +Step 4: vulnerability-scanner (parallel group: analysis) + Purpose: Scan dependencies for known vulnerabilities + Input: { dependencies: $dependencies } + Output: vulnerabilities[] + +Step 5: code-quality-analyzer (parallel group: analysis) + Purpose: Analyze code quality metrics + Input: { repoData: $repoData, languages: $languages } + Output: qualityMetrics + +Step 6: architecture-detector (parallel group: analysis) + Purpose: Detect architectural patterns + Input: { repoData: $repoData } + Output: architecture + +Step 7: api-endpoint-extractor + Purpose: Extract API endpoints if present + Input: { repoData: $repoData, languages: $languages } + Output: apiEndpoints[] + +Step 8: function-documenter + Purpose: Generate function documentation + Input: { repoData: $repoData, languages: $languages } + Output: functionDocs[] + +Step 9: api-documenter + Purpose: Generate API documentation + Input: { endpoints: $apiEndpoints } + Output: apiDocs + +Step 10: security-report-generator + Purpose: Generate security report + Input: { vulnerabilities: $vulnerabilities, dependencies: $dependencies } + Output: securityReport + +Step 11: architecture-diagram-generator + Purpose: Generate architecture diagram + Input: { architecture: $architecture } + Output: architectureDiagram + +Step 12: badge-generator + Purpose: Generate README badges + Input: { + languages: $languages, + qualityMetrics: $qualityMetrics, + vulnerabilities: $vulnerabilities + } + Output: badges[] + +Step 13: readme-generator + Purpose: Generate comprehensive README + Input: { + repoData: $repoData, + architecture: $architecture, + apiDocs: $apiDocs, + badges: $badges + } + Output: readme + +Step 14: changelog-generator + Purpose: Generate CHANGELOG from commits + Input: { repoData: $repoData } + Output: changelog + +Step 15: documentation-packager + Purpose: Package all documentation + Input: { + readme: $readme, + apiDocs: $apiDocs, + functionDocs: $functionDocs, + securityReport: $securityReport, + changelog: $changelog, + diagrams: [$architectureDiagram] + } + Output: documentationPackage +``` + +### Example 3: E-commerce Product Launch (20 steps) + +**User Query:** "I'm launching a new product. Create product descriptions, generate images, write email campaigns, set up social media posts, and prepare a launch checklist" + +```yaml +Plan: Product Launch Pipeline +Steps: 20 +Estimated Duration: 10-15 minutes +Estimated Cost: $1.50 + +Step 1: product-info-parser + Purpose: Parse and structure product information + Input: { rawProductInfo: $userInput } + Output: structuredProduct + +Step 2: market-researcher + Purpose: Research target market and competitors + Input: { product: $structuredProduct } + Output: marketResearch + +Step 3: persona-generator + Purpose: Generate buyer personas + Input: { product: $structuredProduct, marketResearch: $marketResearch } + Output: buyerPersonas[] + +Step 4: unique-selling-points-extractor + Purpose: Identify unique selling points + Input: { product: $structuredProduct, marketResearch: $marketResearch } + Output: usps[] + +Step 5: product-description-writer + Purpose: Write main product description + Input: { product: $structuredProduct, usps: $usps, personas: $buyerPersonas } + Output: productDescription + +Step 6: short-description-writer (parallel group: descriptions) + Purpose: Write short product description + Input: { fullDescription: $productDescription } + Output: shortDescription + +Step 7: bullet-points-generator (parallel group: descriptions) + Purpose: Generate feature bullet points + Input: { product: $structuredProduct, usps: $usps } + Output: bulletPoints[] + +Step 8: seo-keywords-generator + Purpose: Generate SEO keywords + Input: { product: $structuredProduct, marketResearch: $marketResearch } + Output: seoKeywords[] + +Step 9: product-image-prompt-generator + Purpose: Generate prompts for product images + Input: { product: $structuredProduct, count: 5 } + Output: imagePrompts[] + +Step 10: product-image-generator + Purpose: Generate product images + Input: { prompts: $imagePrompts } + Output: productImages[] + +Step 11: email-sequence-planner + Purpose: Plan email marketing sequence + Input: { product: $structuredProduct, personas: $buyerPersonas } + Output: emailSequencePlan + +Step 12: welcome-email-writer (parallel group: emails) + Purpose: Write welcome/announcement email + Input: { plan: $emailSequencePlan, product: $structuredProduct } + Output: welcomeEmail + +Step 13: launch-email-writer (parallel group: emails) + Purpose: Write launch day email + Input: { plan: $emailSequencePlan, product: $structuredProduct, usps: $usps } + Output: launchEmail + +Step 14: followup-email-writer (parallel group: emails) + Purpose: Write follow-up email + Input: { plan: $emailSequencePlan, product: $structuredProduct } + Output: followupEmail + +Step 15: social-media-calendar-generator + Purpose: Generate social media posting calendar + Input: { product: $structuredProduct, launchDate: $userInput.launchDate } + Output: socialCalendar + +Step 16: instagram-posts-generator (parallel group: social) + Purpose: Generate Instagram post content + Input: { calendar: $socialCalendar, images: $productImages } + Output: instagramPosts[] + +Step 17: twitter-posts-generator (parallel group: social) + Purpose: Generate Twitter post content + Input: { calendar: $socialCalendar, product: $structuredProduct } + Output: twitterPosts[] + +Step 18: facebook-posts-generator (parallel group: social) + Purpose: Generate Facebook post content + Input: { calendar: $socialCalendar, product: $structuredProduct } + Output: facebookPosts[] + +Step 19: launch-checklist-generator + Purpose: Generate comprehensive launch checklist + Input: { + product: $structuredProduct, + emails: [$welcomeEmail, $launchEmail, $followupEmail], + socialPosts: { instagram: $instagramPosts, twitter: $twitterPosts, facebook: $facebookPosts } + } + Output: launchChecklist + +Step 20: launch-kit-assembler + Purpose: Assemble complete launch kit + Input: { + product: $structuredProduct, + descriptions: { full: $productDescription, short: $shortDescription, bullets: $bulletPoints }, + images: $productImages, + emails: { welcome: $welcomeEmail, launch: $launchEmail, followup: $followupEmail }, + social: { instagram: $instagramPosts, twitter: $twitterPosts, facebook: $facebookPosts }, + checklist: $launchChecklist, + seo: $seoKeywords + } + Output: launchKit +``` + +### Example 4: Data Pipeline (18 steps) + +**User Query:** "Pull data from our API, clean it, run analytics, generate visualizations, and create a PDF report" + +```yaml +Plan: Data Analytics Pipeline +Steps: 18 +Estimated Duration: 8-12 minutes +Estimated Cost: $0.90 + +Step 1: api-data-fetcher + Purpose: Fetch data from user's API + Input: { endpoint: $userInput.apiEndpoint, auth: $userInput.apiKey } + Output: rawData + +Step 2: data-validator + Purpose: Validate data structure and completeness + Input: { data: $rawData } + Output: validationReport + +Step 3: null-handler + Purpose: Handle missing values + Input: { data: $rawData, strategy: "smart-impute" } + Output: dataWithoutNulls + +Step 4: outlier-detector + Purpose: Detect and flag outliers + Input: { data: $dataWithoutNulls } + Output: outlierReport + +Step 5: data-normalizer + Purpose: Normalize numerical columns + Input: { data: $dataWithoutNulls } + Output: normalizedData + +Step 6: feature-engineer + Purpose: Create derived features + Input: { data: $normalizedData } + Output: enrichedData + +Step 7: descriptive-stats-calculator (parallel group: analytics) + Purpose: Calculate descriptive statistics + Input: { data: $enrichedData } + Output: descriptiveStats + +Step 8: correlation-analyzer (parallel group: analytics) + Purpose: Analyze correlations + Input: { data: $enrichedData } + Output: correlationMatrix + +Step 9: trend-analyzer (parallel group: analytics) + Purpose: Identify trends over time + Input: { data: $enrichedData, timeColumn: $userInput.timeColumn } + Output: trendAnalysis + +Step 10: segmentation-analyzer (parallel group: analytics) + Purpose: Perform customer/data segmentation + Input: { data: $enrichedData } + Output: segments + +Step 11: summary-chart-generator (parallel group: viz) + Purpose: Generate summary charts + Input: { stats: $descriptiveStats } + Output: summaryCharts[] + +Step 12: correlation-heatmap-generator (parallel group: viz) + Purpose: Generate correlation heatmap + Input: { matrix: $correlationMatrix } + Output: correlationHeatmap + +Step 13: trend-chart-generator (parallel group: viz) + Purpose: Generate trend visualizations + Input: { trends: $trendAnalysis } + Output: trendCharts[] + +Step 14: segment-chart-generator (parallel group: viz) + Purpose: Generate segmentation visualizations + Input: { segments: $segments } + Output: segmentCharts[] + +Step 15: insight-generator + Purpose: Generate key insights from analysis + Input: { + stats: $descriptiveStats, + correlations: $correlationMatrix, + trends: $trendAnalysis, + segments: $segments + } + Output: insights[] + +Step 16: executive-summary-writer + Purpose: Write executive summary + Input: { insights: $insights, validationReport: $validationReport } + Output: executiveSummary + +Step 17: report-compiler + Purpose: Compile full report content + Input: { + summary: $executiveSummary, + stats: $descriptiveStats, + insights: $insights, + outliers: $outlierReport + } + Output: reportContent + +Step 18: pdf-generator + Purpose: Generate final PDF report + Input: { + content: $reportContent, + charts: [...$summaryCharts, $correlationHeatmap, ...$trendCharts, ...$segmentCharts], + template: "analytics-report" + } + Output: pdfReport +``` + +### Example 5: Website Audit (22 steps) + +**User Query:** "Perform a complete audit of my website including SEO, performance, accessibility, and security, then generate a prioritized action plan" + +```yaml +Plan: Comprehensive Website Audit +Steps: 22 +Estimated Duration: 15-20 minutes +Estimated Cost: $2.00 + +# Discovery Phase +Step 1: sitemap-discoverer + Purpose: Discover all pages on the website + Input: { url: $userInput.websiteUrl } + Output: sitemap + +Step 2: page-fetcher + Purpose: Fetch all pages for analysis + Input: { sitemap: $sitemap, maxPages: 50 } + Output: pages[] + +# SEO Analysis (parallel group: seo) +Step 3: meta-tag-analyzer + Purpose: Analyze meta tags across all pages + Input: { pages: $pages } + Output: metaTagReport + +Step 4: heading-structure-analyzer + Purpose: Analyze heading hierarchy + Input: { pages: $pages } + Output: headingReport + +Step 5: internal-link-analyzer + Purpose: Analyze internal linking structure + Input: { pages: $pages, sitemap: $sitemap } + Output: internalLinkReport + +Step 6: keyword-density-analyzer + Purpose: Analyze keyword usage + Input: { pages: $pages } + Output: keywordReport + +Step 7: schema-markup-checker + Purpose: Check structured data markup + Input: { pages: $pages } + Output: schemaReport + +# Performance Analysis (parallel group: performance) +Step 8: page-speed-analyzer + Purpose: Analyze page load speeds + Input: { pages: $pages } + Output: speedReport + +Step 9: asset-analyzer + Purpose: Analyze images, scripts, stylesheets + Input: { pages: $pages } + Output: assetReport + +Step 10: core-web-vitals-checker + Purpose: Check Core Web Vitals metrics + Input: { pages: $pages } + Output: webVitalsReport + +# Accessibility Analysis (parallel group: accessibility) +Step 11: wcag-checker + Purpose: Check WCAG compliance + Input: { pages: $pages } + Output: wcagReport + +Step 12: color-contrast-checker + Purpose: Check color contrast ratios + Input: { pages: $pages } + Output: contrastReport + +Step 13: alt-text-checker + Purpose: Check image alt text + Input: { pages: $pages } + Output: altTextReport + +Step 14: keyboard-nav-checker + Purpose: Check keyboard navigation + Input: { pages: $pages } + Output: keyboardReport + +# Security Analysis (parallel group: security) +Step 15: ssl-checker + Purpose: Check SSL/TLS configuration + Input: { url: $userInput.websiteUrl } + Output: sslReport + +Step 16: header-security-checker + Purpose: Check security headers + Input: { pages: $pages } + Output: securityHeadersReport + +Step 17: vulnerability-scanner + Purpose: Scan for common vulnerabilities + Input: { url: $userInput.websiteUrl } + Output: vulnerabilityReport + +# Report Generation +Step 18: seo-score-calculator + Purpose: Calculate overall SEO score + Input: { reports: [$metaTagReport, $headingReport, $internalLinkReport, $keywordReport, $schemaReport] } + Output: seoScore + +Step 19: performance-score-calculator + Purpose: Calculate overall performance score + Input: { reports: [$speedReport, $assetReport, $webVitalsReport] } + Output: performanceScore + +Step 20: accessibility-score-calculator + Purpose: Calculate overall accessibility score + Input: { reports: [$wcagReport, $contrastReport, $altTextReport, $keyboardReport] } + Output: accessibilityScore + +Step 21: action-plan-generator + Purpose: Generate prioritized action plan + Input: { + seo: { score: $seoScore, reports: [$metaTagReport, $headingReport, $internalLinkReport, $keywordReport, $schemaReport] }, + performance: { score: $performanceScore, reports: [$speedReport, $assetReport, $webVitalsReport] }, + accessibility: { score: $accessibilityScore, reports: [$wcagReport, $contrastReport, $altTextReport, $keyboardReport] }, + security: { reports: [$sslReport, $securityHeadersReport, $vulnerabilityReport] } + } + Output: actionPlan + +Step 22: audit-report-generator + Purpose: Generate comprehensive audit PDF + Input: { + sitemap: $sitemap, + scores: { seo: $seoScore, performance: $performanceScore, accessibility: $accessibilityScore }, + actionPlan: $actionPlan, + allReports: [...] + } + Output: auditReport +``` + +--- + +## Tool Discovery & Selection + +### Discovery Strategies + +#### 1. Semantic Search + +Match user intent to tool descriptions using embeddings: + +```typescript +interface SemanticSearchResult { + tool: Tool; + similarity: number; + matchedOn: "description" | "useCase" | "examples"; +} + +async function semanticToolSearch( + capability: string +): Promise { + const embedding = await embed(capability); + + const results = await vectorStore.search({ + vector: embedding, + topK: 10, + filter: { healthStatus: "HEALTHY" } + }); + + return results.map(r => ({ + tool: r.metadata.tool, + similarity: r.score, + matchedOn: r.metadata.matchField + })); +} +``` + +#### 2. Category-Based Search + +Navigate the tool taxonomy: + +```typescript +const categories = { + "web-scraping": ["web-scraper", "puppeteer", "playwright", "cheerio"], + "text-processing": ["markdown-converter", "text-cleaner", "summarizer"], + "data-transformation": ["json-transformer", "csv-parser", "data-merger"], + "image-generation": ["dalle", "midjourney", "stable-diffusion"], + "file-generation": ["pdf-generator", "xlsx-creator", "docx-writer"] +}; +``` + +#### 3. Capability Mapping + +Map abstract capabilities to concrete tools: + +```typescript +const capabilityMap = { + "fetch-webpage": { + primary: "web-scraper", + alternatives: ["puppeteer-scraper", "playwright-fetch"], + fallback: "http-fetcher" + }, + "extract-text": { + primary: "html-to-markdown", + alternatives: ["readability", "mozilla-readability"], + fallback: "html-strip" + }, + "generate-image": { + primary: "dalle-3", + alternatives: ["stable-diffusion", "midjourney-api"], + fallback: "placeholder-image" + } +}; +``` + +### Selection Criteria + +```typescript +interface SelectionCriteria { + // Quality metrics + healthStatus: "HEALTHY"; + qualityScore: { min: 0.7 }; + + // Reliability metrics + successRate: { min: 0.95 }; + avgExecutionTime: { max: 5000 }; + + // Cost metrics + estimatedTokens: { max: 1000 }; + + // Compatibility + inputType: string; + outputType: string; +} + +function selectBestTool( + capability: string, + criteria: SelectionCriteria, + context: ExecutionContext +): Tool { + const candidates = findToolsForCapability(capability); + + return candidates + .filter(t => t.healthStatus === criteria.healthStatus) + .filter(t => t.qualityScore >= criteria.qualityScore.min) + .filter(t => isCompatible(t, context)) + .sort((a, b) => scoreTool(b, criteria) - scoreTools(a, criteria)) + [0]; +} +``` + +--- + +## Context & State Management + +### Context Structure + +```typescript +interface ExecutionContext { + // Original request + query: string; + entities: Entity[]; + + // Accumulated state + variables: Map; + + // Execution history + completedSteps: StepResult[]; + currentStep: string | null; + + // Error tracking + errors: StepError[]; + retryCount: Map; + + // Performance tracking + startTime: number; + stepTimings: Map; + tokenUsage: TokenUsage; +} +``` + +### State Transitions + +``` +┌──────────┐ +│ INIT │ +└────┬─────┘ + │ loadPlan() + ▼ +┌──────────┐ +│ PLANNING │ +└────┬─────┘ + │ validatePlan() + ▼ +┌──────────┐ error +│ RUNNING │─────────────┐ +└────┬─────┘ │ + │ ▼ + │ ┌──────────┐ + │ │ RETRYING │ + │ └────┬─────┘ + │ │ + │ ◄────────────┘ + │ allStepsComplete() + ▼ +┌──────────┐ +│ COMPLETE │ +└──────────┘ +``` + +### Variable Scoping + +```typescript +// Global scope - available to all steps +context.global.set("originalQuery", query); +context.global.set("entities", entities); + +// Step scope - output of each step +context.step.set("step_1.output", result1); +context.step.set("step_2.output", result2); + +// Computed scope - derived values +context.computed.set("combinedResults", merge(result1, result2)); +``` + +### Data Flow Between Steps + +```typescript +// Reference previous step output +{ + input: { + fromStep: { + stepId: "step_1", + path: "$.data.items[*].name" // JSONPath + } + } +} + +// Reference multiple steps +{ + input: { + fromSteps: [ + { stepId: "step_1", path: "$.prices", as: "prices" }, + { stepId: "step_2", path: "$.names", as: "names" } + ] + } +} + +// Computed input +{ + input: { + computed: { + expression: "merge($step_1.output, $step_2.output)", + dependencies: ["step_1", "step_2"] + } + } +} +``` + +--- + +## Error Handling & Recovery + +### Error Types + +```typescript +type ExecutionError = + | { type: "TOOL_NOT_FOUND"; toolName: string } + | { type: "TOOL_UNHEALTHY"; toolName: string; status: string } + | { type: "INPUT_VALIDATION"; stepId: string; errors: ValidationError[] } + | { type: "EXECUTION_TIMEOUT"; stepId: string; timeout: number } + | { type: "EXECUTION_FAILED"; stepId: string; error: string } + | { type: "OUTPUT_VALIDATION"; stepId: string; expected: string; received: string } + | { type: "DEPENDENCY_FAILED"; stepId: string; dependencyId: string }; +``` + +### Recovery Strategies + +#### 1. Retry with Backoff + +```typescript +async function executeWithRetry( + step: ExecutionStep, + context: ExecutionContext +): Promise { + const maxRetries = step.execution.retries; + let lastError: Error; + + for (let attempt = 0; attempt <= maxRetries; attempt++) { + try { + return await executeStep(step, context); + } catch (error) { + lastError = error; + + if (attempt < maxRetries) { + const delay = Math.pow(2, attempt) * 1000; + await sleep(delay); + } + } + } + + throw lastError; +} +``` + +#### 2. Fallback Tools + +```typescript +async function executeWithFallback( + step: ExecutionStep, + context: ExecutionContext +): Promise { + const tools = [ + step.tool, + ...(step.execution.fallbackTools ?? []) + ]; + + for (const tool of tools) { + try { + const modifiedStep = { ...step, tool }; + return await executeStep(modifiedStep, context); + } catch (error) { + console.log(`Tool ${tool.exportName} failed, trying fallback...`); + } + } + + throw new Error(`All tools failed for step ${step.id}`); +} +``` + +#### 3. Skip and Continue + +```typescript +async function executeWithSkip( + step: ExecutionStep, + context: ExecutionContext +): Promise { + try { + return await executeStep(step, context); + } catch (error) { + if (step.execution.canSkipOnError) { + context.errors.push({ + stepId: step.id, + error: error.message, + skipped: true + }); + return null; + } + throw error; + } +} +``` + +#### 4. Dynamic Re-planning + +```typescript +async function executeWithReplanning( + plan: ExecutionPlan, + context: ExecutionContext, + failedStepId: string +): Promise { + // Generate alternative plan for remaining steps + const remainingSteps = plan.steps.filter( + s => !context.completedSteps.includes(s.id) + ); + + const alternativePlan = await generateAlternativePlan( + context.query, + remainingSteps, + context.errors + ); + + return executeParallel(alternativePlan); +} +``` + +--- + +## Optimization Techniques + +### 1. Plan Caching + +Cache generated plans for similar queries: + +```typescript +const planCache = new LRUCache({ + max: 1000, + ttl: 1000 * 60 * 60 // 1 hour +}); + +function getCachedPlan(query: string): ExecutionPlan | null { + const normalizedQuery = normalize(query); + const cacheKey = hash(normalizedQuery); + return planCache.get(cacheKey); +} +``` + +### 2. Tool Preloading + +Preload tools that are likely to be needed: + +```typescript +async function preloadTools(plan: ExecutionPlan): Promise { + const toolNames = plan.steps.map(s => s.tool.packageName); + + await Promise.all( + toolNames.map(name => warmupTool(name)) + ); +} +``` + +### 3. Parallel Maximization + +Identify and execute independent steps in parallel: + +```typescript +function findParallelGroups( + steps: ExecutionStep[] +): ExecutionStep[][] { + const groups: ExecutionStep[][] = []; + const completed = new Set(); + + while (completed.size < steps.length) { + const ready = steps.filter(s => + !completed.has(s.id) && + s.dependsOn.every(d => completed.has(d)) + ); + + if (ready.length === 0) break; + + groups.push(ready); + ready.forEach(s => completed.add(s.id)); + } + + return groups; +} +``` + +### 4. Result Streaming + +Stream partial results as they become available: + +```typescript +async function* streamResults( + plan: ExecutionPlan +): AsyncGenerator { + const context = new ExecutionContext(); + + for (const step of plan.steps) { + yield { type: "step_started", stepId: step.id }; + + const result = await executeStep(step, context); + + yield { + type: "step_completed", + stepId: step.id, + preview: summarize(result) + }; + } +} +``` + +### 5. Cost Optimization + +Minimize token usage by selecting efficient tools: + +```typescript +function optimizeForCost( + plan: ExecutionPlan +): ExecutionPlan { + return { + ...plan, + steps: plan.steps.map(step => { + const alternatives = findAlternativeTools(step.tool); + const cheapest = alternatives.sort( + (a, b) => estimateCost(a) - estimateCost(b) + )[0]; + + return { ...step, tool: cheapest }; + }) + }; +} +``` + +--- + +## Security Considerations + +### 1. Input Sanitization + +```typescript +function sanitizeInput(input: unknown, schema: JSONSchema): unknown { + // Remove potentially dangerous fields + if (typeof input === 'object' && input !== null) { + const sanitized = { ...input }; + delete sanitized.__proto__; + delete sanitized.constructor; + return sanitized; + } + + // Validate against schema + const validated = schema.parse(input); + return validated; +} +``` + +### 2. Output Validation + +```typescript +function validateOutput( + output: unknown, + expectedType: string +): boolean { + // Ensure output matches expected type + // Prevent data exfiltration + // Sanitize any HTML/scripts +} +``` + +### 3. Rate Limiting + +```typescript +const rateLimiter = { + perIp: { limit: 100, window: "1h" }, + perPlan: { limit: 50, window: "1h" }, + perTool: { limit: 20, window: "1m" } +}; +``` + +### 4. Sandboxed Execution + +All tools run in isolated sandboxes with: +- Limited memory +- Limited CPU time +- No filesystem access (except temp) +- No network access (except whitelisted) +- No environment variable access + +### 5. Audit Logging + +```typescript +interface AuditLog { + timestamp: string; + userId: string; + planId: string; + steps: { + stepId: string; + tool: string; + input: Record; // Redacted + output: Record; // Redacted + duration: number; + }[]; +} +``` + +--- + +## Implementation Roadmap + +### Phase 1: Foundation (Current) + +- [x] Tool registry with dynamic loading +- [x] Single tool execution with AI agent +- [x] Health checking and validation +- [x] Rate limiting and abuse prevention + +### Phase 2: Multi-Tool Execution + +- [ ] Sequential multi-tool execution +- [ ] Context passing between tools +- [ ] Basic error handling with retries +- [ ] Execution logging and monitoring + +### Phase 3: Plan Generation + +- [ ] Query analysis and intent extraction +- [ ] Capability-to-tool mapping +- [ ] Single plan generation (X steps) +- [ ] Plan validation and optimization + +### Phase 4: Multiple Plans (Y×X) + +- [ ] Multiple plan generation (Y alternatives) +- [ ] Plan comparison and scoring +- [ ] User plan selection UI +- [ ] Auto-selection based on criteria + +### Phase 5: Advanced Orchestration + +- [ ] Parallel execution with DAG +- [ ] Fallback tool selection +- [ ] Dynamic re-planning on failure +- [ ] Checkpoint and resume + +### Phase 6: Enterprise Features + +- [ ] Plan caching and reuse +- [ ] Custom tool composition +- [ ] Team-shared workflows +- [ ] Analytics and optimization recommendations + +--- + +## Appendix A: Query Complexity Scoring + +```typescript +function calculateComplexity(query: string): number { + let score = 0; + + // Count action verbs + const actions = query.match(/\b(create|generate|analyze|extract|convert|compare|merge|transform)\b/gi); + score += (actions?.length ?? 0) * 2; + + // Count conjunctions indicating multiple tasks + const conjunctions = query.match(/\b(and|then|also|plus|after|before)\b/gi); + score += (conjunctions?.length ?? 0) * 1.5; + + // Count output format requests + const formats = query.match(/\b(pdf|excel|csv|json|markdown|html|image|chart|graph)\b/gi); + score += (formats?.length ?? 0) * 1; + + // Count data sources + const sources = query.match(/\b(from|using|based on|via|through)\b/gi); + score += (sources?.length ?? 0) * 1; + + return Math.min(10, score); +} +``` + +--- + +## Appendix B: Tool Compatibility Matrix + +``` +┌─────────────────┬─────────┬─────────┬─────────┬─────────┐ +│ Output Type │ string │ object │ array │ buffer │ +├─────────────────┼─────────┼─────────┼─────────┼─────────┤ +│ string input │ ✓ │ △ │ △ │ ✗ │ +│ object input │ △ │ ✓ │ △ │ ✗ │ +│ array input │ △ │ △ │ ✓ │ ✗ │ +│ buffer input │ ✗ │ ✗ │ ✗ │ ✓ │ +└─────────────────┴─────────┴─────────┴─────────┴─────────┘ + +✓ = Direct compatibility +△ = Requires transformation +✗ = Incompatible +``` + +--- + +## Appendix C: Cost Estimation Formula + +```typescript +function estimatePlanCost(plan: ExecutionPlan): number { + const BASE_COST_PER_STEP = 0.001; // $0.001 per step + const TOKEN_COST = 0.00003; // $0.00003 per token + + return plan.steps.reduce((total, step) => { + const stepCost = BASE_COST_PER_STEP; + const inputTokens = estimateInputTokens(step); + const outputTokens = estimateOutputTokens(step); + const tokenCost = (inputTokens + outputTokens) * TOKEN_COST; + + return total + stepCost + tokenCost; + }, 0); +} +``` + +--- + +## Conclusion + +Dynamic multi-tool orchestration transforms TPMJS from a tool registry into an intelligent workflow engine. By generating Y alternative plans with X sequential steps, we can solve arbitrarily complex tasks while giving users choice and transparency. + +The key innovations are: + +1. **Dynamic Discovery**: Tools are loaded at runtime, not build time +2. **Intelligent Planning**: AI generates optimal execution plans +3. **Flexible Execution**: Sequential, parallel, or streaming execution +4. **Robust Recovery**: Fallbacks, retries, and re-planning on failure +5. **Cost Optimization**: Smart tool selection minimizes token usage + +This architecture scales from simple single-tool queries to complex 20+ step enterprise workflows, all using the same underlying primitives. diff --git a/docs/HIERARCHICAL_CONTEXT_LOADING.md b/docs/HIERARCHICAL_CONTEXT_LOADING.md new file mode 100644 index 0000000..2c5fe51 --- /dev/null +++ b/docs/HIERARCHICAL_CONTEXT_LOADING.md @@ -0,0 +1,739 @@ +# Hierarchical Cascading Tree: Tool & Context Loading + +A pattern for any agent chat interface where tool plans are generated speculatively, +skills/context are inferred backwards from those plans, and execution proceeds with +minimal context at each step. + +--- + +## The Core Insight + +Traditional agent flow: +``` +User Query → Load ALL tools → Model picks tools → Execute + ↑ + (huge context) +``` + +Hierarchical cascading flow: +``` +User Query → Generate Y Plans → Infer Skills from Plans → Load minimal context per step + ↑ + (context derived from likely tools) +``` + +**Key idea**: The tool plans themselves tell you what context/skills the agent needs. +You don't load everything—you load what the plan reveals is relevant. + +--- + +## Real World Example: Website Audit + +**User Query**: +> "Perform a complete audit of my website including SEO, performance, accessibility, +> and security, then generate a prioritized action plan" + +### Step 1: Generate Y Plans (speculatively, in parallel) + +The system generates 3 alternative plans before any execution: + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ PLAN GENERATION │ +│ │ +│ User Query: "audit my website..." │ +│ │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ PLAN A │ │ PLAN B │ │ PLAN C │ │ +│ │ (thorough) │ │ (quick) │ │ (balanced) │ │ +│ │ 22 steps │ │ 8 steps │ │ 14 steps │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────────┘ +``` + +### Step 2: Analyze Plans → Infer Required Domains + +Look at ALL tools across ALL plans to identify skill domains: + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ DOMAIN INFERENCE FROM PLANS │ +│ │ +│ Plan A Tools: Plan B Tools: Plan C Tools: │ +│ ───────────── ───────────── ───────────── │ +│ sitemap-discoverer lighthouse-runner sitemap-discoverer │ +│ page-fetcher security-scanner lighthouse-runner │ +│ meta-tag-analyzer report-generator wcag-checker │ +│ heading-structure-analyzer ssl-checker │ +│ internal-link-analyzer action-plan-generator │ +│ keyword-density-analyzer report-generator │ +│ schema-markup-checker │ +│ page-speed-analyzer │ +│ asset-analyzer │ +│ core-web-vitals-checker │ +│ wcag-checker │ +│ color-contrast-checker │ +│ alt-text-checker │ +│ keyboard-nav-checker │ +│ ssl-checker │ +│ header-security-checker │ +│ vulnerability-scanner │ +│ ... │ +│ │ +│ ↓ CLUSTER BY DOMAIN ↓ │ +│ │ +│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ +│ │ SEO │ │ PERFORMANCE │ │ACCESSIBILITY│ │ SECURITY │ │ +│ │ domain │ │ domain │ │ domain │ │ domain │ │ +│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────────┘ +``` + +### Step 3: Load Domain-Specific Context (Skills) + +Each domain has associated contextual knowledge: + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ SKILL/CONTEXT LOADING │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────────┐ │ +│ │ SEO SKILL CONTEXT │ │ +│ │ ─────────────────── │ │ +│ │ • Meta tag best practices (title 50-60 chars, desc 150-160) │ │ +│ │ • Heading hierarchy rules (single H1, logical nesting) │ │ +│ │ • Internal linking patterns (hub & spoke, silo structure) │ │ +│ │ • Schema.org markup types and validation │ │ +│ │ • Core Web Vitals thresholds (LCP < 2.5s, FID < 100ms, CLS < 0.1) │ │ +│ └─────────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────────┐ │ +│ │ ACCESSIBILITY SKILL CONTEXT │ │ +│ │ ─────────────────────────── │ │ +│ │ • WCAG 2.1 AA requirements checklist │ │ +│ │ • Color contrast ratios (4.5:1 normal, 3:1 large text) │ │ +│ │ • ARIA roles and proper usage patterns │ │ +│ │ • Keyboard navigation requirements │ │ +│ │ • Screen reader compatibility guidelines │ │ +│ └─────────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────────┐ │ +│ │ SECURITY SKILL CONTEXT │ │ +│ │ ────────────────────── │ │ +│ │ • Security header requirements (CSP, HSTS, X-Frame-Options) │ │ +│ │ • SSL/TLS configuration best practices │ │ +│ │ • OWASP Top 10 vulnerability patterns │ │ +│ │ • Cookie security attributes (Secure, HttpOnly, SameSite) │ │ +│ └─────────────────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────────┘ +``` + +### Step 4: The Cascading Tree During Execution + +Now execution proceeds. At each step, only load: +1. The current tool +2. Context relevant to that tool's domain +3. The likely next 1-2 tools + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ HIERARCHICAL CASCADING EXECUTION │ +│ │ +│ Time ─────────────────────────────────────────────────────────────────────► │ +│ │ +│ STEP 1: Discovery │ +│ ┌────────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ LOADED IN CONTEXT: │ │ +│ │ ┌─────────────────┐ │ │ +│ │ │ sitemap- │ ← Current tool │ │ +│ │ │ discoverer │ │ │ +│ │ └────────┬────────┘ │ │ +│ │ │ │ │ +│ │ │ likely next │ │ +│ │ ▼ │ │ +│ │ ┌─────────────────┐ │ │ +│ │ │ page-fetcher │ ← Preloaded (90% likely) │ │ +│ │ └─────────────────┘ │ │ +│ │ │ │ +│ │ Context: [web-crawling basics, robots.txt rules] │ │ +│ │ Tokens: ~800 │ │ +│ │ │ │ +│ └────────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ ↓ output: sitemap with 47 pages │ +│ │ +│ STEP 2: Fetch Pages │ +│ ┌────────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ LOADED IN CONTEXT: │ │ +│ │ ┌─────────────────┐ │ │ +│ │ │ page-fetcher │ ← Current tool │ │ +│ │ └────────┬────────┘ │ │ +│ │ │ │ │ +│ │ ┌──────┴──────┐ likely next (fan out to parallel) │ │ +│ │ ▼ ▼ │ │ +│ │ ┌─────┐ ┌─────────────┐ │ │ +│ │ │ SEO │ │ PERFORMANCE │ ← Domain branches preloaded │ │ +│ │ │tools│ │ tools │ │ │ +│ │ └─────┘ └─────────────┘ │ │ +│ │ │ │ +│ │ Context: [HTTP fetching, rate limiting, caching headers] │ │ +│ │ Tokens: ~600 │ │ +│ │ │ │ +│ └────────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ ↓ output: 47 page objects │ +│ │ +│ STEP 3-7: SEO Analysis (parallel group) │ +│ ┌────────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ LOADED IN CONTEXT: │ │ +│ │ │ │ +│ │ ┌─────────────┬─────────────┬─────────────┬─────────────┐ │ │ +│ │ │ meta-tag │ heading │ internal │ schema │ │ │ +│ │ │ analyzer │ analyzer │ link │ checker │ │ │ +│ │ │ │ │ analyzer │ │ │ │ +│ │ └─────────────┴─────────────┴─────────────┴─────────────┘ │ │ +│ │ │ │ │ │ │ │ +│ │ └─────────────┴──────┬──────┴─────────────┘ │ │ +│ │ ▼ │ │ +│ │ ┌─────────────────┐ │ │ +│ │ │ seo-score-calc │ ← Convergence point │ │ +│ │ └─────────────────┘ │ │ +│ │ │ │ +│ │ Context: [SEO SKILL - full domain context loaded] │ │ +│ │ Tokens: ~2,400 │ │ +│ │ │ │ +│ └────────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ ... similar parallel groups for PERFORMANCE, ACCESSIBILITY, SECURITY ... │ +│ │ +│ FINAL STEP: Report Generation │ +│ ┌────────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ LOADED IN CONTEXT: │ │ +│ │ │ │ +│ │ ┌───────────────────────┐ │ │ +│ │ │ action-plan-generator │ ← Current tool │ │ +│ │ └───────────┬───────────┘ │ │ +│ │ │ │ │ +│ │ ▼ │ │ +│ │ ┌───────────────────────┐ │ │ +│ │ │ audit-report-generator│ ← Final tool │ │ +│ │ └───────────────────────┘ │ │ +│ │ │ │ +│ │ Context: [report writing, prioritization frameworks, all scores] │ │ +│ │ Tokens: ~1,800 │ │ +│ │ │ │ +│ └────────────────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## The Full Tree Visualization + +Here's the complete hierarchical tree for the website audit: + +``` + USER QUERY + │ + │ "audit my website..." + │ + ┌───────────────────┼───────────────────┐ + │ │ │ + ▼ ▼ ▼ + ┌─────────┐ ┌─────────┐ ┌─────────┐ + │ PLAN A │ │ PLAN B │ │ PLAN C │ + │thorough │ │ quick │ │balanced │ + └────┬────┘ └────┬────┘ └────┬────┘ + │ │ │ + │ │ │ + ┌─────────┴─────────┐ │ ┌────────┴────────┐ + │ │ │ │ │ + ▼ ▼ ▼ ▼ ▼ + ┌─────────┐ ┌─────────┐ (...) ┌─────────┐ ┌─────────┐ + │ SKILL │ │ SKILL │ │ SKILL │ │ SKILL │ + │ SEO │ │SECURITY │ │ PERF │ │ A11Y │ + └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ + │ │ │ │ + │ context │ context │ context │ context + │ docs │ docs │ docs │ docs + ▼ ▼ ▼ ▼ + ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ + │meta-tag │ │ssl-check│ │lighthouse│ │wcag- │ + │heading │ │headers │ │webvitals│ │contrast │ + │links │ │vulns │ │assets │ │alt-text │ + │schema │ │... │ │... │ │keyboard │ + └─────────┘ └─────────┘ └─────────┘ └─────────┘ + + + +DETAIL: Cascading through SEO branch +═══════════════════════════════════════════════════════════════════════════════ + +Step 1 Step 2 Step 3 (parallel) +───────────────────────────────────────────────────────────────────────────── + + ┌──────────────┐ + │ sitemap- │ + │ discoverer │◄─── ACTIVE + └──────┬───────┘ + │ + │ preload likely next + ▼ + ┌──────────────┐ ┌──────────────┐ + │ page- │ │ page- │ + │ fetcher │───────►│ fetcher │◄─── ACTIVE + └──────────────┘ └──────┬───────┘ + (shadowed) │ + │ preload domain tools + ▼ + ┌──────────────┐ + │ SEO tools │ + │ (grouped) │───────────────┐ + └──────────────┘ │ + (shadowed) │ + ▼ + ┌─────────────────────────┐ + │ │ + │ ┌──────────────┐ │ + │ │ meta-tag │◄── │ + │ │ analyzer │ │ │ + │ └──────────────┘ │ │ + │ │ │ + │ ┌──────────────┐ │ │ + │ │ heading │◄─┤ │ + │ │ analyzer │ │ │ + │ └──────────────┘ ├───┼── ALL ACTIVE + │ │ │ (parallel) + │ ┌──────────────┐ │ │ + │ │ link │◄─┤ │ + │ │ analyzer │ │ │ + │ └──────────────┘ │ │ + │ │ │ + │ ┌──────────────┐ │ │ + │ │ schema │◄── │ + │ │ checker │ │ + │ └──────────────┘ │ + │ │ + │ + SEO SKILL CONTEXT │ + │ loaded for all │ + │ │ + └─────────────────────────┘ + + +CONTEXT SIZE AT EACH STEP +═══════════════════════════════════════════════════════════════════════════════ + +Traditional approach (load everything): +┌─────────────────────────────────────────────────────────────────────────────┐ +│ █████████████████████████████████████████████████████████████████████████ │ +│ ALL 22 tools + ALL skill docs = ~45,000 tokens │ +└─────────────────────────────────────────────────────────────────────────────┘ + +Hierarchical cascading approach: +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ Step 1: ██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ~800 tokens │ +│ Step 2: ██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ~600 tokens │ +│ Step 3: █████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ~2,400 tokens │ +│ Step 4: ████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ~2,100 tokens │ +│ Step 5: ███████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ~1,900 tokens │ +│ Step 6: ██████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ~1,600 tokens │ +│ Final: ██████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ~1,800 tokens │ +│ │ +│ Average per step: ~1,600 tokens (96% reduction from loading everything) │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## The Algorithm + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ 1. PLAN GENERATION PHASE │ +│ ───────────────────── │ +│ │ +│ Input: User query │ +│ Output: Y candidate plans │ +│ │ +│ ┌─────────────┐ │ +│ │ Query │ │ +│ │ Analyzer │──────► Extract intent, entities, constraints │ +│ └──────┬──────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────┐ │ +│ │ Tool │ │ +│ │ Searcher │──────► Find candidate tools (semantic + keyword) │ +│ └──────┬──────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────┐ │ +│ │ Plan │ │ +│ │ Generator │──────► Generate Y distinct plans │ +│ └─────────────┘ │ +│ │ +│ │ +│ 2. SKILL INFERENCE PHASE │ +│ ────────────────────── │ +│ │ +│ Input: Y plans │ +│ Output: Skill domains + contextual docs │ +│ │ +│ ┌─────────────┐ │ +│ │ Tool │ │ +│ │ Clusterer │──────► Group tools by domain/category │ +│ └──────┬──────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────┐ │ +│ │ Skill │ │ +│ │ Mapper │──────► Map domains → skill documents │ +│ └──────┬──────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────┐ │ +│ │ Context │ │ +│ │ Loader │──────► Fetch relevant docs, examples, constraints │ +│ └─────────────┘ │ +│ │ +│ │ +│ 3. EXECUTION PHASE (cascading) │ +│ ─────────────────────────── │ +│ │ +│ For each step: │ +│ │ +│ ┌─────────────┐ │ +│ │ Probability │ │ +│ │ Calculator │──────► Calculate P(next_tool) for all candidates │ +│ └──────┬──────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────┐ │ +│ │ Context │ │ +│ │ Assembler │──────► current_tool + top_k likely + domain_context │ +│ └──────┬──────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────┐ │ +│ │ Executor │──────► Run tool, capture output │ +│ └──────┬──────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────┐ │ +│ │ State │ │ +│ │ Updater │──────► Update context, prune unlikely branches │ +│ └─────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Probability-Based Preloading + +At each step, calculate which tools are most likely needed next: + +``` + CURRENT STATE + │ + │ completed: [step_1, step_2] + │ current: step_3 + │ + ▼ + ┌────────────────────────────────────┐ + │ NEXT TOOL PROBABILITIES │ + │ │ + │ Based on: │ + │ • Plan structure (what's next) │ + │ • Current output type │ + │ • Historical patterns │ + │ • User's stated goals │ + │ │ + │ ┌──────────────────────────────┐ │ + │ │ seo-score-calc P=0.92 │──┼──► PRELOAD + │ │ accessibility-check P=0.85 │──┼──► PRELOAD + │ │ perf-score-calc P=0.78 │──┼──► PRELOAD + │ │ security-scanner P=0.45 │ │ + │ │ other-tool P=0.12 │ │ + │ │ ... │ │ + │ └──────────────────────────────┘ │ + │ │ + │ Threshold: P > 0.70 → preload │ + │ │ + └────────────────────────────────────┘ +``` + +--- + +## The User Choice Interface + +When Y plans are generated, present them to the user: + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ Your request: "Audit my website for SEO, performance, and security" │ +│ │ +│ I've generated 3 approaches: │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ ◉ PLAN A: Comprehensive Audit [SELECT] │ │ +│ │ │ │ +│ │ 22 steps • ~15 min • $2.00 estimated │ │ +│ │ │ │ +│ │ Covers: SEO (7), Performance (3), Accessibility (4), Security (3)│ │ +│ │ Plus: Scoring, prioritization, PDF report │ │ +│ │ │ │ +│ │ Skills loaded: SEO best practices, WCAG 2.1, Security headers, │ │ +│ │ Core Web Vitals, Schema.org markup │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ ○ PLAN B: Quick Scan [SELECT] │ │ +│ │ │ │ +│ │ 8 steps • ~3 min • $0.40 estimated │ │ +│ │ │ │ +│ │ Covers: Lighthouse audit, basic security scan │ │ +│ │ Output: Summary scores only │ │ +│ │ │ │ +│ │ Skills loaded: Lighthouse interpretation, SSL basics │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ ○ PLAN C: Balanced Review [SELECT] │ │ +│ │ │ │ +│ │ 14 steps • ~8 min • $1.20 estimated │ │ +│ │ │ │ +│ │ Covers: Key checks from each domain │ │ +│ │ Output: Prioritized action items │ │ +│ │ │ │ +│ │ Skills loaded: SEO essentials, A11y critical, Security must-haves│ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ │ +│ Or: [Let AI decide based on your site] [Customize plan] [Cancel] │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Adaptive Execution: Plan as Guide, Not Law + +Once skills are loaded from the plan, execution can be: + +### Mode 1: Strict Plan Following +``` +Plan Step 1 → Execute Tool A → Plan Step 2 → Execute Tool B → ... + +The plan is the law. Execute exactly as specified. +``` + +### Mode 2: Plan-Guided Free Execution +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ Plan provides: │ +│ • Which tools are available (pre-approved set) │ +│ • What context/skills are loaded │ +│ • Rough ordering guidance │ +│ │ +│ Model decides: │ +│ • Exact tool call order │ +│ • Whether to skip steps │ +│ • Whether to repeat steps │ +│ • Parameter values │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ Agent has access to: │ │ +│ │ │ │ +│ │ TOOLS (from plan): SKILLS (from plan): │ │ +│ │ ├── sitemap-discoverer ├── SEO best practices │ │ +│ │ ├── page-fetcher ├── WCAG 2.1 guidelines │ │ +│ │ ├── meta-analyzer ├── Security header docs │ │ +│ │ ├── wcag-checker └── Core Web Vitals guide │ │ +│ │ ├── ssl-checker │ │ +│ │ └── report-generator │ │ +│ │ │ │ +│ │ Agent can call these tools in any order, with the skills │ │ +│ │ providing domain expertise for intelligent decisions. │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### Mode 3: Hybrid (Checkpoints) +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ Phase 1: Discovery Phase 2: Analysis Phase 3: Report │ +│ ───────────────── ────────────────── ──────────────── │ +│ │ +│ [sitemap-discoverer] [CHECKPOINT: got pages] [CHECKPOINT: got │ +│ │ │ all scores] │ +│ ▼ ▼ │ │ +│ [page-fetcher] Agent freely uses: ▼ │ +│ │ • seo tools [action-plan-gen] │ +│ ▼ • perf tools │ │ +│ [CHECKPOINT] • a11y tools ▼ │ +│ • security tools [report-generator] │ +│ in whatever order │ +│ makes sense │ +│ │ +│ Strict Flexible Strict │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Dynamic Tool Installation (Registry Integration) + +In a registry-backed system (like TPMJS), if the agent needs a tool that isn't loaded: + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ During execution, agent realizes it needs a tool not in the plan: │ +│ │ +│ Agent: "The SSL certificate uses ECDSA which my ssl-checker doesn't │ +│ fully support. I need a more specialized tool." │ +│ │ +│ ┌──────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ 🔍 Searching registry for: "ECDSA certificate" │ │ +│ │ │ │ +│ │ Found: │ │ +│ │ ┌──────────────────────────────────────────────┐ │ │ +│ │ │ ecdsa-cert-analyzer │ │ │ +│ │ │ "Analyzes ECDSA and EdDSA certificates" │ │ │ +│ │ │ Health: ✓ Healthy │ │ │ +│ │ │ Quality: 0.87 │ │ │ +│ │ └──────────────────────────────────────────────┘ │ │ +│ │ │ │ +│ │ [Install and use] [Skip this check] [Ask user] │ │ +│ │ │ │ +│ └──────────────────────────────────────────────────────┘ │ +│ │ +│ On install: │ +│ 1. Fetch tool metadata from registry │ +│ 2. Load tool's associated skill/context docs │ +│ 3. Add to current execution context │ +│ 4. Continue execution │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Summary: The Complete Flow + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ USER QUERY ARRIVES │ +│ │ │ +│ ▼ │ +│ ┌───────────────────────┐ │ +│ │ 1. GENERATE Y PLANS │ │ +│ │ (speculative) │ │ +│ └───────────┬───────────┘ │ +│ │ │ +│ ┌─────────────────┼─────────────────┐ │ +│ ▼ ▼ ▼ │ +│ ┌────────┐ ┌────────┐ ┌────────┐ │ +│ │ Plan A │ │ Plan B │ │ Plan C │ │ +│ └────┬───┘ └────┬───┘ └────┬───┘ │ +│ │ │ │ │ +│ └─────────────────┼─────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌───────────────────────┐ │ +│ │ 2. CLUSTER TOOLS BY │ │ +│ │ DOMAIN/SKILL │ │ +│ └───────────┬───────────┘ │ +│ │ │ +│ ┌─────────┬───────┼───────┬─────────┐ │ +│ ▼ ▼ ▼ ▼ ▼ │ +│ ┌────────┐ ┌──────┐ ┌─────┐ ┌──────┐ ┌───────┐ │ +│ │SEO │ │Perf │ │A11y │ │Sec │ │Report │ │ +│ │domain │ │domain│ │domain│ │domain│ │domain │ │ +│ └────┬───┘ └──┬───┘ └──┬──┘ └──┬───┘ └───┬───┘ │ +│ │ │ │ │ │ │ +│ └────────┴────────┼───────┴─────────┘ │ +│ │ │ +│ ▼ │ +│ ┌───────────────────────┐ │ +│ │ 3. LOAD SKILL DOCS │ │ +│ │ FOR EACH DOMAIN │ │ +│ └───────────┬───────────┘ │ +│ │ │ +│ ▼ │ +│ ┌──────────────────────────────────────┐ │ +│ │ 4. PRESENT PLANS TO USER (optional) │ │ +│ │ or AUTO-SELECT │ │ +│ └───────────────────┬──────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌───────────────────────┐ │ +│ │ 5. EXECUTE WITH │ │ +│ │ CASCADING CONTEXT │ │ +│ └───────────┬───────────┘ │ +│ │ │ +│ ┌─────────────────┴─────────────────┐ │ +│ │ │ │ +│ ▼ ▼ │ +│ ┌─────────────────────┐ ┌─────────────────────┐ │ +│ │ Strict: Follow plan │ │ Flexible: Use plan │ │ +│ │ exactly │ │ as context guide │ │ +│ └─────────────────────┘ └─────────────────────┘ │ +│ │ +│ At each step: │ +│ • Load only current tool + likely next tools │ +│ • Load only relevant domain context │ +│ • Keep context window small (~1-3k tokens) │ +│ • Prune unlikely branches as execution proceeds │ +│ │ +│ │ │ +│ ▼ │ +│ ┌───────────────────────┐ │ +│ │ FINAL OUTPUT │ │ +│ └───────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Key Takeaways + +1. **Plans reveal skills**: Instead of loading all context upfront, generate plans first + and let them tell you what context is actually needed. + +2. **Small context, right context**: At each step, load only what's needed for that step + plus likely next steps. 96% reduction in context size. + +3. **User choice as a feature**: Multiple plans aren't a bug—they're a feature. Users + can pick their preferred approach. + +4. **Adaptive execution**: Plans can be strict guides or loose frameworks. The skill + context enables intelligent tool use either way. + +5. **Registry as escape hatch**: If the agent needs something not in the plan, it can + query the registry, install on-demand, and continue. + +The hierarchical cascading tree pattern makes agents both more capable (access to any +tool in the registry) and more efficient (minimal context at each step). diff --git a/docs/PLANNER_TYPE_DEFINITIONS.ts b/docs/PLANNER_TYPE_DEFINITIONS.ts new file mode 100644 index 0000000..cc7d824 --- /dev/null +++ b/docs/PLANNER_TYPE_DEFINITIONS.ts @@ -0,0 +1,980 @@ +/** + * ============================================================================ + * PLANNER TYPE DEFINITIONS + * ============================================================================ + * + * Complete TypeScript types for the hierarchical cascading tool planner system. + * Based on research into: + * - Dynamic tool orchestration + * - Y×X plan generation (Y alternatives, X steps each) + * - Skill/context inference from tool plans + * - Pathway learning algorithms + * - Fragility management + * + * ============================================================================ + */ + +// ============================================================================ +// CORE PRIMITIVES +// ============================================================================ + +/** + * A tool from the registry + * + * ┌─────────────────────────────────────┐ + * │ TOOL │ + * │ ───── │ + * │ packageName: "tpmjs-web-scraper" │ + * │ exportName: "scrapeUrl" │ + * │ description: "Fetches webpage..." │ + * │ parameters: [...] │ + * │ returns: { type: "string" } │ + * │ category: "web-scraping" │ + * │ qualityScore: 0.87 │ + * │ healthStatus: "HEALTHY" │ + * └─────────────────────────────────────┘ + */ +export interface Tool { + id: string; + packageName: string; + exportName: string; + description: string; + parameters: ToolParameter[]; + returns: ToolReturn; + category: ToolCategory; + qualityScore: number; + healthStatus: ToolHealthStatus; + aiAgent?: ToolAIAgent; + tier: 'minimal' | 'rich'; +} + +export interface ToolParameter { + name: string; + type: ParameterType; + required: boolean; + description: string; + default?: unknown; + enum?: string[]; +} + +export type ParameterType = + | 'string' + | 'number' + | 'boolean' + | 'object' + | 'array' + | 'string[]' + | 'number[]'; + +export interface ToolReturn { + type: string; + description: string; + schema?: JSONSchema; +} + +export interface ToolAIAgent { + useCase: string; + limitations?: string; + examples?: string[]; +} + +export type ToolCategory = + | 'web-scraping' + | 'data-analysis' + | 'file-generation' + | 'image-processing' + | 'text-processing' + | 'communication' + | 'ai-ml' + | 'database' + | 'api-integration' + | 'general'; + +export type ToolHealthStatus = 'HEALTHY' | 'BROKEN' | 'UNKNOWN'; + +export interface JSONSchema { + type: string; + properties?: Record; + items?: JSONSchema; + required?: string[]; + [key: string]: unknown; +} + +// ============================================================================ +// QUERY ANALYSIS +// ============================================================================ + +/** + * Result of analyzing a user query + * + * Query: "Scrape competitor prices from example.com and make a report" + * + * ┌─────────────────────────────────────────────────────┐ + * │ QUERY ANALYSIS │ + * │ ────────────── │ + * │ intent: "price-comparison-report" │ + * │ entities: [{ type: "url", value: "example.com" }] │ + * │ capabilities: ["fetch-webpage", "extract-prices", │ + * │ "analyze-data", "generate-report"] │ + * │ outputFormat: "pdf" │ + * │ complexity: 7 │ + * └─────────────────────────────────────────────────────┘ + */ +export interface QueryAnalysis { + intent: string; + entities: QueryEntity[]; + requiredCapabilities: string[]; + outputFormat?: OutputFormat; + constraints: QueryConstraints; + ambiguities: string[]; + complexity: number; // 1-10 +} + +export interface QueryEntity { + type: EntityType; + value: string; + confidence: number; +} + +export type EntityType = 'url' | 'file_path' | 'email' | 'date' | 'number' | 'name' | 'keyword'; + +export type OutputFormat = 'json' | 'csv' | 'pdf' | 'xlsx' | 'markdown' | 'html' | 'image' | 'text'; + +export interface QueryConstraints { + format?: string; + style?: string; + maxTime?: number; + maxCost?: number; + quality?: 'draft' | 'standard' | 'high'; +} + +// ============================================================================ +// EXECUTION PLANS +// ============================================================================ + +/** + * A complete execution plan (one of Y alternatives) + * + * ┌─────────────────────────────────────────────────────────────┐ + * │ EXECUTION PLAN │ + * │ ────────────── │ + * │ │ + * │ metadata: │ + * │ query: "Scrape competitor prices..." │ + * │ complexity: 7 │ + * │ estimatedDuration: 45000ms │ + * │ estimatedCost: $0.45 │ + * │ confidence: 0.87 │ + * │ │ + * │ classification: │ + * │ approach: "thorough" │ + * │ riskLevel: "low" │ + * │ │ + * │ steps: [step1, step2, step3, ...] │ + * │ skills: [seo, scraping, analysis] │ + * │ │ + * └─────────────────────────────────────────────────────────────┘ + */ +export interface ExecutionPlan { + id: string; + version: '1.0'; + metadata: PlanMetadata; + classification: PlanClassification; + steps: PlanStep[]; + skills: Skill[]; + expectedOutput: ExpectedOutput; +} + +export interface PlanMetadata { + generatedAt: string; + query: string; + complexity: number; + estimatedDuration: number; // milliseconds + estimatedCost: number; // USD + confidence: number; // 0-1 +} + +export interface PlanClassification { + approach: 'thorough' | 'quick' | 'balanced'; + riskLevel: 'low' | 'medium' | 'high'; + parallelizable: boolean; +} + +export interface ExpectedOutput { + type: string; + schema?: JSONSchema; + description: string; +} + +// ============================================================================ +// PLAN STEPS +// ============================================================================ + +/** + * A single step in an execution plan + * + * ┌─────────────────────────────────────────────────────────────┐ + * │ PLAN STEP │ + * │ ───────── │ + * │ │ + * │ id: "step_3" │ + * │ order: 3 │ + * │ tool: { packageName: "tpmjs-price-extractor", ... } │ + * │ purpose: "Extract and normalize price values" │ + * │ │ + * │ input: │ + * │ fromStep: { stepId: "step_2", path: "$.elements" } │ + * │ static: { currency: "USD" } │ + * │ │ + * │ output: │ + * │ type: "array" │ + * │ storeAs: "prices" │ + * │ │ + * │ execution: │ + * │ timeout: 5000 │ + * │ retries: 2 │ + * │ fallbackTools: ["alt-price-extractor"] │ + * │ │ + * │ dependsOn: ["step_2"] │ + * │ parallelGroup: "extraction" │ + * │ │ + * └─────────────────────────────────────────────────────────────┘ + */ +export interface PlanStep { + id: string; + order: number; + tool: ToolReference; + purpose: string; + input: StepInput; + output: StepOutput; + execution: StepExecution; + dependsOn: string[]; + parallelGroup?: string; +} + +export interface ToolReference { + packageName: string; + exportName: string; + version?: string; +} + +export interface StepInput { + static?: Record; + fromStep?: StepReference | StepReference[]; + fromQuery?: QueryReference; + computed?: ComputedInput; +} + +export interface StepReference { + stepId: string; + path: string; // JSONPath + as?: string; // alias +} + +export interface QueryReference { + entityType: EntityType; + index?: number; +} + +export interface ComputedInput { + expression: string; + dependencies: string[]; +} + +export interface StepOutput { + type: string; + storeAs: string; + validate?: ValidationRule[]; +} + +export interface ValidationRule { + rule: 'minLength' | 'maxLength' | 'regex' | 'type' | 'required'; + value: unknown; + message?: string; +} + +export interface StepExecution { + timeout: number; + retries: number; + canSkipOnError: boolean; + fallbackTools?: string[]; +} + +// ============================================================================ +// SKILLS (CONTEXTUAL KNOWLEDGE) +// ============================================================================ + +/** + * A skill is domain knowledge inferred from tools in a plan + * + * Tools in Plan Inferred Skill + * ───────────── ────────────── + * ┌─────────────┐ ┌─────────────────────────────────┐ + * │web-scraper │──┐ │ SKILL: web-scraping │ + * │html-parser │──┼────────►│ │ + * │url-validator│──┘ │ context: │ + * └─────────────┘ │ • Rate limiting rules │ + * │ • Robots.txt guidelines │ + * │ • CSS selector best practices │ + * └─────────────────────────────────┘ + */ +export interface Skill { + domain: ToolCategory; + context: string; + tools: Tool[]; + priority: number; // For ordering in context +} + +export interface SkillContext { + domain: ToolCategory; + content: string; + tokenEstimate: number; +} + +// ============================================================================ +// EXECUTION CONTEXT +// ============================================================================ + +/** + * Runtime state during plan execution + * + * ┌─────────────────────────────────────────────────────────────┐ + * │ EXECUTION CONTEXT │ + * │ ───────────────── │ + * │ │ + * │ query: "Scrape competitor prices..." │ + * │ │ + * │ variables: │ + * │ step_1 ──► { html: "..." } │ + * │ step_2 ──► { elements: [...] } │ + * │ step_3 ──► { prices: [19.99, 24.99] } │ + * │ │ + * │ completed: { step_1, step_2, step_3 } │ + * │ currentStep: "step_4" │ + * │ │ + * │ errors: [] │ + * │ retryCount: { step_2: 1 } │ + * │ │ + * │ timing: │ + * │ startTime: 1702234567890 │ + * │ stepTimings: { step_1: 823, step_2: 234, step_3: 567 } │ + * │ │ + * │ tokens: │ + * │ input: 4521 │ + * │ output: 1234 │ + * │ │ + * └─────────────────────────────────────────────────────────────┘ + */ +export interface ExecutionContext { + query: string; + entities: QueryEntity[]; + variables: Map; + completed: Set; + currentStep: string | null; + errors: ExecutionError[]; + retryCount: Map; + timing: ExecutionTiming; + tokens: TokenUsage; +} + +export interface ExecutionError { + stepId: string; + tool: string; + error: string; + timestamp: number; + recoverable: boolean; +} + +export interface ExecutionTiming { + startTime: number; + stepTimings: Map; +} + +export interface TokenUsage { + input: number; + output: number; + perStep: Map; +} + +// ============================================================================ +// EXECUTION EVENTS (FOR STREAMING) +// ============================================================================ + +/** + * Events emitted during plan execution + * + * Time ────────────────────────────────────────────────────────► + * + * ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────┐ + * │plan_start│►│step_start│►│step_done │►│step_start│►│plan_end│ + * └──────────┘ └──────────┘ └──────────┘ └──────────┘ └────────┘ + */ +export type ExecutionEvent = + | PlanStartEvent + | StepStartEvent + | ContextLoadedEvent + | StepProgressEvent + | StepCompleteEvent + | StepErrorEvent + | StepSkippedEvent + | PlanCompleteEvent + | PlanErrorEvent; + +export interface PlanStartEvent { + type: 'plan_start'; + planId: string; + totalSteps: number; + skills: string[]; +} + +export interface StepStartEvent { + type: 'step_start'; + stepId: string; + tool: string; + purpose: string; +} + +export interface ContextLoadedEvent { + type: 'context_loaded'; + stepId: string; + tokens: number; + skills: string[]; +} + +export interface StepProgressEvent { + type: 'step_progress'; + stepId: string; + progress: number; // 0-100 + message?: string; +} + +export interface StepCompleteEvent { + type: 'step_complete'; + stepId: string; + duration: number; + resultPreview: string; +} + +export interface StepErrorEvent { + type: 'step_error'; + stepId: string; + error: string; + willRetry: boolean; + fallbackTool?: string; +} + +export interface StepSkippedEvent { + type: 'step_skipped'; + stepId: string; + reason: string; +} + +export interface PlanCompleteEvent { + type: 'plan_complete'; + success: boolean; + totalDuration: number; + totalTokens: number; + output: unknown; +} + +export interface PlanErrorEvent { + type: 'plan_error'; + error: string; + failedStep: string; + completedSteps: string[]; +} + +// ============================================================================ +// PATHWAY LEARNING +// ============================================================================ + +/** + * Record of a pathway execution for learning + * + * ┌─────────────────────────────────────────────────────────────┐ + * │ PATHWAY RECORD │ + * │ ────────────── │ + * │ │ + * │ queryPattern: "scrape.*price.*report" │ + * │ steps: ["scraper", "parser", "analyzer", "reporter"] │ + * │ │ + * │ stats: │ + * │ successes: 847 │ + * │ failures: 45 │ + * │ avgDuration: 34500ms │ + * │ │ + * │ lastUsed: 2024-01-15T10:30:00Z │ + * │ firstUsed: 2024-01-01T08:00:00Z │ + * │ │ + * └─────────────────────────────────────────────────────────────┘ + */ +export interface PathwayRecord { + id: string; + queryPattern: string; + steps: string[]; // Tool IDs in order + stats: PathwayStats; + lastUsed: Date; + firstUsed: Date; + metadata: PathwayMetadata; +} + +export interface PathwayStats { + successes: number; + failures: number; + totalRuns: number; + avgDuration: number; + avgTokens: number; + avgCost: number; +} + +export interface PathwayMetadata { + createdBy: 'user' | 'auto'; + tags: string[]; + notes?: string; +} + +/** + * K-factor represents convergence toward determinism + * + * K = 0.00 ──► No pattern, explore freely + * K = 0.50 ──► Weak pattern, prefer but explore + * K = 0.85 ──► Strong pattern, mostly deterministic + * K = 0.99 ──► Near-locked, rare deviation + */ +export interface KFactorResult { + value: number; // 0-1 + confidence: number; + dominantPath: string[] | null; + totalObservations: number; +} + +// ============================================================================ +// LEARNING ALGORITHMS +// ============================================================================ + +/** + * Configuration for pathway selection algorithms + */ +export interface LearningConfig { + algorithm: LearningAlgorithm; + params: AlgorithmParams; +} + +export type LearningAlgorithm = + | 'epsilon_greedy' + | 'ucb' + | 'thompson_sampling' + | 'contextual_bandit' + | 'q_learning' + | 'mcts'; + +export type AlgorithmParams = + | EpsilonGreedyParams + | UCBParams + | ThompsonParams + | ContextualBanditParams + | QLearningParams + | MCTSParams; + +export interface EpsilonGreedyParams { + type: 'epsilon_greedy'; + epsilon: number; // Exploration rate (0-1) + decayRate: number; // How fast epsilon decays + minEpsilon: number; // Floor for epsilon +} + +export interface UCBParams { + type: 'ucb'; + explorationConstant: number; // C in UCB formula +} + +export interface ThompsonParams { + type: 'thompson_sampling'; + priorAlpha: number; // Beta distribution prior + priorBeta: number; +} + +export interface ContextualBanditParams { + type: 'contextual_bandit'; + features: ContextFeature[]; + learningRate: number; +} + +export type ContextFeature = + | 'user_type' + | 'query_complexity' + | 'time_of_day' + | 'previous_success_rate'; + +export interface QLearningParams { + type: 'q_learning'; + learningRate: number; // Alpha + discountFactor: number; // Gamma + explorationRate: number; // Epsilon +} + +export interface MCTSParams { + type: 'mcts'; + simulations: number; + explorationConstant: number; + maxDepth: number; +} + +// ============================================================================ +// FRAGILITY MANAGEMENT +// ============================================================================ + +/** + * Fragility budget for a plan + * + * ┌─────────────────────────────────────────────────────────────┐ + * │ FRAGILITY BUDGET │ + * │ ──────────────── │ + * │ │ + * │ Target success rate: 90% │ + * │ │ + * │ If each step has P(success) = 0.98: │ + * │ Max steps = floor(log(0.90) / log(0.98)) = 5 │ + * │ │ + * │ If each step has P(success) = 0.95: │ + * │ Max steps = floor(log(0.90) / log(0.95)) = 2 │ + * │ │ + * └─────────────────────────────────────────────────────────────┘ + */ +export interface FragilityBudget { + targetSuccessRate: number; // e.g., 0.90 for 90% + avgStepSuccessRate: number; // e.g., 0.98 + maxSteps: number; // Calculated limit + currentSteps: number; + withinBudget: boolean; +} + +export interface FragilityAnalysis { + plan: ExecutionPlan; + budget: FragilityBudget; + sequentialFragility: number; // P(all sequential steps succeed) + parallelBenefit: number; // Improvement from parallel execution + fallbackBenefit: number; // Improvement from fallbacks + effectiveSuccessRate: number; // Final calculated rate + recommendations: FragilityRecommendation[]; +} + +export interface FragilityRecommendation { + type: 'reduce_steps' | 'add_fallbacks' | 'parallelize' | 'add_checkpoints'; + description: string; + impact: number; // Estimated improvement +} + +// ============================================================================ +// PLAN GENERATION OPTIONS +// ============================================================================ + +/** + * Options for generating plans + */ +export interface PlanGenerationOptions { + numPlans: number; // Y in Y×X + maxStepsPerPlan: number; // Max X + strategies: PlanStrategy[]; + fragilityBudget?: FragilityBudget; + preferredCategories?: ToolCategory[]; + excludeTools?: string[]; +} + +export interface PlanStrategy { + name: string; + maxSteps: number; + preferQuality: boolean; + preferSpeed: boolean; + allowParallel: boolean; + requireFallbacks: boolean; +} + +// ============================================================================ +// CASCADING CONTEXT +// ============================================================================ + +/** + * Context assembled for a single step (minimal footprint) + * + * Traditional: Load ALL tools + ALL docs = ~45,000 tokens + * + * Cascading: + * ┌────────────────────────────────────────────────────────────┐ + * │ STEP CONTEXT (~1,500 tokens) │ + * │ ──────────── │ + * │ │ + * │ ┌──────────────────────────────────────────────────────┐ │ + * │ │ CURRENT TOOL (~400 tokens) │ │ + * │ │ web-scraper: description, parameters, examples │ │ + * │ └──────────────────────────────────────────────────────┘ │ + * │ │ + * │ ┌──────────────────────────────────────────────────────┐ │ + * │ │ DOMAIN CONTEXT (~600 tokens) │ │ + * │ │ Web scraping best practices, rate limits, selectors │ │ + * │ └──────────────────────────────────────────────────────┘ │ + * │ │ + * │ ┌──────────────────────────────────────────────────────┐ │ + * │ │ UPCOMING TOOLS (~200 tokens) │ │ + * │ │ Next: html-parser, price-extractor │ │ + * │ └──────────────────────────────────────────────────────┘ │ + * │ │ + * │ ┌──────────────────────────────────────────────────────┐ │ + * │ │ PRIOR RESULTS (~300 tokens) │ │ + * │ │ Summarized output from dependencies │ │ + * │ └──────────────────────────────────────────────────────┘ │ + * │ │ + * └────────────────────────────────────────────────────────────┘ + */ +export interface CascadingContext { + currentTool: ToolContext; + domainContext: SkillContext | null; + upcomingTools: ToolPreview[]; + priorResults: PriorResult[]; + totalTokens: number; +} + +export interface ToolContext { + tool: Tool; + formattedDescription: string; + formattedParameters: string; + examples: string[]; + tokenEstimate: number; +} + +export interface ToolPreview { + exportName: string; + purpose: string; + tokenEstimate: number; +} + +export interface PriorResult { + stepId: string; + summary: string; + tokenEstimate: number; +} + +// ============================================================================ +// PRELOADING / PROBABILITY +// ============================================================================ + +/** + * Probability calculation for preloading next tools + * + * Current: step_2 (html-parser) + * + * ┌────────────────────────────────────────┐ + * │ NEXT TOOL PROBABILITIES │ + * │ │ + * │ price-extractor P = 0.92 ──► LOAD │ + * │ text-cleaner P = 0.78 ──► LOAD │ + * │ image-extractor P = 0.34 │ + * │ link-extractor P = 0.21 │ + * │ │ + * │ Threshold: 0.70 │ + * └────────────────────────────────────────┘ + */ +export interface ToolProbability { + tool: Tool; + probability: number; + reason: ProbabilityReason; +} + +export type ProbabilityReason = + | 'plan_next' // Next in plan + | 'plan_soon' // Coming up in plan + | 'learned_pattern' // Historical data + | 'output_type_match' // Output type matches input + | 'same_domain'; // Same category + +export interface PreloadDecision { + toLoad: Tool[]; + threshold: number; + reasoning: Map; +} + +// ============================================================================ +// USER INTERFACE TYPES +// ============================================================================ + +/** + * Plan summary for UI display + */ +export interface PlanSummary { + id: string; + name: string; + approach: 'thorough' | 'quick' | 'balanced'; + stepCount: number; + estimatedDuration: string; // "~2 min" + estimatedCost: string; // "$0.45" + confidence: number; + skills: string[]; + riskLevel: 'low' | 'medium' | 'high'; +} + +/** + * Execution progress for UI display + */ +export interface ExecutionProgress { + status: 'idle' | 'planning' | 'running' | 'complete' | 'error'; + currentStep: number; + totalSteps: number; + completedSteps: StepProgress[]; + currentStepProgress?: { + stepId: string; + tool: string; + progress: number; + message?: string; + }; + contextTokens: number; + elapsedTime: number; +} + +export interface StepProgress { + stepId: string; + tool: string; + status: 'complete' | 'skipped' | 'error'; + duration: number; + resultPreview?: string; + error?: string; +} + +// ============================================================================ +// API TYPES +// ============================================================================ + +/** + * Request/Response types for API routes + */ +export interface GeneratePlansRequest { + query: string; + numPlans?: number; + options?: Partial; +} + +export interface GeneratePlansResponse { + success: boolean; + data: { + plans: PlanSummary[]; + kFactor: KFactorResult; + learnedPathAvailable: boolean; + }; + error?: string; +} + +export interface ExecutePlanRequest { + planId: string; + query: string; + options?: { + useFallbacks?: boolean; + maxRetries?: number; + }; +} + +// Response is SSE stream of ExecutionEvent + +export interface GetToolsRequest { + capability: string; + category?: ToolCategory; + limit?: number; + healthyOnly?: boolean; +} + +export interface GetToolsResponse { + success: boolean; + data: { + tools: Tool[]; + total: number; + }; + error?: string; +} + +// ============================================================================ +// DATABASE MODELS (for Prisma schema reference) +// ============================================================================ + +/** + * Database models for persistence + * + * Add to packages/db/prisma/schema.prisma: + * + * model PathwayRecord { + * id String @id @default(cuid()) + * queryPattern String + * steps String[] // Tool IDs + * successes Int @default(0) + * failures Int @default(0) + * avgDuration Float @default(0) + * avgTokens Float @default(0) + * avgCost Float @default(0) + * lastUsed DateTime @default(now()) + * firstUsed DateTime @default(now()) + * createdBy String @default("auto") + * tags String[] + * notes String? + * + * @@index([queryPattern]) + * @@index([lastUsed]) + * } + * + * model PlanExecution { + * id String @id @default(cuid()) + * planId String + * query String + * steps Json // PlanStep[] + * status String // 'running' | 'complete' | 'error' + * output Json? + * totalTokens Int @default(0) + * totalCost Float @default(0) + * duration Int @default(0) + * createdAt DateTime @default(now()) + * completedAt DateTime? + * + * @@index([planId]) + * @@index([createdAt]) + * } + */ +export interface PathwayRecordDB { + id: string; + queryPattern: string; + steps: string[]; + successes: number; + failures: number; + avgDuration: number; + avgTokens: number; + avgCost: number; + lastUsed: Date; + firstUsed: Date; + createdBy: string; + tags: string[]; + notes: string | null; +} + +export interface PlanExecutionDB { + id: string; + planId: string; + query: string; + steps: PlanStep[]; + status: 'running' | 'complete' | 'error'; + output: unknown | null; + totalTokens: number; + totalCost: number; + duration: number; + createdAt: Date; + completedAt: Date | null; +} + +// ============================================================================ +// UTILITY TYPES +// ============================================================================ + +export type DeepPartial = { + [P in keyof T]?: T[P] extends object ? DeepPartial : T[P]; +}; + +export type AsyncGenerator = { + next(): Promise<{ value: T; done: boolean }>; + [Symbol.asyncIterator](): AsyncGenerator; +}; + +export type Result = { success: true; data: T } | { success: false; error: E }; diff --git a/docs/TPMJS_PLANNER_TUTORIAL.md b/docs/TPMJS_PLANNER_TUTORIAL.md new file mode 100644 index 0000000..e93cebe --- /dev/null +++ b/docs/TPMJS_PLANNER_TUTORIAL.md @@ -0,0 +1,1140 @@ +# TPMJS Planner: Building a Multi-Tool Agent System + +A tutorial on implementing a hierarchical planning agent that dynamically loads tools from the TPMJS registry. + +--- + +## System Overview + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ USER QUERY │ +│ "Scrape competitor prices, │ +│ analyze trends, make report" │ +│ │ │ +│ ▼ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ PLAN GENERATOR │ │ +│ │ │ │ +│ │ Query ──► Tool Search ──► Generate Y Plans ──► Infer Skills │ │ +│ │ │ │ +│ └──────────────────────────────┬──────────────────────────────────────┘ │ +│ │ │ +│ ┌──────────────────┼──────────────────┐ │ +│ ▼ ▼ ▼ │ +│ ┌────────┐ ┌────────┐ ┌────────┐ │ +│ │ Plan A │ │ Plan B │ │ Plan C │ │ +│ │12 steps│ │ 6 steps│ │ 8 steps│ │ +│ └────┬───┘ └────────┘ └────────┘ │ +│ │ │ +│ ▼ (user selects or auto-select) │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ CASCADING EXECUTOR │ │ +│ │ │ │ +│ │ Load Context ──► Execute Step ──► Update State ──► Next Step │ │ +│ │ ▲ │ │ │ +│ │ └────────────────────────────────────┘ │ │ +│ └──────────────────────────────┬──────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ FINAL OUTPUT │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Part 1: Core Types + +```typescript +// ============================================================================ +// types/planner.ts +// ============================================================================ + +interface Tool { + id: string; + packageName: string; + exportName: string; + description: string; + parameters: Parameter[]; + returns: ReturnType; + category: string; + qualityScore: number; +} + +interface ExecutionPlan { + id: string; + steps: PlanStep[]; + estimatedCost: number; + confidence: number; + skills: Skill[]; // Inferred from tools +} + +interface PlanStep { + id: string; + tool: Tool; + purpose: string; + input: StepInput; + dependsOn: string[]; // Step IDs + fallbacks: Tool[]; // Alternative tools +} + +interface Skill { + domain: string; // "seo", "scraping", "data-analysis" + context: string; // Relevant docs/knowledge + tools: Tool[]; // Tools in this domain +} + +interface ExecutionContext { + query: string; + variables: Map; + completed: Set; + errors: Error[]; +} +``` + +--- + +## Part 2: Tool Discovery + +```typescript +// ============================================================================ +// lib/tool-discovery.ts +// ============================================================================ + +/** + * Search registry for tools matching a capability + * + * ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ + * │ Query │────►│ Registry │────►│ Ranked │ + * │ "scrape" │ │ Search │ │ Tools │ + * └─────────────┘ └─────────────┘ └─────────────┘ + */ +async function discoverTools( + capability: string, + limit: number = 10 +): Promise { + + // 1. Search by keyword + const keywordResults = await fetch( + `/api/tools?search=${encodeURIComponent(capability)}&limit=${limit}` + ).then(r => r.json()); + + // 2. Search by category + const category = inferCategory(capability); + const categoryResults = await fetch( + `/api/tools?category=${category}&limit=${limit}` + ).then(r => r.json()); + + // 3. Merge and rank + const merged = mergeAndDedupe(keywordResults.data, categoryResults.data); + + return rankTools(merged, capability); +} + +/** + * Rank tools by relevance + quality + */ +function rankTools(tools: Tool[], capability: string): Tool[] { + return tools + .map(tool => ({ + tool, + score: + textSimilarity(tool.description, capability) * 0.4 + + tool.qualityScore * 0.3 + + (tool.healthStatus === 'HEALTHY' ? 0.3 : 0) + })) + .sort((a, b) => b.score - a.score) + .map(t => t.tool); +} + +/** + * Category inference from natural language + * + * "scrape website" ──► "web-scraping" + * "analyze data" ──► "data-analysis" + * "generate pdf" ──► "file-generation" + */ +function inferCategory(text: string): string { + const patterns = [ + { pattern: /scrape|crawl|fetch.*web/i, category: 'web-scraping' }, + { pattern: /analyz|statistic|trend/i, category: 'data-analysis' }, + { pattern: /pdf|excel|csv|export/i, category: 'file-generation' }, + { pattern: /image|photo|picture/i, category: 'image-processing' }, + { pattern: /email|notify|alert/i, category: 'communication' }, + ]; + + for (const { pattern, category } of patterns) { + if (pattern.test(text)) return category; + } + return 'general'; +} +``` + +--- + +## Part 3: Plan Generation + +```typescript +// ============================================================================ +// lib/plan-generator.ts +// ============================================================================ + +/** + * Generate Y alternative plans for a query + * + * ┌─────────────┐ + * │ Query │ + * └──────┬──────┘ + * │ + * ┌──────────┼──────────┐ + * ▼ ▼ ▼ + * ┌────────┐ ┌────────┐ ┌────────┐ + * │ Plan A │ │ Plan B │ │ Plan C │ + * │Thorough│ │ Quick │ │Balanced│ + * └────────┘ └────────┘ └────────┘ + */ +async function generatePlans( + query: string, + numPlans: number = 3 +): Promise { + + // 1. Analyze query + const analysis = await analyzeQuery(query); + + // 2. Discover relevant tools + const tools = await discoverToolsForAnalysis(analysis); + + // 3. Generate plan variants + const strategies: PlanStrategy[] = [ + { name: 'thorough', maxSteps: 15, preferQuality: true }, + { name: 'quick', maxSteps: 5, preferSpeed: true }, + { name: 'balanced', maxSteps: 10, balanced: true }, + ]; + + const plans = await Promise.all( + strategies.slice(0, numPlans).map(strategy => + generateSinglePlan(analysis, tools, strategy) + ) + ); + + // 4. Infer skills for each plan + return plans.map(plan => ({ + ...plan, + skills: inferSkills(plan.steps.map(s => s.tool)) + })); +} + +/** + * Query analysis extracts intent and entities + */ +async function analyzeQuery(query: string): Promise { + // Use LLM to extract structured info + const response = await generateText({ + model: openai('gpt-4-turbo'), + prompt: `Analyze this query and extract: + - intent (what user wants to accomplish) + - entities (URLs, names, values mentioned) + - required_capabilities (list of needed operations) + - output_format (what format user expects) + + Query: "${query}" + + Return JSON.` + }); + + return JSON.parse(response.text); +} + +/** + * Generate a single plan with given strategy + */ +async function generateSinglePlan( + analysis: QueryAnalysis, + tools: Tool[], + strategy: PlanStrategy +): Promise { + + const steps: PlanStep[] = []; + const usedTools = new Set(); + + for (const capability of analysis.required_capabilities) { + // Find best tool for this capability + const candidates = tools.filter(t => + matchesCapability(t, capability) && !usedTools.has(t.id) + ); + + if (candidates.length === 0) continue; + + const tool = strategy.preferQuality + ? candidates.sort((a, b) => b.qualityScore - a.qualityScore)[0] + : candidates[0]; + + usedTools.add(tool.id); + + steps.push({ + id: `step_${steps.length + 1}`, + tool, + purpose: capability, + input: inferInput(tool, analysis, steps), + dependsOn: inferDependencies(tool, steps), + fallbacks: candidates.slice(1, 3) // Keep alternatives + }); + + if (steps.length >= strategy.maxSteps) break; + } + + return { + id: generateId(), + steps, + estimatedCost: estimateCost(steps), + confidence: calculateConfidence(steps), + skills: [] // Filled in later + }; +} +``` + +--- + +## Part 4: Skill Inference + +```typescript +// ============================================================================ +// lib/skill-inference.ts +// ============================================================================ + +/** + * Infer skills (contextual knowledge) from tools in a plan + * + * Tools in Plan Inferred Skills + * ───────────── ─────────────── + * ┌─────────────────┐ ┌─────────────────┐ + * │ web-scraper │──┐ │ WEB SCRAPING │ + * │ html-parser │──┼──────────►│ • Rate limiting │ + * │ url-validator │──┘ │ • Robots.txt │ + * └─────────────────┘ │ • Selectors │ + * └─────────────────┘ + * ┌─────────────────┐ ┌─────────────────┐ + * │ price-extractor │──┐ │ DATA ANALYSIS │ + * │ trend-analyzer │──┼──────────►│ • Normalization │ + * │ stats-calculator│──┘ │ • Outliers │ + * └─────────────────┘ └─────────────────┘ + */ +function inferSkills(tools: Tool[]): Skill[] { + // Group tools by category + const byCategory = groupBy(tools, t => t.category); + + const skills: Skill[] = []; + + for (const [category, categoryTools] of Object.entries(byCategory)) { + const skillContext = SKILL_CONTEXTS[category]; + + if (skillContext) { + skills.push({ + domain: category, + context: skillContext, + tools: categoryTools + }); + } + } + + return skills; +} + +/** + * Skill context library - domain knowledge for each category + */ +const SKILL_CONTEXTS: Record = { + 'web-scraping': ` + ## Web Scraping Best Practices + - Always check robots.txt before scraping + - Implement rate limiting (1 req/sec default) + - Handle pagination with cursor or offset + - Use CSS selectors over XPath when possible + - Handle JavaScript-rendered content with headless browser + `, + + 'data-analysis': ` + ## Data Analysis Guidelines + - Normalize numerical data before comparison + - Handle missing values: impute or exclude + - Identify outliers using IQR or z-score + - Use appropriate statistical tests + - Visualize distributions before drawing conclusions + `, + + 'file-generation': ` + ## File Generation Standards + - PDF: Use A4/Letter, embed fonts, compress images + - Excel: Use proper data types, add headers, format numbers + - CSV: Use UTF-8, escape special characters, consistent delimiters + `, + + // ... more domains +}; +``` + +--- + +## Part 5: Cascading Executor + +```typescript +// ============================================================================ +// lib/cascading-executor.ts +// ============================================================================ + +/** + * Execute a plan with cascading context loading + * + * Step 1 Step 2 Step 3 + * ────── ────── ────── + * ┌────────────┐ ┌────────────┐ ┌────────────┐ + * │ Load: │ │ Load: │ │ Load: │ + * │ • Tool A │ │ • Tool B │ │ • Tool C │ + * │ • Skill X │ ───► │ • Skill X │ ───► │ • Skill Y │ + * │ • Next: B │ │ • Next: C │ │ • Next: D │ + * └────────────┘ └────────────┘ └────────────┘ + * ~800 tok ~900 tok ~1100 tok + * + * vs Loading Everything: ~15000 tokens + */ +async function* executeWithCascading( + plan: ExecutionPlan, + context: ExecutionContext +): AsyncGenerator { + + for (let i = 0; i < plan.steps.length; i++) { + const step = plan.steps[i]; + const nextSteps = plan.steps.slice(i + 1, i + 3); // Preload next 2 + + yield { type: 'step_start', stepId: step.id }; + + // 1. Build minimal context for this step + const stepContext = buildStepContext(step, nextSteps, plan.skills, context); + + yield { type: 'context_loaded', tokens: estimateTokens(stepContext) }; + + // 2. Resolve input values + const input = resolveInput(step.input, context); + + // 3. Execute with fallbacks + const result = await executeWithFallbacks(step, input, stepContext); + + // 4. Store result + context.variables.set(step.id, result); + context.completed.add(step.id); + + yield { + type: 'step_complete', + stepId: step.id, + result: summarize(result) + }; + } + + yield { type: 'plan_complete', output: context.variables }; +} + +/** + * Build minimal context for a single step + */ +function buildStepContext( + current: PlanStep, + upcoming: PlanStep[], + skills: Skill[], + context: ExecutionContext +): string { + const parts: string[] = []; + + // 1. Current tool description + parts.push(`## Current Tool: ${current.tool.exportName}`); + parts.push(current.tool.description); + parts.push(formatParameters(current.tool.parameters)); + + // 2. Relevant skill context (only for this tool's domain) + const relevantSkill = skills.find(s => + s.tools.some(t => t.id === current.tool.id) + ); + if (relevantSkill) { + parts.push(`## Domain Knowledge`); + parts.push(relevantSkill.context); + } + + // 3. Upcoming tools (just names, for continuity) + if (upcoming.length > 0) { + parts.push(`## Coming Next`); + parts.push(upcoming.map(s => `- ${s.tool.exportName}: ${s.purpose}`).join('\n')); + } + + // 4. Relevant prior results (summarized) + for (const depId of current.dependsOn) { + const prior = context.variables.get(depId); + if (prior) { + parts.push(`## Input from ${depId}`); + parts.push(summarize(prior, 500)); // Max 500 chars + } + } + + return parts.join('\n\n'); +} + +/** + * Execute step with automatic fallback on failure + * + * ┌──────────┐ ┌──────────┐ ┌──────────┐ + * │ Primary │──X──│ Fallback │──X──│ Fallback │──► Error + * │ Tool │ │ #1 │ │ #2 │ + * └──────────┘ └──────────┘ └──────────┘ + * │ │ │ + * ▼ ▼ ▼ + * Result Result Result + */ +async function executeWithFallbacks( + step: PlanStep, + input: any, + context: string +): Promise { + const tools = [step.tool, ...step.fallbacks]; + + for (const tool of tools) { + try { + return await executeTool(tool, input, context); + } catch (error) { + console.log(`Tool ${tool.exportName} failed, trying fallback...`); + } + } + + throw new Error(`All tools failed for step ${step.id}`); +} + +/** + * Execute a single tool via the registry + */ +async function executeTool( + tool: Tool, + input: any, + context: string +): Promise { + const response = await fetch( + `/api/tools/execute/${tool.packageName}/${tool.exportName}`, + { + method: 'POST', + body: JSON.stringify({ input, context }), + } + ); + + if (!response.ok) { + throw new Error(`Tool execution failed: ${response.statusText}`); + } + + return response.json(); +} +``` + +--- + +## Part 6: Pathway Learning + +```typescript +// ============================================================================ +// lib/pathway-learning.ts +// ============================================================================ + +/** + * Track and learn from pathway execution + * + * ┌─────────────────────────────────────────────────────────┐ + * │ PATHWAY STORE │ + * │ │ + * │ Query Pattern Path Success Weight │ + * │ ───────────── ──── ─────── ────── │ + * │ "scrape.*price" A→B→D→E 847/892 0.95 │ + * │ "scrape.*price" A→B→C→D→E 38/52 0.73 │ + * │ "analyze.*trend" X→Y→Z 412/445 0.93 │ + * │ │ + * └─────────────────────────────────────────────────────────┘ + */ + +interface PathwayRecord { + queryPattern: string; + steps: string[]; // Tool IDs in order + successes: number; + failures: number; + lastUsed: Date; +} + +class PathwayLearner { + private records: Map = new Map(); + + /** + * Record outcome of a pathway execution + */ + recordOutcome( + query: string, + steps: string[], + success: boolean + ): void { + const pattern = extractPattern(query); + const pathKey = steps.join('→'); + + let records = this.records.get(pattern) || []; + let record = records.find(r => r.steps.join('→') === pathKey); + + if (!record) { + record = { + queryPattern: pattern, + steps, + successes: 0, + failures: 0, + lastUsed: new Date() + }; + records.push(record); + } + + if (success) record.successes++; + else record.failures++; + record.lastUsed = new Date(); + + this.records.set(pattern, records); + } + + /** + * Get recommended pathway using Thompson Sampling + * + * Path A: Beta(91, 11) ──► Sample: 0.88 + * Path B: Beta(5, 2) ──► Sample: 0.91 ◄── Winner (uncertain but sampled high) + */ + recommendPathway(query: string): string[] | null { + const pattern = extractPattern(query); + const records = this.records.get(pattern); + + if (!records || records.length === 0) return null; + + // Thompson Sampling: sample from Beta distribution for each path + let bestPath: string[] | null = null; + let bestSample = -1; + + for (const record of records) { + // Beta(successes + 1, failures + 1) + const sample = sampleBeta( + record.successes + 1, + record.failures + 1 + ); + + // Apply recency decay + const daysSinceUse = daysBetween(record.lastUsed, new Date()); + const recencyFactor = Math.pow(0.99, daysSinceUse); + const adjustedSample = sample * recencyFactor; + + if (adjustedSample > bestSample) { + bestSample = adjustedSample; + bestPath = record.steps; + } + } + + return bestPath; + } + + /** + * Get K-factor (convergence toward determinism) + * + * K → 0.0: No dominant path, explore freely + * K → 1.0: Strong dominant path, nearly deterministic + */ + getKFactor(query: string): number { + const pattern = extractPattern(query); + const records = this.records.get(pattern); + + if (!records || records.length === 0) return 0; + + const total = records.reduce((sum, r) => sum + r.successes + r.failures, 0); + if (total < 10) return 0; // Not enough data + + const topPath = records.sort((a, b) => + (b.successes / (b.successes + b.failures)) - + (a.successes / (a.successes + a.failures)) + )[0]; + + const topUsage = (topPath.successes + topPath.failures) / total; + const topSuccess = topPath.successes / (topPath.successes + topPath.failures); + + return topUsage * topSuccess; + } +} + +/** + * Sample from Beta distribution + */ +function sampleBeta(alpha: number, beta: number): number { + // Simplified: use gamma sampling + const x = sampleGamma(alpha); + const y = sampleGamma(beta); + return x / (x + y); +} +``` + +--- + +## Part 7: The Main Orchestrator + +```typescript +// ============================================================================ +// lib/planner-orchestrator.ts +// ============================================================================ + +/** + * Main entry point: Query → Plans → Execution → Result + * + * ┌─────────────────────────────────────────────────────────────────────┐ + * │ │ + * │ 1. QUERY 2. PLANS 3. SELECT 4. EXECUTE │ + * │ ─────── ─────── ──────── ───────── │ + * │ │ + * │ "analyze ┌────────┐ │ + * │ competitor │ Plan A │───┐ User picks ┌──────────┐ │ + * │ prices" ───►│ Plan B │───┼───► or auto ───► │ Cascade │───► │ + * │ │ Plan C │───┘ select │ Execute │ │ + * │ └────────┘ └──────────┘ │ + * │ │ + * └─────────────────────────────────────────────────────────────────────┘ + */ +class PlannerOrchestrator { + private learner = new PathwayLearner(); + + async processQuery( + query: string, + options: OrchestratorOptions = {} + ): AsyncGenerator { + + const { numPlans = 3, autoSelect = false } = options; + + // ───────────────────────────────────────────────────────────────── + // Step 1: Check for learned pathway + // ───────────────────────────────────────────────────────────────── + const kFactor = this.learner.getKFactor(query); + + yield { type: 'k_factor', value: kFactor }; + + if (kFactor > 0.9) { + // Near-deterministic: use learned path directly + const learnedPath = this.learner.recommendPathway(query); + if (learnedPath) { + yield { type: 'using_learned_path', path: learnedPath }; + + const plan = await this.pathToExecutionPlan(learnedPath, query); + yield* this.executePlan(plan, query); + return; + } + } + + // ───────────────────────────────────────────────────────────────── + // Step 2: Generate Y plans + // ───────────────────────────────────────────────────────────────── + yield { type: 'generating_plans' }; + + const plans = await generatePlans(query, numPlans); + + yield { + type: 'plans_ready', + plans: plans.map(p => ({ + id: p.id, + steps: p.steps.length, + cost: p.estimatedCost, + confidence: p.confidence, + skills: p.skills.map(s => s.domain) + })) + }; + + // ───────────────────────────────────────────────────────────────── + // Step 3: Select plan + // ───────────────────────────────────────────────────────────────── + let selectedPlan: ExecutionPlan; + + if (autoSelect) { + // Auto-select: use Thompson Sampling across plans + selectedPlan = this.selectPlanThompson(plans); + yield { type: 'auto_selected', planId: selectedPlan.id }; + } else { + // Wait for user selection + yield { type: 'awaiting_selection' }; + const selection = await this.waitForUserSelection(plans); + selectedPlan = plans.find(p => p.id === selection)!; + } + + // ───────────────────────────────────────────────────────────────── + // Step 4: Execute with cascading context + // ───────────────────────────────────────────────────────────────── + yield* this.executePlan(selectedPlan, query); + } + + private async* executePlan( + plan: ExecutionPlan, + query: string + ): AsyncGenerator { + + yield { + type: 'execution_start', + totalSteps: plan.steps.length, + skills: plan.skills.map(s => s.domain) + }; + + const context: ExecutionContext = { + query, + variables: new Map(), + completed: new Set(), + errors: [] + }; + + let success = true; + + try { + for await (const event of executeWithCascading(plan, context)) { + yield { type: 'execution_event', event }; + } + } catch (error) { + success = false; + yield { type: 'execution_error', error }; + } + + // Record outcome for learning + const pathSteps = plan.steps.map(s => s.tool.id); + this.learner.recordOutcome(query, pathSteps, success); + + yield { + type: 'execution_complete', + success, + output: Object.fromEntries(context.variables) + }; + } + + /** + * Thompson Sampling for plan selection + */ + private selectPlanThompson(plans: ExecutionPlan[]): ExecutionPlan { + let best = plans[0]; + let bestScore = -1; + + for (const plan of plans) { + // Sample based on confidence + randomness + const sample = sampleBeta( + plan.confidence * 100, + (1 - plan.confidence) * 100 + ); + + if (sample > bestScore) { + bestScore = sample; + best = plan; + } + } + + return best; + } +} +``` + +--- + +## Part 8: React Integration + +```typescript +// ============================================================================ +// components/PlannerPlayground.tsx +// ============================================================================ + +/** + * UI for the planner system + * + * ┌─────────────────────────────────────────────────────────────────┐ + * │ Query: [_______________________________________] [Generate] │ + * ├─────────────────────────────────────────────────────────────────┤ + * │ │ + * │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ + * │ │ ◉ Plan A │ │ ○ Plan B │ │ ○ Plan C │ │ + * │ │ 12 steps │ │ 6 steps │ │ 8 steps │ │ + * │ │ $0.45 │ │ $0.15 │ │ $0.28 │ │ + * │ │ 94% conf │ │ 87% conf │ │ 91% conf │ │ + * │ └─────────────┘ └─────────────┘ └─────────────┘ │ + * │ │ + * │ Skills: [SEO] [Scraping] [Data Analysis] │ + * │ │ + * │ [Execute Selected Plan] │ + * │ │ + * ├─────────────────────────────────────────────────────────────────┤ + * │ Execution Progress: │ + * │ ✓ Step 1: Fetch webpage (823ms) │ + * │ ✓ Step 2: Parse HTML (234ms) │ + * │ ► Step 3: Extract prices... [████████░░] 80% │ + * │ ○ Step 4: Analyze trends │ + * │ ○ Step 5: Generate report │ + * │ │ + * │ Context: 1,240 tokens (vs 12,400 if loaded all) │ + * └─────────────────────────────────────────────────────────────────┘ + */ + +function PlannerPlayground() { + const [query, setQuery] = useState(''); + const [plans, setPlans] = useState([]); + const [selectedPlan, setSelectedPlan] = useState(null); + const [execution, setExecution] = useState(null); + const [kFactor, setKFactor] = useState(0); + + const orchestrator = useRef(new PlannerOrchestrator()); + + async function handleGenerate() { + setPlans([]); + setExecution(null); + + for await (const event of orchestrator.current.processQuery(query)) { + switch (event.type) { + case 'k_factor': + setKFactor(event.value); + break; + + case 'plans_ready': + setPlans(event.plans); + break; + + case 'execution_start': + setExecution({ + status: 'running', + totalSteps: event.totalSteps, + currentStep: 0, + skills: event.skills, + events: [] + }); + break; + + case 'execution_event': + setExecution(prev => ({ + ...prev!, + events: [...prev!.events, event.event], + currentStep: event.event.type === 'step_complete' + ? prev!.currentStep + 1 + : prev!.currentStep + })); + break; + + case 'execution_complete': + setExecution(prev => ({ + ...prev!, + status: event.success ? 'complete' : 'error', + output: event.output + })); + break; + } + } + } + + return ( +
+ {/* Query Input */} + + + {/* K-Factor Indicator */} + {kFactor > 0 && ( + + )} + + {/* Plan Selection */} + {plans.length > 0 && ( + + )} + + {/* Execution Progress */} + {execution && ( + + )} +
+ ); +} +``` + +--- + +## Part 9: API Routes + +```typescript +// ============================================================================ +// app/api/planner/generate/route.ts +// ============================================================================ + +export async function POST(req: Request) { + const { query, numPlans } = await req.json(); + + const plans = await generatePlans(query, numPlans); + + return Response.json({ + success: true, + data: plans.map(p => ({ + id: p.id, + steps: p.steps.map(s => ({ + id: s.id, + tool: s.tool.exportName, + purpose: s.purpose + })), + estimatedCost: p.estimatedCost, + confidence: p.confidence, + skills: p.skills.map(s => s.domain) + })) + }); +} + +// ============================================================================ +// app/api/planner/execute/route.ts +// ============================================================================ + +export async function POST(req: Request) { + const { planId, query } = await req.json(); + + // Get full plan from cache/DB + const plan = await getPlan(planId); + + // Create SSE stream + const stream = new ReadableStream({ + async start(controller) { + const encoder = new TextEncoder(); + + const context: ExecutionContext = { + query, + variables: new Map(), + completed: new Set(), + errors: [] + }; + + for await (const event of executeWithCascading(plan, context)) { + controller.enqueue( + encoder.encode(`data: ${JSON.stringify(event)}\n\n`) + ); + } + + controller.close(); + } + }); + + return new Response(stream, { + headers: { + 'Content-Type': 'text/event-stream', + 'Cache-Control': 'no-cache' + } + }); +} +``` + +--- + +## Summary: The Complete Flow + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ TPMJS PLANNER ARCHITECTURE │ +│ │ +│ ┌───────────────────────────────────────────────────────────────────────┐ │ +│ │ USER QUERY │ │ +│ │ "Scrape competitor prices and analyze" │ │ +│ └─────────────────────────────────┬─────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌───────────────────────────────────────────────────────────────────────┐ │ +│ │ 1. CHECK LEARNED PATHS │ │ +│ │ │ │ +│ │ K-factor = 0.85 ──► Strong pattern exists │ │ +│ │ K-factor = 0.30 ──► Generate new plans │ │ +│ └─────────────────────────────────┬─────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌───────────────────────────────────────────────────────────────────────┐ │ +│ │ 2. DISCOVER TOOLS │ │ +│ │ │ │ +│ │ Query Registry ──► Rank by relevance ──► Top 20 tools │ │ +│ └─────────────────────────────────┬─────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌───────────────────────────────────────────────────────────────────────┐ │ +│ │ 3. GENERATE Y PLANS │ │ +│ │ │ │ +│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ +│ │ │ Plan A │ │ Plan B │ │ Plan C │ │ │ +│ │ │Thorough │ │ Quick │ │Balanced │ │ │ +│ │ │12 steps │ │ 5 steps │ │ 8 steps │ │ │ +│ │ └─────────┘ └─────────┘ └─────────┘ │ │ +│ └─────────────────────────────────┬─────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌───────────────────────────────────────────────────────────────────────┐ │ +│ │ 4. INFER SKILLS │ │ +│ │ │ │ +│ │ Tools ──► Cluster by domain ──► Load domain context │ │ +│ │ │ │ +│ │ [web-scraping: robots.txt, selectors, rate limits] │ │ +│ │ [data-analysis: normalization, outliers, trends] │ │ +│ └─────────────────────────────────┬─────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌───────────────────────────────────────────────────────────────────────┐ │ +│ │ 5. USER SELECTS (or auto) │ │ +│ │ │ │ +│ │ Thompson Sampling if auto ──► Pick plan with highest sample │ │ +│ └─────────────────────────────────┬─────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌───────────────────────────────────────────────────────────────────────┐ │ +│ │ 6. CASCADE EXECUTE │ │ +│ │ │ │ +│ │ For each step: │ │ +│ │ ┌────────────────────────────────────────────────────────────────┐ │ │ +│ │ │ • Load current tool + relevant skill context (~1k tokens) │ │ │ +│ │ │ • Preload next 2 likely tools │ │ │ +│ │ │ • Execute via registry │ │ │ +│ │ │ • Try fallbacks on failure │ │ │ +│ │ │ • Store result, update state │ │ │ +│ │ └────────────────────────────────────────────────────────────────┘ │ │ +│ └─────────────────────────────────┬─────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌───────────────────────────────────────────────────────────────────────┐ │ +│ │ 7. RECORD OUTCOME │ │ +│ │ │ │ +│ │ Success/Failure ──► Update pathway stats ──► Adjust K-factor │ │ +│ └─────────────────────────────────┬─────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌───────────────────────────────────────────────────────────────────────┐ │ +│ │ FINAL OUTPUT │ │ +│ └───────────────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Key Files to Create + +``` +apps/web/ +├── src/ +│ ├── lib/ +│ │ ├── planner/ +│ │ │ ├── tool-discovery.ts # Part 2 +│ │ │ ├── plan-generator.ts # Part 3 +│ │ │ ├── skill-inference.ts # Part 4 +│ │ │ ├── cascading-executor.ts # Part 5 +│ │ │ ├── pathway-learning.ts # Part 6 +│ │ │ └── orchestrator.ts # Part 7 +│ │ └── types/ +│ │ └── planner.ts # Part 1 +│ ├── components/ +│ │ └── PlannerPlayground.tsx # Part 8 +│ └── app/ +│ └── api/ +│ └── planner/ +│ ├── generate/route.ts # Part 9 +│ └── execute/route.ts # Part 9 + +packages/db/prisma/ +└── schema.prisma # Add PathwayRecord model +``` diff --git a/packages/ui/src/Spinner/Spinner.tsx b/packages/ui/src/Spinner/Spinner.tsx index cc1daa8..28867f3 100644 --- a/packages/ui/src/Spinner/Spinner.tsx +++ b/packages/ui/src/Spinner/Spinner.tsx @@ -2,25 +2,17 @@ import { cn } from '@tpmjs/utils/cn'; -const sizeClasses = { - xs: 'w-5 h-5', - sm: 'w-8 h-8', - md: 'w-12 h-12', - lg: 'w-16 h-16', - xl: 'w-24 h-24', -} as const; - -const dotSizeClasses = { - xs: 'w-1 h-1', - sm: 'w-1.5 h-1.5', - md: 'w-2 h-2', - lg: 'w-3 h-3', - xl: 'w-4 h-4', +const sizeConfig = { + xs: { container: 'w-4 h-4', block: 3, gap: 1 }, + sm: { container: 'w-6 h-6', block: 4, gap: 2 }, + md: { container: 'w-8 h-8', block: 6, gap: 2 }, + lg: { container: 'w-12 h-12', block: 8, gap: 3 }, + xl: { container: 'w-16 h-16', block: 12, gap: 4 }, } as const; export interface SpinnerProps extends React.HTMLAttributes { /** Size variant */ - size?: keyof typeof sizeClasses; + size?: keyof typeof sizeConfig; /** Optional label for accessibility */ label?: string; } @@ -28,8 +20,9 @@ export interface SpinnerProps extends React.HTMLAttributes { /** * Spinner component * - * An elegant orbital loading spinner with three dots rotating - * in a synchronized dance pattern. + * A brutalist grid-based loader that evokes the feeling of + * tools being constructed, block by block. Matches the TPMJS + * dithering aesthetic with sharp squares and wave animations. */ export function Spinner({ className, @@ -37,68 +30,73 @@ export function Spinner({ label = 'Loading...', ...props }: SpinnerProps): React.ReactElement { - const sizeClass = sizeClasses[size]; - const dotSize = dotSizeClasses[size]; + const config = sizeConfig[size]; + const blockSize = config.block; + const gap = config.gap; + + // 3x3 grid positions with staggered delays (diagonal wave) + const blocks = [ + { id: 'b00', row: 0, col: 0, delay: 0 }, + { id: 'b01', row: 0, col: 1, delay: 0.1 }, + { id: 'b02', row: 0, col: 2, delay: 0.2 }, + { id: 'b10', row: 1, col: 0, delay: 0.1 }, + { id: 'b11', row: 1, col: 1, delay: 0.2 }, + { id: 'b12', row: 1, col: 2, delay: 0.3 }, + { id: 'b20', row: 2, col: 0, delay: 0.2 }, + { id: 'b21', row: 2, col: 1, delay: 0.3 }, + { id: 'b22', row: 2, col: 2, delay: 0.4 }, + ]; return ( - // biome-ignore lint/a11y/useSemanticElements: Spinner requires role="status" for screen reader announcements, is not semantically appropriate + // biome-ignore lint/a11y/useSemanticElements: Spinner requires role="status" for screen reader announcements
- {/* Orbital ring hint */} -
+
+ {blocks.map((block) => ( +
+ ))} +
- {/* Three orbiting dots with staggered animations */} -
-
-
- - {/* Screen reader text */} {label}
);