htmlgraph 0.24.1__py3-none-any.whl → 0.25.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. htmlgraph/__init__.py +20 -1
  2. htmlgraph/agent_detection.py +26 -10
  3. htmlgraph/analytics/cross_session.py +4 -3
  4. htmlgraph/analytics/work_type.py +52 -16
  5. htmlgraph/analytics_index.py +51 -19
  6. htmlgraph/api/__init__.py +3 -0
  7. htmlgraph/api/main.py +2115 -0
  8. htmlgraph/api/static/htmx.min.js +1 -0
  9. htmlgraph/api/static/style-redesign.css +1344 -0
  10. htmlgraph/api/static/style.css +1079 -0
  11. htmlgraph/api/templates/dashboard-redesign.html +812 -0
  12. htmlgraph/api/templates/dashboard.html +783 -0
  13. htmlgraph/api/templates/partials/activity-feed-hierarchical.html +326 -0
  14. htmlgraph/api/templates/partials/activity-feed.html +570 -0
  15. htmlgraph/api/templates/partials/agents-redesign.html +317 -0
  16. htmlgraph/api/templates/partials/agents.html +317 -0
  17. htmlgraph/api/templates/partials/event-traces.html +373 -0
  18. htmlgraph/api/templates/partials/features-kanban-redesign.html +509 -0
  19. htmlgraph/api/templates/partials/features.html +509 -0
  20. htmlgraph/api/templates/partials/metrics-redesign.html +346 -0
  21. htmlgraph/api/templates/partials/metrics.html +346 -0
  22. htmlgraph/api/templates/partials/orchestration-redesign.html +443 -0
  23. htmlgraph/api/templates/partials/orchestration.html +163 -0
  24. htmlgraph/api/templates/partials/spawners.html +375 -0
  25. htmlgraph/atomic_ops.py +560 -0
  26. htmlgraph/builders/base.py +55 -1
  27. htmlgraph/builders/bug.py +17 -2
  28. htmlgraph/builders/chore.py +17 -2
  29. htmlgraph/builders/epic.py +17 -2
  30. htmlgraph/builders/feature.py +25 -2
  31. htmlgraph/builders/phase.py +17 -2
  32. htmlgraph/builders/spike.py +27 -2
  33. htmlgraph/builders/track.py +14 -0
  34. htmlgraph/cigs/__init__.py +4 -0
  35. htmlgraph/cigs/reporter.py +818 -0
  36. htmlgraph/cli.py +1427 -401
  37. htmlgraph/cli_commands/__init__.py +1 -0
  38. htmlgraph/cli_commands/feature.py +195 -0
  39. htmlgraph/cli_framework.py +115 -0
  40. htmlgraph/collections/__init__.py +2 -0
  41. htmlgraph/collections/base.py +21 -0
  42. htmlgraph/collections/session.py +189 -0
  43. htmlgraph/collections/spike.py +7 -1
  44. htmlgraph/collections/task_delegation.py +236 -0
  45. htmlgraph/collections/traces.py +482 -0
  46. htmlgraph/config.py +113 -0
  47. htmlgraph/converter.py +41 -0
  48. htmlgraph/cost_analysis/__init__.py +5 -0
  49. htmlgraph/cost_analysis/analyzer.py +438 -0
  50. htmlgraph/dashboard.html +3315 -492
  51. htmlgraph-0.24.1.data/data/htmlgraph/dashboard.html → htmlgraph/dashboard.html.backup +2246 -248
  52. htmlgraph/dashboard.html.bak +7181 -0
  53. htmlgraph/dashboard.html.bak2 +7231 -0
  54. htmlgraph/dashboard.html.bak3 +7232 -0
  55. htmlgraph/db/__init__.py +38 -0
  56. htmlgraph/db/queries.py +790 -0
  57. htmlgraph/db/schema.py +1334 -0
  58. htmlgraph/deploy.py +26 -27
  59. htmlgraph/docs/API_REFERENCE.md +841 -0
  60. htmlgraph/docs/HTTP_API.md +750 -0
  61. htmlgraph/docs/INTEGRATION_GUIDE.md +752 -0
  62. htmlgraph/docs/ORCHESTRATION_PATTERNS.md +710 -0
  63. htmlgraph/docs/README.md +533 -0
  64. htmlgraph/docs/version_check.py +3 -1
  65. htmlgraph/error_handler.py +544 -0
  66. htmlgraph/event_log.py +2 -0
  67. htmlgraph/hooks/__init__.py +8 -0
  68. htmlgraph/hooks/bootstrap.py +169 -0
  69. htmlgraph/hooks/context.py +271 -0
  70. htmlgraph/hooks/drift_handler.py +521 -0
  71. htmlgraph/hooks/event_tracker.py +405 -15
  72. htmlgraph/hooks/post_tool_use_handler.py +257 -0
  73. htmlgraph/hooks/pretooluse.py +476 -6
  74. htmlgraph/hooks/prompt_analyzer.py +648 -0
  75. htmlgraph/hooks/session_handler.py +583 -0
  76. htmlgraph/hooks/state_manager.py +501 -0
  77. htmlgraph/hooks/subagent_stop.py +309 -0
  78. htmlgraph/hooks/task_enforcer.py +39 -0
  79. htmlgraph/models.py +111 -15
  80. htmlgraph/operations/fastapi_server.py +230 -0
  81. htmlgraph/orchestration/headless_spawner.py +22 -14
  82. htmlgraph/pydantic_models.py +476 -0
  83. htmlgraph/quality_gates.py +350 -0
  84. htmlgraph/repo_hash.py +511 -0
  85. htmlgraph/sdk.py +348 -10
  86. htmlgraph/server.py +194 -0
  87. htmlgraph/session_hooks.py +300 -0
  88. htmlgraph/session_manager.py +131 -1
  89. htmlgraph/session_registry.py +587 -0
  90. htmlgraph/session_state.py +436 -0
  91. htmlgraph/system_prompts.py +449 -0
  92. htmlgraph/templates/orchestration-view.html +350 -0
  93. htmlgraph/track_builder.py +19 -0
  94. htmlgraph/validation.py +115 -0
  95. htmlgraph-0.25.0.data/data/htmlgraph/dashboard.html +7417 -0
  96. {htmlgraph-0.24.1.dist-info → htmlgraph-0.25.0.dist-info}/METADATA +91 -64
  97. {htmlgraph-0.24.1.dist-info → htmlgraph-0.25.0.dist-info}/RECORD +103 -42
  98. {htmlgraph-0.24.1.data → htmlgraph-0.25.0.data}/data/htmlgraph/styles.css +0 -0
  99. {htmlgraph-0.24.1.data → htmlgraph-0.25.0.data}/data/htmlgraph/templates/AGENTS.md.template +0 -0
  100. {htmlgraph-0.24.1.data → htmlgraph-0.25.0.data}/data/htmlgraph/templates/CLAUDE.md.template +0 -0
  101. {htmlgraph-0.24.1.data → htmlgraph-0.25.0.data}/data/htmlgraph/templates/GEMINI.md.template +0 -0
  102. {htmlgraph-0.24.1.dist-info → htmlgraph-0.25.0.dist-info}/WHEEL +0 -0
  103. {htmlgraph-0.24.1.dist-info → htmlgraph-0.25.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,710 @@
1
+ # HtmlGraph Orchestration Patterns
2
+
3
+ Guide to spawning agents, delegating tasks, and coordinating multi-agent workflows.
4
+
5
+ ## Table of Contents
6
+
7
+ 1. [Core Concepts](#core-concepts)
8
+ 2. [Agent Selection](#agent-selection)
9
+ 3. [Task Delegation](#task-delegation)
10
+ 4. [Result Tracking](#result-tracking)
11
+ 5. [Cost Optimization](#cost-optimization)
12
+ 6. [Advanced Patterns](#advanced-patterns)
13
+ 7. [Troubleshooting](#troubleshooting)
14
+
15
+ ---
16
+
17
+ ## Core Concepts
18
+
19
+ ### Agent Spawning
20
+
21
+ Dynamically spawn specialized agents for specific tasks:
22
+
23
+ ```python
24
+ from htmlgraph.orchestration import HeadlessSpawner
25
+
26
+ spawner = HeadlessSpawner()
27
+
28
+ # Spawn different agents for different tasks
29
+ result = spawner.spawn_claude(
30
+ prompt="Implement user authentication module",
31
+ approval="auto"
32
+ )
33
+
34
+ result = spawner.spawn_gemini(
35
+ prompt="Analyze codebase for performance issues",
36
+ model="gemini-2.0-flash"
37
+ )
38
+
39
+ result = spawner.spawn_codex(
40
+ prompt="Generate API endpoint implementation",
41
+ sandbox="workspace-write"
42
+ )
43
+ ```
44
+
45
+ ### Task vs Agent
46
+
47
+ - **Agent**: An AI model spawned to complete work (Claude, Gemini, Codex, Copilot)
48
+ - **Task**: A delegated unit of work tracked in `.htmlgraph/task-delegations/`
49
+ - **Result**: The output of a completed task stored in HtmlGraph
50
+
51
+ ---
52
+
53
+ ## Agent Selection
54
+
55
+ ### Spawn Methods
56
+
57
+ #### Claude Spawning
58
+
59
+ ```python
60
+ from htmlgraph.orchestration import HeadlessSpawner
61
+
62
+ spawner = HeadlessSpawner()
63
+
64
+ result = spawner.spawn_claude(
65
+ prompt="Your task description",
66
+ approval="auto", # "auto", "manual", "never"
67
+ model="claude-opus", # Model to use
68
+ max_thinking_budget=10000, # Extended thinking budget
69
+ output_json=False
70
+ )
71
+
72
+ if result.success:
73
+ print(f"Output: {result.response}")
74
+ print(f"Tokens: {result.tokens_used}")
75
+ else:
76
+ print(f"Error: {result.error}")
77
+ ```
78
+
79
+ **Claude Models:**
80
+ - `claude-opus` - Most capable, highest cost
81
+ - `claude-sonnet` - Balanced capability/cost
82
+ - `claude-haiku` - Fastest, lowest cost
83
+
84
+ ---
85
+
86
+ #### Gemini Spawning
87
+
88
+ ```python
89
+ result = spawner.spawn_gemini(
90
+ prompt="Analyze this code for security issues",
91
+ model="gemini-2.0-flash", # Latest Gemini model
92
+ temperature=0.7, # Creativity (0-1)
93
+ output_json=False
94
+ )
95
+
96
+ if result.success:
97
+ print(result.response)
98
+ else:
99
+ print(f"Error: {result.error}")
100
+ ```
101
+
102
+ **Gemini Models:**
103
+ - `gemini-2.0-flash` - Latest, fastest
104
+ - `gemini-1.5-pro` - More capable
105
+ - `gemini-1.5-flash` - Faster, cheaper
106
+
107
+ ---
108
+
109
+ #### Codex/GPT Spawning
110
+
111
+ ```python
112
+ result = spawner.spawn_codex(
113
+ prompt="Generate implementation for REST API",
114
+ sandbox="workspace-write", # Execution sandbox
115
+ model="gpt-4-turbo", # OpenAI model
116
+ full_auto=False, # Auto-execute code
117
+ output_json=True
118
+ )
119
+
120
+ if result.success:
121
+ print(result.response)
122
+ # Access raw JSONL events
123
+ for event in result.raw_output:
124
+ if event.get("type") == "item.completed":
125
+ print(f"Completed: {event['item']['type']}")
126
+ else:
127
+ print(f"Error: {result.error}")
128
+ ```
129
+
130
+ **Codex Sandbox Levels:**
131
+ - `read-only` - No write access (safe)
132
+ - `workspace-write` - Write to workspace only (recommended)
133
+ - `danger-full-access` - Unrestricted access (risky)
134
+
135
+ ---
136
+
137
+ #### Copilot Spawning
138
+
139
+ ```python
140
+ result = spawner.spawn_copilot(
141
+ prompt="Refactor this Python function",
142
+ model="gpt-4",
143
+ output_json=False
144
+ )
145
+
146
+ if result.success:
147
+ print(result.response)
148
+ else:
149
+ print(f"Error: {result.error}")
150
+ ```
151
+
152
+ ---
153
+
154
+ ### Model Selection Strategy
155
+
156
+ ```python
157
+ from htmlgraph.orchestration import (
158
+ select_model,
159
+ TaskType,
160
+ ComplexityLevel,
161
+ BudgetMode
162
+ )
163
+
164
+ # Automatically select best model
165
+ model = select_model(
166
+ task_type=TaskType.CODE_GENERATION, # Task classification
167
+ complexity=ComplexityLevel.HIGH, # Complexity assessment
168
+ budget_mode=BudgetMode.BALANCED # Cost preference
169
+ )
170
+ # Returns: "gpt-4-turbo" (or other optimal model)
171
+
172
+ # Use selected model
173
+ if model == "gpt-4-turbo":
174
+ result = spawner.spawn_codex(prompt="...", model=model)
175
+ elif model == "claude-opus":
176
+ result = spawner.spawn_claude(prompt="...", model=model)
177
+ elif model == "gemini-2.0-flash":
178
+ result = spawner.spawn_gemini(prompt="...", model=model)
179
+ ```
180
+
181
+ **Task Types:**
182
+ - `CODE_GENERATION` - Writing new code
183
+ - `CODE_REVIEW` - Analyzing code
184
+ - `DEBUGGING` - Finding/fixing bugs
185
+ - `DOCUMENTATION` - Writing docs
186
+ - `ARCHITECTURE` - Design decisions
187
+ - `TESTING` - Test generation
188
+ - `REFACTORING` - Code improvements
189
+
190
+ **Complexity Levels:**
191
+ - `LOW` - Simple, straightforward tasks
192
+ - `MEDIUM` - Moderate complexity
193
+ - `HIGH` - Complex, multi-step tasks
194
+
195
+ **Budget Modes:**
196
+ - `COST_OPTIMIZED` - Prefer cheaper models
197
+ - `BALANCED` - Mix cost/capability
198
+ - `QUALITY_FOCUSED` - Use best models
199
+
200
+ ---
201
+
202
+ ## Task Delegation
203
+
204
+ ### Simple Delegation
205
+
206
+ ```python
207
+ from htmlgraph import SDK, delegate_with_id
208
+
209
+ sdk = SDK(agent="orchestrator")
210
+
211
+ # Delegate single task
212
+ task_id = delegate_with_id(
213
+ prompt="Implement JWT authentication middleware",
214
+ agent="coder",
215
+ task_id="task-auth-001"
216
+ )
217
+
218
+ print(f"Delegated task: {task_id}")
219
+ ```
220
+
221
+ ### Parallel Delegation
222
+
223
+ ```python
224
+ from htmlgraph import parallel_delegate
225
+
226
+ # Delegate multiple tasks in parallel
227
+ tasks = [
228
+ {
229
+ "prompt": "Implement login endpoint",
230
+ "agent": "coder",
231
+ "task_id": "auth-login"
232
+ },
233
+ {
234
+ "prompt": "Implement logout endpoint",
235
+ "agent": "coder",
236
+ "task_id": "auth-logout"
237
+ },
238
+ {
239
+ "prompt": "Write authentication tests",
240
+ "agent": "tester",
241
+ "task_id": "auth-tests"
242
+ },
243
+ {
244
+ "prompt": "Document authentication API",
245
+ "agent": "writer",
246
+ "task_id": "auth-docs"
247
+ }
248
+ ]
249
+
250
+ results = parallel_delegate(tasks)
251
+
252
+ # Process results as they complete
253
+ for task_id, result in results.items():
254
+ print(f"{task_id}: {result['status']}")
255
+ if result['status'] == 'completed':
256
+ print(f"Output: {result['output']}")
257
+ ```
258
+
259
+ ---
260
+
261
+ ### Delegation with Fallback
262
+
263
+ ```python
264
+ # Try Codex, fallback to Claude if fails
265
+ result = spawner.spawn_codex(
266
+ prompt="Generate API implementation",
267
+ sandbox="workspace-write"
268
+ )
269
+
270
+ if not result.success:
271
+ print(f"Codex failed: {result.error}")
272
+ print("Falling back to Claude...")
273
+
274
+ result = spawner.spawn_claude(
275
+ prompt="Generate API implementation",
276
+ approval="auto"
277
+ )
278
+
279
+ print(f"Final result: {result.response}")
280
+ ```
281
+
282
+ ---
283
+
284
+ ## Result Tracking
285
+
286
+ ### Get Task Results
287
+
288
+ ```python
289
+ from htmlgraph import get_results_by_task_id
290
+
291
+ # Check task status
292
+ results = get_results_by_task_id("task-auth-001")
293
+
294
+ if results:
295
+ print(f"Status: {results['status']}")
296
+ print(f"Output: {results['output']}")
297
+ print(f"Tokens used: {results['tokens_used']}")
298
+ else:
299
+ print("Task not found")
300
+ ```
301
+
302
+ ### Track Delegations in SDK
303
+
304
+ ```python
305
+ sdk = SDK(agent="orchestrator")
306
+
307
+ # View all delegations
308
+ all_delegations = sdk.task_delegations.all()
309
+
310
+ # Query specific delegations
311
+ pending = sdk.task_delegations.where(status="pending")
312
+ completed = sdk.task_delegations.where(status="completed")
313
+ failed = sdk.task_delegations.where(status="failed")
314
+
315
+ # Get specific delegation
316
+ delegation = sdk.task_delegations.get("task-auth-001")
317
+ if delegation:
318
+ print(f"Agent: {delegation.agent}")
319
+ print(f"Status: {delegation.status}")
320
+ print(f"Result: {delegation.result}")
321
+ ```
322
+
323
+ ### Delegation Results Structure
324
+
325
+ ```python
326
+ {
327
+ "task_id": "task-auth-001",
328
+ "prompt": "Implement JWT authentication",
329
+ "agent": "coder",
330
+ "status": "completed", # or "pending", "in-progress", "failed"
331
+ "created_at": "2025-01-06T10:30:45.123Z",
332
+ "started_at": "2025-01-06T10:31:00.123Z",
333
+ "completed_at": "2025-01-06T10:45:00.123Z",
334
+ "output": "Authentication module implemented...",
335
+ "tokens_used": 8432,
336
+ "model": "claude-opus",
337
+ "cost": 0.45,
338
+ "error": null # If status is "failed"
339
+ }
340
+ ```
341
+
342
+ ---
343
+
344
+ ## Cost Optimization
345
+
346
+ ### Budget-Aware Selection
347
+
348
+ ```python
349
+ # Select model based on budget
350
+ model = select_model(
351
+ task_type=TaskType.CODE_GENERATION,
352
+ complexity=ComplexityLevel.MEDIUM,
353
+ budget_mode=BudgetMode.COST_OPTIMIZED
354
+ )
355
+ # Returns: "claude-haiku" (cheapest capable model)
356
+
357
+ # Spawn with selected model
358
+ if model == "claude-haiku":
359
+ result = spawner.spawn_claude(prompt="...", model=model)
360
+ ```
361
+
362
+ ### Token Usage Tracking
363
+
364
+ ```python
365
+ # Track tokens for cost calculation
366
+ delegations = sdk.task_delegations.all()
367
+
368
+ total_tokens = sum(d.tokens_used for d in delegations)
369
+ total_cost = sum(d.cost for d in delegations)
370
+
371
+ print(f"Total tokens: {total_tokens}")
372
+ print(f"Total cost: ${total_cost:.2f}")
373
+
374
+ # Cost by model
375
+ from collections import Counter
376
+ model_costs = Counter()
377
+ for d in delegations:
378
+ model_costs[d.model] += d.cost
379
+
380
+ for model, cost in model_costs.items():
381
+ print(f"{model}: ${cost:.2f}")
382
+ ```
383
+
384
+ ### Cost per Task Type
385
+
386
+ ```python
387
+ # Analyze spending by task type
388
+ task_type_costs = {}
389
+
390
+ for delegation in sdk.task_delegations.all():
391
+ task_type = delegation.properties.get("task_type", "unknown")
392
+ if task_type not in task_type_costs:
393
+ task_type_costs[task_type] = {
394
+ "count": 0,
395
+ "total_cost": 0,
396
+ "avg_cost": 0
397
+ }
398
+
399
+ task_type_costs[task_type]["count"] += 1
400
+ task_type_costs[task_type]["total_cost"] += delegation.cost
401
+ task_type_costs[task_type]["avg_cost"] = (
402
+ task_type_costs[task_type]["total_cost"] /
403
+ task_type_costs[task_type]["count"]
404
+ )
405
+
406
+ # Find most expensive task types
407
+ sorted_types = sorted(
408
+ task_type_costs.items(),
409
+ key=lambda x: x[1]["total_cost"],
410
+ reverse=True
411
+ )
412
+
413
+ print("Cost by task type:")
414
+ for task_type, stats in sorted_types:
415
+ print(f" {task_type}: ${stats['total_cost']:.2f} " +
416
+ f"({stats['count']} tasks, avg ${stats['avg_cost']:.2f})")
417
+ ```
418
+
419
+ ---
420
+
421
+ ## Advanced Patterns
422
+
423
+ ### Chain-of-Thought Delegation
424
+
425
+ Decompose complex tasks into subtasks:
426
+
427
+ ```python
428
+ # Step 1: Analysis (cheap/fast)
429
+ analysis_result = spawner.spawn_gemini(
430
+ prompt="Analyze the codebase structure",
431
+ model="gemini-2.0-flash"
432
+ )
433
+
434
+ # Step 2: Design (more capable)
435
+ design_result = spawner.spawn_claude(
436
+ prompt=f"""Based on this analysis:
437
+ {analysis_result.response}
438
+
439
+ Design the implementation approach.""",
440
+ model="claude-opus"
441
+ )
442
+
443
+ # Step 3: Implementation (best model for code)
444
+ impl_result = spawner.spawn_codex(
445
+ prompt=f"""Based on this design:
446
+ {design_result.response}
447
+
448
+ Implement the solution.""",
449
+ sandbox="workspace-write"
450
+ )
451
+
452
+ print(f"Final implementation: {impl_result.response}")
453
+ ```
454
+
455
+ ### Error Recovery Pattern
456
+
457
+ ```python
458
+ def spawn_with_fallback(primary_spawner_fn, fallback_spawner_fn):
459
+ """Try primary spawner, fallback on failure."""
460
+
461
+ result = primary_spawner_fn()
462
+
463
+ if result.success:
464
+ return result
465
+
466
+ print(f"Primary failed: {result.error}")
467
+ print("Attempting fallback...")
468
+
469
+ fallback_result = fallback_spawner_fn()
470
+
471
+ if fallback_result.success:
472
+ return fallback_result
473
+
474
+ print(f"Fallback also failed: {fallback_result.error}")
475
+ raise RuntimeError("All spawners failed")
476
+
477
+ # Usage
478
+ result = spawn_with_fallback(
479
+ primary_spawner_fn=lambda: spawner.spawn_codex(
480
+ prompt="Generate API",
481
+ sandbox="workspace-write"
482
+ ),
483
+ fallback_spawner_fn=lambda: spawner.spawn_claude(
484
+ prompt="Generate API",
485
+ approval="auto"
486
+ )
487
+ )
488
+ ```
489
+
490
+ ### Feedback Loop Pattern
491
+
492
+ ```python
493
+ from htmlgraph import SDK
494
+
495
+ sdk = SDK(agent="orchestrator")
496
+
497
+ def iterative_improvement(initial_prompt, improvement_cycles=3):
498
+ """Iteratively improve output through feedback."""
499
+
500
+ # Initial generation
501
+ result = spawner.spawn_claude(
502
+ prompt=initial_prompt,
503
+ approval="auto"
504
+ )
505
+
506
+ output = result.response
507
+
508
+ # Improvement cycles
509
+ for i in range(improvement_cycles):
510
+ # Get feedback
511
+ feedback = spawner.spawn_claude(
512
+ prompt=f"""Review this output and identify improvements:
513
+
514
+ {output}
515
+
516
+ Provide specific, actionable feedback.""",
517
+ approval="auto"
518
+ )
519
+
520
+ # Apply improvements
521
+ result = spawner.spawn_claude(
522
+ prompt=f"""Based on this feedback:
523
+
524
+ {feedback.response}
525
+
526
+ Improve the output:
527
+
528
+ {output}""",
529
+ approval="auto"
530
+ )
531
+
532
+ output = result.response
533
+
534
+ # Track iteration
535
+ sdk.task_delegations.create(
536
+ task_id=f"improvement-cycle-{i}",
537
+ feedback_iteration=i,
538
+ output_tokens=result.tokens_used
539
+ )
540
+
541
+ return output
542
+
543
+ improved_code = iterative_improvement(
544
+ "Generate a Python REST API",
545
+ improvement_cycles=3
546
+ )
547
+ ```
548
+
549
+ ### Multi-Agent Consensus
550
+
551
+ ```python
552
+ def get_consensus(prompt, num_agents=3):
553
+ """Get consensus from multiple agents."""
554
+
555
+ results = []
556
+
557
+ # Get multiple perspectives
558
+ results.append(("claude-opus", spawner.spawn_claude(
559
+ prompt=prompt, model="claude-opus"
560
+ )))
561
+
562
+ results.append(("gemini-2.0-flash", spawner.spawn_gemini(
563
+ prompt=prompt, model="gemini-2.0-flash"
564
+ )))
565
+
566
+ results.append(("gpt-4-turbo", spawner.spawn_codex(
567
+ prompt=prompt, model="gpt-4-turbo"
568
+ )))
569
+
570
+ # Synthesize consensus
571
+ outputs = "\n".join(
572
+ f"## {agent}\n{result.response}"
573
+ for agent, result in results
574
+ if result.success
575
+ )
576
+
577
+ consensus = spawner.spawn_claude(
578
+ prompt=f"""Review these perspectives and provide consensus:
579
+
580
+ {outputs}
581
+
582
+ Synthesize the best insights.""",
583
+ approval="auto"
584
+ )
585
+
586
+ return consensus.response
587
+
588
+ consensus_result = get_consensus(
589
+ "What's the best approach for caching?"
590
+ )
591
+ ```
592
+
593
+ ---
594
+
595
+ ## Troubleshooting
596
+
597
+ ### Agent Spawn Fails
598
+
599
+ **Problem:** `spawn_claude()` returns `success=False`
600
+
601
+ **Solutions:**
602
+ 1. Check API key is set
603
+ 2. Verify network connectivity
604
+ 3. Check rate limits
605
+ 4. Try fallback spawner
606
+
607
+ ```python
608
+ import os
609
+
610
+ # Verify API key
611
+ if not os.getenv("ANTHROPIC_API_KEY"):
612
+ print("ERROR: ANTHROPIC_API_KEY not set")
613
+
614
+ # Check connectivity
615
+ import socket
616
+ try:
617
+ socket.create_connection(("api.anthropic.com", 443), timeout=5)
618
+ except socket.error as e:
619
+ print(f"Network error: {e}")
620
+
621
+ # Try with longer timeout
622
+ result = spawner.spawn_claude(
623
+ prompt="...",
624
+ timeout=60 # Longer timeout
625
+ )
626
+ ```
627
+
628
+ ---
629
+
630
+ ### Task Delegation Not Tracked
631
+
632
+ **Problem:** Task doesn't appear in `sdk.task_delegations`
633
+
634
+ **Solutions:**
635
+ 1. Use `delegate_with_id()` for tracking
636
+ 2. Check `.htmlgraph/task-delegations/` directory exists
637
+ 3. Verify task_id is unique
638
+
639
+ ```python
640
+ # Create directory if missing
641
+ from pathlib import Path
642
+ Path(".htmlgraph/task-delegations").mkdir(exist_ok=True)
643
+
644
+ # Use proper delegation API
645
+ from htmlgraph import delegate_with_id
646
+
647
+ task_id = delegate_with_id(
648
+ prompt="...",
649
+ agent="coder",
650
+ task_id="unique-task-id" # Must be unique
651
+ )
652
+ ```
653
+
654
+ ---
655
+
656
+ ### High Costs
657
+
658
+ **Problem:** Spending too much on agent spawning
659
+
660
+ **Solutions:**
661
+ 1. Use cheaper models for simple tasks
662
+ 2. Implement task decomposition
663
+ 3. Track costs by agent/task type
664
+ 4. Use budget mode: COST_OPTIMIZED
665
+
666
+ ```python
667
+ # Use budget-aware selection
668
+ from htmlgraph.orchestration import (
669
+ select_model,
670
+ TaskType,
671
+ ComplexityLevel,
672
+ BudgetMode
673
+ )
674
+
675
+ model = select_model(
676
+ task_type=TaskType.CODE_GENERATION,
677
+ complexity=ComplexityLevel.LOW,
678
+ budget_mode=BudgetMode.COST_OPTIMIZED
679
+ )
680
+ # Returns: cheaper model for simple tasks
681
+
682
+ # Track costs
683
+ delegations = sdk.task_delegations.where(status="completed")
684
+ total_cost = sum(d.cost for d in delegations)
685
+ avg_cost = total_cost / len(delegations) if delegations else 0
686
+ print(f"Average cost per task: ${avg_cost:.2f}")
687
+ ```
688
+
689
+ ---
690
+
691
+ ## Best Practices
692
+
693
+ 1. **Always use task IDs for tracking** - Enables result retrieval
694
+ 2. **Implement fallback spawners** - Ensures reliability
695
+ 3. **Monitor token usage** - Control costs
696
+ 4. **Decompose complex tasks** - Improve accuracy
697
+ 5. **Track delegation results** - Enable learning
698
+ 6. **Use appropriate models** - Balance cost/quality
699
+ 7. **Test with cheaper models first** - Validate logic
700
+ 8. **Implement timeouts** - Prevent hanging
701
+ 9. **Cache results** - Avoid duplicate work
702
+ 10. **Monitor error rates** - Improve quality
703
+
704
+ ---
705
+
706
+ ## See Also
707
+
708
+ - [SDK API Reference](API_REFERENCE.md) - Complete SDK documentation
709
+ - [HTTP API Reference](HTTP_API.md) - REST endpoint documentation
710
+ - [Integration Guide](INTEGRATION_GUIDE.md) - Quick start examples